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