OCC22576 ShapeFix_Edge::SameParameter() now retains original 3D interval
[occt.git] / src / ShapeFix / ShapeFix_Edge.cxx
1 // abv 30 Dec 98: code optimizations
2 //:o1 abv 16.02.99: updating vertices tolerance when edge is updated
3 //    rln 03.03.99 S4135: removed unnecessary check for Geom_SphericalSurface (as not V-closed)
4 //:q8 abv 23.03.99: bm4_al_eye.stp #53710: avoid shifting pcurves for pseudo-seam
5 //#78 rln 12.03.99 S4135: checking spatial closure with prec
6 //#81 rln 15.03.99 S4135: for not SP edge chose the best result (either BRepLib or deviation only)
7 //#82 rln 16.03.99 S4135: avoiding setting input precision into the edge in FixAddPCurve
8 //:r4 abv 02.04.99 improving method FixSameParameter()
9 //:s5 abv 22.04.99 Adding debug printouts in catch {} blocks
10 //    abv 05.05.99 S4137: method CopyPCurves moved to ShapeBuild_Edge
11 #include <ShapeFix_Edge.ixx>
12
13 #include <Standard_ErrorHandler.hxx>
14 #include <Standard_Failure.hxx>
15
16 #include <BRep_Builder.hxx>
17 #include <BRep_GCurve.hxx>
18 #include <BRep_TEdge.hxx>
19 #include <BRep_Tool.hxx>
20 #include <BRep_ListIteratorOfListOfCurveRepresentation.hxx>
21 #include <BRep_ListOfCurveRepresentation.hxx>
22 #include <BRepLib.hxx>
23
24 #include <Geom2d_Curve.hxx>
25 #include <Geom2d_Line.hxx>
26 #include <Geom2d_BSplineCurve.hxx>
27 #include <Geom2d_TrimmedCurve.hxx>
28 #include <Geom2d_BezierCurve.hxx>
29
30 #include <Geom_Curve.hxx>
31 #include <GeomLib.hxx>
32
33 #include <Precision.hxx>
34 #include <TopExp.hxx>
35 #include <TopoDS_Vertex.hxx>
36 #include <TopoDS.hxx>
37
38 #include <ShapeAnalysis_Edge.hxx>
39 #include <ShapeExtend.hxx>
40 #include <ShapeBuild_Edge.hxx>
41 #include <ShapeFix_ShapeTolerance.hxx>
42 #include <Geom2d_OffsetCurve.hxx>
43 #include <ShapeAnalysis_Curve.hxx>
44
45
46 //=======================================================================
47 //function : ShapeFix_Edge
48 //purpose  : 
49 //=======================================================================
50
51 ShapeFix_Edge::ShapeFix_Edge()
52 {
53   myStatus = ShapeExtend::EncodeStatus (ShapeExtend_OK);
54   myProjector = new ShapeConstruct_ProjectCurveOnSurface;
55 }
56
57 //=======================================================================
58 //function : Projector
59 //purpose  : 
60 //=======================================================================
61
62 Handle(ShapeConstruct_ProjectCurveOnSurface) ShapeFix_Edge::Projector()
63 {
64   return myProjector;
65 }
66
67
68 //=======================================================================
69 //function : FixRemovePCurve
70 //purpose  : 
71 //=======================================================================
72
73 Standard_Boolean ShapeFix_Edge::FixRemovePCurve (const TopoDS_Edge& edge,
74                                                  const TopoDS_Face& face) 
75 {
76   TopLoc_Location L;
77   const Handle(Geom_Surface)& S = BRep_Tool::Surface(face, L);
78   return FixRemovePCurve (edge, S, L);
79 }
80
81 //=======================================================================
82 //function : FixRemovePCurve
83 //purpose  : 
84 //=======================================================================
85
86 Standard_Boolean ShapeFix_Edge::FixRemovePCurve (const TopoDS_Edge& edge,
87                                                  const Handle(Geom_Surface)& surface,
88                                                  const TopLoc_Location& location) 
89 {
90   myStatus = ShapeExtend::EncodeStatus (ShapeExtend_OK);
91   ShapeAnalysis_Edge EA;
92   Standard_Boolean result = EA.CheckVerticesWithPCurve (edge, surface, location);
93   if (result) ShapeBuild_Edge().RemovePCurve (edge, surface, location);
94   return result;
95 }
96
97 //=======================================================================
98 //function : FixRemoveCurve3d
99 //purpose  : 
100 //=======================================================================
101
102 Standard_Boolean ShapeFix_Edge::FixRemoveCurve3d (const TopoDS_Edge& edge) 
103 {
104   myStatus = ShapeExtend::EncodeStatus (ShapeExtend_OK);
105   ShapeAnalysis_Edge EA;
106   Standard_Boolean result = EA.CheckVerticesWithCurve3d (edge);
107   if (result) ShapeBuild_Edge().RemoveCurve3d (edge);
108   return result;
109 }
110
111 //=======================================================================
112 //function : FixAddPCurve
113 //purpose  : 
114 //=======================================================================
115
116 Standard_Boolean ShapeFix_Edge::FixAddPCurve (const TopoDS_Edge& edge,
117                                               const TopoDS_Face& face,
118                                               const Standard_Boolean isSeam,
119                                               const Standard_Real prec) 
120 {
121   TopLoc_Location L;
122   const Handle(Geom_Surface)& S = BRep_Tool::Surface(face, L);
123   return FixAddPCurve (edge, S, L, isSeam, prec);
124 }
125
126 //=======================================================================
127 //function : FixAddPCurve
128 //purpose  : 
129 //=======================================================================
130
131 Standard_Boolean ShapeFix_Edge::FixAddPCurve (const TopoDS_Edge& edge,
132                                               const Handle(Geom_Surface)& surface,
133                                               const TopLoc_Location& location,
134                                               const Standard_Boolean isSeam,
135                                               const Standard_Real prec)
136 {
137   Handle(ShapeAnalysis_Surface) sas = new ShapeAnalysis_Surface (surface);
138   return FixAddPCurve (edge, surface, location, isSeam, sas, prec);
139 }
140
141 //=======================================================================
142 //function : FixAddPCurve
143 //purpose  : 
144 //=======================================================================
145
146 Standard_Boolean ShapeFix_Edge::FixAddPCurve (const TopoDS_Edge& edge,
147                                               const TopoDS_Face& face,
148                                               const Standard_Boolean isSeam,
149                                               const Handle(ShapeAnalysis_Surface)& surfana,
150                                               const Standard_Real prec) 
151 {
152   TopLoc_Location L;
153   const Handle(Geom_Surface)& S = BRep_Tool::Surface(face, L);
154   return FixAddPCurve (edge, S, L, isSeam, surfana, prec);
155 }
156
157 //=======================================================================
158 //function : FixAddPCurve
159 //purpose  : 
160 //=======================================================================
161
162 //#12 rln 17/03/98 making this method to be more general : if a curve is
163 //parallel to one iso let us translate it parallely in the direction to another
164 //iso (which is located farther from aC2d). Thus, the requirement for closeness
165 //to the surface bounds may be avoid.
166 //For example, instead of Abs(theLoc.X()-uf) <= Tol) ... elseif (...-ul..)...
167 //the comparison if (Abs(theLoc.X()-uf) <= Abs(theLoc.X()-ul)) .... can be used.
168
169 //The reason of this fix #12 is that seam is not sure to lie on the bound :
170 //if a surface is periodic the whole contour may be shifted (e.g. ProSTEP,
171 //file ug_exhaust-A.stp entity #284920)
172
173 static Handle(Geom2d_Curve) TranslatePCurve (const Handle(Geom_Surface)& aSurf,  
174                                              Handle(Geom2d_Curve)& aC2d,
175                                              const Standard_Real& aTol)
176 {
177   Standard_Real uf,ul,vf,vl;
178   aSurf->Bounds(uf,ul,vf,vl);
179   
180   // cas d une ligne
181   Handle(Geom2d_Line) theL2d = Handle(Geom2d_Line)::DownCast(aC2d);
182   if (!theL2d.IsNull()) {
183     gp_Pnt2d theLoc = theL2d->Location();
184     gp_Dir2d theDir = theL2d->Direction();
185
186     gp_Pnt2d newLoc;
187     Handle(Geom2d_Line) theNewL2d = theL2d;
188
189     //case UClosed
190     if (Abs(theDir.X()) <= aTol && Abs(theDir.Y()) >= aTol) {
191       if (Abs(theLoc.X() - uf) < Abs(theLoc.X() - ul))
192         newLoc.SetCoord (theLoc.X() + (ul - uf), theLoc.Y());
193       else
194         newLoc.SetCoord (theLoc.X() - (ul - uf), theLoc.Y());
195       theNewL2d = new Geom2d_Line(newLoc, theDir);
196     }
197 /*    // case UClosed and line in U = UFirst
198     if ((Abs(theLoc.X() - uf) <= aTol) &&
199         (Abs(theDir.X()) <= aTol)      &&
200         (Abs(theDir.Y()) >= aTol)) {
201       // on translate en ul
202       gp_Pnt2d newLoc(ul, theLoc.Y());
203       Handle(Geom2d_Line) theNewL2d = new Geom2d_Line(newLoc, theDir);
204       return theNewL2d;
205     }
206     // cas UClosed and line in U = ULast
207     if ((Abs(theLoc.X() - ul) <= aTol) &&
208         (Abs(theDir.X()) <= aTol)      &&
209         (Abs(theDir.Y()) >= aTol)) {
210       // on translate en uf
211       gp_Pnt2d newLoc(uf, theLoc.Y());
212       Handle(Geom2d_Line) theNewL2d = new Geom2d_Line(newLoc, theDir);
213       return theNewL2d;
214     }
215 */
216     //case VClosed
217     if (Abs(theDir.X()) >= aTol && Abs(theDir.Y()) <= aTol) {
218       if (Abs(theLoc.Y() - vf) < Abs(theLoc.Y() - vl))
219         newLoc.SetCoord (theLoc.X(), theLoc.Y() + (vl - vf));
220       else
221         newLoc.SetCoord (theLoc.X(), theLoc.Y() - (vl - vf));
222       theNewL2d = new Geom2d_Line(newLoc, theDir);
223     }
224 /*    // case VClosed and line in V = VFirst
225     if ((Abs(theLoc.Y() - vf) <= aTol) &&
226         (Abs(theDir.X()) >= aTol)      &&
227         (Abs(theDir.Y()) <= aTol)) {
228       // on translate en vl
229       gp_Pnt2d newLoc(theLoc.X(), vl);
230       Handle(Geom2d_Line) theNewL2d = new Geom2d_Line(newLoc, theDir);
231       return theNewL2d;
232     }
233     // cas VClosed and line in V = VLast
234     if ((Abs(theLoc.Y() - vl) <= aTol) &&
235         (Abs(theDir.X()) >= aTol)      &&
236         (Abs(theDir.Y()) <= aTol)) {
237       // on translate en vf
238       gp_Pnt2d newLoc(theLoc.X(), vf);
239       Handle(Geom2d_Line) theNewL2d = new Geom2d_Line(newLoc, theDir);
240       return theNewL2d;
241     }
242 */
243     // Other case not yet implemented
244 #ifdef DEBUG
245     cout << "TranslatePCurve not performed" << endl;
246 #endif
247     return theNewL2d;//*theL2d;
248   }
249   else {
250     // cas bspline curve
251     Handle(Geom2d_BSplineCurve) 
252       aBC = Handle(Geom2d_BSplineCurve)::DownCast(aC2d);
253     if (aBC.IsNull()) {
254 #ifdef DEBUG
255       cout << "Untreated curve type in TranslatePCurve" << endl;
256 #endif
257       return aC2d;
258     }
259     Handle(Geom2d_BSplineCurve) newC = 
260       Handle(Geom2d_BSplineCurve)::DownCast(aBC->Copy());
261     gp_Pnt2d FirstPoint = aBC->StartPoint();
262     gp_Pnt2d LastPoint  = aBC->EndPoint();
263     gp_Vec2d theVector (FirstPoint, LastPoint);
264     gp_Pnt2d p00(uf, vf), p01(uf,vl), p10(ul,vf);
265     gp_Vec2d VectIsoUF(p00, p01);
266     gp_Vec2d VectIsoVF(p00, p10);
267
268     gp_Trsf2d T;
269     if (theVector.IsParallel(VectIsoUF, aTol)) {
270       if (Abs(FirstPoint.X() - uf) < Abs(FirstPoint.X() - ul))  T.SetTranslation(p00, p10);
271       else                                                      T.SetTranslation(p10, p00);
272       newC->Transform(T);
273       return newC;
274     }
275 /*      // case UClosed and line in U = UFirst
276       if (Abs(FirstPoint.X() - uf) <= aTol) {
277         gp_Trsf2d T;
278         T.SetTranslation(p00, p10);
279         newC->Transform(T);
280         return newC;
281       }
282       // case UClosed and line in U = ULast
283       else if (Abs(FirstPoint.X() - ul) <= aTol) {
284         gp_Trsf2d T;
285         T.SetTranslation(p10, p00);
286         newC->Transform(T);
287         return newC;    
288       }
289       else { // les courbes ne sont pas sur la couture
290         return aC2d;
291       }
292 */
293     else if (theVector.IsParallel(VectIsoVF, aTol)) {
294 //#ifdef DEBUG
295 //      cout << "other curve-VClosed Surface. TranslatePC not impl." << endl;
296 //#endif
297       if (Abs(FirstPoint.Y() - vf) < Abs(FirstPoint.Y() - vl))  T.SetTranslation(p00, p01);
298       else                                                      T.SetTranslation(p01, p00);
299       newC->Transform(T);
300       return newC;
301     }
302   }
303   // les courbes ne sont pas sur la couture
304   return aC2d;
305 }
306
307 //=======================================================================
308 //static : Range3d 
309 //purpose  : contournement du Range de BRep_Builder pour ne pas affecter
310 //           les ranges des pcurves.
311 //=======================================================================
312
313 static void Range3d (const TopoDS_Edge& E, 
314                      const Standard_Real First, const Standard_Real Last,
315                      const Standard_Real myPrecision) 
316 {
317   //  set the range to all the representations
318   const Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*) &E.TShape());
319   
320   BRep_ListOfCurveRepresentation& lcr = TE->ChangeCurves();
321   BRep_ListIteratorOfListOfCurveRepresentation itcr(lcr);
322   Handle(BRep_GCurve) GC;
323   
324   while (itcr.More()) {
325     GC = Handle(BRep_GCurve)::DownCast(itcr.Value());
326     if (!GC.IsNull()) {
327       if (GC->IsCurve3D()) {
328         GC->SetRange(First,Last);
329         // Set the closedness flag to the correct value.
330         Handle(Geom_Curve) C = GC->Curve3D();
331         if ( !C.IsNull() ) {
332           Standard_Boolean closed = C->Value(First).IsEqual(C->Value(Last),myPrecision);
333           TE->Closed(closed);
334         }
335       }
336     }
337     itcr.Next();
338   }
339
340   TE->Modified(Standard_True);
341 }
342 //=======================================================================
343 //function : SameRange (Temp)
344 //purpose  : 
345 //=======================================================================
346 //:b0 abv 16 Feb 98: This is a copy of BRepLib::SameRange()
347 // modified in order to be able to fix seam edges
348 // NOTE: It is to be removed when is fixed either BRepLib::SameRange() 
349 // (concerning seam edges) or BRepLib::SameParameter() (concerning call
350 // to GeomLib::SameRange() with 3d tolerance)
351
352  static void TempSameRange(const TopoDS_Edge& AnEdge,
353                            const Standard_Real Tolerance) 
354 {
355   BRep_ListIteratorOfListOfCurveRepresentation an_Iterator
356     ((*((Handle(BRep_TEdge)*)&AnEdge.TShape()))->ChangeCurves());
357   
358   Handle(Geom2d_Curve) Curve2dPtr, NewCurve2dPtr;
359   Handle(Geom2d_Curve) Curve2dPtr2, NewCurve2dPtr2;
360   TopLoc_Location LocalLoc ;
361
362   //Standard_Boolean  IsSameRange = Standard_True //skl
363   Standard_Boolean first_time_in = Standard_True, has_curve, has_closed_curve;
364   Handle(BRep_GCurve) geometric_representation_ptr;
365   Standard_Real first, current_first, last, current_last;
366
367   const Handle(Geom_Curve) C = BRep_Tool::Curve(AnEdge, LocalLoc, 
368                                                 current_first, current_last);
369   if (!C.IsNull()) first_time_in = Standard_False;
370   
371   while (an_Iterator.More()) {
372     geometric_representation_ptr =
373       Handle(BRep_GCurve)::DownCast(an_Iterator.Value());
374     if (! geometric_representation_ptr.IsNull()) {
375       has_closed_curve = has_curve = Standard_False;
376       first = geometric_representation_ptr->First();
377       last =  geometric_representation_ptr->Last();
378       if (geometric_representation_ptr->IsCurveOnSurface()) {
379         Curve2dPtr = geometric_representation_ptr->PCurve() ; 
380         has_curve = Standard_True ;
381       }
382       if (geometric_representation_ptr->IsCurveOnClosedSurface()) {
383         Curve2dPtr2 = geometric_representation_ptr->PCurve2() ;
384         has_closed_curve = Standard_True ;
385       }
386       if (has_curve || has_closed_curve) {
387         if (first_time_in) {
388           current_first = first;
389           current_last = last;
390           first_time_in = Standard_False;
391         }
392         
393         if (Abs(first - current_first) > Precision::PConfusion() || //:b8 abv 20 Feb 98: Confusion -> PConfusion
394             Abs(last - current_last) > Precision::PConfusion() ) {  //:b8
395           Standard_Real oldFirst=0., oldLast=0.; //skl
396           if (has_curve) {
397             //pdn 20.05.99 Work around 
398             oldFirst = geometric_representation_ptr->First();
399             oldLast = geometric_representation_ptr->Last();
400             // 15.11.2002 PTV OCC966
401             if(ShapeAnalysis_Curve::IsPeriodic(Curve2dPtr)) {
402               Handle(Geom2d_TrimmedCurve) tc = new Geom2d_TrimmedCurve(Curve2dPtr,oldFirst,oldLast);
403               Standard_Real shift = tc->FirstParameter()-oldFirst;
404               oldFirst += shift;
405               oldLast += shift;
406             }
407             //pdn 30.06.2000 work arounf on beziers
408             Standard_Real oldFirstCurve1 = oldFirst, oldLastCurve1 = oldLast;
409             if(Curve2dPtr->IsKind(STANDARD_TYPE(Geom2d_BezierCurve))) {
410               
411               Standard_Real preci = Precision::PConfusion();
412               if ( Abs(oldFirst) > preci || Abs(oldLast-1) > preci ) {
413                 Handle(Geom2d_BezierCurve) bezier = Handle(Geom2d_BezierCurve)::DownCast(Curve2dPtr->Copy());
414                 bezier->Segment(oldFirst,oldLast);
415                 Curve2dPtr = bezier;
416               }
417               oldFirstCurve1 = 0;
418               oldLastCurve1 = 1;
419             }
420                
421             GeomLib::SameRange(Tolerance, Curve2dPtr, 
422                                oldFirstCurve1,
423                                oldLastCurve1,
424                                current_first, current_last, NewCurve2dPtr);
425             geometric_representation_ptr->PCurve(NewCurve2dPtr) ;
426           }
427           if (has_closed_curve) {
428             
429             Standard_Real oldFirstCurve2 = oldFirst, oldLastCurve2 = oldLast;
430             
431             if(Curve2dPtr2->IsKind(STANDARD_TYPE(Geom2d_BezierCurve))) {
432               
433               Standard_Real preci = Precision::PConfusion();
434               if ( Abs(oldFirst) > preci || Abs(oldLast-1) > preci ) {
435                 Handle(Geom2d_BezierCurve) bezier = Handle(Geom2d_BezierCurve)::DownCast(Curve2dPtr2->Copy());
436                 bezier->Segment(oldFirst,oldLast);
437                 Curve2dPtr2 = bezier;
438               }
439               oldFirstCurve2 = 0;
440               oldLastCurve2 = 1;
441             }
442                       
443             GeomLib::SameRange(Tolerance, Curve2dPtr2, 
444                                oldFirstCurve2,
445                                oldLastCurve2,
446                                current_first, current_last, NewCurve2dPtr2);
447             geometric_representation_ptr->PCurve2(NewCurve2dPtr2);
448           }
449         }
450       }
451     }
452     an_Iterator.Next();
453   }
454   BRep_Builder B;
455   B.Range(TopoDS::Edge(AnEdge), current_first, current_last);
456   B.SameRange(AnEdge, Standard_True);
457 }
458
459 //=======================================================================
460 //function : FixAddPCurve
461 //=======================================================================
462
463 Standard_Boolean ShapeFix_Edge::FixAddPCurve (const TopoDS_Edge& edge,
464                                               const Handle(Geom_Surface)& surf,
465                                               const TopLoc_Location& location,
466                                               const Standard_Boolean isSeam,
467                                               const Handle(ShapeAnalysis_Surface)& sas,
468                                               const Standard_Real prec)
469 {
470   ShapeAnalysis_Edge sae;
471   myStatus = ShapeExtend::EncodeStatus (ShapeExtend_OK);
472   if ( (!isSeam && sae.HasPCurve (edge, surf, location))||
473        ( isSeam && sae.IsSeam(edge, surf, location))) return Standard_False;
474
475   // PCurve on Plane not computed
476   if (surf->IsKind(STANDARD_TYPE(Geom_Plane))) return Standard_False;
477
478 //  Standard_Real step = 0;
479   try {
480     OCC_CATCH_SIGNALS
481     Standard_Real First, Last;
482
483     BRep_Builder B;
484
485     Standard_Real preci = ( prec >0. ? prec : BRep_Tool::Tolerance(edge) );
486     Handle(Geom_Curve) c3d = BRep_Tool::Curve(edge, /*Loc,*/ First, Last);
487     //  Handle(Geom_Curve) c3d = BRep_Tool::Curve(E, First, Last);
488     if (c3d.IsNull() || (Abs(Last-First) <Precision::PConfusion())) {
489       myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL1);
490       return Standard_False;
491     }
492
493     // Trim the curve to avoid problem  ??
494 //    c3d = Handle(Geom_Curve)::DownCast(c3d->Transformed(Loc.Transformation()));
495 //    Handle(Geom_TrimmedCurve) theTrimmed = new Geom_TrimmedCurve(c3d, First, Last);
496 //    c3d = theTrimmed;
497
498 //    step = 1;
499
500     //  A present, on projette
501     //  stat : 0 pas pu faire, 1 analytique, 2 approx
502     Handle(Geom2d_Curve) c2d;
503     Standard_Real a1, b1;
504     if ( ! sae.HasPCurve (edge, surf, location)) {
505       myProjector->Init ( sas, preci );
506       myProjector->Perform (c3d,First,Last,c2d);
507       //  stat = 2 : reinterpoler la c3d ?
508       if ( myProjector->Status ( ShapeExtend_DONE4 ) )
509         myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_DONE2);
510       a1 = First;
511       b1 = Last;
512     }
513     else {
514       sae.PCurve ( edge, surf, location, c2d, a1, b1, Standard_False );
515     }
516
517 //    step = 2;
518
519     // adding by skl 28.03.2003 for usung Line instead of BSpline
520     Standard_Real fp=0.,lp=0.;
521     Standard_Boolean isLine=Standard_False;
522     if(c2d->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve))) {
523       Handle(Geom2d_TrimmedCurve) tc = Handle(Geom2d_TrimmedCurve)::DownCast(c2d);
524       if(tc->BasisCurve()->IsKind(STANDARD_TYPE(Geom2d_Line))) {
525         fp = tc->FirstParameter();
526         lp = tc->LastParameter();
527         isLine = Standard_True;
528       }
529     }
530
531     if (isSeam) {
532       // On ne sait pas laquelle est Forward. Au PIF. La geometrie Forward
533       // sera mise a jour dans ComputeWire
534       Handle(Geom2d_Curve) c2d2 = Handle(Geom2d_Curve)::DownCast(c2d->Copy());
535       //  ATTENTION : TranslatePCurve reconstruit une Line // bords, en
536       //  intuitant U ou V ...
537       //  Ici, on exploite les infos deja connues
538       Standard_Real uf,ul,vf,vl;
539       surf->Bounds (uf,ul,vf,vl);
540       //#4 rln 19/02/98 ProSTEP ug_exhaust-A.stp entity #284920 (thoroidal surface)
541       //#13 rln 17/03/98 (updating fix #4) call to TranslatePCurve in the case
542       //when a surface is either u- and vclosed or neither u- nor vclosed
543       //#78 rln 12.03.99 S4135: checking spatial closure with prec
544       if (sas->IsUClosed(prec) && ! sas->IsVClosed(prec) //rln S4135 sphere is not considered as V-closed anymore ||
545           /* rln S4135 sas->Surface()->IsKind(STANDARD_TYPE(Geom_SphericalSurface)) */ )  {//:d9 abv 17 Mar 98: any sphere
546         gp_Vec2d tranvec (ul-uf,0);
547         c2d2->Translate (tranvec);
548       }
549       else if (sas->IsVClosed(prec) && ! sas->IsUClosed(prec) ) {
550         gp_Vec2d tranvec (0,vl-vf);
551         c2d2->Translate (tranvec);
552       }
553       else if ( sas->IsUClosed() && sas->IsVClosed() ) { //:q8 abv 23 Mar 99: bm4_al_eye.stp #53710: avoid shifting pcurves for pseudo-seam
554         //      Doublement fermee (ex tore) : on lance la charge
555         c2d2 = TranslatePCurve(sas->Surface(), c2d2, prec);
556       }
557       B.UpdateEdge (edge,c2d,c2d2,surf,location, 0.); //#82 rln 16.03.99: preci
558 //      if ( c2d->IsKind (STANDARD_TYPE(Geom2d_BoundedCurve)) )
559 //      B.Range    (edge,surf,location,c2d->FirstParameter(),c2d->LastParameter());
560       B.Range    (edge,surf,location,a1,b1);
561     }
562     else {
563       B.UpdateEdge (edge,c2d,surf,location, 0.); //#82 rln 16.03.99: preci
564     }
565
566     if ( isLine ) {
567       B.Range(edge,surf,location,fp,lp);
568       B.SameParameter(edge,Standard_False);
569       B.SameRange(edge,Standard_False);
570     }
571
572     //  Conclusion
573 //    step = 3;
574     if ( myProjector->Status ( ShapeExtend_DONE3 ) ) {
575       Standard_Real G3dCFirst = c3d->FirstParameter();
576       Standard_Real G3dCLast  = c3d->LastParameter();
577       B.UpdateEdge(edge, c3d, 0.);
578       Range3d(edge, G3dCFirst, G3dCLast, 0.);
579     }
580   }   // end try
581   catch(Standard_Failure) {
582     myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL2);
583 #ifdef DEB //:s5
584     cout << "Warning: ShapeFix_Edge::FixAddPCurve(): Exception: ";
585     Standard_Failure::Caught()->Print(cout); cout << endl;
586 #endif
587   }
588   myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_DONE1);
589   return Standard_True;
590 }
591
592 //=======================================================================
593 //function : FixAddCurve3d
594 //purpose  : 
595 //=======================================================================
596
597  Standard_Boolean ShapeFix_Edge::FixAddCurve3d(const TopoDS_Edge& edge) 
598 {
599   myStatus = ShapeExtend::EncodeStatus (ShapeExtend_OK);
600   ShapeAnalysis_Edge EA;
601   if ( BRep_Tool::Degenerated ( edge ) || EA.HasCurve3d (edge) ) return Standard_False;
602   if(!BRep_Tool::SameRange(edge))
603     TempSameRange(edge,Precision::PConfusion());
604     
605   if (!ShapeBuild_Edge().BuildCurve3d(edge)) {
606     myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL1);
607     return Standard_False;
608   }
609   myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_DONE1);
610   return Standard_True;
611 }
612
613 //=======================================================================
614 //function : FixVertexTolerance
615 //purpose  : 
616 //=======================================================================
617
618 Standard_Boolean ShapeFix_Edge::FixVertexTolerance(const TopoDS_Edge& edge,
619                                                    const TopoDS_Face& face)
620 {
621   myStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
622   ShapeAnalysis_Edge sae;
623   Standard_Real toler1, toler2;
624   if (!sae.CheckVertexTolerance (edge, face, toler1, toler2)) return Standard_False;
625   if (sae.Status (ShapeExtend_DONE1))
626     myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE1);
627   if (sae.Status (ShapeExtend_DONE2))
628     myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE2);
629   BRep_Builder B;
630   TopoDS_Vertex V1 = sae.FirstVertex(edge);
631   TopoDS_Vertex V2 = sae.LastVertex(edge);
632   B.UpdateVertex (V1, toler1);
633   B.UpdateVertex (V2, toler2);
634   return Standard_True;
635 }
636
637 //=======================================================================
638 //function : FixVertexTolerance
639 //purpose  : 
640 //=======================================================================
641
642 Standard_Boolean ShapeFix_Edge::FixVertexTolerance(const TopoDS_Edge& edge)
643 {
644   myStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
645   ShapeAnalysis_Edge sae;
646   Standard_Real toler1, toler2;
647   if (!sae.CheckVertexTolerance (edge, toler1, toler2)) return Standard_False;
648   if (sae.Status (ShapeExtend_DONE1))
649     myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE1);
650   if (sae.Status (ShapeExtend_DONE2))
651     myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE2);
652   BRep_Builder B;
653   TopoDS_Vertex V1 = sae.FirstVertex(edge);
654   TopoDS_Vertex V2 = sae.LastVertex(edge);
655   B.UpdateVertex (V1, toler1);
656   B.UpdateVertex (V2, toler2);
657   return Standard_True;
658 }
659
660 //=======================================================================
661 //function : FixReversed2d
662 //purpose  : 
663 //=======================================================================
664
665 Standard_Boolean ShapeFix_Edge::FixReversed2d (const TopoDS_Edge& edge,
666                                                const TopoDS_Face& face) 
667 {
668   TopLoc_Location L;
669   const Handle(Geom_Surface)& S = BRep_Tool::Surface(face, L);
670   return FixReversed2d (edge, S, L);
671 }
672
673 //=======================================================================
674 //function : FixReversed2d
675 //purpose  : 
676 //=======================================================================
677
678 Standard_Boolean ShapeFix_Edge::FixReversed2d (const TopoDS_Edge& edge,
679                                                const Handle(Geom_Surface)& surface,
680                                                const TopLoc_Location& location) 
681 {
682   myStatus = ShapeExtend::EncodeStatus (ShapeExtend_OK);
683   
684   ShapeAnalysis_Edge EA;
685   EA.CheckCurve3dWithPCurve (edge, surface, location);
686   if (EA.Status (ShapeExtend_FAIL1))
687     myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL1);
688   if (EA.Status (ShapeExtend_FAIL2))
689     myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL2);
690   if ( ! EA.Status (ShapeExtend_DONE) ) return Standard_False;
691   
692   Handle(Geom2d_Curve) c2d;
693   Standard_Real f,l;
694   EA.PCurve (edge, surface, location, c2d, f, l, Standard_False);
695   //#46 rln 01.12.98 buc40130, entity 272 (4-th curve)
696   Standard_Real newf = c2d->ReversedParameter (l), newl = c2d->ReversedParameter (f);
697   c2d->Reverse();
698   BRep_Builder B;
699 //will break seams!  B.UpdateEdge (edge, c2d, surface, location, Precision::Confusion());
700   B.Range (edge, surface, location, newf, newl);
701   //#51 rln 15.12.98 pro6562 entity 2788
702   //Because of numerical accuracy the range on B-Splines (moreover, on any curve!)
703   //the range is changed
704   Standard_Real first, last;
705   BRep_Tool::Range (edge, first, last);
706   if (first != newf || last != newl) {
707     B.SameRange     (edge, Standard_False);
708     B.SameParameter (edge, Standard_False);
709   }
710   myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_DONE1);
711   return Standard_True;
712 }
713
714
715 //=======================================================================
716 //function : FixSameParameter
717 //purpose  : 
718 //=======================================================================
719
720 Standard_Boolean ShapeFix_Edge::FixSameParameter(const TopoDS_Edge& edge,
721                                                  const Standard_Real tolerance) 
722 {
723   myStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
724   
725   if ( BRep_Tool::Degenerated ( edge ) ) {
726     BRep_Builder B;
727     if ( ! BRep_Tool::SameRange (edge) )
728       TempSameRange ( edge, Precision::PConfusion() );
729     B.SameParameter ( edge, Standard_True );
730     return Standard_False;
731   }
732   ShapeFix_ShapeTolerance SFST;
733   ShapeAnalysis_Edge sae;
734   BRep_Builder B;
735
736   TopoDS_Edge copyedge;
737   TopoDS_Vertex V1 = sae.FirstVertex (edge);
738   TopoDS_Vertex V2 = sae.LastVertex  (edge);
739   Standard_Real TolFV = ( V1.IsNull() ? 0. : BRep_Tool::Tolerance ( V1 ) );
740   Standard_Real TolLV = ( V2.IsNull() ? 0. : BRep_Tool::Tolerance ( V2 ) );
741   Standard_Real tol = BRep_Tool::Tolerance (edge);
742   
743   Standard_Boolean wasSP = BRep_Tool::SameParameter ( edge ), SP = Standard_False;
744   {
745     try {
746       OCC_CATCH_SIGNALS
747       if ( ! BRep_Tool::SameRange (edge) )
748         TempSameRange ( edge, Precision::PConfusion() );
749       //#81 rln 15.03.99 S4135: for not SP edge choose the best result (either BRepLib or deviation only)
750       if ( ! wasSP ) {
751         //create copyedge as copy of edge with the same vertices and copy of pcurves on the same surface(s)
752         copyedge = ShapeBuild_Edge().Copy ( edge, Standard_False );
753         B.SameParameter ( copyedge, Standard_False );
754         // ShapeBuild_Edge::Copy() may change 3D curve range (if it's outside of its period).
755         // In this case pcurves in BRepLib::SameParameter() will be changed as well
756         // and later ShapeBuild_Edge::CopyPCurves() will copy pcurves keeping original range.
757         // To prevent this discrepancy we enforce original 3D range.
758         Standard_Real aF, aL;
759         BRep_Tool::Range (edge, aF, aL);
760         B.Range (copyedge, aF, aL, Standard_True); // only 3D
761         BRepLib::SameParameter ( copyedge, ( tolerance >= Precision::Confusion() ? 
762                                             tolerance : tol ) );
763         SP = BRep_Tool::SameParameter ( copyedge );
764         if ( ! SP ) myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL2 );
765       }
766     }
767     catch(Standard_Failure) {
768 #ifdef DEB
769       cout << "\nWarning: ShapeFix_Edge: Exception in SameParameter: "; 
770       Standard_Failure::Caught()->Print(cout); cout << endl;
771 #endif
772       myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL2 );
773     }
774   }
775   
776   // compute deviation on the original pcurves
777   Standard_Real maxdev;
778   B.SameParameter ( edge, Standard_True );
779   sae.CheckSameParameter ( edge, maxdev );
780   if ( sae.Status ( ShapeExtend_FAIL2 ) )
781     myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
782   
783   // if BRepLib was OK, compare and select the best variant
784   if ( SP ) {
785     Standard_Real BRLTol = BRep_Tool::Tolerance ( copyedge ), BRLDev;
786     sae.CheckSameParameter ( copyedge, BRLDev );
787     myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE3 );
788     if ( BRLTol < BRLDev ) BRLTol = BRLDev;
789     
790     //chose the best result
791     if ( BRLTol < maxdev ) {
792       if ( sae.Status ( ShapeExtend_FAIL2 ) )
793         myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
794       //copy pcurves and tolerances from copyedge
795       ShapeBuild_Edge().CopyPCurves ( edge, copyedge );
796       maxdev = BRLTol;
797       SFST.SetTolerance (edge, BRLTol, TopAbs_EDGE);
798       myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE5 );
799     }
800   }
801   //restore tolerances because they could be modified by BRepLib
802   if ( ! V1.IsNull() ) SFST.SetTolerance ( V1, Max (maxdev, TolFV), TopAbs_VERTEX);
803   if ( ! V2.IsNull() ) SFST.SetTolerance ( V2, Max (maxdev, TolLV), TopAbs_VERTEX);
804   
805   if ( maxdev > tol ) { 
806     myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
807     B.UpdateEdge ( edge, maxdev );
808     FixVertexTolerance(edge);
809   }
810
811   if ( ! wasSP && ! SP ) myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE2 );
812   return Status ( ShapeExtend_DONE );
813 }
814
815 //=======================================================================
816 //function : Status
817 //purpose  : 
818 //=======================================================================
819
820  Standard_Boolean ShapeFix_Edge::Status(const ShapeExtend_Status status) const
821 {
822   return ShapeExtend::DecodeStatus (myStatus, status);
823 }