1 // Copyright (c) 1999-2014 OPEN CASCADE SAS
3 // This file is part of Open CASCADE Technology software library.
5 // This library is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU Lesser General Public License version 2.1 as published
7 // by the Free Software Foundation, with special exception defined in the file
8 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9 // distribution for complete text of the license and disclaimer of any warranty.
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
14 // szv 19.08.99: new methods for fixing gaps between edges (3d curves and pcurves)
15 #include <ShapeFix_Wire.hxx>
16 #include <Standard_ErrorHandler.hxx>
17 #include <Standard_Failure.hxx>
19 #include <Precision.hxx>
20 #include <Bnd_Box2d.hxx>
21 #include <Geom_Curve.hxx>
22 #include <Geom2d_Curve.hxx>
23 #include <Geom2d_Line.hxx>
25 #include <IntRes2d_SequenceOfIntersectionPoint.hxx>
26 #include <IntRes2d_IntersectionPoint.hxx>
27 #include <TColgp_SequenceOfPnt.hxx>
30 #include <TopoDS_Vertex.hxx>
31 #include <TopoDS_Edge.hxx>
32 #include <TopTools_HSequenceOfShape.hxx>
34 #include <BRep_Tool.hxx>
35 #include <BRep_Builder.hxx>
37 #include <ShapeExtend.hxx>
38 #include <ShapeBuild_Edge.hxx>
39 #include <ShapeBuild_Vertex.hxx>
40 #include <ShapeAnalysis_Curve.hxx>
41 #include <ShapeAnalysis_Edge.hxx>
42 #include <ShapeAnalysis_Surface.hxx>
43 #include <ShapeAnalysis.hxx>
44 #include <GeomConvert_CompCurveToBSplineCurve.hxx>
45 #include <Geom_TrimmedCurve.hxx>
47 #include <GeomAPI.hxx>
48 #include <TColgp_Array1OfPnt.hxx>
49 #include <TColStd_Array1OfReal.hxx>
50 #include <TColStd_Array1OfInteger.hxx>
51 #include <Geom_BSplineCurve.hxx>
52 #include <Geom_SphericalSurface.hxx> //S4135
53 #include <Geom2d_BSplineCurve.hxx>
54 #include <GeomAdaptor_Curve.hxx>
55 #include <GeomAdaptor_HSurface.hxx>
56 #include <GeomAdaptor_Surface.hxx>
57 #include <TopTools_Array1OfShape.hxx>
58 #include <BRepTools.hxx>
59 #include <Bnd_Array1OfBox2d.hxx>
60 #include <BndLib_Add2dCurve.hxx>
61 #include <Geom2dAdaptor_Curve.hxx>
62 #include <Geom2dConvert.hxx>
63 #include <Geom2d_TrimmedCurve.hxx>
64 #include <ShapeBuild_ReShape.hxx>
67 #include <TColgp_Array1OfPnt2d.hxx>
68 #include <Geom2d_Circle.hxx>
69 #include <Geom2d_Ellipse.hxx>
70 #include <Geom2d_Parabola.hxx>
71 #include <Geom2d_Hyperbola.hxx>
72 #include <Geom2d_OffsetCurve.hxx>
73 #include <Geom2dInt_GInter.hxx>
74 #include <IntRes2d_Domain.hxx>
75 #include <IntRes2d_IntersectionSegment.hxx>
76 #include <Geom2dAPI_ExtremaCurveCurve.hxx>
77 #include <Geom2dAPI_ProjectPointOnCurve.hxx>
78 #include <Geom2dAdaptor_HCurve.hxx>
79 #include <Approx_Curve2d.hxx>
80 #include <Geom2dConvert.hxx>
82 #include <Geom_Line.hxx>
83 #include <Geom_Circle.hxx>
84 #include <Geom_Ellipse.hxx>
85 #include <Geom_Parabola.hxx>
86 #include <Geom_Hyperbola.hxx>
87 #include <Geom_OffsetCurve.hxx>
88 #include <GeomAPI_ExtremaCurveCurve.hxx>
89 #include <GeomAPI_ProjectPointOnCurve.hxx>
90 #include <GeomAdaptor_HCurve.hxx>
91 #include <Approx_Curve3d.hxx>
92 #include <GeomConvert.hxx>
93 #include <TopoDS_Iterator.hxx>
94 #include <ShapeFix_ShapeTolerance.hxx>
95 #include <ShapeAnalysis_TransferParametersProj.hxx>
96 #include <Geom_Conic.hxx>
97 #include <Geom_BezierCurve.hxx>
98 #include <Geom2d_Conic.hxx>
99 #include <Geom2d_BezierCurve.hxx>
100 //=======================================================================
101 //function : FixGaps3d
103 //=======================================================================
105 Standard_Boolean ShapeFix_Wire::FixGaps3d ()
107 myStatusGaps3d = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
108 // if ( !IsReady() ) return Standard_False;
110 Standard_Integer i, start = ( myClosedMode ? 1 : 2 );
111 if (myFixGapsByRanges)
113 for ( i = start; i <= NbEdges(); i++ )
116 myStatusGaps3d |= myLastFixStatus;
119 for ( i = start; i <= NbEdges(); i++ )
121 FixGap3d ( i, Standard_True );
122 myStatusGaps3d |= myLastFixStatus;
125 return StatusGaps3d ( ShapeExtend_DONE );
128 //=======================================================================
129 //function : FixGaps2d
131 //=======================================================================
133 Standard_Boolean ShapeFix_Wire::FixGaps2d ()
135 myStatusGaps2d = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
136 // if ( !IsReady() ) return Standard_False;
138 Standard_Integer i, start = ( myClosedMode ? 1 : 2 );
139 if (myFixGapsByRanges)
141 for ( i = start; i <= NbEdges(); i++ )
144 myStatusGaps2d |= myLastFixStatus;
147 for ( i = start; i <= NbEdges(); i++ )
149 FixGap2d ( i, Standard_True );
150 myStatusGaps2d |= myLastFixStatus;
153 return StatusGaps2d ( ShapeExtend_DONE );
156 //=======================================================================
157 //function : FixGap3d
159 //=======================================================================
161 static Standard_Real AdjustOnPeriodic3d (const Handle(Geom_Curve)& c,
162 const Standard_Boolean takefirst,
163 const Standard_Real first,
164 const Standard_Real last,
165 const Standard_Real param)
167 // 15.11.2002 PTV OCC966
168 if (ShapeAnalysis_Curve::IsPeriodic(c))
170 Standard_Real T = c->Period();
171 Standard_Real shift = -IntegerPart(first/T)*T; if (first<0.) shift += T;
172 Standard_Real sfirst = first+shift, slast = last+shift;
173 if ( takefirst && (param>slast) && (param>sfirst)) return param-T-shift;
174 if (!takefirst && (param<slast) && (param<sfirst)) return param+T-shift;
179 Standard_Boolean ShapeFix_Wire::FixGap3d (const Standard_Integer num,
180 const Standard_Boolean convert)
182 myLastFixStatus = ShapeExtend::EncodeStatus( ShapeExtend_OK );
183 // if ( !IsReady() ) return Standard_False;
186 // First phase: analysis whether the problem (gap) exists
189 if (Context().IsNull()) SetContext(new ShapeBuild_ReShape);
191 Standard_Real preci = Precision();
193 Handle(ShapeExtend_WireData) sbwd = WireData();
194 Standard_Integer n2 = ( num >0 ? num : sbwd->NbEdges() );
195 Standard_Integer n1 = ( n2 >1 ? n2-1 : sbwd->NbEdges() );
197 TopoDS_Shape tmp1 = Context()->Apply(sbwd->Edge(n1)),
198 tmp2 = Context()->Apply(sbwd->Edge(n2));
199 TopoDS_Edge E1 = TopoDS::Edge(tmp1),
200 E2 = TopoDS::Edge(tmp2);
201 // TopoDS_Face face = myAnalyzer->Face(); // comment by enk
203 // Retrieve curves on edges
204 Standard_Real cfirst1, clast1, cfirst2, clast2;
205 Handle(Geom_Curve) C1, C2;
206 ShapeAnalysis_Edge SAE;
207 if (!SAE.Curve3d(E1,C1,cfirst1,clast1) ||
208 !SAE.Curve3d(E2,C2,cfirst2,clast2))
210 myLastFixStatus |= ShapeExtend::EncodeStatus( ShapeExtend_FAIL1 );
211 return Standard_False;
214 // Check gap in 3d space
215 gp_Pnt cpnt1 = C1->Value(clast1), cpnt2 = C2->Value(cfirst2);
216 Standard_Real gap = cpnt1.Distance(cpnt2);
217 if (!convert && gap<=preci) return Standard_False;
220 // Second phase: collecting data necessary for further analysis
223 Standard_Boolean reversed1 = (E1.Orientation()==TopAbs_REVERSED),
224 reversed2 = (E2.Orientation()==TopAbs_REVERSED);
226 TopoDS_Vertex V1 = SAE.LastVertex(E1), V2 = SAE.FirstVertex(E2);
227 gp_Pnt vpnt = (V1.IsSame(V2))? BRep_Tool::Pnt(V1) :
228 gp_Pnt((BRep_Tool::Pnt(V1).XYZ()+BRep_Tool::Pnt(V2).XYZ())*0.5);
230 Standard_Real first1, last1, first2, last2;
233 first1 = clast1; last1 = cfirst1;
237 first1 = cfirst1; last1 = clast1;
241 first2 = clast2; last2 = cfirst2;
245 first2 = cfirst2; last2 = clast2;
248 Handle(Geom_Curve) c1 = C1, c2 = C2;
250 // Extract basic curves from trimmed and offset
251 Standard_Boolean basic = Standard_False;
252 Standard_Boolean trimmed1 = Standard_False, offset1 = Standard_False;
253 gp_XYZ offval1(0.,0.,0.);
256 if (c1->IsKind(STANDARD_TYPE(Geom_TrimmedCurve)))
258 c1 = Handle(Geom_TrimmedCurve)::DownCast(c1)->BasisCurve();
259 trimmed1 = Standard_True;
261 else if (c1->IsKind(STANDARD_TYPE(Geom_OffsetCurve)))
263 Handle(Geom_OffsetCurve) oc = Handle(Geom_OffsetCurve)::DownCast(c1);
264 c1 = oc->BasisCurve();
265 offval1 += oc->Offset()*oc->Direction().XYZ();
266 offset1 = Standard_True;
268 else basic = Standard_True;
270 basic = Standard_False;
271 Standard_Boolean trimmed2 = Standard_False, offset2 = Standard_False;
272 gp_XYZ offval2(0.,0.,0.);
275 if (c2->IsKind(STANDARD_TYPE(Geom_TrimmedCurve)))
277 c2 = Handle(Geom_TrimmedCurve)::DownCast(c2)->BasisCurve();
278 trimmed2 = Standard_True;
280 else if (c2->IsKind(STANDARD_TYPE(Geom_OffsetCurve)))
282 Handle(Geom_OffsetCurve) oc = Handle(Geom_OffsetCurve)::DownCast(c2);
283 c2 = oc->BasisCurve();
284 offval2 += oc->Offset()*oc->Direction().XYZ();
285 offset2 = Standard_True;
287 else basic = Standard_True;
289 // Restore offset curves
290 if (offset1) c1 = new Geom_OffsetCurve(c1,offval1.Modulus(),gp_Dir(offval1));
291 if (offset2) c2 = new Geom_OffsetCurve(c2,offval2.Modulus(),gp_Dir(offval2));
293 Standard_Boolean done1 = Standard_False, done2 = Standard_False;
297 // Check that gap satisfies the precision - in this case no convertation produced
298 if (cpnt1.Distance(vpnt) < preci && cpnt2.Distance(vpnt) < preci)
299 return Standard_False;
301 Handle(Geom_BSplineCurve) bsp1, bsp2;
302 Handle(Geom_Curve) c;
303 Standard_Real first, last;
306 Standard_Integer nbcurv = (n1==n2? 1 : 2);
307 for (Standard_Integer j=1; j<=nbcurv; j++)
309 //Standard_Boolean trim = Standard_False; // skl
312 if (cpnt1.Distance(vpnt)<preci)
316 if (cpnt2.Distance(vpnt)<preci) continue;
320 c = c1; first = first1; last = last1; /*trim = trimmed1;*/ // skl
324 if (cpnt2.Distance(vpnt)<preci) continue;
325 c = c2; first = first2; last = last2; /*trim = trimmed2;*/ // skl
328 Handle(Geom_BSplineCurve) bsp;
330 // Convert curve to bspline
331 if (c->IsKind(STANDARD_TYPE(Geom_BSplineCurve)))
333 bsp = Handle(Geom_BSplineCurve)::DownCast(c->Copy());
334 // take segment if trim and range differ
335 Standard_Real fbsp = bsp->FirstParameter(), lbsp = bsp->LastParameter();
336 Standard_Boolean segment = Standard_False;
339 fbsp = first; segment = Standard_True;
343 lbsp = last; segment = Standard_True;
346 bsp = GeomConvert::SplitBSplineCurve(bsp,fbsp,lbsp,
347 ::Precision::Confusion());
349 else if (c->IsKind(STANDARD_TYPE(Geom_Conic)))
351 Approx_Curve3d Conv(new GeomAdaptor_HCurve(c,first,last),
352 myAnalyzer->Precision(),GeomAbs_C1,9,1000);
353 if (Conv.IsDone() || Conv.HasResult()) bsp = Conv.Curve();
357 // Restore trim for pcurve
358 Handle(Geom_Curve) tc ;
362 // 15.11.2002 PTV OCC966
363 if(!ShapeAnalysis_Curve::IsPeriodic(c))
364 tc = new Geom_TrimmedCurve(c,Max(first,c->FirstParameter()),Min(last,c->LastParameter()));
365 else tc = new Geom_TrimmedCurve(c,first,last);
366 bsp = GeomConvert::CurveToBSplineCurve(tc);
368 catch (Standard_Failure)
371 cout << "Warning: ShapeFix_Wire_1::FixGap3d: Exception in TrimmedCurve" <<first<<" " <<last<<endl;
372 Standard_Failure::Caught()->Print(cout); cout << endl;
377 if (j==1) bsp1 = bsp; else bsp2 = bsp;
380 // Take curves ends if could not convert
381 if (bsp1.IsNull()) vpnt = cpnt1;
382 else if (bsp2.IsNull()) vpnt = cpnt2;
386 if(bsp1->Degree() == 1) bsp1->IncreaseDegree(2); //gka
389 bsp1->SetPole(1,vpnt); bsp1->SetPole(bsp1->NbPoles(),vpnt);
393 if (reversed1) bsp1->SetPole(1,vpnt);
394 else bsp1->SetPole(bsp1->NbPoles(),vpnt);
396 first1 = bsp1->FirstParameter(); last1 = bsp1->LastParameter();
398 done1 = Standard_True;
402 if(bsp2->Degree() == 1) bsp2->IncreaseDegree(2); //gka
403 if (reversed2) bsp2->SetPole(bsp2->NbPoles(),vpnt);
404 else bsp2->SetPole(1,vpnt);
405 first2 = bsp2->FirstParameter(); last2 = bsp2->LastParameter();
407 done2 = Standard_True;
415 if (c1->IsKind(STANDARD_TYPE(Geom_Circle)) ||
416 c1->IsKind(STANDARD_TYPE(Geom_Ellipse)))
418 Standard_Real diff = M_PI - Abs(clast1-cfirst2)*0.5;
419 first1 -= diff; last1 += diff;
420 done1 = Standard_True;
426 // Determine domains for extremal points locating
427 Standard_Real domfirst1 = first1, domlast1 = last1;
428 if (c1->IsKind(STANDARD_TYPE(Geom_BSplineCurve)) ||
429 c1->IsKind(STANDARD_TYPE(Geom_BezierCurve)))
431 domfirst1 = c1->FirstParameter();
432 domlast1 = c1->LastParameter();
434 else if (c1->IsKind(STANDARD_TYPE(Geom_Line)) ||
435 c1->IsKind(STANDARD_TYPE(Geom_Parabola)) ||
436 c1->IsKind(STANDARD_TYPE(Geom_Hyperbola)))
438 Standard_Real diff = domlast1 - domfirst1;
439 if (reversed1) domfirst1 -= 10.*diff;
440 else domlast1 += 10.*diff;
442 else if (c1->IsKind(STANDARD_TYPE(Geom_Circle)) ||
443 c1->IsKind(STANDARD_TYPE(Geom_Ellipse)))
445 domfirst1 = 0.; domlast1 = 2*M_PI;
447 Standard_Real domfirst2 = first2, domlast2 = last2;
448 if (c2->IsKind(STANDARD_TYPE(Geom_BSplineCurve)) ||
449 c2->IsKind(STANDARD_TYPE(Geom_BezierCurve)))
451 domfirst2 = c2->FirstParameter();
452 domlast2 = c2->LastParameter();
454 else if (c2->IsKind(STANDARD_TYPE(Geom_Line)) ||
455 c2->IsKind(STANDARD_TYPE(Geom_Parabola)) ||
456 c2->IsKind(STANDARD_TYPE(Geom_Hyperbola)))
458 Standard_Real diff = domlast2 - domfirst2;
459 if (reversed2) domlast2 += 10.*diff;
460 else domfirst2 -= 10.*diff;
462 else if (c2->IsKind(STANDARD_TYPE(Geom_Circle)) ||
463 c2->IsKind(STANDARD_TYPE(Geom_Ellipse)))
465 domfirst2 = 0.; domlast2 = 2*M_PI;
468 Standard_Real ipar1 = clast1, ipar2 = cfirst2;
470 // Try to find projections of vertex point
471 GeomAPI_ProjectPointOnCurve Proj;
472 Standard_Real u1 = ipar1, u2 = ipar2;
473 Proj.Init(vpnt,c1,domfirst1,domlast1);
476 Standard_Integer index = 1;
477 Standard_Real dist, mindist=-1.;
478 for (Standard_Integer i=1; i<=Proj.NbPoints(); i++)
480 dist = vpnt.Distance(Proj.Point(i));
481 if (mindist>dist || mindist<0.)
483 index = i; mindist = dist;
485 u1 = Proj.Parameter(index);
488 Proj.Init(vpnt,c2,domfirst2,domlast2);
491 Standard_Integer index = 1;
492 Standard_Real dist, mindist=-1.;
493 for (Standard_Integer i=1; i<=Proj.NbPoints(); i++)
495 dist = vpnt.Distance(Proj.Point(i));
496 if (mindist>dist || mindist<0.)
498 index = i; mindist = dist;
500 u2 = Proj.Parameter(index);
503 // Ajust parameters on periodic curves
504 u1 = AdjustOnPeriodic3d(c1,reversed1,first1,last1,u1);
505 u2 = AdjustOnPeriodic3d(c2,!reversed2,first2,last2,u2);
506 // Check points to satisfy distance criterium
507 gp_Pnt p1 = c1->Value(u1), p2 = c2->Value(u2);
508 if (p1.Distance(p2)<=gap &&
509 Abs(cfirst1-u1) > ::Precision::PConfusion() &&
510 Abs(clast2-u2) > ::Precision::PConfusion() &&
511 (((u1>first1) && (u1<last1)) || ((u2>first2) && (u2<last2)) ||
512 (cpnt1.Distance(p1)<=gap) || (cpnt2.Distance(p2)<=gap)))
514 ipar1 = u1; ipar2 = u2;
515 done1 = done2 = Standard_True;
518 // Try to find closest points if nothing yet found
525 domfirst1 = ipar1; domlast1 = last1;
529 domfirst1 = first1; domlast1 = ipar1;
533 domfirst2 = first2; domlast2 = ipar2;
537 domfirst2 = ipar2; domlast2 = last2;
540 GeomAPI_ExtremaCurveCurve Extr(c1,c2,domfirst1,domlast1,domfirst2,domlast2);
541 if (Extr.NbExtrema())
546 // First find all intersections
548 Standard_Integer index1=0, index2=0;
549 Standard_Real uu1, uu2, pardist, pardist1=-1., pardist2=-1.;
550 for (Standard_Integer i=1; i<=Extr.NbExtrema(); i++)
552 Extr.Parameters(i,uu1,uu2);
553 // Ajust parameters on periodic curves
554 uu1 = AdjustOnPeriodic3d(c1,reversed1,first1,last1,uu1);
555 uu2 = AdjustOnPeriodic3d(c2,!reversed2,first2,last2,uu2);
556 pp1 = c1->Value(uu1); pp2 = c2->Value(uu2);
557 if (pp1.Distance(pp2) < ::Precision::Confusion())
559 // assume intersection
560 pardist = Abs(cfirst1-uu1);
561 if (pardist1>pardist || pardist1<0.)
563 index1 = i; pardist1 = pardist;
565 pardist = Abs(clast2-uu2);
566 if (pardist2>pardist || pardist2<0.)
568 index2 = i; pardist2 = pardist;
572 if (index1!=0 && index2!=0)
576 // take intersection closer to vertex point
577 Extr.Parameters(index1,uu1,uu2);
578 pp1 = gp_Pnt((c1->Value(uu1).XYZ()+c2->Value(uu2).XYZ())*0.5);
579 Extr.Parameters(index2,uu1,uu2);
580 pp2 = gp_Pnt((c1->Value(uu1).XYZ()+c2->Value(uu2).XYZ())*0.5);
581 if (pp2.Distance(vpnt) < pp1.Distance(vpnt)) index1 = index2;
583 Extr.Parameters(index1,uu1,uu2);
585 else Extr.LowerDistanceParameters(uu1,uu2);
586 // Ajust parameters on periodic curves
587 uu1 = AdjustOnPeriodic3d(c1,reversed1,first1,last1,uu1);
588 uu2 = AdjustOnPeriodic3d(c2,!reversed2,first2,last2,uu2);
589 // Check points to satisfy distance criterium
590 pp1 = c1->Value(uu1), pp2 = c2->Value(uu2);
591 if (pp1.Distance(pp2)<=gap &&
592 Abs(cfirst1-uu1) > ::Precision::PConfusion() &&
593 Abs(clast2-uu2) > ::Precision::PConfusion() &&
594 (((uu1>first1) && (uu1<last1)) || ((uu2>first2) && (uu2<last2)) ||
595 (cpnt1.Distance(pp1)<=gap) || (cpnt2.Distance(pp2)<=gap)))
597 ipar1 = uu1; ipar2 = uu2;
598 done1 = done2 = Standard_True;
601 catch ( Standard_Failure )
612 if (ipar1==clast1) done1 = Standard_False;
615 // Set up new bounds for curve
616 if (reversed1) first1 = ipar1; else last1 = ipar1;
617 // Set new trim for old curve
620 // Standard_Real ff1 = c1->FirstParameter();
621 // Standard_Real ll1 = c1->LastParameter();
622 c1 = new Geom_TrimmedCurve(c1,first1,last1);
628 if (ipar2==cfirst2) done2 = Standard_False;
631 // Set up new bounds for curve
632 if (reversed2) last2 = ipar2; else first2 = ipar2;
633 // Set new trim for old curve
636 // Standard_Real ff2 = c2->FirstParameter();
637 // Standard_Real ll2 = c2->LastParameter();
638 c2 = new Geom_TrimmedCurve(c2,first2,last2);
643 catch (Standard_Failure)
646 cout << "Warning: ShapeFix_Wire_1::FixGap3d: Exception in TrimmedCurve :"<<endl;
647 Standard_Failure::Caught()->Print(cout); cout << endl;
658 ShapeFix_ShapeTolerance SFST;
661 TopoDS_Vertex nullV, newV1;
663 TopoDS_Shape emptyCopiedV2 = V2.EmptyCopied();
664 TopoDS_Vertex newV2 = TopoDS::Vertex(emptyCopiedV2);
665 SFST.SetTolerance(newV2,::Precision::Confusion());
666 Context()->Replace(V2,newV2);
670 TopoDS_Shape tmpV2 = newV2.Oriented(TopAbs_REVERSED);
671 newV1 = TopoDS::Vertex(tmpV2);
676 TopoDS_Shape emptyCopied = V1.EmptyCopied();
677 newV1 = TopoDS::Vertex(emptyCopied);
678 SFST.SetTolerance(newV1,::Precision::Confusion());
679 Context()->Replace(V1,newV1);
685 TopoDS_Edge newE1 = SBE.CopyReplaceVertices(E1,nullV,newV1);
687 TopoDS_Shape tmpE1 = newE1.Oriented(TopAbs_FORWARD);
688 B.UpdateEdge(TopoDS::Edge(tmpE1),c1,0.);
689 SBE.SetRange3d(TopoDS::Edge(tmpE1),first1,last1);
690 SFST.SetTolerance(newE1,::Precision::Confusion(),TopAbs_EDGE);
691 B.SameRange(newE1,Standard_False);
692 // B.SameParameter(newE1,Standard_False);
694 //To keep NM vertices belonging initial edges
695 TopoDS_Iterator aItv(E1,Standard_False);
696 for( ; aItv.More(); aItv.Next()) {
697 if(aItv.Value().Orientation() == TopAbs_INTERNAL ||
698 aItv.Value().Orientation() == TopAbs_EXTERNAL) {
699 TopoDS_Vertex aOldV = TopoDS::Vertex(aItv.Value());
700 TopoDS_Vertex anewV = ShapeAnalysis_TransferParametersProj::CopyNMVertex(aOldV,newE1,E1);
702 Context()->Replace(aOldV,anewV);
706 Context()->Replace(E1,newE1);
712 // Update second edge
713 TopoDS_Edge newE2 = SBE.CopyReplaceVertices(E2,newV2,nullV);
715 TopoDS_Shape tmpE2 = newE2.Oriented(TopAbs_FORWARD);
716 B.UpdateEdge(TopoDS::Edge(tmpE2),c2,0.);
717 SBE.SetRange3d(TopoDS::Edge(tmpE2),first2,last2);
718 SFST.SetTolerance(newE2,::Precision::Confusion(),TopAbs_EDGE);
719 B.SameRange(newE2,Standard_False);
720 // B.SameParameter(newE2,Standard_False);
722 //To keep NM vertices belonging initial edges
723 TopoDS_Iterator aItv(E2,Standard_False);
724 for( ; aItv.More(); aItv.Next()) {
725 if(aItv.Value().Orientation() == TopAbs_INTERNAL ||
726 aItv.Value().Orientation() == TopAbs_EXTERNAL) {
727 TopoDS_Vertex aOldV = TopoDS::Vertex(aItv.Value());
728 TopoDS_Vertex anewV = ShapeAnalysis_TransferParametersProj::CopyNMVertex(aOldV,newE2,E2);
730 Context()->Replace(aOldV,anewV);
733 Context()->Replace(E2,newE2);
737 myLastFixStatus |= ShapeExtend::EncodeStatus( ShapeExtend_DONE1 );
741 myLastFixStatus |= ShapeExtend::EncodeStatus( ShapeExtend_FAIL2 );
743 return (done1 || done2);
746 //=======================================================================
747 //function : FixGap2d
749 //=======================================================================
751 static Standard_Real AdjustOnPeriodic2d (const Handle(Geom2d_Curve)& pc,
752 const Standard_Boolean takefirst,
753 const Standard_Real first,
754 const Standard_Real last,
755 const Standard_Real param)
757 // 15.11.2002 PTV OCC966
758 if (ShapeAnalysis_Curve::IsPeriodic(pc))
760 Standard_Real T = pc->Period();
761 Standard_Real shift = -IntegerPart(first/T)*T; if (first<0.) shift += T;
762 Standard_Real sfirst = first+shift, slast = last+shift;
763 if ( takefirst && (param>slast) && (param>sfirst)) return param-T-shift;
764 if (!takefirst && (param<slast) && (param<sfirst)) return param+T-shift;
769 Standard_Boolean ShapeFix_Wire::FixGap2d (const Standard_Integer num,
770 const Standard_Boolean convert)
772 myLastFixStatus = ShapeExtend::EncodeStatus( ShapeExtend_OK );
773 if ( !IsReady() ) return Standard_False;
776 // First phase: analysis whether the problem (gap) exists
779 if (Context().IsNull()) SetContext(new ShapeBuild_ReShape);
781 Standard_Real preci = ::Precision::PConfusion();
782 //Standard_Real preci = Precision();
783 //GeomAdaptor_Surface& SA = Analyzer().Surface()->Adaptor()->ChangeSurface();
784 //preci = Max(SA.UResolution(preci), SA.VResolution(preci));
786 Handle(ShapeExtend_WireData) sbwd = WireData();
787 Standard_Integer n2 = ( num >0 ? num : sbwd->NbEdges() );
788 Standard_Integer n1 = ( n2 >1 ? n2-1 : sbwd->NbEdges() );
790 TopoDS_Shape tmp1 = Context()->Apply(sbwd->Edge(n1)),
791 tmp2 = Context()->Apply(sbwd->Edge(n2));
792 TopoDS_Edge E1 = TopoDS::Edge(tmp1),
793 E2 = TopoDS::Edge(tmp2);
794 TopoDS_Face face = myAnalyzer->Face();
796 // Retrieve pcurves on edges
797 Standard_Real cfirst1, clast1, cfirst2, clast2;
798 Handle(Geom2d_Curve) PC1, PC2;
799 ShapeAnalysis_Edge SAE;
800 if (!SAE.PCurve(E1,face,PC1,cfirst1,clast1) ||
801 !SAE.PCurve(E2,face,PC2,cfirst2,clast2) ||
802 sbwd->IsSeam(n1) || sbwd->IsSeam(n2))
804 myLastFixStatus |= ShapeExtend::EncodeStatus( ShapeExtend_FAIL1 );
805 return Standard_False;
808 // Check gap in 2d space
809 gp_Pnt2d cpnt1 = PC1->Value(clast1), cpnt2 = PC2->Value(cfirst2);
810 Standard_Real gap = cpnt1.Distance(cpnt2);
811 if (gap<=preci) return Standard_False;
814 // Second phase: collecting data necessary for further analysis
817 Standard_Boolean reversed1 = (E1.Orientation()==TopAbs_REVERSED),
818 reversed2 = (E2.Orientation()==TopAbs_REVERSED);
820 Standard_Real first1, last1, first2, last2;
823 first1 = clast1; last1 = cfirst1;
827 first1 = cfirst1; last1 = clast1;
831 first2 = clast2; last2 = cfirst2;
835 first2 = cfirst2; last2 = clast2;
838 Handle(Geom2d_Curve) pc1 = PC1, pc2 = PC2;
840 // Extract basic curves from trimmed and offset
841 Standard_Boolean basic = Standard_False;
842 Standard_Boolean trimmed1 = Standard_False, offset1 = Standard_False;
843 Standard_Real offval1 = 0.;
846 if (pc1->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve)))
848 pc1 = Handle(Geom2d_TrimmedCurve)::DownCast(pc1)->BasisCurve();
849 trimmed1 = Standard_True;
851 else if (pc1->IsKind(STANDARD_TYPE(Geom2d_OffsetCurve)))
853 Handle(Geom2d_OffsetCurve) oc = Handle(Geom2d_OffsetCurve)::DownCast(pc1);
854 pc1 = oc->BasisCurve();
855 offval1 += oc->Offset();
856 offset1 = Standard_True;
858 else basic = Standard_True;
860 basic = Standard_False;
861 Standard_Boolean trimmed2 = Standard_False, offset2 = Standard_False;
862 Standard_Real offval2 = 0.;
865 if (pc2->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve)))
867 pc2 = Handle(Geom2d_TrimmedCurve)::DownCast(pc2)->BasisCurve();
868 trimmed2 = Standard_True;
870 else if (pc2->IsKind(STANDARD_TYPE(Geom2d_OffsetCurve)))
872 Handle(Geom2d_OffsetCurve) oc = Handle(Geom2d_OffsetCurve)::DownCast(pc2);
873 pc2 = oc->BasisCurve();
874 offval2 += oc->Offset();
875 offset2 = Standard_True;
877 else basic = Standard_True;
879 // Restore offset curves
880 if (offset1) pc1 = new Geom2d_OffsetCurve(pc1,offval1);
881 if (offset2) pc2 = new Geom2d_OffsetCurve(pc2,offval2);
883 Standard_Boolean done1 = Standard_False, done2 = Standard_False;
885 // Determine same edge case
889 Handle(Geom2d_BSplineCurve) bsp1, bsp2;
890 Handle(Geom2d_Curve) pc;
891 Standard_Real first, last;
893 // iterate on pcurves
894 Standard_Integer nbcurv = (n1==n2? 1 : 2);
895 for (Standard_Integer j=1; j<=nbcurv; j++)
897 //Standard_Integer trim = Standard_False; // skl
898 Handle(Geom2d_BSplineCurve) bsp;
902 pc = pc1; first = first1; last = last1; /*trim = trimmed1;*/
906 pc = pc2; first = first2; last = last2; /*trim = trimmed2;*/
909 // Convert pcurve to bspline
910 if (pc->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve)))
912 bsp = Handle(Geom2d_BSplineCurve)::DownCast(pc->Copy());
913 // take segment if trim and range differ
914 Standard_Real fbsp = bsp->FirstParameter(), lbsp = bsp->LastParameter();
915 Standard_Boolean segment = Standard_False;
918 fbsp = first; segment = Standard_True;
922 lbsp = last; segment = Standard_True;
925 bsp = Geom2dConvert::SplitBSplineCurve(bsp,fbsp,lbsp,
926 ::Precision::PConfusion());
928 else if (pc->IsKind(STANDARD_TYPE(Geom2d_Conic)))
930 GeomAdaptor_Surface& AS = myAnalyzer->Surface()->Adaptor3d()->ChangeSurface();
931 Standard_Real tolu = AS.UResolution(myAnalyzer->Precision()),
932 tolv = AS.VResolution(myAnalyzer->Precision());
933 Approx_Curve2d Conv(new Geom2dAdaptor_HCurve(pc,first,last),
934 first,last,tolu,tolv,GeomAbs_C1,9,1000);
935 if (Conv.IsDone() || Conv.HasResult()) bsp = Conv.Curve();
939 // Restore trim for pcurve
943 Handle(Geom2d_Curve) c;
944 // 15.11.2002 PTV OCC966
945 if(!ShapeAnalysis_Curve::IsPeriodic(pc))
946 c = new Geom2d_TrimmedCurve(pc,Max(first,pc->FirstParameter()),Min(last,pc->LastParameter()));
948 c = new Geom2d_TrimmedCurve(pc,first,last);
949 bsp = Geom2dConvert::CurveToBSplineCurve(c);
951 catch (Standard_Failure)
954 cout << "Warning: ShapeFix_Wire_1::FixGap2d: Exception in TrimmedCurve2d" <<first<<" " <<last<<endl;
955 Standard_Failure::Caught()->Print(cout); cout << endl;
960 if (j==1) bsp1 = bsp; else bsp2 = bsp;
963 // Take curves ends if could not convert
964 gp_Pnt2d mpnt((cpnt1.XY()+cpnt2.XY())*0.5);
965 if (bsp1.IsNull()) mpnt = cpnt1;
966 else if (bsp2.IsNull()) mpnt = cpnt2;
970 if(bsp1->Degree() == 1) bsp1->IncreaseDegree(2);
973 bsp1->SetPole(1,mpnt); bsp1->SetPole(bsp1->NbPoles(),mpnt);
977 if (reversed1) bsp1->SetPole(1,mpnt);
978 else bsp1->SetPole(bsp1->NbPoles(),mpnt);
980 first1 = bsp1->FirstParameter(); last1 = bsp1->LastParameter();
982 done1 = Standard_True;
986 if(bsp2->Degree() == 1) bsp2->IncreaseDegree(2);
987 if (reversed2) bsp2->SetPole(bsp2->NbPoles(),mpnt);
988 else bsp2->SetPole(1,mpnt);
989 first2 = bsp2->FirstParameter(); last2 = bsp2->LastParameter();
991 done2 = Standard_True;
999 if (pc1->IsKind(STANDARD_TYPE(Geom2d_Circle)) ||
1000 pc1->IsKind(STANDARD_TYPE(Geom2d_Ellipse)))
1002 Standard_Real diff = M_PI - Abs(clast1-cfirst2)*0.5;
1003 first1 -= diff; last1 += diff;
1004 done1 = Standard_True;
1010 // Determine domains for extremal points locating
1011 Standard_Real domfirst1 = first1, domlast1 = last1;
1012 if (pc1->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve)) ||
1013 pc1->IsKind(STANDARD_TYPE(Geom2d_BezierCurve)))
1015 domfirst1 = pc1->FirstParameter();
1016 domlast1 = pc1->LastParameter();
1018 else if (pc1->IsKind(STANDARD_TYPE(Geom2d_Line)) ||
1019 pc1->IsKind(STANDARD_TYPE(Geom2d_Parabola)) ||
1020 pc1->IsKind(STANDARD_TYPE(Geom2d_Hyperbola)))
1022 Standard_Real diff = domlast1 - domfirst1;
1023 if (reversed1) domfirst1 -= 10.*diff;
1024 else domlast1 += 10.*diff;
1026 else if (pc1->IsKind(STANDARD_TYPE(Geom2d_Circle)) ||
1027 pc1->IsKind(STANDARD_TYPE(Geom2d_Ellipse)))
1029 domfirst1 = 0.; domlast1 = 2*M_PI;
1031 Standard_Real domfirst2 = first2, domlast2 = last2;
1032 if (pc2->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve)) ||
1033 pc2->IsKind(STANDARD_TYPE(Geom2d_BezierCurve)))
1035 domfirst2 = pc2->FirstParameter();
1036 domlast2 = pc2->LastParameter();
1038 else if (pc2->IsKind(STANDARD_TYPE(Geom2d_Line)) ||
1039 pc2->IsKind(STANDARD_TYPE(Geom2d_Parabola)) ||
1040 pc2->IsKind(STANDARD_TYPE(Geom2d_Hyperbola)))
1042 Standard_Real diff = domlast2 - domfirst2;
1043 if (reversed2) domlast2 += 10.*diff;
1044 else domfirst2 -= 10.*diff;
1046 else if (pc2->IsKind(STANDARD_TYPE(Geom2d_Circle)) ||
1047 pc2->IsKind(STANDARD_TYPE(Geom2d_Ellipse)))
1049 domfirst2 = 0.; domlast2 = 2*M_PI;
1052 Standard_Real ipar1 = clast1, ipar2 = cfirst2;
1054 Geom2dInt_GInter Inter;
1055 Standard_Real tolint = ::Precision::PConfusion();
1057 Geom2dAdaptor_Curve AC1(pc1), AC2(pc2);
1059 // Try to find intersection points
1060 IntRes2d_Domain dom1(pc1->Value(domfirst1),domfirst1,tolint,
1061 pc1->Value(domlast1),domlast1,tolint);
1062 IntRes2d_Domain dom2(pc2->Value(domfirst2),domfirst2,tolint,
1063 pc2->Value(domlast2),domlast2,tolint);
1064 Inter.Perform( AC1, dom1, AC2, dom2, tolint, tolint );
1067 if (Inter.NbPoints() || Inter.NbSegments())
1069 Standard_Integer i, index1 = 0, index2 = 0;
1070 Standard_Real pardist, pardist1=-1., pardist2=-1.;
1071 // iterate on intersection points
1072 IntRes2d_IntersectionPoint IP;
1073 for ( i=1; i<=Inter.NbPoints(); i++ )
1075 IP = Inter.Point(i);
1076 // Adjust parameters on periodic curves
1077 Standard_Real u1 = AdjustOnPeriodic2d(pc1,reversed1,first1,last1,
1079 Standard_Real u2 = AdjustOnPeriodic2d(pc2,!reversed2,first2,last2,
1080 IP.ParamOnSecond());
1081 pardist = Abs(cfirst1-u1);
1082 if (pardist1>pardist || pardist1<0.)
1084 index1 = i; pardist1 = pardist;
1086 pardist = Abs(clast2-u2);
1087 if (pardist2>pardist || pardist2<0.)
1089 index2 = i; pardist2 = pardist;
1092 Standard_Integer flag1 = 0, flag2 = 0;
1093 // iterate on intersection segments
1094 IntRes2d_IntersectionSegment IS;
1095 for ( i=1; i<=Inter.NbSegments(); i++ )
1097 IS = Inter.Segment(i);
1098 for (Standard_Integer j=1; j<=2; j++)
1100 if ((j==1 && IS.HasFirstPoint()) ||
1101 (j==2 && IS.HasLastPoint()))
1103 if (j==1) IP = IS.FirstPoint();
1104 else IP = IS.LastPoint();
1105 // Adjust parameters on periodic curves
1106 Standard_Real u1 = AdjustOnPeriodic2d(pc1,reversed1,first1,last1,
1108 Standard_Real u2 = AdjustOnPeriodic2d(pc2,!reversed2,first2,last2,
1109 IP.ParamOnSecond());
1110 pardist = Abs(cfirst1-u1);
1111 if (pardist1>pardist || pardist1<0.)
1113 flag1 = j; index1 = i; pardist1 = pardist;
1115 pardist = Abs(clast2-u2);
1116 if (pardist2>pardist || pardist2<0.)
1118 flag2 = j; index2 = i; pardist2 = pardist;
1123 if (index1!=index2 || flag1!=flag2)
1125 // take intersection closer to mean point
1127 if (flag1==0) pt1 = Inter.Point(index1).Value();
1130 IS = Inter.Segment(index1);
1131 if (flag1==1) pt1 = IS.FirstPoint().Value();
1132 else pt1 = IS.LastPoint().Value();
1134 if (flag2==0) pt2 = Inter.Point(index2).Value();
1137 IS = Inter.Segment(index2);
1138 if (flag2==1) pt2 = IS.FirstPoint().Value();
1139 else pt2 = IS.LastPoint().Value();
1141 gp_Pnt2d mpnt((cpnt1.XY()+cpnt2.XY())*0.5);
1142 if (pt2.Distance(mpnt) < pt1.Distance(mpnt))
1144 index1 = index2; flag1 = flag2;
1147 if (flag1==0) IP = Inter.Point(index1);
1150 IS = Inter.Segment(index1);
1151 if (flag1==1) IP = IS.FirstPoint();
1152 else IP = IS.LastPoint();
1154 // Ajust parameters on periodic curves
1155 Standard_Real u1 = AdjustOnPeriodic2d(pc1,reversed1,first1,last1,
1157 Standard_Real u2 = AdjustOnPeriodic2d(pc2,!reversed2,first2,last2,
1158 IP.ParamOnSecond());
1159 // Check points to satisfy distance criterium
1160 gp_Pnt2d p1 = pc1->Value(u1), p2 = pc2->Value(u2);
1161 if (p1.Distance(p2)<=gap &&
1162 Abs(cfirst1-u1) > ::Precision::PConfusion() &&
1163 Abs(clast2 -u2) > ::Precision::PConfusion() &&
1164 (((u1>first1) && (u1<last1)) || ((u2>first2) && (u2<last2)) ||
1165 (cpnt1.Distance(p1)<=gap) || (cpnt2.Distance(p2)<=gap)))
1167 ipar1 = u1; ipar2 = u2;
1168 done1 = done2 = Standard_True;
1173 // Try to find closest points if nothing yet found
1176 Geom2dAPI_ExtremaCurveCurve Extr(pc1,pc2,domfirst1,domlast1,domfirst2,domlast2);
1177 if (Extr.NbExtrema())
1179 Standard_Real u1, u2;
1180 Extr.LowerDistanceParameters(u1,u2);
1181 // Ajust parameters on periodic curves
1182 u1 = AdjustOnPeriodic2d(pc1,reversed1,first1,last1,u1);
1183 u2 = AdjustOnPeriodic2d(pc2,!reversed2,first2,last2,u2);
1184 // Check points to satisfy distance criterium
1185 gp_Pnt2d p1 = pc1->Value(u1), p2 = pc2->Value(u2);
1186 if (p1.Distance(p2)<=gap &&
1187 Abs(cfirst1-u1) > ::Precision::PConfusion() &&
1188 Abs(clast2 -u2) > ::Precision::PConfusion() &&
1189 (((u1>first1) && (u1<last1)) || ((u2>first2) && (u2<last2)) ||
1190 (cpnt1.Distance(p1)<=gap) || (cpnt2.Distance(p2)<=gap)))
1192 ipar1 = u1; ipar2 = u2;
1193 done1 = done2 = Standard_True;
1198 // Try to find projections if nothing yet found
1201 Geom2dAPI_ProjectPointOnCurve Proj;
1202 gp_Pnt2d ipnt1 = cpnt1, ipnt2 = cpnt2;
1203 Standard_Real u1 = ipar1, u2 = ipar2;
1204 Proj.Init(cpnt2,pc1,domfirst1,domlast1);
1205 if (Proj.NbPoints())
1207 Standard_Integer index = 1;
1208 Standard_Real dist, mindist=-1.;
1209 for (Standard_Integer i=1; i<=Proj.NbPoints(); i++)
1211 dist = cpnt2.Distance(Proj.Point(i));
1212 if (mindist>dist || mindist<0.)
1214 index = i; mindist = dist;
1216 ipnt1 = Proj.Point(index);
1217 u1 = Proj.Parameter(index);
1220 Proj.Init(cpnt1,pc2,domfirst2,domlast2);
1221 if (Proj.NbPoints())
1223 Standard_Integer index = 1;
1224 Standard_Real dist, mindist=-1.;
1225 for (Standard_Integer i=1; i<=Proj.NbPoints(); i++)
1227 dist = cpnt1.Distance(Proj.Point(i));
1228 if (mindist>dist || mindist<0.)
1230 index = i; mindist = dist;
1232 ipnt2 = Proj.Point(index);
1233 u2 = Proj.Parameter(index);
1236 // Ajust parameters on periodic curves
1237 u1 = AdjustOnPeriodic2d(pc1,reversed1,first1,last1,u1);
1238 u2 = AdjustOnPeriodic2d(pc2,!reversed2,first2,last2,u2);
1239 // Process special case of projection
1240 if ((((reversed1 && u1>clast1) || (!reversed1 && u1<clast1)) &&
1241 ((reversed2 && u2<cfirst2) || (!reversed2 && u2>cfirst2))) ||
1242 (((reversed1 && u1<clast1) || (!reversed1 && u1>clast1)) &&
1243 ((reversed2 && u2>cfirst2) || (!reversed2 && u2<cfirst2))))
1245 // both projections lie inside/outside initial domains
1246 // project mean point
1247 gp_Pnt2d mpnt((cpnt1.XY()+cpnt2.XY())*0.5);
1248 u1 = ipar1; u2 = ipar2;
1249 Proj.Init(mpnt,pc1,domfirst1,domlast1);
1250 if (Proj.NbPoints())
1252 Standard_Integer index = 1;
1253 Standard_Real dist, mindist=-1.;
1254 for (Standard_Integer i=1; i<=Proj.NbPoints(); i++)
1256 dist = mpnt.Distance(Proj.Point(i));
1257 if (mindist>dist || mindist<0.)
1259 index = i; mindist = dist;
1261 ipnt1 = Proj.Point(index);
1262 u1 = Proj.Parameter(index);
1265 Proj.Init(mpnt,pc2,domfirst2,domlast2);
1266 if (Proj.NbPoints())
1268 Standard_Integer index = 1;
1269 Standard_Real dist, mindist=-1.;
1270 for (Standard_Integer i=1; i<=Proj.NbPoints(); i++)
1272 dist = mpnt.Distance(Proj.Point(i));
1273 if (mindist>dist || mindist<0.)
1275 index = i; mindist = dist;
1277 ipnt2 = Proj.Point(index);
1278 u2 = Proj.Parameter(index);
1284 if (cpnt1.Distance(ipnt2)<cpnt2.Distance(ipnt1)) u1 = ipar1;
1287 // Ajust parameters on periodic curves
1288 u1 = AdjustOnPeriodic2d(pc1,reversed1,first1,last1,u1);
1289 u2 = AdjustOnPeriodic2d(pc2,!reversed2,first2,last2,u2);
1290 // Check points to satisfy distance criterium
1291 gp_Pnt2d p1 = pc1->Value(u1), p2 = pc2->Value(u2);
1292 if (p1.Distance(p2)<=gap &&
1293 Abs(cfirst1-u1) > ::Precision::PConfusion() &&
1294 Abs(clast2 -u2) > ::Precision::PConfusion() &&
1295 (((u1>first1) && (u1<last1)) || ((u2>first2) && (u2<last2)) ||
1296 (cpnt1.Distance(p1)<=gap) || (cpnt2.Distance(p2)<=gap)))
1298 ipar1 = u1; ipar2 = u2;
1299 done1 = done2 = Standard_True;
1306 if (ipar1<first1 || ipar1>last1 || ipar2<first2 || ipar2>last2)
1309 // Check whether new points lie inside the surface bounds
1310 Standard_Real umin, umax, vmin, vmax;
1311 myAnalyzer->Surface()->Surface()->Bounds(umin,umax,vmin,vmax);
1312 if (::Precision::IsInfinite(umin) || ::Precision::IsInfinite(umax) ||
1313 ::Precision::IsInfinite(vmin) || ::Precision::IsInfinite(vmax))
1315 Standard_Real fumin, fumax, fvmin, fvmax;
1316 BRepTools::UVBounds(face,fumin,fumax,fvmin,fvmax);
1317 if (::Precision::IsInfinite(umin)) umin = fumin-preci;
1318 if (::Precision::IsInfinite(umax)) umax = fumax+preci;
1319 if (::Precision::IsInfinite(vmin)) vmin = fvmin-preci;
1320 if (::Precision::IsInfinite(vmax)) vmax = fvmax+preci;
1323 gp_Pnt2d ipnt, P1, P2;
1325 Standard_Boolean out;
1326 // iterate on curves
1327 for (Standard_Integer j=1; j<=2; j++)
1332 if (ipar1>=first1 && ipar1<=last1) continue;
1333 ipnt = pc1->Value(ipar1);
1337 if (ipar2>=first2 && ipar2<=last2) continue;
1338 ipnt = pc2->Value(ipar2);
1341 // iterate on bounding lines
1342 for (Standard_Integer k=1; k<=2; k++)
1345 u = ipnt.X(); v = ipnt.Y();
1347 out = Standard_True;
1352 P1 = gp_Pnt2d(umin,vmin); P2 = gp_Pnt2d(umin,vmax);
1356 P1 = gp_Pnt2d(umax,vmin); P2 = gp_Pnt2d(umax,vmax);
1358 else out = Standard_False;
1364 P1 = gp_Pnt2d(umin,vmin); P2 = gp_Pnt2d(umax,vmin);
1368 P1 = gp_Pnt2d(umin,vmax); P2 = gp_Pnt2d(umax,vmax);
1370 else out = Standard_False;
1375 // Intersect pcurve with bounding line
1376 Handle(Geom2d_Line) lin = new Geom2d_Line(P1,gp_Dir2d(gp_Vec2d(P1,P2)));
1377 Geom2dAdaptor_Curve ACL(lin);
1378 IntRes2d_Domain dlin(P1,0.,tolint,P2,P1.Distance(P2),tolint);
1380 Handle(Geom2d_Curve) pc;
1381 Standard_Real fpar, lpar;
1386 fpar = cfirst1, lpar = ipar1;
1390 fpar = ipar1, lpar = cfirst1;
1398 fpar = clast2, lpar = ipar2;
1402 fpar = ipar2, lpar = clast2;
1406 Geom2dAdaptor_Curve ACC(pc);
1407 IntRes2d_Domain domc(pc->Value(fpar),fpar,tolint,
1408 pc->Value(lpar),lpar,tolint);
1410 // Intersect line with the pcurve
1411 Inter.Perform( ACL, dlin, ACC, domc, tolint, tolint );
1414 if (Inter.NbPoints() || Inter.NbSegments())
1416 Standard_Integer i, index = 1;
1417 Standard_Real uu, dist, mindist=-1.;
1418 // iterate on intersection points
1419 for ( i=1; i<=Inter.NbPoints(); i++ )
1421 // Adjust parameters on periodic curve
1422 uu = AdjustOnPeriodic2d(pc,(j==1? reversed1 : !reversed2),
1423 fpar,lpar,Inter.Point(i).ParamOnSecond());
1424 dist = Abs((j==1? cfirst1 : clast2)-uu);
1425 if (mindist>dist || mindist<0.)
1427 index = i; mindist = dist;
1430 // iterate on intersection segments
1431 Standard_Integer flag = 0;
1432 IntRes2d_IntersectionPoint IP;
1433 IntRes2d_IntersectionSegment IS;
1434 for ( i=1; i<=Inter.NbSegments(); i++ )
1436 IS = Inter.Segment(i);
1437 for (Standard_Integer jj=1; jj<=2; jj++)
1439 if ((jj==1 && IS.HasFirstPoint()) ||
1440 (jj==2 && IS.HasLastPoint()))
1442 if (jj==1) IP = IS.FirstPoint();
1443 else IP = IS.LastPoint();
1444 // Adjust parameters on periodic curve
1445 uu = AdjustOnPeriodic2d(pc,(jj==1? reversed1 : !reversed2),
1446 fpar,lpar,IP.ParamOnSecond());
1447 dist = Abs((jj==1? cfirst1 : clast2)-uu);
1448 if (mindist>dist || mindist<0.)
1450 flag = jj; index = i; mindist = dist;
1455 if (flag==0) IP = Inter.Point(index);
1458 IS = Inter.Segment(index);
1459 if (flag==1) IP = IS.FirstPoint();
1460 else IP = IS.LastPoint();
1462 // Ajust parameters on periodic curve
1463 uu = AdjustOnPeriodic2d(pc,(j==1? reversed1 : !reversed2),
1464 fpar,lpar,IP.ParamOnSecond());
1465 if (j==1 && Abs(cfirst1-uu) > ::Precision::PConfusion())
1467 ipar1 = uu; ipnt = IP.Value();
1469 if (j==2 && Abs(clast2-uu) > ::Precision::PConfusion())
1471 ipar2 = uu; ipnt = IP.Value();
1478 // Adjust if intersection lies inside old bounds
1483 if (ipar1>first1) ipar1 = first1;
1487 if (ipar1<last1) ipar1 = last1;
1494 if (ipar2<last2) ipar2 = last2;
1498 if (ipar2>first2) ipar2 = first2;
1509 if (ipar1==clast1) done1 = Standard_False;
1512 // Set up new bounds for pcurve
1513 if (reversed1) first1 = ipar1; else last1 = ipar1;
1514 // Set new trim for old pcurve
1515 if (trimmed1) pc1 = new Geom2d_TrimmedCurve(pc1,first1,last1);
1520 if (ipar2==cfirst2) done2 = Standard_False;
1523 // Set up new bounds for pcurve
1524 if (reversed2) last2 = ipar2; else first2 = ipar2;
1525 // Set new trim for old pcurve
1526 if (trimmed2) pc2 = new Geom2d_TrimmedCurve(pc2,first2,last2);
1530 catch (Standard_Failure)
1534 cout << "Warning: ShapeFix_Wire_1::FixGap2d: Exception in TrimmedCurve2d :"<<endl;
1535 Standard_Failure::Caught()->Print(cout); cout << endl;
1545 ShapeBuild_Edge SBE;
1546 ShapeFix_ShapeTolerance SFST;
1549 TopoDS_Vertex V1 = SAE.LastVertex(E1), V2 = SAE.FirstVertex(E2);
1550 TopoDS_Vertex nullV, newV1;
1552 TopoDS_Shape emptyCopiedV2 = V2.EmptyCopied();
1553 TopoDS_Vertex newV2 = TopoDS::Vertex(emptyCopiedV2);
1554 SFST.SetTolerance(newV2,::Precision::Confusion());
1555 Context()->Replace(V2,newV2);
1559 TopoDS_Shape tmpVertexRev = newV2.Oriented(TopAbs_REVERSED);
1560 newV1 = TopoDS::Vertex(tmpVertexRev);
1565 TopoDS_Shape emptyCopiedV1 = V1.EmptyCopied();
1566 newV1 = TopoDS::Vertex(emptyCopiedV1);
1567 SFST.SetTolerance(newV1,::Precision::Confusion());
1568 Context()->Replace(V1,newV1);
1573 // Update first edge
1574 TopoDS_Edge newE1 = SBE.CopyReplaceVertices(E1,nullV,newV1);
1576 TopoDS_Shape tmpE1 = newE1.Oriented(TopAbs_FORWARD);
1577 B.UpdateEdge(TopoDS::Edge(tmpE1),pc1,face,0.);
1578 B.Range(TopoDS::Edge(tmpE1),face,first1,last1);
1579 SFST.SetTolerance(newE1,::Precision::Confusion(),TopAbs_EDGE);
1580 B.SameRange(newE1,Standard_False);
1581 // B.SameParameter(newE1,Standard_False);
1583 //To keep NM vertices belonging initial edges
1584 TopoDS_Iterator aItv(E1,Standard_False);
1585 for( ; aItv.More(); aItv.Next()) {
1586 if(aItv.Value().Orientation() == TopAbs_INTERNAL ||
1587 aItv.Value().Orientation() == TopAbs_EXTERNAL) {
1588 TopoDS_Vertex aOldV = TopoDS::Vertex(aItv.Value());
1589 TopoDS_Vertex anewV = ShapeAnalysis_TransferParametersProj::CopyNMVertex(aOldV,newE1,E1);
1591 Context()->Replace(aOldV,anewV);
1595 Context()->Replace(E1,newE1);
1596 sbwd->Set(newE1,n1);
1601 // Update second edge
1602 TopoDS_Edge newE2 = SBE.CopyReplaceVertices(E2,newV2,nullV);
1604 TopoDS_Shape tmpE2 = newE2.Oriented(TopAbs_FORWARD);
1605 B.UpdateEdge(TopoDS::Edge(tmpE2),pc2,face,0.);
1606 B.Range(TopoDS::Edge(tmpE2),face,first2,last2);
1607 SFST.SetTolerance(newE2,::Precision::Confusion(),TopAbs_EDGE);
1608 B.SameRange(newE2,Standard_False);
1609 // B.SameParameter(newE2,Standard_False);
1610 //To keep NM vertices belonging initial edges
1611 TopoDS_Iterator aItv(E2,Standard_False);
1612 for( ; aItv.More(); aItv.Next()) {
1613 if(aItv.Value().Orientation() == TopAbs_INTERNAL ||
1614 aItv.Value().Orientation() == TopAbs_EXTERNAL) {
1615 TopoDS_Vertex aOldV = TopoDS::Vertex(aItv.Value());
1616 TopoDS_Vertex anewV = ShapeAnalysis_TransferParametersProj::CopyNMVertex(aOldV,newE2,E2);
1618 Context()->Replace(aOldV,anewV);
1621 Context()->Replace(E2,newE2);
1622 sbwd->Set(newE2,n2);
1625 myLastFixStatus |= ShapeExtend::EncodeStatus( ShapeExtend_DONE1 );
1629 myLastFixStatus |= ShapeExtend::EncodeStatus( ShapeExtend_FAIL2 );
1631 return (done1 || done2);