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