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_Surface.hxx>
56 #include <TopTools_Array1OfShape.hxx>
57 #include <BRepTools.hxx>
58 #include <Bnd_Array1OfBox2d.hxx>
59 #include <BndLib_Add2dCurve.hxx>
60 #include <Geom2dAdaptor_Curve.hxx>
61 #include <Geom2dConvert.hxx>
62 #include <Geom2d_TrimmedCurve.hxx>
63 #include <ShapeBuild_ReShape.hxx>
66 #include <TColgp_Array1OfPnt2d.hxx>
67 #include <Geom2d_Circle.hxx>
68 #include <Geom2d_Ellipse.hxx>
69 #include <Geom2d_Parabola.hxx>
70 #include <Geom2d_Hyperbola.hxx>
71 #include <Geom2d_OffsetCurve.hxx>
72 #include <Geom2dInt_GInter.hxx>
73 #include <IntRes2d_Domain.hxx>
74 #include <IntRes2d_IntersectionSegment.hxx>
75 #include <Geom2dAPI_ExtremaCurveCurve.hxx>
76 #include <Geom2dAPI_ProjectPointOnCurve.hxx>
77 #include <Geom2dAdaptor_Curve.hxx>
78 #include <Approx_Curve2d.hxx>
79 #include <Geom2dConvert.hxx>
81 #include <Geom_Line.hxx>
82 #include <Geom_Circle.hxx>
83 #include <Geom_Ellipse.hxx>
84 #include <Geom_Parabola.hxx>
85 #include <Geom_Hyperbola.hxx>
86 #include <Geom_OffsetCurve.hxx>
87 #include <GeomAPI_ExtremaCurveCurve.hxx>
88 #include <GeomAPI_ProjectPointOnCurve.hxx>
89 #include <GeomAdaptor_Curve.hxx>
90 #include <Approx_Curve3d.hxx>
91 #include <GeomConvert.hxx>
92 #include <TopoDS_Iterator.hxx>
93 #include <ShapeFix_ShapeTolerance.hxx>
94 #include <ShapeAnalysis_TransferParametersProj.hxx>
95 #include <Geom_Conic.hxx>
96 #include <Geom_BezierCurve.hxx>
97 #include <Geom2d_Conic.hxx>
98 #include <Geom2d_BezierCurve.hxx>
99 //=======================================================================
100 //function : FixGaps3d
102 //=======================================================================
104 Standard_Boolean ShapeFix_Wire::FixGaps3d ()
106 myStatusGaps3d = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
107 // if ( !IsReady() ) return Standard_False;
109 Standard_Integer i, start = ( myClosedMode ? 1 : 2 );
110 if (myFixGapsByRanges)
112 for ( i = start; i <= NbEdges(); i++ )
115 myStatusGaps3d |= myLastFixStatus;
118 for ( i = start; i <= NbEdges(); i++ )
120 FixGap3d ( i, Standard_True );
121 myStatusGaps3d |= myLastFixStatus;
124 return StatusGaps3d ( ShapeExtend_DONE );
127 //=======================================================================
128 //function : FixGaps2d
130 //=======================================================================
132 Standard_Boolean ShapeFix_Wire::FixGaps2d ()
134 myStatusGaps2d = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
135 // if ( !IsReady() ) return Standard_False;
137 Standard_Integer i, start = ( myClosedMode ? 1 : 2 );
138 if (myFixGapsByRanges)
140 for ( i = start; i <= NbEdges(); i++ )
143 myStatusGaps2d |= myLastFixStatus;
146 for ( i = start; i <= NbEdges(); i++ )
148 FixGap2d ( i, Standard_True );
149 myStatusGaps2d |= myLastFixStatus;
152 return StatusGaps2d ( ShapeExtend_DONE );
155 //=======================================================================
156 //function : FixGap3d
158 //=======================================================================
160 static Standard_Real AdjustOnPeriodic3d (const Handle(Geom_Curve)& c,
161 const Standard_Boolean takefirst,
162 const Standard_Real first,
163 const Standard_Real last,
164 const Standard_Real param)
166 // 15.11.2002 PTV OCC966
167 if (ShapeAnalysis_Curve::IsPeriodic(c))
169 Standard_Real T = c->Period();
170 Standard_Real shift = -IntegerPart(first/T)*T; if (first<0.) shift += T;
171 Standard_Real sfirst = first+shift, slast = last+shift;
172 if ( takefirst && (param>slast) && (param>sfirst)) return param-T-shift;
173 if (!takefirst && (param<slast) && (param<sfirst)) return param+T-shift;
178 Standard_Boolean ShapeFix_Wire::FixGap3d (const Standard_Integer num,
179 const Standard_Boolean convert)
181 myLastFixStatus = ShapeExtend::EncodeStatus( ShapeExtend_OK );
182 // if ( !IsReady() ) return Standard_False;
185 // First phase: analysis whether the problem (gap) exists
188 if (Context().IsNull()) SetContext(new ShapeBuild_ReShape);
190 Standard_Real preci = Precision();
192 Handle(ShapeExtend_WireData) sbwd = WireData();
193 Standard_Integer n2 = ( num >0 ? num : sbwd->NbEdges() );
194 Standard_Integer n1 = ( n2 >1 ? n2-1 : sbwd->NbEdges() );
196 TopoDS_Shape tmp1 = Context()->Apply(sbwd->Edge(n1)),
197 tmp2 = Context()->Apply(sbwd->Edge(n2));
198 TopoDS_Edge E1 = TopoDS::Edge(tmp1),
199 E2 = TopoDS::Edge(tmp2);
200 // TopoDS_Face face = myAnalyzer->Face(); // comment by enk
202 // Retrieve curves on edges
203 Standard_Real cfirst1, clast1, cfirst2, clast2;
204 Handle(Geom_Curve) C1, C2;
205 ShapeAnalysis_Edge SAE;
206 if (!SAE.Curve3d(E1,C1,cfirst1,clast1) ||
207 !SAE.Curve3d(E2,C2,cfirst2,clast2))
209 myLastFixStatus |= ShapeExtend::EncodeStatus( ShapeExtend_FAIL1 );
210 return Standard_False;
213 // Check gap in 3d space
214 gp_Pnt cpnt1 = C1->Value(clast1), cpnt2 = C2->Value(cfirst2);
215 Standard_Real gap = cpnt1.Distance(cpnt2);
216 if (!convert && gap<=preci) return Standard_False;
219 // Second phase: collecting data necessary for further analysis
222 Standard_Boolean reversed1 = (E1.Orientation()==TopAbs_REVERSED),
223 reversed2 = (E2.Orientation()==TopAbs_REVERSED);
225 TopoDS_Vertex V1 = SAE.LastVertex(E1), V2 = SAE.FirstVertex(E2);
226 gp_Pnt vpnt = (V1.IsSame(V2))? BRep_Tool::Pnt(V1) :
227 gp_Pnt((BRep_Tool::Pnt(V1).XYZ()+BRep_Tool::Pnt(V2).XYZ())*0.5);
229 Standard_Real first1, last1, first2, last2;
232 first1 = clast1; last1 = cfirst1;
236 first1 = cfirst1; last1 = clast1;
240 first2 = clast2; last2 = cfirst2;
244 first2 = cfirst2; last2 = clast2;
247 Handle(Geom_Curve) c1 = C1, c2 = C2;
249 // Extract basic curves from trimmed and offset
250 Standard_Boolean basic = Standard_False;
251 Standard_Boolean trimmed1 = Standard_False, offset1 = Standard_False;
252 gp_XYZ offval1(0.,0.,0.);
255 if (c1->IsKind(STANDARD_TYPE(Geom_TrimmedCurve)))
257 c1 = Handle(Geom_TrimmedCurve)::DownCast(c1)->BasisCurve();
258 trimmed1 = Standard_True;
260 else if (c1->IsKind(STANDARD_TYPE(Geom_OffsetCurve)))
262 Handle(Geom_OffsetCurve) oc = Handle(Geom_OffsetCurve)::DownCast(c1);
263 c1 = oc->BasisCurve();
264 offval1 += oc->Offset()*oc->Direction().XYZ();
265 offset1 = Standard_True;
267 else basic = Standard_True;
269 basic = Standard_False;
270 Standard_Boolean trimmed2 = Standard_False, offset2 = Standard_False;
271 gp_XYZ offval2(0.,0.,0.);
274 if (c2->IsKind(STANDARD_TYPE(Geom_TrimmedCurve)))
276 c2 = Handle(Geom_TrimmedCurve)::DownCast(c2)->BasisCurve();
277 trimmed2 = Standard_True;
279 else if (c2->IsKind(STANDARD_TYPE(Geom_OffsetCurve)))
281 Handle(Geom_OffsetCurve) oc = Handle(Geom_OffsetCurve)::DownCast(c2);
282 c2 = oc->BasisCurve();
283 offval2 += oc->Offset()*oc->Direction().XYZ();
284 offset2 = Standard_True;
286 else basic = Standard_True;
288 // Restore offset curves
289 if (offset1) c1 = new Geom_OffsetCurve(c1,offval1.Modulus(),gp_Dir(offval1));
290 if (offset2) c2 = new Geom_OffsetCurve(c2,offval2.Modulus(),gp_Dir(offval2));
292 Standard_Boolean done1 = Standard_False, done2 = Standard_False;
296 // Check that gap satisfies the precision - in this case no conversion produced
297 if (cpnt1.Distance(vpnt) < preci && cpnt2.Distance(vpnt) < preci)
298 return Standard_False;
300 Handle(Geom_BSplineCurve) bsp1, bsp2;
301 Handle(Geom_Curve) c;
302 Standard_Real first, last;
305 Standard_Integer nbcurv = (n1==n2? 1 : 2);
306 for (Standard_Integer j=1; j<=nbcurv; j++)
308 //Standard_Boolean trim = Standard_False; // skl
311 if (cpnt1.Distance(vpnt)<preci)
315 if (cpnt2.Distance(vpnt)<preci) continue;
319 c = c1; first = first1; last = last1; /*trim = trimmed1;*/ // skl
323 if (cpnt2.Distance(vpnt)<preci) continue;
324 c = c2; first = first2; last = last2; /*trim = trimmed2;*/ // skl
327 Handle(Geom_BSplineCurve) bsp;
329 // Convert curve to bspline
330 if (c->IsKind(STANDARD_TYPE(Geom_BSplineCurve)))
332 bsp = Handle(Geom_BSplineCurve)::DownCast(c->Copy());
333 // take segment if trim and range differ
334 Standard_Real fbsp = bsp->FirstParameter(), lbsp = bsp->LastParameter();
335 Standard_Boolean segment = Standard_False;
338 fbsp = first; segment = Standard_True;
342 lbsp = last; segment = Standard_True;
345 bsp = GeomConvert::SplitBSplineCurve(bsp,fbsp,lbsp,
346 ::Precision::Confusion());
348 else if (c->IsKind(STANDARD_TYPE(Geom_Conic)))
350 Approx_Curve3d Conv(new GeomAdaptor_Curve(c,first,last),
351 myAnalyzer->Precision(),GeomAbs_C1,9,1000);
352 if (Conv.IsDone() || Conv.HasResult()) bsp = Conv.Curve();
356 // Restore trim for pcurve
357 Handle(Geom_Curve) tc ;
361 // 15.11.2002 PTV OCC966
362 if(!ShapeAnalysis_Curve::IsPeriodic(c))
363 tc = new Geom_TrimmedCurve(c,Max(first,c->FirstParameter()),Min(last,c->LastParameter()));
364 else tc = new Geom_TrimmedCurve(c,first,last);
365 bsp = GeomConvert::CurveToBSplineCurve(tc);
367 catch (Standard_Failure const& anException) {
369 std::cout << "Warning: ShapeFix_Wire_1::FixGap3d: Exception in TrimmedCurve" <<first<<" " <<last<<std::endl;
370 anException.Print(std::cout); std::cout << std::endl;
376 if (j==1) bsp1 = bsp; else bsp2 = bsp;
379 // Take curves ends if could not convert
380 if (bsp1.IsNull()) vpnt = cpnt1;
381 else if (bsp2.IsNull()) vpnt = cpnt2;
385 if(bsp1->Degree() == 1) bsp1->IncreaseDegree(2); //gka
388 bsp1->SetPole(1,vpnt); bsp1->SetPole(bsp1->NbPoles(),vpnt);
392 if (reversed1) bsp1->SetPole(1,vpnt);
393 else bsp1->SetPole(bsp1->NbPoles(),vpnt);
395 first1 = bsp1->FirstParameter(); last1 = bsp1->LastParameter();
397 done1 = Standard_True;
401 if(bsp2->Degree() == 1) bsp2->IncreaseDegree(2); //gka
402 if (reversed2) bsp2->SetPole(bsp2->NbPoles(),vpnt);
403 else bsp2->SetPole(1,vpnt);
404 first2 = bsp2->FirstParameter(); last2 = bsp2->LastParameter();
406 done2 = Standard_True;
414 if (c1->IsKind(STANDARD_TYPE(Geom_Circle)) ||
415 c1->IsKind(STANDARD_TYPE(Geom_Ellipse)))
417 Standard_Real diff = M_PI - Abs(clast1-cfirst2)*0.5;
418 first1 -= diff; last1 += diff;
419 done1 = Standard_True;
425 // Determine domains for extremal points locating
426 Standard_Real domfirst1 = first1, domlast1 = last1;
427 if (c1->IsKind(STANDARD_TYPE(Geom_BSplineCurve)) ||
428 c1->IsKind(STANDARD_TYPE(Geom_BezierCurve)))
430 domfirst1 = c1->FirstParameter();
431 domlast1 = c1->LastParameter();
433 else if (c1->IsKind(STANDARD_TYPE(Geom_Line)) ||
434 c1->IsKind(STANDARD_TYPE(Geom_Parabola)) ||
435 c1->IsKind(STANDARD_TYPE(Geom_Hyperbola)))
437 Standard_Real diff = domlast1 - domfirst1;
438 if (reversed1) domfirst1 -= 10.*diff;
439 else domlast1 += 10.*diff;
441 else if (c1->IsKind(STANDARD_TYPE(Geom_Circle)) ||
442 c1->IsKind(STANDARD_TYPE(Geom_Ellipse)))
444 domfirst1 = 0.; domlast1 = 2*M_PI;
446 Standard_Real domfirst2 = first2, domlast2 = last2;
447 if (c2->IsKind(STANDARD_TYPE(Geom_BSplineCurve)) ||
448 c2->IsKind(STANDARD_TYPE(Geom_BezierCurve)))
450 domfirst2 = c2->FirstParameter();
451 domlast2 = c2->LastParameter();
453 else if (c2->IsKind(STANDARD_TYPE(Geom_Line)) ||
454 c2->IsKind(STANDARD_TYPE(Geom_Parabola)) ||
455 c2->IsKind(STANDARD_TYPE(Geom_Hyperbola)))
457 Standard_Real diff = domlast2 - domfirst2;
458 if (reversed2) domlast2 += 10.*diff;
459 else domfirst2 -= 10.*diff;
461 else if (c2->IsKind(STANDARD_TYPE(Geom_Circle)) ||
462 c2->IsKind(STANDARD_TYPE(Geom_Ellipse)))
464 domfirst2 = 0.; domlast2 = 2*M_PI;
467 Standard_Real ipar1 = clast1, ipar2 = cfirst2;
469 // Try to find projections of vertex point
470 GeomAPI_ProjectPointOnCurve Proj;
471 Standard_Real u1 = ipar1, u2 = ipar2;
472 Proj.Init(vpnt,c1,domfirst1,domlast1);
475 Standard_Integer index = 1;
476 Standard_Real dist, mindist=-1.;
477 for (Standard_Integer i=1; i<=Proj.NbPoints(); i++)
479 dist = vpnt.Distance(Proj.Point(i));
480 if (mindist>dist || mindist<0.)
482 index = i; mindist = dist;
484 u1 = Proj.Parameter(index);
487 Proj.Init(vpnt,c2,domfirst2,domlast2);
490 Standard_Integer index = 1;
491 Standard_Real dist, mindist=-1.;
492 for (Standard_Integer i=1; i<=Proj.NbPoints(); i++)
494 dist = vpnt.Distance(Proj.Point(i));
495 if (mindist>dist || mindist<0.)
497 index = i; mindist = dist;
499 u2 = Proj.Parameter(index);
502 // Adjust parameters on periodic curves
503 u1 = AdjustOnPeriodic3d(c1,reversed1,first1,last1,u1);
504 u2 = AdjustOnPeriodic3d(c2,!reversed2,first2,last2,u2);
505 // Check points to satisfy distance criterium
506 gp_Pnt p1 = c1->Value(u1), p2 = c2->Value(u2);
507 if (p1.Distance(p2)<=gap &&
508 Abs(cfirst1-u1) > ::Precision::PConfusion() &&
509 Abs(clast2-u2) > ::Precision::PConfusion() &&
510 (((u1>first1) && (u1<last1)) || ((u2>first2) && (u2<last2)) ||
511 (cpnt1.Distance(p1)<=gap) || (cpnt2.Distance(p2)<=gap)))
513 ipar1 = u1; ipar2 = u2;
514 done1 = done2 = Standard_True;
517 // Try to find closest points if nothing yet found
524 domfirst1 = ipar1; domlast1 = last1;
528 domfirst1 = first1; domlast1 = ipar1;
532 domfirst2 = first2; domlast2 = ipar2;
536 domfirst2 = ipar2; domlast2 = last2;
539 GeomAPI_ExtremaCurveCurve Extr(c1,c2,domfirst1,domlast1,domfirst2,domlast2);
540 if (Extr.NbExtrema())
545 // First find all intersections
547 Standard_Integer index1=0, index2=0;
548 Standard_Real uu1, uu2, pardist, pardist1=-1., pardist2=-1.;
549 for (Standard_Integer i=1; i<=Extr.NbExtrema(); i++)
551 Extr.Parameters(i,uu1,uu2);
552 // Adjust parameters on periodic curves
553 uu1 = AdjustOnPeriodic3d(c1,reversed1,first1,last1,uu1);
554 uu2 = AdjustOnPeriodic3d(c2,!reversed2,first2,last2,uu2);
555 pp1 = c1->Value(uu1); pp2 = c2->Value(uu2);
556 if (pp1.Distance(pp2) < ::Precision::Confusion())
558 // assume intersection
559 pardist = Abs(cfirst1-uu1);
560 if (pardist1>pardist || pardist1<0.)
562 index1 = i; pardist1 = pardist;
564 pardist = Abs(clast2-uu2);
565 if (pardist2>pardist || pardist2<0.)
567 index2 = i; pardist2 = pardist;
571 if (index1!=0 && index2!=0)
575 // take intersection closer to vertex point
576 Extr.Parameters(index1,uu1,uu2);
577 pp1 = gp_Pnt((c1->Value(uu1).XYZ()+c2->Value(uu2).XYZ())*0.5);
578 Extr.Parameters(index2,uu1,uu2);
579 pp2 = gp_Pnt((c1->Value(uu1).XYZ()+c2->Value(uu2).XYZ())*0.5);
580 if (pp2.Distance(vpnt) < pp1.Distance(vpnt)) index1 = index2;
582 Extr.Parameters(index1,uu1,uu2);
584 else Extr.LowerDistanceParameters(uu1,uu2);
585 // Adjust parameters on periodic curves
586 uu1 = AdjustOnPeriodic3d(c1,reversed1,first1,last1,uu1);
587 uu2 = AdjustOnPeriodic3d(c2,!reversed2,first2,last2,uu2);
588 // Check points to satisfy distance criterium
589 pp1 = c1->Value(uu1), pp2 = c2->Value(uu2);
590 if (pp1.Distance(pp2)<=gap &&
591 Abs(cfirst1-uu1) > ::Precision::PConfusion() &&
592 Abs(clast2-uu2) > ::Precision::PConfusion() &&
593 (((uu1>first1) && (uu1<last1)) || ((uu2>first2) && (uu2<last2)) ||
594 (cpnt1.Distance(pp1)<=gap) || (cpnt2.Distance(pp2)<=gap)))
596 ipar1 = uu1; ipar2 = uu2;
597 done1 = done2 = Standard_True;
600 catch ( Standard_Failure const& )
611 if (ipar1==clast1) done1 = Standard_False;
614 // Set up new bounds for curve
615 if (reversed1) first1 = ipar1; else last1 = ipar1;
616 // Set new trim for old curve
619 // Standard_Real ff1 = c1->FirstParameter();
620 // Standard_Real ll1 = c1->LastParameter();
621 c1 = new Geom_TrimmedCurve(c1,first1,last1);
627 if (ipar2==cfirst2) done2 = Standard_False;
630 // Set up new bounds for curve
631 if (reversed2) last2 = ipar2; else first2 = ipar2;
632 // Set new trim for old curve
635 // Standard_Real ff2 = c2->FirstParameter();
636 // Standard_Real ll2 = c2->LastParameter();
637 c2 = new Geom_TrimmedCurve(c2,first2,last2);
642 catch (Standard_Failure const& anException) {
644 std::cout << "Warning: ShapeFix_Wire_1::FixGap3d: Exception in TrimmedCurve :"<<std::endl;
645 anException.Print(std::cout); std::cout << std::endl;
657 ShapeFix_ShapeTolerance SFST;
660 TopoDS_Vertex nullV, newV1;
662 TopoDS_Shape emptyCopiedV2 = V2.EmptyCopied();
663 TopoDS_Vertex newV2 = TopoDS::Vertex(emptyCopiedV2);
664 SFST.SetTolerance(newV2,::Precision::Confusion());
665 Context()->Replace(V2,newV2);
669 TopoDS_Shape tmpV2 = newV2.Oriented(TopAbs_REVERSED);
670 newV1 = TopoDS::Vertex(tmpV2);
675 TopoDS_Shape emptyCopied = V1.EmptyCopied();
676 newV1 = TopoDS::Vertex(emptyCopied);
677 SFST.SetTolerance(newV1,::Precision::Confusion());
678 Context()->Replace(V1,newV1);
684 TopoDS_Edge newE1 = SBE.CopyReplaceVertices(E1,nullV,newV1);
686 TopoDS_Shape tmpE1 = newE1.Oriented(TopAbs_FORWARD);
687 B.UpdateEdge(TopoDS::Edge(tmpE1),c1,0.);
688 SBE.SetRange3d(TopoDS::Edge(tmpE1),first1,last1);
689 SFST.SetTolerance(newE1,::Precision::Confusion(),TopAbs_EDGE);
690 B.SameRange(newE1,Standard_False);
691 // B.SameParameter(newE1,Standard_False);
693 //To keep NM vertices belonging initial edges
694 TopoDS_Iterator aItv(E1,Standard_False);
695 for( ; aItv.More(); aItv.Next()) {
696 if(aItv.Value().Orientation() == TopAbs_INTERNAL ||
697 aItv.Value().Orientation() == TopAbs_EXTERNAL) {
698 TopoDS_Vertex aOldV = TopoDS::Vertex(aItv.Value());
699 TopoDS_Vertex anewV = ShapeAnalysis_TransferParametersProj::CopyNMVertex(aOldV,newE1,E1);
701 Context()->Replace(aOldV,anewV);
705 Context()->Replace(E1,newE1);
711 // Update second edge
712 TopoDS_Edge newE2 = SBE.CopyReplaceVertices(E2,newV2,nullV);
714 TopoDS_Shape tmpE2 = newE2.Oriented(TopAbs_FORWARD);
715 B.UpdateEdge(TopoDS::Edge(tmpE2),c2,0.);
716 SBE.SetRange3d(TopoDS::Edge(tmpE2),first2,last2);
717 SFST.SetTolerance(newE2,::Precision::Confusion(),TopAbs_EDGE);
718 B.SameRange(newE2,Standard_False);
719 // B.SameParameter(newE2,Standard_False);
721 //To keep NM vertices belonging initial edges
722 TopoDS_Iterator aItv(E2,Standard_False);
723 for( ; aItv.More(); aItv.Next()) {
724 if(aItv.Value().Orientation() == TopAbs_INTERNAL ||
725 aItv.Value().Orientation() == TopAbs_EXTERNAL) {
726 TopoDS_Vertex aOldV = TopoDS::Vertex(aItv.Value());
727 TopoDS_Vertex anewV = ShapeAnalysis_TransferParametersProj::CopyNMVertex(aOldV,newE2,E2);
729 Context()->Replace(aOldV,anewV);
732 Context()->Replace(E2,newE2);
736 myLastFixStatus |= ShapeExtend::EncodeStatus( ShapeExtend_DONE1 );
740 myLastFixStatus |= ShapeExtend::EncodeStatus( ShapeExtend_FAIL2 );
742 return (done1 || done2);
745 //=======================================================================
746 //function : FixGap2d
748 //=======================================================================
750 static Standard_Real AdjustOnPeriodic2d (const Handle(Geom2d_Curve)& pc,
751 const Standard_Boolean takefirst,
752 const Standard_Real first,
753 const Standard_Real last,
754 const Standard_Real param)
756 // 15.11.2002 PTV OCC966
757 if (ShapeAnalysis_Curve::IsPeriodic(pc))
759 Standard_Real T = pc->Period();
760 Standard_Real shift = -IntegerPart(first/T)*T; if (first<0.) shift += T;
761 Standard_Real sfirst = first+shift, slast = last+shift;
762 if ( takefirst && (param>slast) && (param>sfirst)) return param-T-shift;
763 if (!takefirst && (param<slast) && (param<sfirst)) return param+T-shift;
768 Standard_Boolean ShapeFix_Wire::FixGap2d (const Standard_Integer num,
769 const Standard_Boolean convert)
771 myLastFixStatus = ShapeExtend::EncodeStatus( ShapeExtend_OK );
772 if ( !IsReady() ) return Standard_False;
775 // First phase: analysis whether the problem (gap) exists
778 if (Context().IsNull()) SetContext(new ShapeBuild_ReShape);
780 Standard_Real preci = ::Precision::PConfusion();
781 //Standard_Real preci = Precision();
782 //GeomAdaptor_Surface& SA = Analyzer().Surface()->Adaptor()->ChangeSurface();
783 //preci = Max(SA.UResolution(preci), SA.VResolution(preci));
785 Handle(ShapeExtend_WireData) sbwd = WireData();
786 Standard_Integer n2 = ( num >0 ? num : sbwd->NbEdges() );
787 Standard_Integer n1 = ( n2 >1 ? n2-1 : sbwd->NbEdges() );
789 TopoDS_Shape tmp1 = Context()->Apply(sbwd->Edge(n1)),
790 tmp2 = Context()->Apply(sbwd->Edge(n2));
791 TopoDS_Edge E1 = TopoDS::Edge(tmp1),
792 E2 = TopoDS::Edge(tmp2);
793 TopoDS_Face face = myAnalyzer->Face();
795 // Retrieve pcurves on edges
796 Standard_Real cfirst1, clast1, cfirst2, clast2;
797 Handle(Geom2d_Curve) PC1, PC2;
798 ShapeAnalysis_Edge SAE;
799 if (!SAE.PCurve(E1,face,PC1,cfirst1,clast1) ||
800 !SAE.PCurve(E2,face,PC2,cfirst2,clast2) ||
801 sbwd->IsSeam(n1) || sbwd->IsSeam(n2))
803 myLastFixStatus |= ShapeExtend::EncodeStatus( ShapeExtend_FAIL1 );
804 return Standard_False;
807 // Check gap in 2d space
808 gp_Pnt2d cpnt1 = PC1->Value(clast1), cpnt2 = PC2->Value(cfirst2);
809 Standard_Real gap = cpnt1.Distance(cpnt2);
810 if (gap<=preci) return Standard_False;
813 // Second phase: collecting data necessary for further analysis
816 Standard_Boolean reversed1 = (E1.Orientation()==TopAbs_REVERSED),
817 reversed2 = (E2.Orientation()==TopAbs_REVERSED);
819 Standard_Real first1, last1, first2, last2;
822 first1 = clast1; last1 = cfirst1;
826 first1 = cfirst1; last1 = clast1;
830 first2 = clast2; last2 = cfirst2;
834 first2 = cfirst2; last2 = clast2;
837 Handle(Geom2d_Curve) pc1 = PC1, pc2 = PC2;
839 // Extract basic curves from trimmed and offset
840 Standard_Boolean basic = Standard_False;
841 Standard_Boolean trimmed1 = Standard_False, offset1 = Standard_False;
842 Standard_Real offval1 = 0.;
845 if (pc1->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve)))
847 pc1 = Handle(Geom2d_TrimmedCurve)::DownCast(pc1)->BasisCurve();
848 trimmed1 = Standard_True;
850 else if (pc1->IsKind(STANDARD_TYPE(Geom2d_OffsetCurve)))
852 Handle(Geom2d_OffsetCurve) oc = Handle(Geom2d_OffsetCurve)::DownCast(pc1);
853 pc1 = oc->BasisCurve();
854 offval1 += oc->Offset();
855 offset1 = Standard_True;
857 else basic = Standard_True;
859 basic = Standard_False;
860 Standard_Boolean trimmed2 = Standard_False, offset2 = Standard_False;
861 Standard_Real offval2 = 0.;
864 if (pc2->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve)))
866 pc2 = Handle(Geom2d_TrimmedCurve)::DownCast(pc2)->BasisCurve();
867 trimmed2 = Standard_True;
869 else if (pc2->IsKind(STANDARD_TYPE(Geom2d_OffsetCurve)))
871 Handle(Geom2d_OffsetCurve) oc = Handle(Geom2d_OffsetCurve)::DownCast(pc2);
872 pc2 = oc->BasisCurve();
873 offval2 += oc->Offset();
874 offset2 = Standard_True;
876 else basic = Standard_True;
878 // Restore offset curves
879 if (offset1) pc1 = new Geom2d_OffsetCurve(pc1,offval1);
880 if (offset2) pc2 = new Geom2d_OffsetCurve(pc2,offval2);
882 Standard_Boolean done1 = Standard_False, done2 = Standard_False;
884 // Determine same edge case
888 Handle(Geom2d_BSplineCurve) bsp1, bsp2;
889 Handle(Geom2d_Curve) pc;
890 Standard_Real first, last;
892 // iterate on pcurves
893 Standard_Integer nbcurv = (n1==n2? 1 : 2);
894 for (Standard_Integer j=1; j<=nbcurv; j++)
896 //Standard_Integer trim = Standard_False; // skl
897 Handle(Geom2d_BSplineCurve) bsp;
901 pc = pc1; first = first1; last = last1; /*trim = trimmed1;*/
905 pc = pc2; first = first2; last = last2; /*trim = trimmed2;*/
908 // Convert pcurve to bspline
909 if (pc->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve)))
911 bsp = Handle(Geom2d_BSplineCurve)::DownCast(pc->Copy());
912 // take segment if trim and range differ
913 Standard_Real fbsp = bsp->FirstParameter(), lbsp = bsp->LastParameter();
914 Standard_Boolean segment = Standard_False;
917 fbsp = first; segment = Standard_True;
921 lbsp = last; segment = Standard_True;
924 bsp = Geom2dConvert::SplitBSplineCurve(bsp,fbsp,lbsp,
925 ::Precision::PConfusion());
927 else if (pc->IsKind(STANDARD_TYPE(Geom2d_Conic)))
929 GeomAdaptor_Surface& AS = *myAnalyzer->Surface()->Adaptor3d();
930 Standard_Real tolu = AS.UResolution(myAnalyzer->Precision()),
931 tolv = AS.VResolution(myAnalyzer->Precision());
932 Approx_Curve2d Conv(new Geom2dAdaptor_Curve(pc,first,last),
933 first,last,tolu,tolv,GeomAbs_C1,9,1000);
934 if (Conv.IsDone() || Conv.HasResult()) bsp = Conv.Curve();
938 // Restore trim for pcurve
942 Handle(Geom2d_Curve) c;
943 // 15.11.2002 PTV OCC966
944 if(!ShapeAnalysis_Curve::IsPeriodic(pc))
945 c = new Geom2d_TrimmedCurve(pc,Max(first,pc->FirstParameter()),Min(last,pc->LastParameter()));
947 c = new Geom2d_TrimmedCurve(pc,first,last);
948 bsp = Geom2dConvert::CurveToBSplineCurve(c);
950 catch (Standard_Failure const& anException) {
952 std::cout << "Warning: ShapeFix_Wire_1::FixGap2d: Exception in TrimmedCurve2d" <<first<<" " <<last<<std::endl;
953 anException.Print(std::cout); std::cout << std::endl;
959 if (j==1) bsp1 = bsp; else bsp2 = bsp;
962 // Take curves ends if could not convert
963 gp_Pnt2d mpnt((cpnt1.XY()+cpnt2.XY())*0.5);
964 if (bsp1.IsNull()) mpnt = cpnt1;
965 else if (bsp2.IsNull()) mpnt = cpnt2;
969 if(bsp1->Degree() == 1) bsp1->IncreaseDegree(2);
972 bsp1->SetPole(1,mpnt); bsp1->SetPole(bsp1->NbPoles(),mpnt);
976 if (reversed1) bsp1->SetPole(1,mpnt);
977 else bsp1->SetPole(bsp1->NbPoles(),mpnt);
979 first1 = bsp1->FirstParameter(); last1 = bsp1->LastParameter();
981 done1 = Standard_True;
985 if(bsp2->Degree() == 1) bsp2->IncreaseDegree(2);
986 if (reversed2) bsp2->SetPole(bsp2->NbPoles(),mpnt);
987 else bsp2->SetPole(1,mpnt);
988 first2 = bsp2->FirstParameter(); last2 = bsp2->LastParameter();
990 done2 = Standard_True;
998 if (pc1->IsKind(STANDARD_TYPE(Geom2d_Circle)) ||
999 pc1->IsKind(STANDARD_TYPE(Geom2d_Ellipse)))
1001 Standard_Real diff = M_PI - Abs(clast1-cfirst2)*0.5;
1002 first1 -= diff; last1 += diff;
1003 done1 = Standard_True;
1009 // Determine domains for extremal points locating
1010 Standard_Real domfirst1 = first1, domlast1 = last1;
1011 if (pc1->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve)) ||
1012 pc1->IsKind(STANDARD_TYPE(Geom2d_BezierCurve)))
1014 domfirst1 = pc1->FirstParameter();
1015 domlast1 = pc1->LastParameter();
1017 else if (pc1->IsKind(STANDARD_TYPE(Geom2d_Line)) ||
1018 pc1->IsKind(STANDARD_TYPE(Geom2d_Parabola)) ||
1019 pc1->IsKind(STANDARD_TYPE(Geom2d_Hyperbola)))
1021 Standard_Real diff = domlast1 - domfirst1;
1022 if (reversed1) domfirst1 -= 10.*diff;
1023 else domlast1 += 10.*diff;
1025 else if (pc1->IsKind(STANDARD_TYPE(Geom2d_Circle)) ||
1026 pc1->IsKind(STANDARD_TYPE(Geom2d_Ellipse)))
1028 domfirst1 = 0.; domlast1 = 2*M_PI;
1030 Standard_Real domfirst2 = first2, domlast2 = last2;
1031 if (pc2->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve)) ||
1032 pc2->IsKind(STANDARD_TYPE(Geom2d_BezierCurve)))
1034 domfirst2 = pc2->FirstParameter();
1035 domlast2 = pc2->LastParameter();
1037 else if (pc2->IsKind(STANDARD_TYPE(Geom2d_Line)) ||
1038 pc2->IsKind(STANDARD_TYPE(Geom2d_Parabola)) ||
1039 pc2->IsKind(STANDARD_TYPE(Geom2d_Hyperbola)))
1041 Standard_Real diff = domlast2 - domfirst2;
1042 if (reversed2) domlast2 += 10.*diff;
1043 else domfirst2 -= 10.*diff;
1045 else if (pc2->IsKind(STANDARD_TYPE(Geom2d_Circle)) ||
1046 pc2->IsKind(STANDARD_TYPE(Geom2d_Ellipse)))
1048 domfirst2 = 0.; domlast2 = 2*M_PI;
1051 Standard_Real ipar1 = clast1, ipar2 = cfirst2;
1053 Geom2dInt_GInter Inter;
1054 Standard_Real tolint = ::Precision::PConfusion();
1056 Geom2dAdaptor_Curve AC1(pc1), AC2(pc2);
1058 // Try to find intersection points
1059 IntRes2d_Domain dom1(pc1->Value(domfirst1),domfirst1,tolint,
1060 pc1->Value(domlast1),domlast1,tolint);
1061 IntRes2d_Domain dom2(pc2->Value(domfirst2),domfirst2,tolint,
1062 pc2->Value(domlast2),domlast2,tolint);
1063 Inter.Perform( AC1, dom1, AC2, dom2, tolint, tolint );
1066 if (Inter.NbPoints() || Inter.NbSegments())
1068 Standard_Integer i, index1 = 0, index2 = 0;
1069 Standard_Real pardist, pardist1=-1., pardist2=-1.;
1070 // iterate on intersection points
1071 IntRes2d_IntersectionPoint IP;
1072 for ( i=1; i<=Inter.NbPoints(); i++ )
1074 IP = Inter.Point(i);
1075 // Adjust parameters on periodic curves
1076 Standard_Real u1 = AdjustOnPeriodic2d(pc1,reversed1,first1,last1,
1078 Standard_Real u2 = AdjustOnPeriodic2d(pc2,!reversed2,first2,last2,
1079 IP.ParamOnSecond());
1080 pardist = Abs(cfirst1-u1);
1081 if (pardist1>pardist || pardist1<0.)
1083 index1 = i; pardist1 = pardist;
1085 pardist = Abs(clast2-u2);
1086 if (pardist2>pardist || pardist2<0.)
1088 index2 = i; pardist2 = pardist;
1091 Standard_Integer flag1 = 0, flag2 = 0;
1092 // iterate on intersection segments
1093 IntRes2d_IntersectionSegment IS;
1094 for ( i=1; i<=Inter.NbSegments(); i++ )
1096 IS = Inter.Segment(i);
1097 for (Standard_Integer j=1; j<=2; j++)
1099 if ((j==1 && IS.HasFirstPoint()) ||
1100 (j==2 && IS.HasLastPoint()))
1102 if (j==1) IP = IS.FirstPoint();
1103 else IP = IS.LastPoint();
1104 // Adjust parameters on periodic curves
1105 Standard_Real u1 = AdjustOnPeriodic2d(pc1,reversed1,first1,last1,
1107 Standard_Real u2 = AdjustOnPeriodic2d(pc2,!reversed2,first2,last2,
1108 IP.ParamOnSecond());
1109 pardist = Abs(cfirst1-u1);
1110 if (pardist1>pardist || pardist1<0.)
1112 flag1 = j; index1 = i; pardist1 = pardist;
1114 pardist = Abs(clast2-u2);
1115 if (pardist2>pardist || pardist2<0.)
1117 flag2 = j; index2 = i; pardist2 = pardist;
1122 if (index1!=index2 || flag1!=flag2)
1124 // take intersection closer to mean point
1126 if (flag1==0) pt1 = Inter.Point(index1).Value();
1129 IS = Inter.Segment(index1);
1130 if (flag1==1) pt1 = IS.FirstPoint().Value();
1131 else pt1 = IS.LastPoint().Value();
1133 if (flag2==0) pt2 = Inter.Point(index2).Value();
1136 IS = Inter.Segment(index2);
1137 if (flag2==1) pt2 = IS.FirstPoint().Value();
1138 else pt2 = IS.LastPoint().Value();
1140 gp_Pnt2d mpnt((cpnt1.XY()+cpnt2.XY())*0.5);
1141 if (pt2.Distance(mpnt) < pt1.Distance(mpnt))
1143 index1 = index2; flag1 = flag2;
1146 if (flag1==0) IP = Inter.Point(index1);
1149 IS = Inter.Segment(index1);
1150 if (flag1==1) IP = IS.FirstPoint();
1151 else IP = IS.LastPoint();
1153 // Adjust parameters on periodic curves
1154 Standard_Real u1 = AdjustOnPeriodic2d(pc1,reversed1,first1,last1,
1156 Standard_Real u2 = AdjustOnPeriodic2d(pc2,!reversed2,first2,last2,
1157 IP.ParamOnSecond());
1158 // Check points to satisfy distance criterium
1159 gp_Pnt2d p1 = pc1->Value(u1), p2 = pc2->Value(u2);
1160 if (p1.Distance(p2)<=gap &&
1161 Abs(cfirst1-u1) > ::Precision::PConfusion() &&
1162 Abs(clast2 -u2) > ::Precision::PConfusion() &&
1163 (((u1>first1) && (u1<last1)) || ((u2>first2) && (u2<last2)) ||
1164 (cpnt1.Distance(p1)<=gap) || (cpnt2.Distance(p2)<=gap)))
1166 ipar1 = u1; ipar2 = u2;
1167 done1 = done2 = Standard_True;
1172 // Try to find closest points if nothing yet found
1175 Geom2dAPI_ExtremaCurveCurve Extr(pc1,pc2,domfirst1,domlast1,domfirst2,domlast2);
1176 if (Extr.NbExtrema())
1178 Standard_Real u1, u2;
1179 Extr.LowerDistanceParameters(u1,u2);
1180 // Adjust parameters on periodic curves
1181 u1 = AdjustOnPeriodic2d(pc1,reversed1,first1,last1,u1);
1182 u2 = AdjustOnPeriodic2d(pc2,!reversed2,first2,last2,u2);
1183 // Check points to satisfy distance criterium
1184 gp_Pnt2d p1 = pc1->Value(u1), p2 = pc2->Value(u2);
1185 if (p1.Distance(p2)<=gap &&
1186 Abs(cfirst1-u1) > ::Precision::PConfusion() &&
1187 Abs(clast2 -u2) > ::Precision::PConfusion() &&
1188 (((u1>first1) && (u1<last1)) || ((u2>first2) && (u2<last2)) ||
1189 (cpnt1.Distance(p1)<=gap) || (cpnt2.Distance(p2)<=gap)))
1191 ipar1 = u1; ipar2 = u2;
1192 done1 = done2 = Standard_True;
1197 // Try to find projections if nothing yet found
1200 Geom2dAPI_ProjectPointOnCurve Proj;
1201 gp_Pnt2d ipnt1 = cpnt1, ipnt2 = cpnt2;
1202 Standard_Real u1 = ipar1, u2 = ipar2;
1203 Proj.Init(cpnt2,pc1,domfirst1,domlast1);
1204 if (Proj.NbPoints())
1206 Standard_Integer index = 1;
1207 Standard_Real dist, mindist=-1.;
1208 for (Standard_Integer i=1; i<=Proj.NbPoints(); i++)
1210 dist = cpnt2.Distance(Proj.Point(i));
1211 if (mindist>dist || mindist<0.)
1213 index = i; mindist = dist;
1215 ipnt1 = Proj.Point(index);
1216 u1 = Proj.Parameter(index);
1219 Proj.Init(cpnt1,pc2,domfirst2,domlast2);
1220 if (Proj.NbPoints())
1222 Standard_Integer index = 1;
1223 Standard_Real dist, mindist=-1.;
1224 for (Standard_Integer i=1; i<=Proj.NbPoints(); i++)
1226 dist = cpnt1.Distance(Proj.Point(i));
1227 if (mindist>dist || mindist<0.)
1229 index = i; mindist = dist;
1231 ipnt2 = Proj.Point(index);
1232 u2 = Proj.Parameter(index);
1235 // Adjust parameters on periodic curves
1236 u1 = AdjustOnPeriodic2d(pc1,reversed1,first1,last1,u1);
1237 u2 = AdjustOnPeriodic2d(pc2,!reversed2,first2,last2,u2);
1238 // Process special case of projection
1239 if ((((reversed1 && u1>clast1) || (!reversed1 && u1<clast1)) &&
1240 ((reversed2 && u2<cfirst2) || (!reversed2 && u2>cfirst2))) ||
1241 (((reversed1 && u1<clast1) || (!reversed1 && u1>clast1)) &&
1242 ((reversed2 && u2>cfirst2) || (!reversed2 && u2<cfirst2))))
1244 // both projections lie inside/outside initial domains
1245 // project mean point
1246 gp_Pnt2d mpnt((cpnt1.XY()+cpnt2.XY())*0.5);
1247 u1 = ipar1; u2 = ipar2;
1248 Proj.Init(mpnt,pc1,domfirst1,domlast1);
1249 if (Proj.NbPoints())
1251 Standard_Integer index = 1;
1252 Standard_Real dist, mindist=-1.;
1253 for (Standard_Integer i=1; i<=Proj.NbPoints(); i++)
1255 dist = mpnt.Distance(Proj.Point(i));
1256 if (mindist>dist || mindist<0.)
1258 index = i; mindist = dist;
1260 ipnt1 = Proj.Point(index);
1261 u1 = Proj.Parameter(index);
1264 Proj.Init(mpnt,pc2,domfirst2,domlast2);
1265 if (Proj.NbPoints())
1267 Standard_Integer index = 1;
1268 Standard_Real dist, mindist=-1.;
1269 for (Standard_Integer i=1; i<=Proj.NbPoints(); i++)
1271 dist = mpnt.Distance(Proj.Point(i));
1272 if (mindist>dist || mindist<0.)
1274 index = i; mindist = dist;
1276 ipnt2 = Proj.Point(index);
1277 u2 = Proj.Parameter(index);
1283 if (cpnt1.Distance(ipnt2)<cpnt2.Distance(ipnt1)) u1 = ipar1;
1286 // Adjust parameters on periodic curves
1287 u1 = AdjustOnPeriodic2d(pc1,reversed1,first1,last1,u1);
1288 u2 = AdjustOnPeriodic2d(pc2,!reversed2,first2,last2,u2);
1289 // Check points to satisfy distance criterium
1290 gp_Pnt2d p1 = pc1->Value(u1), p2 = pc2->Value(u2);
1291 if (p1.Distance(p2)<=gap &&
1292 Abs(cfirst1-u1) > ::Precision::PConfusion() &&
1293 Abs(clast2 -u2) > ::Precision::PConfusion() &&
1294 (((u1>first1) && (u1<last1)) || ((u2>first2) && (u2<last2)) ||
1295 (cpnt1.Distance(p1)<=gap) || (cpnt2.Distance(p2)<=gap)))
1297 ipar1 = u1; ipar2 = u2;
1298 done1 = done2 = Standard_True;
1305 if (ipar1<first1 || ipar1>last1 || ipar2<first2 || ipar2>last2)
1308 // Check whether new points lie inside the surface bounds
1309 Standard_Real umin, umax, vmin, vmax;
1310 myAnalyzer->Surface()->Surface()->Bounds(umin,umax,vmin,vmax);
1311 if (::Precision::IsInfinite(umin) || ::Precision::IsInfinite(umax) ||
1312 ::Precision::IsInfinite(vmin) || ::Precision::IsInfinite(vmax))
1314 Standard_Real fumin, fumax, fvmin, fvmax;
1315 BRepTools::UVBounds(face,fumin,fumax,fvmin,fvmax);
1316 if (::Precision::IsInfinite(umin)) umin = fumin-preci;
1317 if (::Precision::IsInfinite(umax)) umax = fumax+preci;
1318 if (::Precision::IsInfinite(vmin)) vmin = fvmin-preci;
1319 if (::Precision::IsInfinite(vmax)) vmax = fvmax+preci;
1322 gp_Pnt2d ipnt, P1, P2;
1324 Standard_Boolean out;
1325 // iterate on curves
1326 for (Standard_Integer j=1; j<=2; j++)
1331 if (ipar1>=first1 && ipar1<=last1) continue;
1332 ipnt = pc1->Value(ipar1);
1336 if (ipar2>=first2 && ipar2<=last2) continue;
1337 ipnt = pc2->Value(ipar2);
1340 // iterate on bounding lines
1341 for (Standard_Integer k=1; k<=2; k++)
1344 u = ipnt.X(); v = ipnt.Y();
1346 out = Standard_True;
1351 P1 = gp_Pnt2d(umin,vmin); P2 = gp_Pnt2d(umin,vmax);
1355 P1 = gp_Pnt2d(umax,vmin); P2 = gp_Pnt2d(umax,vmax);
1357 else out = Standard_False;
1363 P1 = gp_Pnt2d(umin,vmin); P2 = gp_Pnt2d(umax,vmin);
1367 P1 = gp_Pnt2d(umin,vmax); P2 = gp_Pnt2d(umax,vmax);
1369 else out = Standard_False;
1374 // Intersect pcurve with bounding line
1375 Handle(Geom2d_Line) lin = new Geom2d_Line(P1,gp_Dir2d(gp_Vec2d(P1,P2)));
1376 Geom2dAdaptor_Curve ACL(lin);
1377 IntRes2d_Domain dlin(P1,0.,tolint,P2,P1.Distance(P2),tolint);
1379 Handle(Geom2d_Curve) pc;
1380 Standard_Real fpar, lpar;
1385 fpar = cfirst1, lpar = ipar1;
1389 fpar = ipar1, lpar = cfirst1;
1397 fpar = clast2, lpar = ipar2;
1401 fpar = ipar2, lpar = clast2;
1405 Geom2dAdaptor_Curve ACC(pc);
1406 IntRes2d_Domain domc(pc->Value(fpar),fpar,tolint,
1407 pc->Value(lpar),lpar,tolint);
1409 // Intersect line with the pcurve
1410 Inter.Perform( ACL, dlin, ACC, domc, tolint, tolint );
1413 if (Inter.NbPoints() || Inter.NbSegments())
1415 Standard_Integer i, index = 1;
1416 Standard_Real uu, dist, mindist=-1.;
1417 // iterate on intersection points
1418 for ( i=1; i<=Inter.NbPoints(); i++ )
1420 // Adjust parameters on periodic curve
1421 uu = AdjustOnPeriodic2d(pc,(j==1? reversed1 : !reversed2),
1422 fpar,lpar,Inter.Point(i).ParamOnSecond());
1423 dist = Abs((j==1? cfirst1 : clast2)-uu);
1424 if (mindist>dist || mindist<0.)
1426 index = i; mindist = dist;
1429 // iterate on intersection segments
1430 Standard_Integer flag = 0;
1431 IntRes2d_IntersectionPoint IP;
1432 IntRes2d_IntersectionSegment IS;
1433 for ( i=1; i<=Inter.NbSegments(); i++ )
1435 IS = Inter.Segment(i);
1436 for (Standard_Integer jj=1; jj<=2; jj++)
1438 if ((jj==1 && IS.HasFirstPoint()) ||
1439 (jj==2 && IS.HasLastPoint()))
1441 if (jj==1) IP = IS.FirstPoint();
1442 else IP = IS.LastPoint();
1443 // Adjust parameters on periodic curve
1444 uu = AdjustOnPeriodic2d(pc,(jj==1? reversed1 : !reversed2),
1445 fpar,lpar,IP.ParamOnSecond());
1446 dist = Abs((jj==1? cfirst1 : clast2)-uu);
1447 if (mindist>dist || mindist<0.)
1449 flag = jj; index = i; mindist = dist;
1454 if (flag==0) IP = Inter.Point(index);
1457 IS = Inter.Segment(index);
1458 if (flag==1) IP = IS.FirstPoint();
1459 else IP = IS.LastPoint();
1461 // Adjust parameters on periodic curve
1462 uu = AdjustOnPeriodic2d(pc,(j==1? reversed1 : !reversed2),
1463 fpar,lpar,IP.ParamOnSecond());
1464 if (j==1 && Abs(cfirst1-uu) > ::Precision::PConfusion())
1466 ipar1 = uu; ipnt = IP.Value();
1468 if (j==2 && Abs(clast2-uu) > ::Precision::PConfusion())
1470 ipar2 = uu; ipnt = IP.Value();
1477 // Adjust if intersection lies inside old bounds
1482 if (ipar1>first1) ipar1 = first1;
1486 if (ipar1<last1) ipar1 = last1;
1493 if (ipar2<last2) ipar2 = last2;
1497 if (ipar2>first2) ipar2 = first2;
1508 if (ipar1==clast1) done1 = Standard_False;
1511 // Set up new bounds for pcurve
1512 if (reversed1) first1 = ipar1; else last1 = ipar1;
1513 // Set new trim for old pcurve
1514 if (trimmed1) pc1 = new Geom2d_TrimmedCurve(pc1,first1,last1);
1519 if (ipar2==cfirst2) done2 = Standard_False;
1522 // Set up new bounds for pcurve
1523 if (reversed2) last2 = ipar2; else first2 = ipar2;
1524 // Set new trim for old pcurve
1525 if (trimmed2) pc2 = new Geom2d_TrimmedCurve(pc2,first2,last2);
1529 catch (Standard_Failure const& anException) {
1531 std::cout << "Warning: ShapeFix_Wire_1::FixGap2d: Exception in TrimmedCurve2d :"<<std::endl;
1532 anException.Print(std::cout); std::cout << std::endl;
1543 ShapeBuild_Edge SBE;
1544 ShapeFix_ShapeTolerance SFST;
1547 TopoDS_Vertex V1 = SAE.LastVertex(E1), V2 = SAE.FirstVertex(E2);
1548 TopoDS_Vertex nullV, newV1;
1550 TopoDS_Shape emptyCopiedV2 = V2.EmptyCopied();
1551 TopoDS_Vertex newV2 = TopoDS::Vertex(emptyCopiedV2);
1552 SFST.SetTolerance(newV2,::Precision::Confusion());
1553 Context()->Replace(V2,newV2);
1557 TopoDS_Shape tmpVertexRev = newV2.Oriented(TopAbs_REVERSED);
1558 newV1 = TopoDS::Vertex(tmpVertexRev);
1563 TopoDS_Shape emptyCopiedV1 = V1.EmptyCopied();
1564 newV1 = TopoDS::Vertex(emptyCopiedV1);
1565 SFST.SetTolerance(newV1,::Precision::Confusion());
1566 Context()->Replace(V1,newV1);
1571 // Update first edge
1572 TopoDS_Edge newE1 = SBE.CopyReplaceVertices(E1,nullV,newV1);
1574 TopoDS_Shape tmpE1 = newE1.Oriented(TopAbs_FORWARD);
1575 B.UpdateEdge(TopoDS::Edge(tmpE1),pc1,face,0.);
1576 B.Range(TopoDS::Edge(tmpE1),face,first1,last1);
1577 SFST.SetTolerance(newE1,::Precision::Confusion(),TopAbs_EDGE);
1578 B.SameRange(newE1,Standard_False);
1579 // B.SameParameter(newE1,Standard_False);
1581 //To keep NM vertices belonging initial edges
1582 TopoDS_Iterator aItv(E1,Standard_False);
1583 for( ; aItv.More(); aItv.Next()) {
1584 if(aItv.Value().Orientation() == TopAbs_INTERNAL ||
1585 aItv.Value().Orientation() == TopAbs_EXTERNAL) {
1586 TopoDS_Vertex aOldV = TopoDS::Vertex(aItv.Value());
1587 TopoDS_Vertex anewV = ShapeAnalysis_TransferParametersProj::CopyNMVertex(aOldV,newE1,E1);
1589 Context()->Replace(aOldV,anewV);
1593 Context()->Replace(E1,newE1);
1594 sbwd->Set(newE1,n1);
1599 // Update second edge
1600 TopoDS_Edge newE2 = SBE.CopyReplaceVertices(E2,newV2,nullV);
1602 TopoDS_Shape tmpE2 = newE2.Oriented(TopAbs_FORWARD);
1603 B.UpdateEdge(TopoDS::Edge(tmpE2),pc2,face,0.);
1604 B.Range(TopoDS::Edge(tmpE2),face,first2,last2);
1605 SFST.SetTolerance(newE2,::Precision::Confusion(),TopAbs_EDGE);
1606 B.SameRange(newE2,Standard_False);
1607 // B.SameParameter(newE2,Standard_False);
1608 //To keep NM vertices belonging initial edges
1609 TopoDS_Iterator aItv(E2,Standard_False);
1610 for( ; aItv.More(); aItv.Next()) {
1611 if(aItv.Value().Orientation() == TopAbs_INTERNAL ||
1612 aItv.Value().Orientation() == TopAbs_EXTERNAL) {
1613 TopoDS_Vertex aOldV = TopoDS::Vertex(aItv.Value());
1614 TopoDS_Vertex anewV = ShapeAnalysis_TransferParametersProj::CopyNMVertex(aOldV,newE2,E2);
1616 Context()->Replace(aOldV,anewV);
1619 Context()->Replace(E2,newE2);
1620 sbwd->Set(newE2,n2);
1623 myLastFixStatus |= ShapeExtend::EncodeStatus( ShapeExtend_DONE1 );
1627 myLastFixStatus |= ShapeExtend::EncodeStatus( ShapeExtend_FAIL2 );
1629 return (done1 || done2);