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

ShapeFix_Wire_1.cxx

// szv 19.08.99: new methods for fixing gaps between edges (3d curves and pcurves)
#include <ShapeFix_Wire.hxx>
#include <Standard_ErrorHandler.hxx>
#include <Standard_Failure.hxx>

#include <Precision.hxx>
#include <Bnd_Box2d.hxx>
#include <Geom_Curve.hxx>
#include <Geom2d_Curve.hxx>
#include <Geom2d_Line.hxx>

#include <IntRes2d_SequenceOfIntersectionPoint.hxx>
#include <IntRes2d_IntersectionPoint.hxx>
#include <TColgp_SequenceOfPnt.hxx>

#include <TopoDS.hxx>
#include <TopoDS_Vertex.hxx>
#include <TopoDS_Edge.hxx>
#include <TopTools_HSequenceOfShape.hxx>

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

#include <ShapeExtend.hxx>
#include <ShapeBuild_Edge.hxx>
#include <ShapeBuild_Vertex.hxx>
#include <ShapeAnalysis_Curve.hxx>
#include <ShapeAnalysis_Edge.hxx>
#include <ShapeAnalysis_Surface.hxx>
#include <ShapeAnalysis.hxx>
#include <GeomConvert_CompCurveToBSplineCurve.hxx>
#include <Geom_TrimmedCurve.hxx>
#include <gp_Pln.hxx>
#include <GeomAPI.hxx>
#include <TColgp_Array1OfPnt.hxx>
#include <TColStd_Array1OfReal.hxx>
#include <TColStd_Array1OfInteger.hxx>
#include <Geom_BSplineCurve.hxx>
#include <Geom_SphericalSurface.hxx> //S4135
#include <Geom2d_BSplineCurve.hxx>
#include <GeomAdaptor_Curve.hxx>
#include <GeomAdaptor_HSurface.hxx>
#include <GeomAdaptor_Surface.hxx>  
#include <TopTools_Array1OfShape.hxx>
#include <BRepTools.hxx>
#include <Bnd_Array1OfBox2d.hxx>
#include <BndLib_Add2dCurve.hxx>
#include <Geom2dAdaptor_Curve.hxx>
#include <Geom2dConvert.hxx>
#include <Geom2d_TrimmedCurve.hxx>
#include <ShapeBuild_ReShape.hxx>
  
//szv
#include <TColgp_Array1OfPnt2d.hxx>
#include <Geom2d_Circle.hxx>
#include <Geom2d_Ellipse.hxx>
#include <Geom2d_Parabola.hxx>
#include <Geom2d_Hyperbola.hxx>
#include <Geom2d_OffsetCurve.hxx>
#include <Geom2dInt_GInter.hxx>
#include <IntRes2d_Domain.hxx>
#include <IntRes2d_IntersectionSegment.hxx>
#include <Geom2dAPI_ExtremaCurveCurve.hxx>
#include <Geom2dAPI_ProjectPointOnCurve.hxx>
#include <Geom2dAdaptor_HCurve.hxx>
#include <Approx_Curve2d.hxx>
#include <Geom2dConvert.hxx>

#include <Geom_Line.hxx>
#include <Geom_Circle.hxx>
#include <Geom_Ellipse.hxx>
#include <Geom_Parabola.hxx>
#include <Geom_Hyperbola.hxx>
#include <Geom_OffsetCurve.hxx>
#include <GeomAPI_ExtremaCurveCurve.hxx>
#include <GeomAPI_ProjectPointOnCurve.hxx>
#include <GeomAdaptor_HCurve.hxx>
#include <Approx_Curve3d.hxx>
#include <GeomConvert.hxx>
#include <TopoDS_Iterator.hxx>
#include <ShapeFix_ShapeTolerance.hxx>
#include <ShapeAnalysis_TransferParametersProj.hxx>
//=======================================================================
//function : FixGaps3d
//purpose  : 
//=======================================================================

00088  Standard_Boolean ShapeFix_Wire::FixGaps3d ()
{
  myStatusGaps3d = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
// if ( !IsReady() ) return Standard_False;
  
  Standard_Integer i, start = ( myClosedMode ? 1 : 2 );
  if (myFixGapsByRanges) 
  {
    for ( i = start; i <= NbEdges(); i++ ) 
    {
      FixGap3d ( i );
      myStatusGaps3d |= myLastFixStatus;
    }
  }
  for ( i = start; i <= NbEdges(); i++ ) 
  {
    FixGap3d ( i, Standard_True );
    myStatusGaps3d |= myLastFixStatus;
  }

  return StatusGaps3d ( ShapeExtend_DONE );
}

//=======================================================================
//function : FixGaps2d
//purpose  : 
//=======================================================================

00116  Standard_Boolean ShapeFix_Wire::FixGaps2d ()
{
  myStatusGaps2d = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
//  if ( !IsReady() ) return Standard_False;

  Standard_Integer i, start = ( myClosedMode ? 1 : 2 );
  if (myFixGapsByRanges) 
  {
    for ( i = start; i <= NbEdges(); i++ ) 
    {
      FixGap2d ( i );
      myStatusGaps2d |= myLastFixStatus;
    }
  }
  for ( i = start; i <= NbEdges(); i++ ) 
  {
    FixGap2d ( i, Standard_True );
    myStatusGaps2d |= myLastFixStatus;
  }

  return StatusGaps2d ( ShapeExtend_DONE );
}

//=======================================================================
//function : FixGap3d
//purpose  : 
//=======================================================================

static Standard_Real AdjustOnPeriodic3d (const Handle(Geom_Curve)& c,
                               const Standard_Boolean takefirst,
                               const Standard_Real first,
                               const Standard_Real last,
                               const Standard_Real param)
{
  // 15.11.2002 PTV OCC966
  if (ShapeAnalysis_Curve::IsPeriodic(c)) 
  {
    Standard_Real T = c->Period();
    Standard_Real shift = -IntegerPart(first/T)*T; if (first<0.) shift += T;
    Standard_Real sfirst = first+shift, slast = last+shift;
    if ( takefirst && (param>slast) && (param>sfirst)) return param-T-shift;
    if (!takefirst && (param<slast) && (param<sfirst)) return param+T-shift;
  }
  return param;
}

