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

Standard_Boolean ShapeFix_Wire::FixGap2d ( const Standard_Integer  num,
const Standard_Boolean  convert = Standard_False 
)

Fixes gap between ends of pcurves on num-1 and num-th edges.
myPrecision is used to detect the gap.
If convert is True, converts pcurves to bsplines to bend.

Definition at line 749 of file ShapeFix_Wire_1.cxx.

References TopoDS_Builder::Add(), Standard_Failure::Caught(), Precision::Confusion(), ShapeFix_Root::Context(), Geom2d_Geometry::Copy(), ShapeAnalysis_TransferParametersProj::CopyNMVertex(), ShapeBuild_Edge::CopyReplaceVertices(), Approx_Curve2d::Curve(), gp_Pnt2d::Distance(), TopoDS_Shape::EmptyCopied(), ShapeExtend::EncodeStatus(), Geom2d_Curve::FirstParameter(), IntRes2d_IntersectionSegment::FirstPoint(), ShapeAnalysis_Edge::FirstVertex(), IntRes2d_IntersectionSegment::HasFirstPoint(), IntRes2d_IntersectionSegment::HasLastPoint(), Approx_Curve2d::HasResult(), Geom2dAPI_ProjectPointOnCurve::Init(), Approx_Curve2d::IsDone(), Precision::IsInfinite(), Standard_Transient::IsKind(), ShapeAnalysis_Curve::IsPeriodic(), IsReady(), TopoDS_Shape::IsSame(), Geom2d_Curve::LastParameter(), IntRes2d_IntersectionSegment::LastPoint(), ShapeAnalysis_Edge::LastVertex(), Geom2dAPI_ExtremaCurveCurve::LowerDistanceParameters(), TopoDS_Iterator::More(), Geom2dAPI_ExtremaCurveCurve::NbExtrema(), Geom2dAPI_ProjectPointOnCurve::NbPoints(), TopoDS_Iterator::Next(), TopoDS_Shape::Orientation(), TopoDS_Shape::Oriented(), Geom2dAPI_ProjectPointOnCurve::Parameter(), IntRes2d_IntersectionPoint::ParamOnFirst(), IntRes2d_IntersectionPoint::ParamOnSecond(), Precision::PConfusion(), ShapeAnalysis_Edge::PCurve(), Geom2dAPI_ProjectPointOnCurve::Point(), BRep_Builder::Range(), BRep_Builder::SameRange(), ShapeFix_Root::SetContext(), ShapeFix_ShapeTolerance::SetTolerance(), Geom2dConvert::SplitBSplineCurve(), BRep_Builder::UpdateEdge(), GeomAdaptor_Surface::UResolution(), BRepTools::UVBounds(), TopoDS_Iterator::Value(), IntRes2d_IntersectionPoint::Value(), GeomAdaptor_Surface::VResolution(), WireData(), gp_Pnt2d::X(), gp_Pnt2d::XY(), and gp_Pnt2d::Y().

Referenced by FixGaps2d().

{
  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