00162  Standard_Boolean ShapeFix_Wire::FixGap3d (const Standard_Integer num,
                                 const Standard_Boolean convert)
{
  myLastFixStatus = ShapeExtend::EncodeStatus( ShapeExtend_OK );
//  if ( !IsReady() ) return Standard_False;

  //=============
  // First phase: analysis whether the problem (gap) exists
  //=============

  if (Context().IsNull()) SetContext(new ShapeBuild_ReShape);

  Standard_Real preci = Precision();

  Handle(ShapeExtend_WireData) sbwd = WireData();
  Standard_Integer n2 = ( num >0 ? num  : sbwd->NbEdges() );
  Standard_Integer n1 = ( n2  >1 ? n2-1 : sbwd->NbEdges() );
//smh#8
  TopoDS_Shape tmp1 = Context()->Apply(sbwd->Edge(n1)),
               tmp2 = Context()->Apply(sbwd->Edge(n2));
  TopoDS_Edge E1 = TopoDS::Edge(tmp1),
              E2 = TopoDS::Edge(tmp2);
//  TopoDS_Face face = myAnalyzer->Face(); // comment by enk 

  // Retrieve curves on edges
  Standard_Real cfirst1, clast1, cfirst2, clast2;
  Handle(Geom_Curve) C1, C2;
  ShapeAnalysis_Edge SAE;
  if (!SAE.Curve3d(E1,C1,cfirst1,clast1) ||
      !SAE.Curve3d(E2,C2,cfirst2,clast2)) 
  {
    myLastFixStatus |= ShapeExtend::EncodeStatus( ShapeExtend_FAIL1 );
    return Standard_False;
  }
  
  // Check gap in 3d space
  gp_Pnt cpnt1 = C1->Value(clast1), cpnt2 = C2->Value(cfirst2);
  Standard_Real gap = cpnt1.Distance(cpnt2);
  if (!convert && gap<=preci) return Standard_False;
    
  //=============
  // Second phase: collecting data necessary for further analysis
  //=============

  Standard_Boolean reversed1 = (E1.Orientation()==TopAbs_REVERSED),
                   reversed2 = (E2.Orientation()==TopAbs_REVERSED);

  TopoDS_Vertex V1 = SAE.LastVertex(E1), V2 = SAE.FirstVertex(E2);
  gp_Pnt vpnt = (V1.IsSame(V2))? BRep_Tool::Pnt(V1) :
    gp_Pnt((BRep_Tool::Pnt(V1).XYZ()+BRep_Tool::Pnt(V2).XYZ())*0.5);

  Standard_Real first1, last1, first2, last2;
  if (reversed1) 
  { 
    first1 = clast1;  last1 = cfirst1; 
  }
  else           
  { 
    first1 = cfirst1; last1 = clast1;  
  }
  if (reversed2) 
  { 
    first2 = clast2;  last2 = cfirst2; 
  }
  else           
  { 
    first2 = cfirst2; last2 = clast2;  
  }

  Handle(Geom_Curve) c1 = C1, c2 = C2;

  // Extract basic curves from trimmed and offset
  Standard_Boolean basic = Standard_False;
  Standard_Boolean trimmed1 = Standard_False, offset1 = Standard_False;
  gp_XYZ offval1(0.,0.,0.);
  while (!basic) 
  {
    if (c1->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))) 
    {
      c1 = Handle(Geom_TrimmedCurve)::DownCast(c1)->BasisCurve();
      trimmed1 = Standard_True;
    }
    else if (c1->IsKind(STANDARD_TYPE(Geom_OffsetCurve))) 
    {
      Handle(Geom_OffsetCurve) oc = Handle(Geom_OffsetCurve)::DownCast(c1);
      c1 = oc->BasisCurve();
      offval1 += oc->Offset()*oc->Direction().XYZ();
      offset1 = Standard_True;
    }
    else basic = Standard_True;
  }
  basic = Standard_False;
  Standard_Boolean trimmed2 = Standard_False, offset2 = Standard_False;
  gp_XYZ offval2(0.,0.,0.);
  while (!basic) 
  {
    if (c2->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))) 
    {
      c2 = Handle(Geom_TrimmedCurve)::DownCast(c2)->BasisCurve();
      trimmed2 = Standard_True;
    }
    else if (c2->IsKind(STANDARD_TYPE(Geom_OffsetCurve))) 
    {
      Handle(Geom_OffsetCurve) oc = Handle(Geom_OffsetCurve)::DownCast(c2);
      c2 = oc->BasisCurve();
      offval2 += oc->Offset()*oc->Direction().XYZ();
      offset2 = Standard_True;
    }
    else basic = Standard_True;
  }
  // Restore offset curves
  if (offset1) c1 = new Geom_OffsetCurve(c1,offval1.Modulus(),gp_Dir(offval1));
  if (offset2) c2 = new Geom_OffsetCurve(c2,offval2.Modulus(),gp_Dir(offval2));

  Standard_Boolean done1 = Standard_False, done2 = Standard_False;

  if (convert) 
  {

    Handle(Geom_BSplineCurve) bsp1, bsp2;
    Handle(Geom_Curve) c;
    Standard_Real first, last;

    // iterate on curves
    Standard_Integer nbcurv = (n1==n2? 1 : 2);
    for (Standard_Integer j=1; j<=nbcurv; j++) 
    {
      //Standard_Boolean trim = Standard_False;  // skl
      if (j==1) 
      {
      if (cpnt1.Distance(vpnt)<preci) 
        {
        if (n1==n2) 
          { 
            if (cpnt2.Distance(vpnt)<preci) continue; 
          }
        else continue;
      }
      c = c1; first = first1; last = last1; /*trim = trimmed1;*/ // skl
      }
      else 
      {
      if (cpnt2.Distance(vpnt)<preci) continue;
      c = c2; first = first2; last = last2; /*trim = trimmed2;*/ // skl
      }

      Handle(Geom_BSplineCurve) bsp;

      // Convert curve to bspline
      if (c->IsKind(STANDARD_TYPE(Geom_BSplineCurve))) 
      {
      bsp = Handle(Geom_BSplineCurve)::DownCast(c->Copy());
      // take segment if trim and range differ
      Standard_Real fbsp = bsp->FirstParameter(), lbsp = bsp->LastParameter();
      Standard_Boolean segment = Standard_False;
      if (first>fbsp) 
        { 
          fbsp = first; segment = Standard_True; 
        }
      if (last<lbsp) 
        { 
          lbsp = last; segment = Standard_True; 
        }
      if (segment)
        bsp = GeomConvert::SplitBSplineCurve(bsp,fbsp,lbsp,
                                     ::Precision::Confusion());
      }
      else if (c->IsKind(STANDARD_TYPE(Geom_Conic))) 
      {
      Approx_Curve3d Conv(new GeomAdaptor_HCurve(c,first,last),
                      myAnalyzer->Precision(),GeomAbs_C1,9,1000);
      if (Conv.IsDone() || Conv.HasResult()) bsp = Conv.Curve();
      }
      else 
      {
      // Restore trim for pcurve
      Handle(Geom_Curve) tc ;     
      try 
        {
          OCC_CATCH_SIGNALS
          // 15.11.2002 PTV OCC966
        if(!ShapeAnalysis_Curve::IsPeriodic(c))
          tc = new Geom_TrimmedCurve(c,Max(first,c->FirstParameter()),Min(last,c->LastParameter()));
        else tc = new Geom_TrimmedCurve(c,first,last);
        bsp = GeomConvert::CurveToBSplineCurve(tc);
      }
      catch (Standard_Failure) 
        {
#ifdef DEB 
        cout << "Warning: ShapeFix_Wire_1::FixGap3d: Exception in TrimmedCurve" <<first<<" " <<last<<endl;
        Standard_Failure::Caught()->Print(cout); cout << endl; 
#endif  
      }
      }

      if (j==1) bsp1 = bsp; else bsp2 = bsp;
    }
    
    // Take curves ends if could not convert
    if (bsp1.IsNull()) vpnt = cpnt1;
    else if (bsp2.IsNull()) vpnt = cpnt2;

    if (!bsp1.IsNull()) 
    {
      if(bsp1->Degree() == 1) bsp1->IncreaseDegree(2); //gka
      if (n1==n2) 
      { 
        bsp1->SetPole(1,vpnt); bsp1->SetPole(bsp1->NbPoles(),vpnt); 
      }
      else 
      {
      if (reversed1) bsp1->SetPole(1,vpnt);
      else bsp1->SetPole(bsp1->NbPoles(),vpnt);
      }
      first1 = bsp1->FirstParameter(); last1 = bsp1->LastParameter();
      c1 = bsp1;
      done1 = Standard_True;
    }
    if (!bsp2.IsNull()) 
    {
      if(bsp2->Degree() == 1) bsp2->IncreaseDegree(2); //gka
      if (reversed2) bsp2->SetPole(bsp2->NbPoles(),vpnt);
      else bsp2->SetPole(1,vpnt);
      first2 = bsp2->FirstParameter(); last2 = bsp2->LastParameter();
      c2 = bsp2;
      done2 = Standard_True;
    }
  }
  else 
  {

    if (n1==n2) 
    {
      if (c1->IsKind(STANDARD_TYPE(Geom_Circle)) ||
        c1->IsKind(STANDARD_TYPE(Geom_Ellipse))) 
      {
      Standard_Real diff = PI - Abs(clast1-cfirst2)*0.5;
      first1 -= diff; last1 += diff;
      done1 = Standard_True;
      }
    }
    else 
    {

      // Determine domains for extremal points locating
      Standard_Real domfirst1 = first1, domlast1 = last1;
      if (c1->IsKind(STANDARD_TYPE(Geom_BSplineCurve)) ||
        c1->IsKind(STANDARD_TYPE(Geom_BezierCurve))) 
      {
      domfirst1 = c1->FirstParameter();
      domlast1  = c1->LastParameter();
      }
      else if (c1->IsKind(STANDARD_TYPE(Geom_Line)) ||
             c1->IsKind(STANDARD_TYPE(Geom_Parabola)) ||
             c1->IsKind(STANDARD_TYPE(Geom_Hyperbola))) 
      {
      Standard_Real diff = domlast1 - domfirst1;
      if (reversed1) domfirst1 -= 10.*diff;
      else           domlast1 += 10.*diff;
      }
      else if (c1->IsKind(STANDARD_TYPE(Geom_Circle)) ||
             c1->IsKind(STANDARD_TYPE(Geom_Ellipse))) 
      {
      domfirst1 = 0.; domlast1 = 2*PI;
      }
      Standard_Real domfirst2 = first2, domlast2 = last2;
      if (c2->IsKind(STANDARD_TYPE(Geom_BSplineCurve)) ||
        c2->IsKind(STANDARD_TYPE(Geom_BezierCurve))) 
      {
      domfirst2 = c2->FirstParameter();
      domlast2  = c2->LastParameter();
      }
      else if (c2->IsKind(STANDARD_TYPE(Geom_Line)) ||
             c2->IsKind(STANDARD_TYPE(Geom_Parabola)) ||
             c2->IsKind(STANDARD_TYPE(Geom_Hyperbola))) 
      {
      Standard_Real diff = domlast2 - domfirst2;
      if (reversed2) domlast2 += 10.*diff;
      else           domfirst2 -= 10.*diff;
      }
      else if (c2->IsKind(STANDARD_TYPE(Geom_Circle)) ||
             c2->IsKind(STANDARD_TYPE(Geom_Ellipse))) 
      {
      domfirst2 = 0.; domlast2 = 2*PI;
      }

      Standard_Real ipar1 = clast1, ipar2 = cfirst2;

      // Try to find projections of vertex point
      GeomAPI_ProjectPointOnCurve Proj;
      Standard_Real u1 = ipar1, u2 = ipar2;
      Proj.Init(vpnt,c1,domfirst1,domlast1);
      if (Proj.NbPoints()) 
      {
      Standard_Integer index = 1;
      Standard_Real dist, mindist=-1.;
      for (Standard_Integer i=1; i<=Proj.NbPoints(); i++) 
        {
        dist = vpnt.Distance(Proj.Point(i));
        if (mindist>dist || mindist<0.) 
          { 
            index = i; mindist = dist; 
          }
        u1 = Proj.Parameter(index);
      }
      }
      Proj.Init(vpnt,c2,domfirst2,domlast2);
      if (Proj.NbPoints()) 
      {
      Standard_Integer index = 1;
      Standard_Real dist, mindist=-1.;
      for (Standard_Integer i=1; i<=Proj.NbPoints(); i++) 
        {
        dist = vpnt.Distance(Proj.Point(i));
        if (mindist>dist || mindist<0.) 
          { 
            index = i; mindist = dist; 
          }
        u2 = Proj.Parameter(index);
      }
      }
      // Ajust parameters on periodic curves
      u1 = AdjustOnPeriodic3d(c1,reversed1,first1,last1,u1);
      u2 = AdjustOnPeriodic3d(c2,!reversed2,first2,last2,u2);
      // Check points to satisfy distance criterium
      gp_Pnt p1 = c1->Value(u1), p2 = c2->Value(u2);
      if (p1.Distance(p2)<=gap &&
        Abs(cfirst1-u1) > ::Precision::PConfusion() &&
        Abs(clast2-u2) > ::Precision::PConfusion() &&
        (((u1>first1) && (u1<last1)) || ((u2>first2) && (u2<last2)) ||
         (cpnt1.Distance(p1)<=gap) || (cpnt2.Distance(p2)<=gap))) 
      {
      ipar1 = u1; ipar2 = u2;
      done1 = done2 = Standard_True;
      }

      // Try to find closest points if nothing yet found
      if (!done1) 
      {

      // Recompute domains
      if (reversed1) 
        { 
          domfirst1 = ipar1; domlast1 = last1; 
        }
      else 
        { 
          domfirst1 = first1; domlast1 = ipar1; 
        }
      if (reversed2) 
        { 
          domfirst2 = first2; domlast2 = ipar2; 
        }
      else 
        { 
          domfirst2 = ipar2; domlast2 = last2; 
        }

      GeomAPI_ExtremaCurveCurve Extr(c1,c2,domfirst1,domlast1,domfirst2,domlast2);
      if (Extr.NbExtrema()) 
        {
        try 
          {
            OCC_CATCH_SIGNALS
          // First find all intersections
          gp_Pnt pp1, pp2;
          Standard_Integer index1=0, index2=0;
          Standard_Real uu1, uu2, pardist, pardist1=-1., pardist2=-1.;
          for (Standard_Integer i=1; i<=Extr.NbExtrema(); i++) 
            {
            Extr.Parameters(i,uu1,uu2);
            // Ajust parameters on periodic curves
            uu1 = AdjustOnPeriodic3d(c1,reversed1,first1,last1,uu1);
            uu2 = AdjustOnPeriodic3d(c2,!reversed2,first2,last2,uu2);
            pp1 = c1->Value(uu1); pp2 = c2->Value(uu2);
            if (pp1.Distance(pp2) < ::Precision::Confusion()) 
              {
            // assume intersection
            pardist = Abs(cfirst1-uu1);
            if (pardist1>pardist || pardist1<0.) 
                { 
                  index1 = i; pardist1 = pardist; 
                }
            pardist = Abs(clast2-uu2);
            if (pardist2>pardist || pardist2<0.) 
                { 
                  index2 = i; pardist2 = pardist; 
                }
            }
          }
          if (index1!=0 && index2!=0) 
            {
            if (index1!=index2) 
              {
            // take intersection closer to vertex point
            Extr.Parameters(index1,uu1,uu2);
            pp1 = gp_Pnt((c1->Value(uu1).XYZ()+c2->Value(uu2).XYZ())*0.5);
            Extr.Parameters(index2,uu1,uu2);
            pp2 = gp_Pnt((c1->Value(uu1).XYZ()+c2->Value(uu2).XYZ())*0.5);
            if (pp2.Distance(vpnt) < pp1.Distance(vpnt)) index1 = index2;
            }
            Extr.Parameters(index1,uu1,uu2);
          }
          else Extr.LowerDistanceParameters(uu1,uu2);
          // Ajust parameters on periodic curves
          uu1 = AdjustOnPeriodic3d(c1,reversed1,first1,last1,uu1);
          uu2 = AdjustOnPeriodic3d(c2,!reversed2,first2,last2,uu2);
          // Check points to satisfy distance criterium
          pp1 = c1->Value(uu1), pp2 = c2->Value(uu2);
          if (pp1.Distance(pp2)<=gap &&
            Abs(cfirst1-uu1) > ::Precision::PConfusion() &&
            Abs(clast2-uu2) > ::Precision::PConfusion() &&
            (((uu1>first1) && (uu1<last1)) || ((uu2>first2) && (uu2<last2)) ||
             (cpnt1.Distance(pp1)<=gap) || (cpnt2.Distance(pp2)<=gap))) 
            {
            ipar1 = uu1; ipar2 = uu2;
            done1 = done2 = Standard_True;
          }
        }
        catch ( Standard_Failure ) 
          {
          }
      }
      }
      
      try 
      {
        OCC_CATCH_SIGNALS
      if (done1) 
        {
        if (ipar1==clast1) done1 = Standard_False;
        else 
          {
          // Set up new bounds for curve
          if (reversed1) first1 = ipar1; else last1 = ipar1;
          // Set new trim for old curve
          if (trimmed1) 
            {
            // Standard_Real ff1 = c1->FirstParameter();
            // Standard_Real ll1 = c1->LastParameter();
            c1 = new Geom_TrimmedCurve(c1,first1,last1);
          }
        }
      }
      if (done2) 
        {
        if (ipar2==cfirst2) done2 = Standard_False;
        else 
          {
          // Set up new bounds for curve
          if (reversed2) last2 = ipar2; else first2 = ipar2;
          // Set new trim for old curve
          if (trimmed2) 
            {
            // Standard_Real ff2 = c2->FirstParameter();
            // Standard_Real ll2 = c2->LastParameter();
            c2 = new Geom_TrimmedCurve(c2,first2,last2);
          }
        }
      }
      }
      catch (Standard_Failure) 
      {
#ifdef DEB       
      cout << "Warning: ShapeFix_Wire_1::FixGap3d: Exception in TrimmedCurve      :"<<endl;
      Standard_Failure::Caught()->Print(cout); cout << endl;
#endif
      }  
    }
  }
  
  if (done1 || done2) 
  {

    BRep_Builder B;
    ShapeBuild_Edge SBE;
    ShapeFix_ShapeTolerance SFST;

    // Update vertices
    TopoDS_Vertex nullV, newV1;
//smh#8
    TopoDS_Shape emptyCopiedV2 = V2.EmptyCopied();
    TopoDS_Vertex newV2 = TopoDS::Vertex(emptyCopiedV2);
    SFST.SetTolerance(newV2,::Precision::Confusion());
    Context()->Replace(V2,newV2);
    if (V1.IsSame(V2))
//smh#8
      {
      TopoDS_Shape tmpV2 = newV2.Oriented(TopAbs_REVERSED);
      newV1 = TopoDS::Vertex(tmpV2);
      }
    else 
    {
//smh#8
      TopoDS_Shape emptyCopied = V1.EmptyCopied();
      newV1 = TopoDS::Vertex(emptyCopied);
      SFST.SetTolerance(newV1,::Precision::Confusion());
      Context()->Replace(V1,newV1);
    }

    if (done1) 
    {
      // Update first edge
      TopoDS_Edge newE1 = SBE.CopyReplaceVertices(E1,nullV,newV1);
//smh#8
      TopoDS_Shape tmpE1 = newE1.Oriented(TopAbs_FORWARD);
      B.UpdateEdge(TopoDS::Edge(tmpE1),c1,0.);
      SBE.SetRange3d(TopoDS::Edge(tmpE1),first1,last1);
      SFST.SetTolerance(newE1,::Precision::Confusion(),TopAbs_EDGE);
      B.SameRange(newE1,Standard_False);
//      B.SameParameter(newE1,Standard_False);
      
      //To keep NM vertices belonging initial edges
      TopoDS_Iterator aItv(E1,Standard_False);
      for( ; aItv.More(); aItv.Next()) {
      if(aItv.Value().Orientation() == TopAbs_INTERNAL ||
         aItv.Value().Orientation() == TopAbs_EXTERNAL) {
        TopoDS_Vertex aOldV = TopoDS::Vertex(aItv.Value());
        TopoDS_Vertex anewV =  ShapeAnalysis_TransferParametersProj::CopyNMVertex(aOldV,newE1,E1);
        B.Add(newE1,anewV);
        Context()->Replace(aOldV,anewV);
      }
      }
      
      Context()->Replace(E1,newE1);
      sbwd->Set(newE1,n1);
    }

    if (done2) 
    {
      // Update second edge
      TopoDS_Edge newE2 = SBE.CopyReplaceVertices(E2,newV2,nullV);
//smh#8
      TopoDS_Shape tmpE2 = newE2.Oriented(TopAbs_FORWARD);
      B.UpdateEdge(TopoDS::Edge(tmpE2),c2,0.);
      SBE.SetRange3d(TopoDS::Edge(tmpE2),first2,last2);
      SFST.SetTolerance(newE2,::Precision::Confusion(),TopAbs_EDGE);
      B.SameRange(newE2,Standard_False);
//      B.SameParameter(newE2,Standard_False);
      
      //To keep NM vertices belonging initial edges
      TopoDS_Iterator aItv(E2,Standard_False);
      for( ; aItv.More(); aItv.Next()) {
      if(aItv.Value().Orientation() == TopAbs_INTERNAL ||
         aItv.Value().Orientation() == TopAbs_EXTERNAL) {
        TopoDS_Vertex aOldV = TopoDS::Vertex(aItv.Value());
        TopoDS_Vertex anewV =  ShapeAnalysis_TransferParametersProj::CopyNMVertex(aOldV,newE2,E2);
        B.Add(newE2,anewV);
        Context()->Replace(aOldV,anewV);
      }
      }
      Context()->Replace(E2,newE2);
      sbwd->Set(newE2,n2);
    }

    myLastFixStatus |= ShapeExtend::EncodeStatus( ShapeExtend_DONE1 );
  }
  else
    if (convert)
      myLastFixStatus |= ShapeExtend::EncodeStatus( ShapeExtend_FAIL2 );

  return (done1 || done2);
}

//=======================================================================
//function : FixGap2d
//purpose  : 
//=======================================================================

static Standard_Real AdjustOnPeriodic2d (const Handle(Geom2d_Curve)& pc,
                               const Standard_Boolean takefirst,
                               const Standard_Real first,
                               const Standard_Real last,
                               const Standard_Real param)
{
  // 15.11.2002 PTV OCC966
  if (ShapeAnalysis_Curve::IsPeriodic(pc)) 
  {
    Standard_Real T = pc->Period();
    Standard_Real shift = -IntegerPart(first/T)*T; if (first<0.) shift += T;
    Standard_Real sfirst = first+shift, slast = last+shift;
    if ( takefirst && (param>slast) && (param>sfirst)) return param-T-shift;
    if (!takefirst && (param<slast) && (param<sfirst)) return param+T-shift;
  }
  return param;
}

00749  Standard_Boolean ShapeFix_Wire::FixGap2d (const Standard_Integer num,
                                 const Standard_Boolean convert)
{
  myLastFixStatus = ShapeExtend::EncodeStatus( ShapeExtend_OK );
  if ( !IsReady() ) return Standard_False;

  //=============
  // First phase: analysis whether the problem (gap) exists
  //=============

  if (Context().IsNull()) SetContext(new ShapeBuild_ReShape);

  Standard_Real preci = ::Precision::PConfusion();
  //Standard_Real preci = Precision();
  //GeomAdaptor_Surface& SA = Analyzer().Surface()->Adaptor()->ChangeSurface();
  //preci = Max(SA.UResolution(preci), SA.VResolution(preci));

  Handle(ShapeExtend_WireData) sbwd = WireData();
  Standard_Integer n2 = ( num >0 ? num  : sbwd->NbEdges() );
  Standard_Integer n1 = ( n2  >1 ? n2-1 : sbwd->NbEdges() );
//smh#8
  TopoDS_Shape tmp1 = Context()->Apply(sbwd->Edge(n1)),
               tmp2 = Context()->Apply(sbwd->Edge(n2));
  TopoDS_Edge E1 = TopoDS::Edge(tmp1),
              E2 = TopoDS::Edge(tmp2);
  TopoDS_Face face = myAnalyzer->Face();

  // Retrieve pcurves on edges
  Standard_Real cfirst1, clast1, cfirst2, clast2;
  Handle(Geom2d_Curve) PC1, PC2;
  ShapeAnalysis_Edge SAE;
  if (!SAE.PCurve(E1,face,PC1,cfirst1,clast1) ||
      !SAE.PCurve(E2,face,PC2,cfirst2,clast2) ||
      sbwd->IsSeam(n1) || sbwd->IsSeam(n2)) 
  {
    myLastFixStatus |= ShapeExtend::EncodeStatus( ShapeExtend_FAIL1 );
    return Standard_False;
  }
  
  // Check gap in 2d space
  gp_Pnt2d cpnt1 = PC1->Value(clast1), cpnt2 = PC2->Value(cfirst2);
  Standard_Real gap = cpnt1.Distance(cpnt2);
  if (gap<=preci) return Standard_False;
    
  //=============
  // Second phase: collecting data necessary for further analysis
  //=============

  Standard_Boolean reversed1 = (E1.Orientation()==TopAbs_REVERSED),
                   reversed2 = (E2.Orientation()==TopAbs_REVERSED);

  Standard_Real first1, last1, first2, last2;
  if (reversed1) 
  { 
    first1 = clast1;  last1 = cfirst1; 
  }
  else           
  { 
    first1 = cfirst1; last1 = clast1;  
  }
  if (reversed2) 
  { 
    first2 = clast2;  last2 = cfirst2; 
  }
  else           
  { 
    first2 = cfirst2; last2 = clast2;  
  }

  Handle(Geom2d_Curve) pc1 = PC1, pc2 = PC2;

  // Extract basic curves from trimmed and offset
  Standard_Boolean basic = Standard_False;
  Standard_Boolean trimmed1 = Standard_False, offset1 = Standard_False;
  Standard_Real offval1 = 0.;
  while (!basic) 
  {
    if (pc1->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve))) 
    {
      pc1 = Handle(Geom2d_TrimmedCurve)::DownCast(pc1)->BasisCurve();
      trimmed1 = Standard_True;
    }
    else if (pc1->IsKind(STANDARD_TYPE(Geom2d_OffsetCurve))) 
    {
      Handle(Geom2d_OffsetCurve) oc = Handle(Geom2d_OffsetCurve)::DownCast(pc1);
      pc1 = oc->BasisCurve();
      offval1 += oc->Offset();
      offset1 = Standard_True;
    }
    else basic = Standard_True;
  }
  basic = Standard_False;
  Standard_Boolean trimmed2 = Standard_False, offset2 = Standard_False;
  Standard_Real offval2 = 0.;
  while (!basic) 
  {
    if (pc2->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve))) 
    {
      pc2 = Handle(Geom2d_TrimmedCurve)::DownCast(pc2)->BasisCurve();
      trimmed2 = Standard_True;
    }
    else if (pc2->IsKind(STANDARD_TYPE(Geom2d_OffsetCurve))) 
    {
      Handle(Geom2d_OffsetCurve) oc = Handle(Geom2d_OffsetCurve)::DownCast(pc2);
      pc2 = oc->BasisCurve();
      offval2 += oc->Offset();
      offset2 = Standard_True;
    }
    else basic = Standard_True;
  }
  // Restore offset curves
  if (offset1) pc1 = new Geom2d_OffsetCurve(pc1,offval1);
  if (offset2) pc2 = new Geom2d_OffsetCurve(pc2,offval2);

  Standard_Boolean done1 = Standard_False, done2 = Standard_False;

  // Determine same edge case
  if (convert) 
  {

    Handle(Geom2d_BSplineCurve) bsp1, bsp2;
    Handle(Geom2d_Curve) pc;
    Standard_Real first, last;

    // iterate on pcurves
    Standard_Integer nbcurv = (n1==n2? 1 : 2);
    for (Standard_Integer j=1; j<=nbcurv; j++) 
    {
      //Standard_Integer trim = Standard_False; // skl
      Handle(Geom2d_BSplineCurve) bsp;

      if (j==1) 
      { 
        pc = pc1; first = first1; last = last1; /*trim = trimmed1;*/
      } // skl
      else      
      { 
        pc = pc2; first = first2; last = last2; /*trim = trimmed2;*/
      } // skl

      // Convert pcurve to bspline
      if (pc->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve))) 
      {
      bsp = Handle(Geom2d_BSplineCurve)::DownCast(pc->Copy());
      // take segment if trim and range differ
      Standard_Real fbsp = bsp->FirstParameter(), lbsp = bsp->LastParameter();
      Standard_Boolean segment = Standard_False;
      if (first>fbsp) 
        { 
          fbsp = first; segment = Standard_True; 
        }
      if (last<lbsp) 
        { 
          lbsp = last; segment = Standard_True; 
        }
      if (segment)
        bsp = Geom2dConvert::SplitBSplineCurve(bsp,fbsp,lbsp,
                                     ::Precision::PConfusion());
      }
      else if (pc->IsKind(STANDARD_TYPE(Geom2d_Conic))) 
      {
      GeomAdaptor_Surface& AS = myAnalyzer->Surface()->Adaptor3d()->ChangeSurface();
      Standard_Real tolu = AS.UResolution(myAnalyzer->Precision()),
      tolv = AS.VResolution(myAnalyzer->Precision());
      Approx_Curve2d Conv(new Geom2dAdaptor_HCurve(pc,first,last),
                      first,last,tolu,tolv,GeomAbs_C1,9,1000);
      if (Conv.IsDone() || Conv.HasResult()) bsp = Conv.Curve();
      }
      else 
      {
      // Restore trim for pcurve
      try 
        {
          OCC_CATCH_SIGNALS
        Handle(Geom2d_Curve) c;
          // 15.11.2002 PTV OCC966
        if(!ShapeAnalysis_Curve::IsPeriodic(pc))
          c = new Geom2d_TrimmedCurve(pc,Max(first,pc->FirstParameter()),Min(last,pc->LastParameter()));
        else 
          c = new Geom2d_TrimmedCurve(pc,first,last);
        bsp = Geom2dConvert::CurveToBSplineCurve(c);
      }
      catch (Standard_Failure) 
        {
#ifdef DEB
        cout << "Warning: ShapeFix_Wire_1::FixGap2d: Exception in TrimmedCurve2d" <<first<<" " <<last<<endl;
        Standard_Failure::Caught()->Print(cout); cout << endl; 
#endif  
      }
      }
      
      if (j==1) bsp1 = bsp; else bsp2 = bsp;
    }
    
    // Take curves ends if could not convert
    gp_Pnt2d mpnt((cpnt1.XY()+cpnt2.XY())*0.5);
    if (bsp1.IsNull()) mpnt = cpnt1;
    else if (bsp2.IsNull()) mpnt = cpnt2;

    if (!bsp1.IsNull()) 
    {
      if(bsp1->Degree() == 1) bsp1->IncreaseDegree(2);
      if (n1==n2) 
      { 
        bsp1->SetPole(1,mpnt); bsp1->SetPole(bsp1->NbPoles(),mpnt); 
      }
      else 
      {
      if (reversed1) bsp1->SetPole(1,mpnt);
      else bsp1->SetPole(bsp1->NbPoles(),mpnt);
      }
      first1 = bsp1->FirstParameter(); last1 = bsp1->LastParameter();
      pc1 = bsp1;
      done1 = Standard_True;
    }
    if (!bsp2.IsNull()) 
    {
      if(bsp2->Degree() == 1) bsp2->IncreaseDegree(2);
      if (reversed2) bsp2->SetPole(bsp2->NbPoles(),mpnt);
      else bsp2->SetPole(1,mpnt);
      first2 = bsp2->FirstParameter(); last2 = bsp2->LastParameter();
      pc2 = bsp2;
      done2 = Standard_True;
    }
  }
  else 
  {

    if (n1==n2) 
    {
      if (pc1->IsKind(STANDARD_TYPE(Geom2d_Circle)) ||
        pc1->IsKind(STANDARD_TYPE(Geom2d_Ellipse))) 
      {
      Standard_Real diff = PI - Abs(clast1-cfirst2)*0.5;
      first1 -= diff; last1 += diff;
      done1 = Standard_True;
      }
    }
    else 
    {

      // Determine domains for extremal points locating
      Standard_Real domfirst1 = first1, domlast1 = last1;
      if (pc1->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve)) ||
        pc1->IsKind(STANDARD_TYPE(Geom2d_BezierCurve))) 
      {
      domfirst1 = pc1->FirstParameter();
      domlast1  = pc1->LastParameter();
      }
      else if (pc1->IsKind(STANDARD_TYPE(Geom2d_Line)) ||
             pc1->IsKind(STANDARD_TYPE(Geom2d_Parabola)) ||
             pc1->IsKind(STANDARD_TYPE(Geom2d_Hyperbola))) 
      {
      Standard_Real diff = domlast1 - domfirst1;
      if (reversed1) domfirst1 -= 10.*diff;
      else           domlast1 += 10.*diff;
      }
      else if (pc1->IsKind(STANDARD_TYPE(Geom2d_Circle)) ||
             pc1->IsKind(STANDARD_TYPE(Geom2d_Ellipse))) 
      {
      domfirst1 = 0.; domlast1 = 2*PI;
      }
      Standard_Real domfirst2 = first2, domlast2 = last2;
      if (pc2->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve)) ||
        pc2->IsKind(STANDARD_TYPE(Geom2d_BezierCurve))) 
      {
      domfirst2 = pc2->FirstParameter();
      domlast2  = pc2->LastParameter();
      }
      else if (pc2->IsKind(STANDARD_TYPE(Geom2d_Line)) ||
             pc2->IsKind(STANDARD_TYPE(Geom2d_Parabola)) ||
             pc2->IsKind(STANDARD_TYPE(Geom2d_Hyperbola))) 
      {
      Standard_Real diff = domlast2 - domfirst2;
      if (reversed2) domlast2 += 10.*diff;
      else           domfirst2 -= 10.*diff;
      }
      else if (pc2->IsKind(STANDARD_TYPE(Geom2d_Circle)) ||
             pc2->IsKind(STANDARD_TYPE(Geom2d_Ellipse))) 
      {
      domfirst2 = 0.; domlast2 = 2*PI;
      }

      Standard_Real ipar1 = clast1, ipar2 = cfirst2;

      Geom2dInt_GInter Inter;
      Standard_Real tolint = ::Precision::PConfusion();

      Geom2dAdaptor_Curve AC1(pc1), AC2(pc2);

      // Try to find intersection points
      IntRes2d_Domain dom1(pc1->Value(domfirst1),domfirst1,tolint,
                     pc1->Value(domlast1),domlast1,tolint);
      IntRes2d_Domain dom2(pc2->Value(domfirst2),domfirst2,tolint,
                     pc2->Value(domlast2),domlast2,tolint);
      Inter.Perform( AC1, dom1, AC2, dom2, tolint, tolint );
      if (Inter.IsDone()) 
      {
      if (Inter.NbPoints() || Inter.NbSegments()) 
        {
        Standard_Integer i, index1 = 0, index2 = 0;
        Standard_Real pardist, pardist1=-1., pardist2=-1.;
        // iterate on intersection points
        IntRes2d_IntersectionPoint IP;
        for ( i=1; i<=Inter.NbPoints(); i++ ) 
          {
          IP = Inter.Point(i);
          // Adjust parameters on periodic curves
          Standard_Real u1 = AdjustOnPeriodic2d(pc1,reversed1,first1,last1,
                                      IP.ParamOnFirst());
          Standard_Real u2 = AdjustOnPeriodic2d(pc2,!reversed2,first2,last2,
                                      IP.ParamOnSecond());
          pardist = Abs(cfirst1-u1);
          if (pardist1>pardist || pardist1<0.) 
            { 
              index1 = i; pardist1 = pardist; 
            }
            pardist = Abs(clast2-u2);
          if (pardist2>pardist || pardist2<0.) 
            { 
              index2 = i; pardist2 = pardist; 
            }
        }
        Standard_Integer flag1 = 0, flag2 = 0;
        // iterate on intersection segments
        IntRes2d_IntersectionSegment IS;
        for ( i=1; i<=Inter.NbSegments(); i++ ) 
          {
          IS = Inter.Segment(i);
          for (Standard_Integer j=1; j<=2; j++) 
            {
            if ((j==1 && IS.HasFirstPoint()) ||
              (j==2 && IS.HasLastPoint())) 
              {
            if (j==1) IP = IS.FirstPoint();
            else      IP = IS.LastPoint();
            // Adjust parameters on periodic curves
            Standard_Real u1 = AdjustOnPeriodic2d(pc1,reversed1,first1,last1,
                                          IP.ParamOnFirst());
            Standard_Real u2 = AdjustOnPeriodic2d(pc2,!reversed2,first2,last2,
                                          IP.ParamOnSecond());
            pardist = Abs(cfirst1-u1);
            if (pardist1>pardist || pardist1<0.) 
                {
              flag1 = j; index1 = i; pardist1 = pardist;
            }
            pardist = Abs(clast2-u2);
            if (pardist2>pardist || pardist2<0.) 
                {
              flag2 = j; index2 = i; pardist2 = pardist;
            }
            }
          }
        }
        if (index1!=index2 || flag1!=flag2) 
          {
          // take intersection closer to mean point
          gp_Pnt2d pt1, pt2;
          if (flag1==0) pt1 = Inter.Point(index1).Value();
          else 
            {
            IS = Inter.Segment(index1);
            if (flag1==1) pt1 = IS.FirstPoint().Value();
            else          pt1 = IS.LastPoint().Value();
          }
          if (flag2==0) pt2 = Inter.Point(index2).Value();
          else 
            {
            IS = Inter.Segment(index2);
            if (flag2==1) pt2 = IS.FirstPoint().Value();
            else          pt2 = IS.LastPoint().Value();
          }
          gp_Pnt2d mpnt((cpnt1.XY()+cpnt2.XY())*0.5);
          if (pt2.Distance(mpnt) < pt1.Distance(mpnt)) 
            {
            index1 = index2; flag1 = flag2;
          }
        }
        if (flag1==0) IP = Inter.Point(index1);
        else 
          {
          IS = Inter.Segment(index1);
          if (flag1==1) IP = IS.FirstPoint();
          else          IP = IS.LastPoint();
        }
        // Ajust parameters on periodic curves
        Standard_Real u1 = AdjustOnPeriodic2d(pc1,reversed1,first1,last1,
                                    IP.ParamOnFirst());
        Standard_Real u2 = AdjustOnPeriodic2d(pc2,!reversed2,first2,last2,
                                    IP.ParamOnSecond());
        // Check points to satisfy distance criterium
        gp_Pnt2d p1 = pc1->Value(u1), p2 = pc2->Value(u2);
        if (p1.Distance(p2)<=gap &&
            Abs(cfirst1-u1) > ::Precision::PConfusion() &&
            Abs(clast2 -u2) > ::Precision::PConfusion() &&
            (((u1>first1) && (u1<last1)) || ((u2>first2) && (u2<last2)) ||
             (cpnt1.Distance(p1)<=gap) || (cpnt2.Distance(p2)<=gap))) 
          {
          ipar1 = u1; ipar2 = u2;
          done1 = done2 = Standard_True;
        }
      }
      }

      // Try to find closest points if nothing yet found
      if (!done1) 
      {
      Geom2dAPI_ExtremaCurveCurve Extr(pc1,pc2,domfirst1,domlast1,domfirst2,domlast2);
      if (Extr.NbExtrema()) 
        {
        Standard_Real u1, u2;
        Extr.LowerDistanceParameters(u1,u2);
        // Ajust parameters on periodic curves
        u1 = AdjustOnPeriodic2d(pc1,reversed1,first1,last1,u1);
        u2 = AdjustOnPeriodic2d(pc2,!reversed2,first2,last2,u2);
        // Check points to satisfy distance criterium
        gp_Pnt2d p1 = pc1->Value(u1), p2 = pc2->Value(u2);
        if (p1.Distance(p2)<=gap &&
            Abs(cfirst1-u1) > ::Precision::PConfusion() &&
            Abs(clast2 -u2) > ::Precision::PConfusion() &&
            (((u1>first1) && (u1<last1)) || ((u2>first2) && (u2<last2)) ||
             (cpnt1.Distance(p1)<=gap) || (cpnt2.Distance(p2)<=gap))) 
          {
          ipar1 = u1; ipar2 = u2;
          done1 = done2 = Standard_True;
        }
      }
      }

      // Try to find projections if nothing yet found
      if (!done1) 
      {
      Geom2dAPI_ProjectPointOnCurve Proj;
      gp_Pnt2d ipnt1 = cpnt1, ipnt2 = cpnt2;
      Standard_Real u1 = ipar1, u2 = ipar2;
      Proj.Init(cpnt2,pc1,domfirst1,domlast1);
      if (Proj.NbPoints()) 
        {
        Standard_Integer index = 1;
        Standard_Real dist, mindist=-1.;
        for (Standard_Integer i=1; i<=Proj.NbPoints(); i++) 
          {
          dist = cpnt2.Distance(Proj.Point(i));
          if (mindist>dist || mindist<0.) 
            { 
              index = i; mindist = dist; 
            }
          ipnt1 = Proj.Point(index);
          u1 = Proj.Parameter(index);
        }
      }
      Proj.Init(cpnt1,pc2,domfirst2,domlast2);
      if (Proj.NbPoints()) 
        {
        Standard_Integer index = 1;
        Standard_Real dist, mindist=-1.;
        for (Standard_Integer i=1; i<=Proj.NbPoints(); i++) 
          {
          dist = cpnt1.Distance(Proj.Point(i));
          if (mindist>dist || mindist<0.) 
            { 
              index = i; mindist = dist; 
            }
          ipnt2 = Proj.Point(index);
          u2 = Proj.Parameter(index);
        }
      }
      // Ajust parameters on periodic curves
      u1 = AdjustOnPeriodic2d(pc1,reversed1,first1,last1,u1);
      u2 = AdjustOnPeriodic2d(pc2,!reversed2,first2,last2,u2);
      // Process special case of projection
      if ((((reversed1 && u1>clast1)  || (!reversed1 && u1<clast1)) &&
           ((reversed2 && u2<cfirst2) || (!reversed2 && u2>cfirst2))) ||
          (((reversed1 && u1<clast1)  || (!reversed1 && u1>clast1)) &&
           ((reversed2 && u2>cfirst2) || (!reversed2 && u2<cfirst2)))) 
        {
        // both projections lie inside/outside initial domains
        // project mean point
        gp_Pnt2d mpnt((cpnt1.XY()+cpnt2.XY())*0.5);
        u1 = ipar1; u2 = ipar2;
        Proj.Init(mpnt,pc1,domfirst1,domlast1);
        if (Proj.NbPoints()) 
          {
          Standard_Integer index = 1;
          Standard_Real dist, mindist=-1.;
          for (Standard_Integer i=1; i<=Proj.NbPoints(); i++) 
            {
            dist = mpnt.Distance(Proj.Point(i));
            if (mindist>dist || mindist<0.) 
              { 
                index = i; mindist = dist; 
              }
            ipnt1 = Proj.Point(index);
            u1 = Proj.Parameter(index);
          }
        }
        Proj.Init(mpnt,pc2,domfirst2,domlast2);
        if (Proj.NbPoints()) 
          {
          Standard_Integer index = 1;
          Standard_Real dist, mindist=-1.;
          for (Standard_Integer i=1; i<=Proj.NbPoints(); i++) 
            {
            dist = mpnt.Distance(Proj.Point(i));
            if (mindist>dist || mindist<0.) 
              { 
                index = i; mindist = dist; 
              }
            ipnt2 = Proj.Point(index);
            u2 = Proj.Parameter(index);
          }
        }
      }
      else 
        {
        if (cpnt1.Distance(ipnt2)<cpnt2.Distance(ipnt1)) u1 = ipar1;
        else                                             u2 = ipar2;
      }
      // Ajust parameters on periodic curves
      u1 = AdjustOnPeriodic2d(pc1,reversed1,first1,last1,u1);
      u2 = AdjustOnPeriodic2d(pc2,!reversed2,first2,last2,u2);
      // Check points to satisfy distance criterium
      gp_Pnt2d p1 = pc1->Value(u1), p2 = pc2->Value(u2);
      if (p1.Distance(p2)<=gap &&
          Abs(cfirst1-u1) > ::Precision::PConfusion() &&
          Abs(clast2 -u2) > ::Precision::PConfusion() &&
          (((u1>first1) && (u1<last1)) || ((u2>first2) && (u2<last2)) ||
           (cpnt1.Distance(p1)<=gap) || (cpnt2.Distance(p2)<=gap))) 
        {
        ipar1 = u1; ipar2 = u2;
        done1 = done2 = Standard_True;
      }
      }

      if (done1) 
      {

      if (ipar1<first1 || ipar1>last1 || ipar2<first2 || ipar2>last2) 
        {

        // Check whether new points lie inside the surface bounds
        Standard_Real umin, umax, vmin, vmax;
        myAnalyzer->Surface()->Surface()->Bounds(umin,umax,vmin,vmax);
        if (::Precision::IsInfinite(umin) || ::Precision::IsInfinite(umax) ||
            ::Precision::IsInfinite(vmin) || ::Precision::IsInfinite(vmax)) 
          {
          Standard_Real fumin, fumax, fvmin, fvmax;
          BRepTools::UVBounds(face,fumin,fumax,fvmin,fvmax);
          if (::Precision::IsInfinite(umin)) umin = fumin-preci;
          if (::Precision::IsInfinite(umax)) umax = fumax+preci;
          if (::Precision::IsInfinite(vmin)) vmin = fvmin-preci;
          if (::Precision::IsInfinite(vmax)) vmax = fvmax+preci;
        }

        gp_Pnt2d ipnt, P1, P2;
        Standard_Real u, v;
        Standard_Boolean out;
        // iterate on curves
        for (Standard_Integer j=1; j<=2; j++) 
          {

          if (j==1) 
            {
            if (ipar1>=first1 && ipar1<=last1) continue;
            ipnt = pc1->Value(ipar1);
          }
          else 
            {
            if (ipar2>=first2 && ipar2<=last2) continue;
            ipnt = pc2->Value(ipar2);
          }

          // iterate on bounding lines
          for (Standard_Integer k=1; k<=2; k++) 
            {

            u = ipnt.X(); v = ipnt.Y();

            out = Standard_True;
            if (k==1) 
              {
            if (u<umin) 
                { 
                  P1 = gp_Pnt2d(umin,vmin); P2 = gp_Pnt2d(umin,vmax); 
                }
            else if (u>umax) 
                { 
                  P1 = gp_Pnt2d(umax,vmin); P2 = gp_Pnt2d(umax,vmax); 
                }
            else out = Standard_False;
            }
            else 
              {
            if (v<vmin) 
                { 
                  P1 = gp_Pnt2d(umin,vmin); P2 = gp_Pnt2d(umax,vmin); 
                }
            else if (v>vmax) 
                { 
                  P1 = gp_Pnt2d(umin,vmax); P2 = gp_Pnt2d(umax,vmax); 
                }
            else out = Standard_False;
            }

            if (out) 
              {
            // Intersect pcurve with bounding line
            Handle(Geom2d_Line) lin = new Geom2d_Line(P1,gp_Dir2d(gp_Vec2d(P1,P2)));
            Geom2dAdaptor_Curve ACL(lin);
            IntRes2d_Domain dlin(P1,0.,tolint,P2,P1.Distance(P2),tolint);

            Handle(Geom2d_Curve) pc;
            Standard_Real fpar, lpar;
            if (j==1) 
                {
              if (cfirst1<ipar1) 
                  { 
                    fpar = cfirst1, lpar = ipar1; 
                  }
              else 
                  { 
                    fpar = ipar1, lpar = cfirst1; 
                  }
              pc = pc1;
            }
            else 
                {
              if (clast2<ipar2) 
                  { 
                    fpar = clast2, lpar = ipar2; 
                  }
              else 
                  { 
                    fpar = ipar2, lpar = clast2; 
                  }
              pc = pc2;
            }
            Geom2dAdaptor_Curve ACC(pc);
            IntRes2d_Domain domc(pc->Value(fpar),fpar,tolint,
                             pc->Value(lpar),lpar,tolint);

            // Intersect line with the pcurve
            Inter.Perform( ACL, dlin, ACC, domc, tolint, tolint );
            if (Inter.IsDone()) 
                {
              if (Inter.NbPoints() || Inter.NbSegments()) 
                  {
                Standard_Integer i, index = 1;
                Standard_Real uu, dist, mindist=-1.;
                // iterate on intersection points
                for ( i=1; i<=Inter.NbPoints(); i++ ) 
                    {
                  // Adjust parameters on periodic curve
                  uu = AdjustOnPeriodic2d(pc,(j==1? reversed1 : !reversed2),
                                              fpar,lpar,Inter.Point(i).ParamOnSecond());
                  dist = Abs((j==1? cfirst1 : clast2)-uu);
                  if (mindist>dist || mindist<0.) 
                      { 
                        index = i; mindist = dist; 
                      }
                }
                // iterate on intersection segments
                Standard_Integer flag = 0;
                IntRes2d_IntersectionPoint IP;
                IntRes2d_IntersectionSegment IS;
                for ( i=1; i<=Inter.NbSegments(); i++ ) 
                    {
                  IS = Inter.Segment(i);
                  for (Standard_Integer jj=1; jj<=2; jj++) 
                      {
                  if ((jj==1 && IS.HasFirstPoint()) ||
                      (jj==2 && IS.HasLastPoint())) 
                        {
                    if (jj==1) IP = IS.FirstPoint();
                    else       IP = IS.LastPoint();
                    // Adjust parameters on periodic curve
                    uu = AdjustOnPeriodic2d(pc,(jj==1? reversed1 : !reversed2),
                                                  fpar,lpar,IP.ParamOnSecond());
                    dist = Abs((jj==1? cfirst1 : clast2)-uu);
                    if (mindist>dist || mindist<0.)
                    { 
                            flag = jj; index = i; mindist = dist; 
                          }
                  }
                  }
                }
                if (flag==0) IP = Inter.Point(index);
                else 
                    {
                  IS = Inter.Segment(index);
                  if (flag==1) IP = IS.FirstPoint();
                  else         IP = IS.LastPoint();
                }
                // Ajust parameters on periodic curve
                uu = AdjustOnPeriodic2d(pc,(j==1? reversed1 : !reversed2),
                                            fpar,lpar,IP.ParamOnSecond());
                if (j==1 && Abs(cfirst1-uu) > ::Precision::PConfusion())
                    { 
                      ipar1 = uu; ipnt = IP.Value(); 
                    }
                if (j==2 && Abs(clast2-uu) > ::Precision::PConfusion())
                    { 
                      ipar2 = uu; ipnt = IP.Value(); 
                    }
              }
            }
            }
          }

          // Adjust if intersection lies inside old bounds
          if (j==1) 
            {
            if (reversed1) 
              { 
                if (ipar1>first1) ipar1 = first1; 
              }
            else           
              { 
                if (ipar1<last1) ipar1 = last1; 
              }
          }
          else 
            {
            if (reversed2) 
              { 
                if (ipar2<last2) ipar2 = last2; 
              }
            else           
              { 
                if (ipar2>first2) ipar2 = first2; 
              }
          }
        }
      }
      }
      try 
      {
        OCC_CATCH_SIGNALS
      if (done1) 
        {
        if (ipar1==clast1) done1 = Standard_False;
        else 
          {
          // Set up new bounds for pcurve
          if (reversed1) first1 = ipar1; else last1 = ipar1;
          // Set new trim for old pcurve
          if (trimmed1) pc1 = new Geom2d_TrimmedCurve(pc1,first1,last1);
        }
      }
      if (done2) 
        {
        if (ipar2==cfirst2) done2 = Standard_False;
        else 
          {
          // Set up new bounds for pcurve
          if (reversed2) last2 = ipar2; else first2 = ipar2;
          // Set new trim for old pcurve
          if (trimmed2) pc2 = new Geom2d_TrimmedCurve(pc2,first2,last2);
        }
      }
      }
      catch (Standard_Failure) 
      {
      
#ifdef DEB        
      cout << "Warning: ShapeFix_Wire_1::FixGap2d: Exception in TrimmedCurve2d  :"<<endl;
      Standard_Failure::Caught()->Print(cout); cout << endl;
#endif      
      }  
    }
  }

  if (done1 || done2) 
  {

    BRep_Builder B;
    ShapeBuild_Edge SBE;
    ShapeFix_ShapeTolerance SFST;

    // Update vertices
    TopoDS_Vertex V1 = SAE.LastVertex(E1), V2 = SAE.FirstVertex(E2);
    TopoDS_Vertex nullV, newV1;
//smh#8
    TopoDS_Shape emptyCopiedV2 = V2.EmptyCopied();
    TopoDS_Vertex newV2 = TopoDS::Vertex(emptyCopiedV2);
    SFST.SetTolerance(newV2,::Precision::Confusion());
    Context()->Replace(V2,newV2);
    if (V1.IsSame(V2))
//smh#8
    {
      TopoDS_Shape tmpVertexRev = newV2.Oriented(TopAbs_REVERSED);
      newV1 = TopoDS::Vertex(tmpVertexRev);
    }
    else 
    {
//smh#8
      TopoDS_Shape emptyCopiedV1 = V1.EmptyCopied();
      newV1 = TopoDS::Vertex(emptyCopiedV1);
      SFST.SetTolerance(newV1,::Precision::Confusion());
      Context()->Replace(V1,newV1);
    }

    if (done1) 
    {
      // Update first edge
      TopoDS_Edge newE1 = SBE.CopyReplaceVertices(E1,nullV,newV1);
//smh#8
      TopoDS_Shape tmpE1 = newE1.Oriented(TopAbs_FORWARD);
      B.UpdateEdge(TopoDS::Edge(tmpE1),pc1,face,0.);
      B.Range(TopoDS::Edge(tmpE1),face,first1,last1);
      SFST.SetTolerance(newE1,::Precision::Confusion(),TopAbs_EDGE);
      B.SameRange(newE1,Standard_False);
//      B.SameParameter(newE1,Standard_False);
      
      //To keep NM vertices belonging initial edges
      TopoDS_Iterator aItv(E1,Standard_False);
      for( ; aItv.More(); aItv.Next()) {
      if(aItv.Value().Orientation() == TopAbs_INTERNAL ||
         aItv.Value().Orientation() == TopAbs_EXTERNAL) {
        TopoDS_Vertex aOldV = TopoDS::Vertex(aItv.Value());
        TopoDS_Vertex anewV =  ShapeAnalysis_TransferParametersProj::CopyNMVertex(aOldV,newE1,E1);
        B.Add(newE1,anewV);
        Context()->Replace(aOldV,anewV);
      }
      }
      
      Context()->Replace(E1,newE1);
      sbwd->Set(newE1,n1);
    }

    if (done2) 
    {
      // Update second edge
      TopoDS_Edge newE2 = SBE.CopyReplaceVertices(E2,newV2,nullV);
//smh#8
      TopoDS_Shape tmpE2 = newE2.Oriented(TopAbs_FORWARD);
      B.UpdateEdge(TopoDS::Edge(tmpE2),pc2,face,0.);
      B.Range(TopoDS::Edge(tmpE2),face,first2,last2);
      SFST.SetTolerance(newE2,::Precision::Confusion(),TopAbs_EDGE);
      B.SameRange(newE2,Standard_False);
//      B.SameParameter(newE2,Standard_False);
      //To keep NM vertices belonging initial edges
      TopoDS_Iterator aItv(E2,Standard_False);
      for( ; aItv.More(); aItv.Next()) {
      if(aItv.Value().Orientation() == TopAbs_INTERNAL ||
         aItv.Value().Orientation() == TopAbs_EXTERNAL) {
        TopoDS_Vertex aOldV = TopoDS::Vertex(aItv.Value());
        TopoDS_Vertex anewV =  ShapeAnalysis_TransferParametersProj::CopyNMVertex(aOldV,newE2,E2);
        B.Add(newE2,anewV);
        Context()->Replace(aOldV,anewV);
      }
      }
      Context()->Replace(E2,newE2);
      sbwd->Set(newE2,n2);
    }

    myLastFixStatus |= ShapeExtend::EncodeStatus( ShapeExtend_DONE1 );
  }
  else
    if (convert)
      myLastFixStatus |= ShapeExtend::EncodeStatus( ShapeExtend_FAIL2 );

  return (done1 || done2);
}

Generated by  Doxygen 1.6.0   Back to index