1 // Created on: 1993-12-15
2 // Created by: Remi LEQUETTE
3 // Copyright (c) 1993-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16 
17 //pmn 26/09/97 Add parameters of approximation in BuildCurve3d
18 //  Modified by skv - Thu Jun  3 12:39:19 2004 OCC5898
19 
20 #include <BRepLib.hxx>
21 
22 #include <Adaptor3d_CurveOnSurface.hxx>
23 #include <AdvApprox_ApproxAFunction.hxx>
24 #include <AppParCurves_MultiBSpCurve.hxx>
25 #include <AppParCurves_MultiCurve.hxx>
26 #include <Approx_CurvilinearParameter.hxx>
27 #include <Approx_SameParameter.hxx>
28 #include <Bnd_Box.hxx>
29 #include <BRep_Builder.hxx>
30 #include <BRep_CurveRepresentation.hxx>
31 #include <BRep_GCurve.hxx>
32 #include <BRep_ListIteratorOfListOfCurveRepresentation.hxx>
33 #include <BRep_ListOfCurveRepresentation.hxx>
34 #include <BRepCheck.hxx>
35 #include <BRep_TEdge.hxx>
36 #include <BRep_TFace.hxx>
37 #include <BRep_Tool.hxx>
38 #include <BRep_TVertex.hxx>
39 #include <BRepAdaptor_Curve.hxx>
40 #include <BRepAdaptor_Curve2d.hxx>
41 #include <BRepAdaptor_Surface.hxx>
42 #include <BRepBndLib.hxx>
43 #include <BRepClass3d_SolidClassifier.hxx>
44 #include <BRepLib_MakeFace.hxx>
45 #include <BSplCLib.hxx>
46 #include <ElSLib.hxx>
47 #include <Extrema_LocateExtPC.hxx>
48 #include <GCPnts_QuasiUniformDeflection.hxx>
49 #include <Geom2d_BSplineCurve.hxx>
50 #include <Geom2d_Curve.hxx>
51 #include <Geom2d_TrimmedCurve.hxx>
52 #include <Geom2dAdaptor.hxx>
53 #include <Geom2dAdaptor_Curve.hxx>
54 #include <Geom2dConvert.hxx>
55 #include <Geom_BSplineCurve.hxx>
56 #include <Geom_BSplineSurface.hxx>
57 #include <Geom_Curve.hxx>
58 #include <Geom_Plane.hxx>
59 #include <Geom_RectangularTrimmedSurface.hxx>
60 #include <Geom_Surface.hxx>
61 #include <Geom_TrimmedCurve.hxx>
62 #include <GeomAdaptor_Curve.hxx>
63 #include <GeomAdaptor_Surface.hxx>
64 #include <GeomLib.hxx>
65 #include <GeomLProp_SLProps.hxx>
66 #include <gp.hxx>
67 #include <gp_Ax2.hxx>
68 #include <gp_Pln.hxx>
69 #include <Poly_PolygonOnTriangulation.hxx>
70 #include <Poly_Triangulation.hxx>
71 #include <Precision.hxx>
72 #include <ProjLib_ProjectedCurve.hxx>
73 #include <Standard_ErrorHandler.hxx>
74 #include <Standard_Real.hxx>
75 #include <TColgp_Array1OfPnt.hxx>
76 #include <TColgp_Array1OfPnt2d.hxx>
77 #include <TColStd_Array1OfReal.hxx>
78 #include <TColStd_MapOfTransient.hxx>
79 #include <TopExp.hxx>
80 #include <TopExp_Explorer.hxx>
81 #include <TopoDS.hxx>
82 #include <TopoDS_Edge.hxx>
83 #include <TopoDS_Face.hxx>
84 #include <TopoDS_Shape.hxx>
85 #include <TopoDS_Solid.hxx>
86 #include <TopoDS_Vertex.hxx>
87 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
88 #include <TopTools_ListIteratorOfListOfShape.hxx>
89 #include <TopTools_MapOfShape.hxx>
90 #include <TShort_HArray1OfShortReal.hxx>
91 #include <TColgp_Array1OfXY.hxx>
92 #include <BRepTools_ReShape.hxx>
93 #include <TopTools_DataMapOfShapeReal.hxx>
94 #include <TopoDS_LockedShape.hxx>
95 
96 #include <algorithm>
97 
98 // TODO - not thread-safe static variables
99 static Standard_Real thePrecision = Precision::Confusion();
100 static Handle(Geom_Plane) thePlane;
101 
102 static void InternalUpdateTolerances(const TopoDS_Shape& theOldShape,
103   const Standard_Boolean IsVerifyTolerance, const Standard_Boolean IsMutableInput, BRepTools_ReShape& theReshaper);
104 
105 //=======================================================================
106 // function: BRepLib_ComparePoints
107 // purpose:  implementation of IsLess() function for two points
108 //=======================================================================
109 struct BRepLib_ComparePoints {
operator ()BRepLib_ComparePoints110   bool operator()(const gp_Pnt& theP1, const gp_Pnt& theP2)
111   {
112     for (Standard_Integer i = 1; i <= 3; ++i) {
113       if (theP1.Coord(i) < theP2.Coord(i)) {
114         return Standard_True;
115       }
116       else if (theP1.Coord(i) > theP2.Coord(i)) {
117         return Standard_False;
118       }
119     }
120     return Standard_False;
121   }
122 };
123 
124 
125 //=======================================================================
126 //function : Precision
127 //purpose  :
128 //=======================================================================
129 
Precision(const Standard_Real P)130 void BRepLib::Precision(const Standard_Real P)
131 {
132   thePrecision = P;
133 }
134 
135 //=======================================================================
136 //function : Precision
137 //purpose  :
138 //=======================================================================
139 
Precision()140 Standard_Real  BRepLib::Precision()
141 {
142   return thePrecision;
143 }
144 
145 //=======================================================================
146 //function : Plane
147 //purpose  :
148 //=======================================================================
149 
Plane(const Handle (Geom_Plane)& P)150 void  BRepLib::Plane(const Handle(Geom_Plane)& P)
151 {
152   thePlane = P;
153 }
154 
155 
156 //=======================================================================
157 //function : Plane
158 //purpose  :
159 //=======================================================================
160 
Handle(Geom_Plane)161 const Handle(Geom_Plane)&  BRepLib::Plane()
162 {
163   if (thePlane.IsNull()) thePlane = new Geom_Plane(gp::XOY());
164   return thePlane;
165 }
166 //=======================================================================
167 //function : CheckSameRange
168 //purpose  :
169 //=======================================================================
170 
CheckSameRange(const TopoDS_Edge & AnEdge,const Standard_Real Tolerance)171 Standard_Boolean  BRepLib::CheckSameRange(const TopoDS_Edge& AnEdge,
172   const Standard_Real Tolerance)
173 {
174   Standard_Boolean  IsSameRange = Standard_True,
175     first_time_in = Standard_True ;
176 
177   BRep_ListIteratorOfListOfCurveRepresentation an_Iterator
178     ((*((Handle(BRep_TEdge)*)&AnEdge.TShape()))->ChangeCurves());
179 
180   Standard_Real first, last;
181   Standard_Real current_first =0., current_last =0. ;
182   Handle(BRep_GCurve) geometric_representation_ptr ;
183 
184   while (IsSameRange && an_Iterator.More()) {
185     geometric_representation_ptr =
186       Handle(BRep_GCurve)::DownCast(an_Iterator.Value());
187     if (!geometric_representation_ptr.IsNull()) {
188 
189       first = geometric_representation_ptr->First();
190       last =  geometric_representation_ptr->Last();
191       if (first_time_in ) {
192         current_first = first ;
193         current_last = last   ;
194         first_time_in = Standard_False ;
195       }
196       else {
197         IsSameRange = (Abs(current_first - first) <= Tolerance)
198           && (Abs(current_last -last) <= Tolerance ) ;
199       }
200     }
201     an_Iterator.Next() ;
202   }
203   return IsSameRange ;
204 }
205 
206 //=======================================================================
207 //function : SameRange
208 //purpose  :
209 //=======================================================================
210 
SameRange(const TopoDS_Edge & AnEdge,const Standard_Real Tolerance)211 void BRepLib::SameRange(const TopoDS_Edge& AnEdge,
212   const Standard_Real Tolerance)
213 {
214   BRep_ListIteratorOfListOfCurveRepresentation an_Iterator
215     ((*((Handle(BRep_TEdge)*)&AnEdge.TShape()))->ChangeCurves());
216 
217   Handle(Geom2d_Curve) Curve2dPtr, Curve2dPtr2, NewCurve2dPtr, NewCurve2dPtr2;
218   TopLoc_Location LocalLoc ;
219 
220   Standard_Boolean first_time_in = Standard_True,
221     has_curve,
222     has_closed_curve ;
223   Handle(BRep_GCurve) geometric_representation_ptr ;
224   Standard_Real first,
225     current_first,
226     last,
227     current_last ;
228 
229   const Handle(Geom_Curve) C = BRep_Tool::Curve(AnEdge,
230     LocalLoc,
231     current_first,
232     current_last);
233   if (!C.IsNull()) {
234     first_time_in = Standard_False ;
235   }
236 
237   while (an_Iterator.More()) {
238     geometric_representation_ptr =
239       Handle(BRep_GCurve)::DownCast(an_Iterator.Value());
240     if (! geometric_representation_ptr.IsNull()) {
241       has_closed_curve =
242         has_curve = Standard_False ;
243       first = geometric_representation_ptr->First();
244       last =  geometric_representation_ptr->Last();
245       if (geometric_representation_ptr->IsCurveOnSurface()) {
246         Curve2dPtr = geometric_representation_ptr->PCurve() ;
247         has_curve = Standard_True ;
248       }
249       if (geometric_representation_ptr->IsCurveOnClosedSurface()) {
250         Curve2dPtr2 = geometric_representation_ptr->PCurve2() ;
251         has_closed_curve = Standard_True ;
252       }
253       if (has_curve || has_closed_curve) {
254         if (first_time_in) {
255           current_first = first ;
256           current_last = last ;
257           first_time_in = Standard_False ;
258         }
259 
260         if (Abs(first - current_first) > Precision::Confusion() ||
261           Abs(last - current_last) > Precision::Confusion() )
262         {
263           if (has_curve)
264           {
265             GeomLib::SameRange(Tolerance,
266               Curve2dPtr,
267               geometric_representation_ptr->First(),
268               geometric_representation_ptr->Last(),
269               current_first,
270               current_last,
271               NewCurve2dPtr);
272             geometric_representation_ptr->PCurve(NewCurve2dPtr) ;
273           }
274           if (has_closed_curve)
275           {
276             GeomLib::SameRange(Tolerance,
277               Curve2dPtr2,
278               geometric_representation_ptr->First(),
279               geometric_representation_ptr->Last(),
280               current_first,
281               current_last,
282               NewCurve2dPtr2);
283             geometric_representation_ptr->PCurve2(NewCurve2dPtr2) ;
284           }
285         }
286       }
287     }
288     an_Iterator.Next() ;
289   }
290   BRep_Builder B;
291   B.Range(TopoDS::Edge(AnEdge),
292     current_first,
293     current_last) ;
294 
295   B.SameRange(AnEdge,
296     Standard_True) ;
297 }
298 
299 //=======================================================================
300 //function : EvaluateMaxSegment
301 //purpose  : return MaxSegment to pass in approximation, if MaxSegment==0 provided
302 //=======================================================================
303 
evaluateMaxSegment(const Standard_Integer aMaxSegment,const Adaptor3d_CurveOnSurface & aCurveOnSurface)304 static Standard_Integer evaluateMaxSegment(const Standard_Integer aMaxSegment,
305   const Adaptor3d_CurveOnSurface& aCurveOnSurface)
306 {
307   if (aMaxSegment != 0) return aMaxSegment;
308 
309   Handle(Adaptor3d_Surface) aSurf   = aCurveOnSurface.GetSurface();
310   Handle(Adaptor2d_Curve2d) aCurv2d = aCurveOnSurface.GetCurve();
311 
312   Standard_Real aNbSKnots = 0, aNbC2dKnots = 0;
313 
314   if (aSurf->GetType() == GeomAbs_BSplineSurface) {
315     Handle(Geom_BSplineSurface) aBSpline = aSurf->BSpline();
316     aNbSKnots = Max(aBSpline->NbUKnots(), aBSpline->NbVKnots());
317   }
318   if (aCurv2d->GetType() == GeomAbs_BSplineCurve) {
319     aNbC2dKnots = aCurv2d->NbKnots();
320   }
321   Standard_Integer aReturn = (Standard_Integer) (  30 + Max(aNbSKnots, aNbC2dKnots) ) ;
322   return aReturn;
323 }
324 
325 //=======================================================================
326 //function : BuildCurve3d
327 //purpose  :
328 //=======================================================================
329 
BuildCurve3d(const TopoDS_Edge & AnEdge,const Standard_Real Tolerance,const GeomAbs_Shape Continuity,const Standard_Integer MaxDegree,const Standard_Integer MaxSegment)330 Standard_Boolean  BRepLib::BuildCurve3d(const TopoDS_Edge& AnEdge,
331   const Standard_Real Tolerance,
332   const GeomAbs_Shape Continuity,
333   const Standard_Integer MaxDegree,
334   const Standard_Integer MaxSegment)
335 {
336   Standard_Integer //ErrorCode,
337     //                   ReturnCode = 0,
338     ii,
339     //                   num_knots,
340     jj;
341 
342   TopLoc_Location LocalLoc,L[2],LC;
343   Standard_Real f,l,fc,lc, first[2], last[2],
344     tolerance,
345     max_deviation,
346     average_deviation ;
347   Handle(Geom2d_Curve) Curve2dPtr, Curve2dArray[2]  ;
348   Handle(Geom_Surface) SurfacePtr, SurfaceArray[2]  ;
349 
350   Standard_Integer not_done ;
351   // if the edge has a 3d curve returns true
352 
353 
354   const Handle(Geom_Curve) C = BRep_Tool::Curve(AnEdge,LocalLoc,f,l);
355   if (!C.IsNull())
356     return Standard_True;
357   //
358   // this should not exists but UpdateEdge makes funny things
359   // if the edge is not same range
360   //
361   if (! CheckSameRange(AnEdge,
362     Precision::Confusion())) {
363       SameRange(AnEdge,
364         Tolerance) ;
365   }
366 
367 
368 
369   // search a curve on a plane
370   Handle(Geom_Surface) S;
371   Handle(Geom2d_Curve) PC;
372   Standard_Integer i = 0;
373   Handle(Geom_Plane) P;
374   not_done = 1 ;
375 
376   while (not_done) {
377     i++;
378     BRep_Tool::CurveOnSurface(AnEdge,PC,S,LocalLoc,f,l,i);
379     Handle(Geom_RectangularTrimmedSurface) RT =
380       Handle(Geom_RectangularTrimmedSurface)::DownCast(S);
381     if ( RT.IsNull()) {
382       P = Handle(Geom_Plane)::DownCast(S);
383     }
384     else {
385       P = Handle(Geom_Plane)::DownCast(RT->BasisSurface());
386     }
387     not_done = ! (S.IsNull() || !P.IsNull()) ;
388   }
389   if (! P.IsNull()) {
390     // compute the 3d curve
391     gp_Ax2 axes = P->Position().Ax2();
392     Handle(Geom_Curve) C3d = GeomLib::To3d(axes,PC);
393     if (C3d.IsNull())
394       return Standard_False;
395     // update the edge
396     Standard_Real First, Last;
397 
398     BRep_Builder B;
399     B.UpdateEdge(AnEdge,C3d,LocalLoc,0.0e0);
400     BRep_Tool::Range(AnEdge, S, LC, First, Last);
401     B.Range(AnEdge, First, Last); //Do not forget 3D range.(PRO6412)
402   }
403   else {
404     //
405     // compute the 3d curve using existing surface
406     //
407     fc = f ;
408     lc = l ;
409     if (!BRep_Tool::Degenerated(AnEdge)) {
410       jj = 0 ;
411       for (ii = 0 ; ii < 3 ; ii++ ) {
412         BRep_Tool::CurveOnSurface(TopoDS::Edge(AnEdge),
413           Curve2dPtr,
414           SurfacePtr,
415           LocalLoc,
416           fc,
417           lc,
418           ii) ;
419 
420         if (!Curve2dPtr.IsNull() && jj < 2){
421           Curve2dArray[jj] = Curve2dPtr ;
422           SurfaceArray[jj] = SurfacePtr ;
423           L[jj] = LocalLoc ;
424           first[jj] = fc ;
425           last[jj] = lc ;
426           jj += 1 ;
427         }
428       }
429       f = first[0] ;
430       l = last[0] ;
431       Curve2dPtr = Curve2dArray[0] ;
432       SurfacePtr = SurfaceArray[0] ;
433 
434       Geom2dAdaptor_Curve     AnAdaptor3dCurve2d (Curve2dPtr, f, l) ;
435       GeomAdaptor_Surface     AnAdaptor3dSurface (SurfacePtr) ;
436       Handle(Geom2dAdaptor_Curve) AnAdaptor3dCurve2dPtr =
437         new Geom2dAdaptor_Curve(AnAdaptor3dCurve2d) ;
438       Handle(GeomAdaptor_Surface) AnAdaptor3dSurfacePtr =
439         new GeomAdaptor_Surface (AnAdaptor3dSurface) ;
440       Adaptor3d_CurveOnSurface  CurveOnSurface( AnAdaptor3dCurve2dPtr,
441         AnAdaptor3dSurfacePtr) ;
442 
443       Handle(Geom_Curve) NewCurvePtr ;
444 
445       GeomLib::BuildCurve3d(Tolerance,
446         CurveOnSurface,
447         f,
448         l,
449         NewCurvePtr,
450         max_deviation,
451         average_deviation,
452         Continuity,
453         MaxDegree,
454         evaluateMaxSegment(MaxSegment,CurveOnSurface)) ;
455       BRep_Builder B;
456       tolerance = BRep_Tool::Tolerance(AnEdge) ;
457       //Patch
458       //max_deviation = Max(tolerance, max_deviation) ;
459       max_deviation = Max( tolerance, Tolerance );
460       if (NewCurvePtr.IsNull())
461         return Standard_False;
462       B.UpdateEdge(TopoDS::Edge(AnEdge),
463         NewCurvePtr,
464         L[0],
465         max_deviation) ;
466       if (jj == 1 ) {
467         //
468         // if there is only one curve on surface attached to the edge
469         // than it can be qualified sameparameter
470         //
471         B.SameParameter(TopoDS::Edge(AnEdge),
472           Standard_True) ;
473       }
474     }
475     else {
476       return Standard_False ;
477     }
478 
479   }
480   return Standard_True;
481 }
482 //=======================================================================
483 //function : BuildCurves3d
484 //purpose  :
485 //=======================================================================
486 
BuildCurves3d(const TopoDS_Shape & S)487 Standard_Boolean  BRepLib::BuildCurves3d(const TopoDS_Shape& S)
488 
489 {
490   return BRepLib::BuildCurves3d(S,
491     1.0e-5) ;
492 }
493 
494 //=======================================================================
495 //function : BuildCurves3d
496 //purpose  :
497 //=======================================================================
498 
BuildCurves3d(const TopoDS_Shape & S,const Standard_Real Tolerance,const GeomAbs_Shape Continuity,const Standard_Integer MaxDegree,const Standard_Integer MaxSegment)499 Standard_Boolean  BRepLib::BuildCurves3d(const TopoDS_Shape& S,
500   const Standard_Real Tolerance,
501   const GeomAbs_Shape Continuity,
502   const Standard_Integer MaxDegree,
503   const Standard_Integer MaxSegment)
504 {
505   Standard_Boolean boolean_value,
506     ok = Standard_True;
507   TopTools_MapOfShape a_counter ;
508   TopExp_Explorer ex(S,TopAbs_EDGE);
509 
510   while (ex.More()) {
511     if (a_counter.Add(ex.Current())) {
512       boolean_value =
513         BuildCurve3d(TopoDS::Edge(ex.Current()),
514         Tolerance, Continuity,
515         MaxDegree, MaxSegment);
516       ok = ok && boolean_value ;
517     }
518     ex.Next();
519   }
520   return ok;
521 }
522 //=======================================================================
523 //function : UpdateEdgeTolerance
524 //purpose  :
525 //=======================================================================
526 
UpdateEdgeTol(const TopoDS_Edge & AnEdge,const Standard_Real MinToleranceRequested,const Standard_Real MaxToleranceToCheck)527 Standard_Boolean  BRepLib::UpdateEdgeTol(const TopoDS_Edge& AnEdge,
528   const Standard_Real MinToleranceRequested,
529   const Standard_Real MaxToleranceToCheck)
530 {
531 
532   Standard_Integer curve_on_surface_index,
533     curve_index,
534     not_done,
535     has_closed_curve,
536     has_curve,
537     jj,
538     ii,
539     geom_reference_curve_flag = 0,
540     max_sampling_points = 90,
541     min_sampling_points = 30 ;
542 
543   Standard_Real factor = 100.0e0,
544     //     sampling_array[2],
545     safe_factor = 1.4e0,
546     current_last,
547     current_first,
548     max_distance,
549     coded_edge_tolerance,
550     edge_tolerance = 0.0e0 ;
551   Handle(TColStd_HArray1OfReal) parameters_ptr ;
552   Handle(BRep_GCurve) geometric_representation_ptr ;
553 
554   if (BRep_Tool::Degenerated(AnEdge)) return Standard_False ;
555   coded_edge_tolerance = BRep_Tool::Tolerance(AnEdge) ;
556   if (coded_edge_tolerance > MaxToleranceToCheck) return Standard_False ;
557 
558   const Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*)&AnEdge.TShape());
559   BRep_ListOfCurveRepresentation& list_curve_rep = TE->ChangeCurves() ;
560   BRep_ListIteratorOfListOfCurveRepresentation an_iterator(list_curve_rep),
561     second_iterator(list_curve_rep) ;
562   Handle(Geom2d_Curve) curve2d_ptr, new_curve2d_ptr;
563   Handle(Geom_Surface) surface_ptr ;
564   TopLoc_Location local_location ;
565   GCPnts_QuasiUniformDeflection  a_sampler ;
566   GeomAdaptor_Curve  geom_reference_curve ;
567   Adaptor3d_CurveOnSurface  curve_on_surface_reference ;
568   Handle(Geom_Curve) C = BRep_Tool::Curve(AnEdge,
569     local_location,
570     current_first,
571     current_last);
572   curve_on_surface_index = -1 ;
573   if (!C.IsNull()) {
574     if (! local_location.IsIdentity()) {
575       C = Handle(Geom_Curve)::
576         DownCast(C-> Transformed(local_location.Transformation()) ) ;
577     }
578     geom_reference_curve.Load(C) ;
579     geom_reference_curve_flag = 1 ;
580     a_sampler.Initialize(geom_reference_curve,
581       MinToleranceRequested * factor,
582       current_first,
583       current_last) ;
584   }
585   else {
586     not_done = 1 ;
587     curve_on_surface_index = 0 ;
588 
589     while (not_done && an_iterator.More()) {
590       geometric_representation_ptr =
591         Handle(BRep_GCurve)::DownCast(second_iterator.Value());
592       if (!geometric_representation_ptr.IsNull()
593         && geometric_representation_ptr->IsCurveOnSurface()) {
594           curve2d_ptr = geometric_representation_ptr->PCurve() ;
595           local_location = geometric_representation_ptr->Location() ;
596           current_first = geometric_representation_ptr->First();
597           //first = geometric_representation_ptr->First();
598           current_last =  geometric_representation_ptr->Last();
599           // must be inverted
600           //
601           if (! local_location.IsIdentity() ) {
602             surface_ptr = Handle(Geom_Surface)::
603               DownCast( geometric_representation_ptr->Surface()->
604               Transformed(local_location.Transformation()) ) ;
605           }
606           else {
607             surface_ptr =
608               geometric_representation_ptr->Surface() ;
609           }
610           not_done = 0 ;
611       }
612       curve_on_surface_index += 1 ;
613     }
614     Geom2dAdaptor_Curve     AnAdaptor3dCurve2d (curve2d_ptr) ;
615     GeomAdaptor_Surface     AnAdaptor3dSurface (surface_ptr) ;
616     Handle(Geom2dAdaptor_Curve) AnAdaptor3dCurve2dPtr =
617       new Geom2dAdaptor_Curve(AnAdaptor3dCurve2d) ;
618     Handle(GeomAdaptor_Surface) AnAdaptor3dSurfacePtr =
619       new GeomAdaptor_Surface (AnAdaptor3dSurface) ;
620     curve_on_surface_reference.Load (AnAdaptor3dCurve2dPtr, AnAdaptor3dSurfacePtr);
621     a_sampler.Initialize(curve_on_surface_reference,
622       MinToleranceRequested * factor,
623       current_first,
624       current_last) ;
625   }
626   TColStd_Array1OfReal   sampling_parameters(1,a_sampler.NbPoints()) ;
627   for (ii = 1 ; ii <= a_sampler.NbPoints() ; ii++) {
628     sampling_parameters(ii) = a_sampler.Parameter(ii) ;
629   }
630   if (a_sampler.NbPoints() < min_sampling_points) {
631     GeomLib::DensifyArray1OfReal(min_sampling_points,
632       sampling_parameters,
633       parameters_ptr) ;
634   }
635   else if (a_sampler.NbPoints() > max_sampling_points) {
636     GeomLib::RemovePointsFromArray(max_sampling_points,
637       sampling_parameters,
638       parameters_ptr) ;
639   }
640   else {
641     jj = 1 ;
642     parameters_ptr =
643       new TColStd_HArray1OfReal(1,sampling_parameters.Length()) ;
644     for (ii = sampling_parameters.Lower() ; ii <= sampling_parameters.Upper() ; ii++) {
645       parameters_ptr->ChangeArray1()(jj) =
646         sampling_parameters(ii) ;
647       jj +=1 ;
648     }
649   }
650 
651   curve_index = 0 ;
652 
653   while (second_iterator.More()) {
654     geometric_representation_ptr =
655       Handle(BRep_GCurve)::DownCast(second_iterator.Value());
656     if (! geometric_representation_ptr.IsNull() &&
657       curve_index != curve_on_surface_index) {
658         has_closed_curve =
659           has_curve = Standard_False ;
660         //	first = geometric_representation_ptr->First();
661         //	last =  geometric_representation_ptr->Last();
662         local_location = geometric_representation_ptr->Location() ;
663         if (geometric_representation_ptr->IsCurveOnSurface()) {
664           curve2d_ptr = geometric_representation_ptr->PCurve() ;
665           has_curve = Standard_True ;
666         }
667         if (geometric_representation_ptr->IsCurveOnClosedSurface()) {
668           curve2d_ptr = geometric_representation_ptr->PCurve2() ;
669           has_closed_curve = Standard_True ;
670         }
671 
672         if (has_curve ||
673           has_closed_curve) {
674             if (! local_location.IsIdentity() ) {
675               surface_ptr = Handle(Geom_Surface)::
676                 DownCast( geometric_representation_ptr->Surface()->
677                 Transformed(local_location.Transformation()) ) ;
678             }
679             else {
680               surface_ptr =
681                 geometric_representation_ptr->Surface() ;
682             }
683             Geom2dAdaptor_Curve     an_adaptor_curve2d (curve2d_ptr) ;
684             GeomAdaptor_Surface     an_adaptor_surface(surface_ptr) ;
685             Handle(Geom2dAdaptor_Curve) an_adaptor_curve2d_ptr =
686               new Geom2dAdaptor_Curve(an_adaptor_curve2d) ;
687             Handle(GeomAdaptor_Surface) an_adaptor_surface_ptr =
688               new GeomAdaptor_Surface (an_adaptor_surface) ;
689             Adaptor3d_CurveOnSurface a_curve_on_surface(an_adaptor_curve2d_ptr,
690               an_adaptor_surface_ptr) ;
691 
692             if (BRep_Tool::SameParameter(AnEdge)) {
693 
694               GeomLib::EvalMaxParametricDistance(a_curve_on_surface,
695                 geom_reference_curve,
696                 MinToleranceRequested,
697                 parameters_ptr->Array1(),
698                 max_distance) ;
699             }
700             else if (geom_reference_curve_flag) {
701               GeomLib::EvalMaxDistanceAlongParameter(a_curve_on_surface,
702                 geom_reference_curve,
703                 MinToleranceRequested,
704                 parameters_ptr->Array1(),
705                 max_distance) ;
706             }
707             else {
708 
709               GeomLib::EvalMaxDistanceAlongParameter(a_curve_on_surface,
710                 curve_on_surface_reference,
711                 MinToleranceRequested,
712                 parameters_ptr->Array1(),
713                 max_distance) ;
714             }
715             max_distance *= safe_factor ;
716             edge_tolerance = Max(max_distance, edge_tolerance) ;
717         }
718 
719 
720     }
721     curve_index += 1 ;
722     second_iterator.Next() ;
723   }
724 
725   TE->Tolerance(edge_tolerance);
726   return Standard_True ;
727 
728 }
729 //=======================================================================
730 //function : UpdateEdgeTolerance
731 //purpose  :
732 //=======================================================================
UpdateEdgeTolerance(const TopoDS_Shape & S,const Standard_Real MinToleranceRequested,const Standard_Real MaxToleranceToCheck)733 Standard_Boolean BRepLib::UpdateEdgeTolerance(const TopoDS_Shape& S,
734   const Standard_Real MinToleranceRequested,
735   const Standard_Real MaxToleranceToCheck)
736 {
737   TopExp_Explorer ex(S,TopAbs_EDGE);
738   TopTools_MapOfShape  a_counter ;
739 
740   Standard_Boolean     return_status = Standard_False,
741     local_flag ;
742 
743   while (ex.More()) {
744     if (a_counter.Add(ex.Current())) {
745       local_flag =
746         BRepLib::UpdateEdgeTol(TopoDS::Edge(ex.Current()),
747         MinToleranceRequested,
748         MaxToleranceToCheck) ;
749       if (local_flag && ! return_status) {
750         return_status = Standard_True ;
751       }
752     }
753     ex.Next();
754   }
755   return return_status ;
756 }
757 
758 //=======================================================================
759 //function : GetEdgeTol
760 //purpose  :
761 //=======================================================================
GetEdgeTol(const TopoDS_Edge & theEdge,const TopoDS_Face & theFace,Standard_Real & theEdTol)762 static void GetEdgeTol(const TopoDS_Edge& theEdge,
763   const TopoDS_Face& theFace, Standard_Real& theEdTol)
764 {
765   TopLoc_Location L;
766   const Handle(Geom_Surface)& S = BRep_Tool::Surface(theFace,L);
767   TopLoc_Location l = L.Predivided(theEdge.Location());
768 
769   const Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*)&theEdge.TShape());
770   BRep_ListIteratorOfListOfCurveRepresentation itcr(TE->Curves());
771 
772   while (itcr.More()) {
773     const Handle(BRep_CurveRepresentation)& cr = itcr.Value();
774     if(cr->IsCurveOnSurface(S,l)) return;
775     itcr.Next();
776   }
777 
778   Handle(Geom_Plane) GP;
779   Handle(Geom_RectangularTrimmedSurface) GRTS;
780   GRTS = Handle(Geom_RectangularTrimmedSurface)::DownCast(S);
781   if(!GRTS.IsNull())
782     GP = Handle(Geom_Plane)::DownCast(GRTS->BasisSurface());
783   else
784     GP = Handle(Geom_Plane)::DownCast(S);
785 
786   Handle(GeomAdaptor_Curve) HC = new GeomAdaptor_Curve();
787   Handle(GeomAdaptor_Surface) HS = new GeomAdaptor_Surface();
788 
789   TopLoc_Location LC;
790   Standard_Real First, Last;
791   HC->Load(BRep_Tool::Curve(theEdge,LC,First,Last));
792   LC = L.Predivided(LC);
793 
794   if (!LC.IsIdentity()) {
795     GP = Handle(Geom_Plane)::DownCast(
796       GP->Transformed(LC.Transformation()));
797   }
798   GeomAdaptor_Surface& GAS = *HS;
799   GAS.Load(GP);
800 
801   ProjLib_ProjectedCurve Proj(HS,HC);
802   Handle(Geom2d_Curve) pc = Geom2dAdaptor::MakeCurve(Proj);
803 
804   gp_Pln pln = GAS.Plane();
805   Standard_Real d2 = 0.;
806   Standard_Integer nn = 23;
807   Standard_Real unsurnn = 1./nn;
808   for(Standard_Integer i = 0; i <= nn; i++){
809     Standard_Real t = unsurnn*i;
810     Standard_Real u = First*(1.-t) + Last*t;
811     gp_Pnt Pc3d = HC->Value(u);
812     gp_Pnt2d p2d = pc->Value(u);
813     gp_Pnt Pcons = ElSLib::Value(p2d.X(),p2d.Y(),pln);
814     Standard_Real eps = Max(Pc3d.XYZ().SquareModulus(), Pcons.XYZ().SquareModulus());
815     eps = Epsilon(eps);
816     Standard_Real temp = Pc3d.SquareDistance(Pcons);
817     if(temp <= eps)
818     {
819       temp = 0.;
820     }
821     if(temp > d2) d2 = temp;
822   }
823   d2 = 1.5*sqrt(d2);
824   theEdTol = d2;
825 }
826 
827 //=======================================================================
828 //function : UpdTolMap
829 //purpose  : Update map ShToTol (shape to tolerance)
830 //=======================================================================
UpdTolMap(const TopoDS_Shape & theSh,Standard_Real theNewTol,TopTools_DataMapOfShapeReal & theShToTol)831 static void UpdTolMap(const TopoDS_Shape& theSh, Standard_Real theNewTol,
832   TopTools_DataMapOfShapeReal& theShToTol)
833 {
834   TopAbs_ShapeEnum aSt = theSh.ShapeType();
835   Standard_Real aShTol;
836   if (aSt == TopAbs_VERTEX)
837     aShTol = BRep_Tool::Tolerance(TopoDS::Vertex(theSh));
838   else if (aSt == TopAbs_EDGE)
839     aShTol = BRep_Tool::Tolerance(TopoDS::Edge(theSh));
840   else
841     return;
842   //
843   if (theNewTol > aShTol)
844   {
845     const Standard_Real* anOldtol = theShToTol.Seek(theSh);
846     if (!anOldtol)
847       theShToTol.Bind(theSh, theNewTol);
848     else
849       theShToTol(theSh) = Max(*anOldtol, theNewTol);
850   }
851 }
852 
853 //=======================================================================
854 //function : UpdShTol
855 //purpose  : Update vertices/edges/faces according to ShToTol map (create copies of necessary)
856 //=======================================================================
UpdShTol(const TopTools_DataMapOfShapeReal & theShToTol,const Standard_Boolean IsMutableInput,BRepTools_ReShape & theReshaper,Standard_Boolean theVForceUpdate)857 static void UpdShTol(const TopTools_DataMapOfShapeReal& theShToTol,
858   const Standard_Boolean IsMutableInput, BRepTools_ReShape& theReshaper,
859   Standard_Boolean theVForceUpdate)
860 {
861   BRep_Builder aB;
862   TopTools_DataMapIteratorOfDataMapOfShapeReal SHToTolit(theShToTol);
863   for (;SHToTolit.More();SHToTolit.Next())
864   {
865     const TopoDS_Shape& aSh = SHToTolit.Key();
866     Standard_Real aTol = SHToTolit.Value();
867     //
868     TopoDS_Shape aNsh;
869     const TopoDS_Shape& aVsh = theReshaper.Value(aSh);
870     Standard_Boolean UseOldSh = IsMutableInput || theReshaper.IsNewShape(aSh) || !aVsh.IsSame(aSh);
871     if (UseOldSh)
872       aNsh = aVsh;
873     else
874     {
875       aNsh = aSh.EmptyCopied();
876       //add subshapes from the original shape
877       TopoDS_Iterator sit(aSh);
878       for (;sit.More();sit.Next())
879         aB.Add(aNsh, sit.Value());
880       //
881       aNsh.Free(aSh.Free());
882       aNsh.Checked(aSh.Checked());
883       aNsh.Orientable(aSh.Orientable());
884       aNsh.Closed(aSh.Closed());
885       aNsh.Infinite(aSh.Infinite());
886       aNsh.Convex(aSh.Convex());
887       //
888     }
889     //
890     switch (aSh.ShapeType())
891     {
892     case TopAbs_FACE:
893       {
894         aB.UpdateFace(TopoDS::Face(aNsh), aTol);
895         break;
896       }
897     case TopAbs_EDGE:
898       {
899         aB.UpdateEdge(TopoDS::Edge(aNsh), aTol);
900         break;
901       }
902     case TopAbs_VERTEX:
903       {
904         const Handle(BRep_TVertex)& aTV = *((Handle(BRep_TVertex)*)&aNsh.TShape());
905         //
906         if(aTV->Locked())
907           throw TopoDS_LockedShape("BRep_Builder::UpdateVertex");
908         //
909         if (theVForceUpdate)
910           aTV->Tolerance(aTol);
911         else
912           aTV->UpdateTolerance(aTol);
913         aTV->Modified(Standard_True);
914         break;
915       }
916     default:
917       break;
918     }
919     //
920     if (!UseOldSh)
921       theReshaper.Replace(aSh, aNsh);
922   }
923 }
924 
925 //=======================================================================
926 //function : InternalSameParameter
927 //purpose  :
928 //=======================================================================
InternalSameParameter(const TopoDS_Shape & theSh,BRepTools_ReShape & theReshaper,const Standard_Real theTol,const Standard_Boolean IsForced,const Standard_Boolean IsMutableInput)929 static void InternalSameParameter(const TopoDS_Shape& theSh, BRepTools_ReShape& theReshaper,
930   const Standard_Real theTol, const Standard_Boolean IsForced, const Standard_Boolean IsMutableInput )
931 {
932   TopExp_Explorer ex(theSh,TopAbs_EDGE);
933   TopTools_MapOfShape  Done;
934   BRep_Builder aB;
935   TopTools_DataMapOfShapeReal aShToTol;
936 
937   while (ex.More())
938   {
939     const TopoDS_Edge& aCE = TopoDS::Edge(ex.Current());
940     if (Done.Add(aCE))
941     {
942       TopoDS_Edge aNE = TopoDS::Edge(theReshaper.Value(aCE));
943       Standard_Boolean UseOldEdge = IsMutableInput || theReshaper.IsNewShape(aCE) || !aNE.IsSame(aCE);
944       if (IsForced && (BRep_Tool::SameRange(aCE) || BRep_Tool::SameParameter(aCE)))
945       {
946         if (!UseOldEdge)
947         {
948           aNE = TopoDS::Edge(aCE.EmptyCopied());
949           TopoDS_Iterator sit(aCE);
950           for (;sit.More();sit.Next())
951             aB.Add(aNE, sit.Value());
952           theReshaper.Replace(aCE, aNE);
953           UseOldEdge = Standard_True;
954         }
955         aB.SameRange(aNE, Standard_False);
956         aB.SameParameter(aNE, Standard_False);
957       }
958       Standard_Real aNewTol = -1;
959       TopoDS_Edge aResEdge = BRepLib::SameParameter(aNE, theTol, aNewTol, UseOldEdge);
960       if (!UseOldEdge && !aResEdge.IsNull())
961         //NE have been empty-copied
962         theReshaper.Replace(aNE, aResEdge);
963       if (aNewTol > 0)
964       {
965         TopoDS_Vertex aV1, aV2;
966         TopExp::Vertices(aCE,aV1,aV2);
967         if (!aV1.IsNull())
968           UpdTolMap(aV1, aNewTol, aShToTol);
969         if (!aV2.IsNull())
970           UpdTolMap(aV2, aNewTol, aShToTol);
971       }
972     }
973     ex.Next();
974   }
975 
976   Done.Clear();
977   BRepAdaptor_Surface BS;
978   for(ex.Init(theSh,TopAbs_FACE); ex.More(); ex.Next()){
979     const TopoDS_Face& curface = TopoDS::Face(ex.Current());
980     if(!Done.Add(curface)) continue;
981     BS.Initialize(curface);
982     if(BS.GetType() != GeomAbs_Plane) continue;
983     TopExp_Explorer ex2;
984     for(ex2.Init(curface,TopAbs_EDGE); ex2.More(); ex2.Next()){
985       const TopoDS_Edge& E = TopoDS::Edge(ex2.Current());
986       TopoDS_Shape aNe = theReshaper.Value(E);
987       Standard_Real aNewEtol = -1;
988       GetEdgeTol(TopoDS::Edge(aNe), curface, aNewEtol);
989       if (aNewEtol >= 0) //not equal to -1
990         UpdTolMap(E, aNewEtol, aShToTol);
991     }
992   }
993 
994   //
995   UpdShTol(aShToTol, IsMutableInput, theReshaper, Standard_False );
996 
997   InternalUpdateTolerances(theSh, Standard_False, IsMutableInput, theReshaper );
998 }
999 
1000 //================================================================
1001 //function : SameParameter
1002 //WARNING  : New spec DUB LBO 9/9/97.
1003 //  Recode in the edge the best tolerance found,
1004 //  for vertex extremities it is required to find something else
1005 //================================================================
SameParameter(const TopoDS_Shape & S,const Standard_Real Tolerance,const Standard_Boolean forced)1006 void  BRepLib::SameParameter(const TopoDS_Shape& S,
1007   const Standard_Real Tolerance,
1008   const Standard_Boolean forced)
1009 {
1010   BRepTools_ReShape reshaper;
1011   InternalSameParameter( S, reshaper, Tolerance, forced, Standard_True);
1012 }
1013 
1014 //=======================================================================
1015 //function : SameParameter
1016 //purpose  :
1017 //=======================================================================
SameParameter(const TopoDS_Shape & S,BRepTools_ReShape & theReshaper,const Standard_Real Tolerance,const Standard_Boolean forced)1018 void BRepLib::SameParameter(const TopoDS_Shape& S, BRepTools_ReShape& theReshaper,
1019   const Standard_Real Tolerance, const Standard_Boolean forced )
1020 {
1021   InternalSameParameter( S, theReshaper, Tolerance, forced, Standard_False);
1022 }
1023 
1024 //=======================================================================
1025 //function : EvalTol
1026 //purpose  :
1027 //=======================================================================
EvalTol(const Handle (Geom2d_Curve)& pc,const Handle (Geom_Surface)& s,const GeomAdaptor_Curve & gac,const Standard_Real tol,Standard_Real & tolbail)1028 static Standard_Boolean EvalTol(const Handle(Geom2d_Curve)& pc,
1029   const Handle(Geom_Surface)& s,
1030   const GeomAdaptor_Curve&    gac,
1031   const Standard_Real         tol,
1032   Standard_Real&              tolbail)
1033 {
1034   Standard_Integer ok = 0;
1035   Standard_Real f = gac.FirstParameter();
1036   Standard_Real l = gac.LastParameter();
1037   Extrema_LocateExtPC Projector;
1038   Projector.Initialize(gac,f,l,tol);
1039   Standard_Real u,v;
1040   gp_Pnt p;
1041   tolbail = tol;
1042   for(Standard_Integer i = 1; i <= 5; i++){
1043     Standard_Real t = i/6.;
1044     t = (1.-t) * f + t * l;
1045     pc->Value(t).Coord(u,v);
1046     p = s->Value(u,v);
1047     Projector.Perform(p,t);
1048     if (Projector.IsDone()) {
1049       Standard_Real dist2 = Projector.SquareDistance();
1050       if(dist2 > tolbail * tolbail) tolbail = sqrt (dist2);
1051       ok++;
1052     }
1053   }
1054   return (ok > 2);
1055 }
1056 
1057 //=======================================================================
1058 //function : ComputeTol
1059 //purpose  :
1060 //=======================================================================
ComputeTol(const Handle (Adaptor3d_Curve)& c3d,const Handle (Adaptor2d_Curve2d)& c2d,const Handle (Adaptor3d_Surface)& surf,const Standard_Integer nbp)1061 static Standard_Real ComputeTol(const Handle(Adaptor3d_Curve)& c3d,
1062   const Handle(Adaptor2d_Curve2d)& c2d,
1063   const Handle(Adaptor3d_Surface)& surf,
1064   const Standard_Integer        nbp)
1065 
1066 {
1067 
1068   TColStd_Array1OfReal dist(1,nbp+10);
1069   dist.Init(-1.);
1070 
1071   //Adaptor3d_CurveOnSurface  cons(c2d,surf);
1072   Standard_Real uf = surf->FirstUParameter(), ul = surf->LastUParameter(),
1073                 vf = surf->FirstVParameter(), vl = surf->LastVParameter();
1074   Standard_Real du = 0.01 * (ul - uf), dv = 0.01 * (vl - vf);
1075   Standard_Boolean isUPeriodic = surf->IsUPeriodic(), isVPeriodic = surf->IsVPeriodic();
1076   Standard_Real DSdu = 1./surf->UResolution(1.), DSdv = 1./surf->VResolution(1.);
1077   Standard_Real d2 = 0.;
1078   Standard_Real first = c3d->FirstParameter();
1079   Standard_Real last  = c3d->LastParameter();
1080   Standard_Real dapp = -1.;
1081   for (Standard_Integer i = 0; i <= nbp; ++i)
1082   {
1083     const Standard_Real t = IntToReal(i)/IntToReal(nbp);
1084     const Standard_Real u = first*(1.-t) + last*t;
1085     gp_Pnt Pc3d = c3d->Value(u);
1086     gp_Pnt2d Puv = c2d->Value(u);
1087     if(!isUPeriodic)
1088     {
1089       if(Puv.X() < uf - du)
1090       {
1091         dapp = Max(dapp, DSdu * (uf - Puv.X()));
1092         continue;
1093       }
1094       else if(Puv.X() > ul + du)
1095       {
1096         dapp = Max(dapp, DSdu * (Puv.X() - ul));
1097         continue;
1098       }
1099     }
1100     if(!isVPeriodic)
1101     {
1102       if(Puv.Y() < vf - dv)
1103       {
1104         dapp = Max(dapp, DSdv * (vf - Puv.Y()));
1105         continue;
1106       }
1107       else if(Puv.Y() > vl + dv)
1108       {
1109         dapp = Max(dapp, DSdv * (Puv.Y() - vl));
1110         continue;
1111       }
1112     }
1113     gp_Pnt Pcons = surf->Value(Puv.X(), Puv.Y());
1114     if (Precision::IsInfinite(Pcons.X()) ||
1115         Precision::IsInfinite(Pcons.Y()) ||
1116         Precision::IsInfinite(Pcons.Z()))
1117     {
1118       d2 = Precision::Infinite();
1119       break;
1120     }
1121     Standard_Real temp = Pc3d.SquareDistance(Pcons);
1122 
1123     dist(i+1) = temp;
1124 
1125     d2 = Max (d2, temp);
1126   }
1127 
1128   if(Precision::IsInfinite(d2))
1129   {
1130     return d2;
1131   }
1132 
1133   d2 = Sqrt(d2);
1134   if(dapp > d2)
1135   {
1136     return dapp;
1137   }
1138 
1139   Standard_Boolean ana = Standard_False;
1140   Standard_Real D2 = 0;
1141   Standard_Integer N1 = 0;
1142   Standard_Integer N2 = 0;
1143   Standard_Integer N3 = 0;
1144 
1145   for (Standard_Integer i = 1; i<= nbp+10; ++i)
1146   {
1147     if (dist(i) > 0)
1148     {
1149       if (dist(i) < 1.0)
1150       {
1151         ++N1;
1152       }
1153       else
1154       {
1155         ++N2;
1156       }
1157     }
1158   }
1159 
1160   if (N1 > N2 && N2 != 0)
1161   {
1162     N3 = 100*N2/(N1+N2);
1163   }
1164   if (N3 < 10 && N3 != 0)
1165   {
1166     ana = Standard_True;
1167     for (Standard_Integer i = 1; i <= nbp+10; ++i)
1168     {
1169       if (dist(i) > 0 && dist(i) < 1.0)
1170       {
1171         D2 = Max (D2, dist(i));
1172       }
1173     }
1174   }
1175 
1176   //d2 = 1.5*sqrt(d2);
1177   d2 = (!ana) ? 1.5 * d2 : 1.5*sqrt(D2);
1178   d2 = Max (d2, 1.e-7);
1179   return d2;
1180 }
1181 
1182 //=======================================================================
1183 //function : GetCurve3d
1184 //purpose  :
1185 //=======================================================================
GetCurve3d(const TopoDS_Edge & theEdge,Handle (Geom_Curve)& theC3d,Standard_Real & theF3d,Standard_Real & theL3d,TopLoc_Location & theLoc3d,BRep_ListOfCurveRepresentation & theCList)1186 static void GetCurve3d(const TopoDS_Edge& theEdge, Handle(Geom_Curve)& theC3d, Standard_Real& theF3d,
1187   Standard_Real& theL3d, TopLoc_Location& theLoc3d, BRep_ListOfCurveRepresentation& theCList)
1188 {
1189   const Handle(BRep_TEdge)& aTE = *((Handle(BRep_TEdge)*) &theEdge.TShape());
1190   theCList = aTE->ChangeCurves(); // current function (i.e. GetCurve3d()) will not change any of this curves
1191   BRep_ListIteratorOfListOfCurveRepresentation anIt(theCList);
1192   Standard_Boolean NotDone = Standard_True;
1193   while (NotDone && anIt.More()) {
1194     Handle(BRep_GCurve) GCurve = Handle(BRep_GCurve)::DownCast(anIt.Value());
1195     if (!GCurve.IsNull() && GCurve->IsCurve3D()) {
1196       theC3d = GCurve->Curve3D() ;
1197       theF3d = GCurve->First();
1198       theL3d = GCurve->Last();
1199       theLoc3d = GCurve->Location() ;
1200       NotDone = Standard_False;
1201     }
1202     anIt.Next() ;
1203   }
1204 }
1205 
1206 //=======================================================================
1207 //function : UpdateVTol
1208 //purpose  :
1209 //=======================================================================
UpdateVTol(const TopoDS_Vertex theV1,const TopoDS_Vertex & theV2,Standard_Real theTol)1210 void UpdateVTol(const TopoDS_Vertex theV1, const TopoDS_Vertex& theV2, Standard_Real theTol)
1211 {
1212   BRep_Builder aB;
1213   if (!theV1.IsNull())
1214     aB.UpdateVertex(theV1,theTol);
1215   if (!theV2.IsNull())
1216     aB.UpdateVertex(theV2,theTol);
1217 }
1218 
1219 //=======================================================================
1220 //function : SameParameter
1221 //purpose  :
1222 //=======================================================================
SameParameter(const TopoDS_Edge & theEdge,const Standard_Real theTolerance)1223 void BRepLib::SameParameter(const TopoDS_Edge& theEdge,
1224   const Standard_Real theTolerance)
1225 {
1226   Standard_Real aNewTol = -1;
1227   SameParameter(theEdge, theTolerance, aNewTol, Standard_True);
1228   if (aNewTol > 0)
1229   {
1230     TopoDS_Vertex aV1, aV2;
1231     TopExp::Vertices(theEdge,aV1,aV2);
1232     UpdateVTol(aV1, aV2, aNewTol);
1233   }
1234 }
1235 
1236 //=======================================================================
1237 //function : SameParameter
1238 //purpose  :
1239 //=======================================================================
SameParameter(const TopoDS_Edge & theEdge,const Standard_Real theTolerance,Standard_Real & theNewTol,Standard_Boolean IsUseOldEdge)1240 TopoDS_Edge BRepLib::SameParameter(const TopoDS_Edge& theEdge,
1241   const Standard_Real theTolerance, Standard_Real& theNewTol, Standard_Boolean IsUseOldEdge)
1242 {
1243   if (BRep_Tool::SameParameter(theEdge))
1244     return TopoDS_Edge();
1245   Standard_Real f3d =0.,l3d =0.;
1246   TopLoc_Location L3d;
1247   Handle(Geom_Curve) C3d;
1248   BRep_ListOfCurveRepresentation CList;
1249   GetCurve3d(theEdge, C3d, f3d, l3d, L3d, CList);
1250   if(C3d.IsNull())
1251     return TopoDS_Edge();
1252 
1253   BRep_Builder B;
1254   TopoDS_Edge aNE;
1255   Handle(BRep_TEdge) aNTE;
1256   if (IsUseOldEdge)
1257   {
1258     aNE = theEdge;
1259     aNTE = *((Handle(BRep_TEdge)*) &theEdge.TShape());
1260   }
1261   else
1262   {
1263     aNE = TopoDS::Edge(theEdge.EmptyCopied()); //will be modified a little bit later, so copy anyway
1264     GetCurve3d(aNE, C3d, f3d, l3d, L3d, CList); //C3d pointer and CList will be differ after copying
1265     aNTE = *((Handle(BRep_TEdge)*) &aNE.TShape());
1266     TopoDS_Iterator sit(theEdge);
1267     for (;sit.More();sit.Next()) //add vertices from old edge to the new ones
1268       B.Add(aNE, sit.Value());
1269   }
1270 
1271   BRep_ListIteratorOfListOfCurveRepresentation It(CList);
1272 
1273   const Standard_Integer NCONTROL = 22;
1274 
1275   Handle(GeomAdaptor_Curve) HC = new GeomAdaptor_Curve();
1276   Handle(Geom2dAdaptor_Curve) HC2d = new Geom2dAdaptor_Curve();
1277   Handle(GeomAdaptor_Surface) HS = new GeomAdaptor_Surface();
1278   GeomAdaptor_Curve& GAC = *HC;
1279   Geom2dAdaptor_Curve& GAC2d = *HC2d;
1280   GeomAdaptor_Surface& GAS = *HS;
1281 
1282   // modified by NIZHNY-OCC486  Tue Aug 27 17:15:13 2002 :
1283   Standard_Boolean m_TrimmedPeriodical = Standard_False;
1284   Handle(Standard_Type) TheType = C3d->DynamicType();
1285   if( TheType == STANDARD_TYPE(Geom_TrimmedCurve))
1286   {
1287     Handle(Geom_Curve) gtC (Handle(Geom_TrimmedCurve)::DownCast (C3d)->BasisCurve());
1288     m_TrimmedPeriodical = gtC->IsPeriodic();
1289   }
1290   // modified by NIZHNY-OCC486  Tue Aug 27 17:15:17 2002 .
1291 
1292 
1293   if(!C3d->IsPeriodic()) {
1294     Standard_Real Udeb = C3d->FirstParameter();
1295     Standard_Real Ufin = C3d->LastParameter();
1296     // modified by NIZHNY-OCC486  Tue Aug 27 17:17:14 2002 :
1297     //if (Udeb > f3d) f3d = Udeb;
1298     //if (l3d > Ufin) l3d = Ufin;
1299     if(!m_TrimmedPeriodical)
1300     {
1301       if (Udeb > f3d) f3d = Udeb;
1302       if (l3d > Ufin) l3d = Ufin;
1303     }
1304     // modified by NIZHNY-OCC486  Tue Aug 27 17:17:55 2002 .
1305   }
1306   if(!L3d.IsIdentity()){
1307     C3d = Handle(Geom_Curve)::DownCast(C3d->Transformed(L3d.Transformation()));
1308   }
1309   GAC.Load(C3d,f3d,l3d);
1310 
1311   Standard_Real Prec_C3d = BRepCheck::PrecCurve(GAC);
1312 
1313   Standard_Boolean IsSameP = 1;
1314   Standard_Real maxdist = 0.;
1315 
1316   //  Modified by skv - Thu Jun  3 12:39:19 2004 OCC5898 Begin
1317   Standard_Real anEdgeTol = BRep_Tool::Tolerance(aNE);
1318   //  Modified by skv - Thu Jun  3 12:39:20 2004 OCC5898 End
1319   Standard_Boolean SameRange = BRep_Tool::SameRange(aNE);
1320   Standard_Boolean YaPCu = Standard_False;
1321   const Standard_Real BigError = 1.e10;
1322   It.Initialize(CList);
1323 
1324   while (It.More()) {
1325 
1326     Standard_Boolean isANA = Standard_False;
1327     Standard_Boolean isBSP = Standard_False;
1328     Handle(BRep_GCurve) GCurve = Handle(BRep_GCurve)::DownCast(It.Value());
1329     Handle(Geom2d_Curve) PC[2];
1330     Handle(Geom_Surface) S;
1331     if (!GCurve.IsNull() && GCurve->IsCurveOnSurface()) {
1332       YaPCu = Standard_True;
1333       PC[0] = GCurve->PCurve();
1334       TopLoc_Location PCLoc = GCurve->Location();
1335       S = GCurve->Surface();
1336       if (!PCLoc.IsIdentity() ) {
1337         S = Handle(Geom_Surface)::DownCast(S->Transformed(PCLoc.Transformation()));
1338       }
1339 
1340       GAS.Load(S);
1341       if (GCurve->IsCurveOnClosedSurface()) {
1342         PC[1] = GCurve->PCurve2();
1343       }
1344 
1345       // Eval tol2d to compute SameRange
1346       Standard_Real TolSameRange = Max(GAC.Resolution(theTolerance), Precision::PConfusion());
1347       for(Standard_Integer i = 0; i < 2; i++){
1348         Handle(Geom2d_Curve) curPC = PC[i];
1349         Standard_Boolean updatepc = 0;
1350         if(curPC.IsNull()) break;
1351         if(!SameRange){
1352           GeomLib::SameRange(TolSameRange,
1353             PC[i],GCurve->First(),GCurve->Last(),
1354             f3d,l3d,curPC);
1355 
1356           updatepc = (curPC != PC[i]);
1357 
1358         }
1359         Standard_Boolean goodpc = 1;
1360         GAC2d.Load(curPC,f3d,l3d);
1361 
1362         Standard_Real error = ComputeTol(HC, HC2d, HS, NCONTROL);
1363 
1364         if(error > BigError)
1365         {
1366           maxdist = error;
1367           break;
1368         }
1369 
1370         if(GAC2d.GetType() == GeomAbs_BSplineCurve &&
1371           GAC2d.Continuity() == GeomAbs_C0) {
1372             Standard_Real UResol = GAS.UResolution(theTolerance);
1373             Standard_Real VResol = GAS.VResolution(theTolerance);
1374             Standard_Real TolConf2d = Min(UResol, VResol);
1375             TolConf2d = Max(TolConf2d, Precision::PConfusion());
1376             Handle(Geom2d_BSplineCurve) bs2d = GAC2d.BSpline();
1377             Handle(Geom2d_BSplineCurve) bs2dsov = bs2d;
1378             Standard_Real fC0 = bs2d->FirstParameter(), lC0 = bs2d->LastParameter();
1379             Standard_Boolean repar = Standard_True;
1380             gp_Pnt2d OriginPoint;
1381             bs2d->D0(fC0, OriginPoint);
1382             Geom2dConvert::C0BSplineToC1BSplineCurve(bs2d, TolConf2d);
1383             isBSP = Standard_True;
1384 
1385             if(bs2d->IsPeriodic()) { // -------- IFV, Jan 2000
1386               gp_Pnt2d NewOriginPoint;
1387               bs2d->D0(bs2d->FirstParameter(), NewOriginPoint);
1388               if(Abs(OriginPoint.X() - NewOriginPoint.X()) > Precision::PConfusion() ||
1389                 Abs(OriginPoint.Y() - NewOriginPoint.Y()) > Precision::PConfusion()    ) {
1390 
1391                   TColStd_Array1OfReal Knotbs2d (1, bs2d->NbKnots());
1392                   bs2d->Knots(Knotbs2d);
1393 
1394                   for(Standard_Integer Index = 1; Index <= bs2d->NbKnots(); Index++) {
1395                     bs2d->D0(Knotbs2d(Index), NewOriginPoint);
1396                     if(Abs(OriginPoint.X() - NewOriginPoint.X()) > Precision::PConfusion() ||
1397                       Abs(OriginPoint.Y() - NewOriginPoint.Y()) > Precision::PConfusion()    ) continue;
1398 
1399                     bs2d->SetOrigin(Index);
1400                     break;
1401                   }
1402               }
1403             }
1404 
1405             if(bs2d->Continuity() == GeomAbs_C0) {
1406               Standard_Real tolbail;
1407               if(EvalTol(curPC,S,GAC,theTolerance,tolbail)){
1408                 bs2d = bs2dsov;
1409                 Standard_Real UResbail = GAS.UResolution(tolbail);
1410                 Standard_Real VResbail = GAS.VResolution(tolbail);
1411                 Standard_Real Tol2dbail  = Min(UResbail,VResbail);
1412                 bs2d->D0(bs2d->FirstParameter(), OriginPoint);
1413 
1414                 Standard_Integer nbp = bs2d->NbPoles();
1415                 TColgp_Array1OfPnt2d poles(1,nbp);
1416                 bs2d->Poles(poles);
1417                 gp_Pnt2d p = poles(1), p1;
1418                 Standard_Real d = Precision::Infinite();
1419                 for(Standard_Integer ip = 2; ip <= nbp; ip++) {
1420                   p1 = poles(ip);
1421                   d = Min(d,p.SquareDistance(p1));
1422                   p = p1;
1423                 }
1424                 d = sqrt(d)*.1;
1425 
1426                 Tol2dbail = Max(Min(Tol2dbail,d), TolConf2d);
1427 
1428                 Geom2dConvert::C0BSplineToC1BSplineCurve(bs2d,Tol2dbail);
1429 
1430                 if(bs2d->IsPeriodic()) { // -------- IFV, Jan 2000
1431                   gp_Pnt2d NewOriginPoint;
1432                   bs2d->D0(bs2d->FirstParameter(), NewOriginPoint);
1433                   if(Abs(OriginPoint.X() - NewOriginPoint.X()) > Precision::PConfusion() ||
1434                     Abs(OriginPoint.Y() - NewOriginPoint.Y()) > Precision::PConfusion()    ) {
1435 
1436                       TColStd_Array1OfReal Knotbs2d (1, bs2d->NbKnots());
1437                       bs2d->Knots(Knotbs2d);
1438 
1439                       for(Standard_Integer Index = 1; Index <= bs2d->NbKnots(); Index++) {
1440                         bs2d->D0(Knotbs2d(Index), NewOriginPoint);
1441                         if(Abs(OriginPoint.X() - NewOriginPoint.X()) > Precision::PConfusion() ||
1442                           Abs(OriginPoint.Y() - NewOriginPoint.Y()) > Precision::PConfusion()    ) continue;
1443 
1444                         bs2d->SetOrigin(Index);
1445                         break;
1446                       }
1447                   }
1448                 }
1449 
1450 
1451                 if(bs2d->Continuity() == GeomAbs_C0) {
1452                   goodpc = 1;
1453                   bs2d = bs2dsov;
1454                   repar = Standard_False;
1455                 }
1456               }
1457               else goodpc = 0;
1458             }
1459 
1460             if(goodpc){
1461               if(repar) {
1462                 Standard_Integer NbKnots = bs2d->NbKnots();
1463                 TColStd_Array1OfReal Knots(1,NbKnots);
1464                 bs2d->Knots(Knots);
1465                 //	    BSplCLib::Reparametrize(f3d,l3d,Knots);
1466                 BSplCLib::Reparametrize(fC0,lC0,Knots);
1467                 bs2d->SetKnots(Knots);
1468                 GAC2d.Load(bs2d,f3d,l3d);
1469                 curPC = bs2d;
1470                 Standard_Boolean updatepcsov = updatepc;
1471                 updatepc = Standard_True;
1472 
1473                 Standard_Real error1 = ComputeTol(HC, HC2d, HS, NCONTROL);
1474                 if(error1 > error) {
1475                   bs2d = bs2dsov;
1476                   GAC2d.Load(bs2d,f3d,l3d);
1477                   curPC = bs2d;
1478                   updatepc = updatepcsov;
1479                   isANA = Standard_True;
1480                 }
1481                 else {
1482                   error = error1;
1483                 }
1484               }
1485 
1486               //check, if new BSpline "good" or not --------- IFV, Jan of 2000
1487               GeomAbs_Shape cont = bs2d->Continuity();
1488               Standard_Boolean IsBad = Standard_False;
1489 
1490               if(cont > GeomAbs_C0 && error > Max(1.e-3,theTolerance)) {
1491                 Standard_Integer NbKnots = bs2d->NbKnots();
1492                 TColStd_Array1OfReal Knots(1,NbKnots);
1493                 bs2d->Knots(Knots);
1494                 Standard_Real critratio = 10.;
1495                 Standard_Real dtprev = Knots(2) - Knots(1), dtratio = 1.;
1496                 Standard_Real dtmin = dtprev;
1497                 Standard_Real dtcur;
1498                 for(Standard_Integer j = 2; j < NbKnots; j++) {
1499                   dtcur = Knots(j+1) - Knots(j);
1500                   dtmin = Min(dtmin, dtcur);
1501 
1502                   if(IsBad) continue;
1503 
1504                   if(dtcur > dtprev) dtratio = dtcur/dtprev;
1505                   else dtratio = dtprev/dtcur;
1506                   if(dtratio > critratio) {IsBad = Standard_True;}
1507                   dtprev = dtcur;
1508 
1509                 }
1510                 if(IsBad) {
1511                   // To avoid failures in Approx_CurvilinearParameter
1512                   bs2d->Resolution(Max(1.e-3,theTolerance), dtcur);
1513                   if(dtmin < dtcur) IsBad = Standard_False;
1514                 }
1515               }
1516 
1517 
1518               if(IsBad ) { //if BSpline "bad", try to reparametrize it
1519                 // by its curve length
1520 
1521                 //	      GeomAbs_Shape cont = bs2d->Continuity();
1522                 if(cont > GeomAbs_C2) cont = GeomAbs_C2;
1523                 Standard_Integer maxdeg = bs2d->Degree();
1524                 if(maxdeg == 1) maxdeg = 14;
1525                 Approx_CurvilinearParameter AppCurPar(HC2d, HS, Max(1.e-3,theTolerance),
1526                   cont, maxdeg, 10);
1527                 if(AppCurPar.IsDone() || AppCurPar.HasResult()) {
1528                   bs2d = AppCurPar.Curve2d1();
1529                   GAC2d.Load(bs2d,f3d,l3d);
1530                   curPC = bs2d;
1531 
1532                   if(Abs(bs2d->FirstParameter() - fC0) > TolSameRange ||
1533                     Abs(bs2d->LastParameter() - lC0) > TolSameRange) {
1534                       Standard_Integer NbKnots = bs2d->NbKnots();
1535                       TColStd_Array1OfReal Knots(1,NbKnots);
1536                       bs2d->Knots(Knots);
1537                       //		  BSplCLib::Reparametrize(f3d,l3d,Knots);
1538                       BSplCLib::Reparametrize(fC0,lC0,Knots);
1539                       bs2d->SetKnots(Knots);
1540                       GAC2d.Load(bs2d,f3d,l3d);
1541                       curPC = bs2d;
1542 
1543                   }
1544                 }
1545               }
1546 
1547 
1548             }
1549         }
1550 
1551 
1552         if(goodpc){
1553           //	  Approx_SameParameter SameP(HC,HC2d,HS,Tolerance);
1554           Standard_Real aTol = (isANA && isBSP) ? 1.e-7 : theTolerance;
1555           const Handle(Adaptor3d_Curve)& aHCurv = HC; // to avoid ambiguity
1556           const Handle(Adaptor2d_Curve2d)& aHCurv2d = HC2d; // to avoid ambiguity
1557           Approx_SameParameter SameP(aHCurv,aHCurv2d,HS,aTol);
1558 
1559           if (SameP.IsSameParameter()) {
1560             maxdist = Max(maxdist,SameP.TolReached());
1561             if(updatepc){
1562               if (i == 0) GCurve->PCurve(curPC);
1563               else GCurve->PCurve2(curPC);
1564             }
1565           }
1566           else if (SameP.IsDone()) {
1567             Standard_Real tolreached = SameP.TolReached();
1568             if(tolreached <= error) {
1569               curPC = SameP.Curve2d();
1570               updatepc = Standard_True;
1571               maxdist = Max(maxdist,tolreached);
1572             }
1573             else {
1574               maxdist = Max(maxdist, error);
1575             }
1576             if(updatepc){
1577               if (i == 0) GCurve->PCurve(curPC);
1578               else GCurve->PCurve2(curPC);
1579             }
1580           }
1581           else
1582           {
1583             //Approx_SameParameter has failed.
1584             //Consequently, the situation might be,
1585             //when 3D and 2D-curve do not have same-range.
1586             GeomLib::SameRange( TolSameRange, PC[i],
1587                                 GCurve->First(), GCurve->Last(),
1588                                 f3d,l3d,curPC);
1589 
1590             if (i == 0) GCurve->PCurve(curPC);
1591             else GCurve->PCurve2(curPC);
1592 
1593             IsSameP = 0;
1594           }
1595 
1596         }
1597         else IsSameP = 0;
1598 
1599         //  Modified by skv - Thu Jun  3 12:39:19 2004 OCC5898 Begin
1600         if (!IsSameP) {
1601           Standard_Real Prec_Surf = BRepCheck::PrecSurface(HS);
1602           Standard_Real CurTol = anEdgeTol + Max(Prec_C3d, Prec_Surf);
1603           if (CurTol >= error) {
1604             maxdist = Max(maxdist, anEdgeTol);
1605             IsSameP = Standard_True;
1606           }
1607         }
1608         //  Modified by skv - Thu Jun  3 12:39:20 2004 OCC5898 End
1609       }
1610     }
1611     It.Next() ;
1612   }
1613   B.Range(aNE,f3d,l3d);
1614   B.SameRange(aNE,Standard_True);
1615   if ( IsSameP) {
1616     // Reduce eventually the tolerance of the edge, as
1617     // all its representations are processed (except for some associated
1618     // to planes and not stored in the edge !)
1619     // The same cannot be done with vertices that cannot be enlarged
1620     // or left as is.
1621     if (YaPCu) {
1622       // Avoid setting too small tolerances.
1623       maxdist = Max(maxdist,Precision::Confusion());
1624       theNewTol = maxdist;
1625       aNTE->Modified(Standard_True);
1626       aNTE->Tolerance(maxdist);
1627     }
1628     B.SameParameter(aNE,Standard_True);
1629   }
1630 
1631   return aNE;
1632 }
1633 
1634 //=======================================================================
1635 //function : InternalUpdateTolerances
1636 //purpose  :
1637 //=======================================================================
InternalUpdateTolerances(const TopoDS_Shape & theOldShape,const Standard_Boolean IsVerifyTolerance,const Standard_Boolean IsMutableInput,BRepTools_ReShape & theReshaper)1638 static void InternalUpdateTolerances(const TopoDS_Shape& theOldShape,
1639   const Standard_Boolean IsVerifyTolerance, const Standard_Boolean IsMutableInput, BRepTools_ReShape& theReshaper)
1640 {
1641   TopTools_DataMapOfShapeReal aShToTol;
1642   // Harmonize tolerances
1643   // with rule Tolerance(VERTEX)>=Tolerance(EDGE)>=Tolerance(FACE)
1644   Standard_Real tol=0;
1645   if (IsVerifyTolerance) {
1646     // Set tolerance to its minimum value
1647     Handle(Geom_Surface) S;
1648     TopLoc_Location l;
1649     TopExp_Explorer ex;
1650     Bnd_Box aB;
1651     Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax, dMax;
1652     for (ex.Init(theOldShape, TopAbs_FACE); ex.More(); ex.Next()) {
1653       const TopoDS_Face& curf=TopoDS::Face(ex.Current());
1654       S = BRep_Tool::Surface(curf, l);
1655       if (!S.IsNull()) {
1656         aB.SetVoid();
1657         BRepBndLib::Add(curf,aB);
1658         if (S->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
1659           S = Handle(Geom_RectangularTrimmedSurface)::DownCast (S)->BasisSurface();
1660         }
1661         GeomAdaptor_Surface AS(S);
1662         switch (AS.GetType()) {
1663         case GeomAbs_Plane:
1664         case GeomAbs_Cylinder:
1665         case GeomAbs_Cone:
1666           {
1667             tol=Precision::Confusion();
1668             break;
1669           }
1670         case GeomAbs_Sphere:
1671         case GeomAbs_Torus:
1672           {
1673             tol=Precision::Confusion()*2;
1674             break;
1675           }
1676         default:
1677           tol=Precision::Confusion()*4;
1678         }
1679         if (!aB.IsWhole()) {
1680           aB.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
1681           dMax=1.;
1682           if (!aB.IsOpenXmin() && !aB.IsOpenXmax()) dMax=aXmax-aXmin;
1683           if (!aB.IsOpenYmin() && !aB.IsOpenYmax()) aYmin=aYmax-aYmin;
1684           if (!aB.IsOpenZmin() && !aB.IsOpenZmax()) aZmin=aZmax-aZmin;
1685           if (aYmin>dMax) dMax=aYmin;
1686           if (aZmin>dMax) dMax=aZmin;
1687           tol=tol*dMax;
1688           // Do not process tolerances > 1.
1689           if (tol>1.) tol=0.99;
1690         }
1691         aShToTol.Bind(curf, tol);
1692       }
1693     }
1694   }
1695 
1696   //Process edges
1697   TopTools_IndexedDataMapOfShapeListOfShape parents;
1698   TopExp::MapShapesAndAncestors(theOldShape, TopAbs_EDGE, TopAbs_FACE, parents);
1699   TopTools_ListIteratorOfListOfShape lConx;
1700   Standard_Integer iCur;
1701   for (iCur=1; iCur<=parents.Extent(); iCur++) {
1702     tol=0;
1703     for (lConx.Initialize(parents(iCur)); lConx.More(); lConx.Next())
1704     {
1705       const TopoDS_Face& FF = TopoDS::Face(lConx.Value());
1706       Standard_Real Ftol;
1707       if (IsVerifyTolerance && aShToTol.IsBound(FF)) //first condition for speed-up
1708         Ftol = aShToTol(FF);
1709       else
1710         Ftol = BRep_Tool::Tolerance(FF); //tolerance have not been updated
1711       tol=Max(tol, Ftol);
1712     }
1713     // Update can only increase tolerance, so if the edge has a greater
1714     //  tolerance than its faces it is not concerned
1715     const TopoDS_Edge& EK = TopoDS::Edge(parents.FindKey(iCur));
1716     if (tol > BRep_Tool::Tolerance(EK))
1717       aShToTol.Bind(EK, tol);
1718   }
1719 
1720   //Vertices are processed
1721   const Standard_Real BigTol = 1.e10;
1722   parents.Clear();
1723 
1724   TopExp::MapShapesAndUniqueAncestors(theOldShape, TopAbs_VERTEX, TopAbs_EDGE, parents);
1725   TColStd_MapOfTransient Initialized;
1726   Standard_Integer nbV = parents.Extent();
1727   for (iCur=1; iCur<=nbV; iCur++) {
1728     tol=0;
1729     const TopoDS_Vertex& V = TopoDS::Vertex(parents.FindKey(iCur));
1730     Bnd_Box box;
1731     box.Add(BRep_Tool::Pnt(V));
1732     gp_Pnt p3d;
1733     for (lConx.Initialize(parents(iCur)); lConx.More(); lConx.Next()) {
1734       const TopoDS_Edge& E = TopoDS::Edge(lConx.Value());
1735       const Standard_Real* aNtol = aShToTol.Seek(E);
1736       tol=Max(tol, aNtol ? *aNtol : BRep_Tool::Tolerance(E));
1737       if(tol > BigTol) continue;
1738       if(!BRep_Tool::SameRange(E)) continue;
1739       Standard_Real par = BRep_Tool::Parameter(V,E);
1740       Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*)&E.TShape());
1741       BRep_ListIteratorOfListOfCurveRepresentation itcr(TE->Curves());
1742       const TopLoc_Location& Eloc = E.Location();
1743       while (itcr.More()) {
1744         // For each CurveRepresentation, check the provided parameter
1745         const Handle(BRep_CurveRepresentation)& cr = itcr.Value();
1746         const TopLoc_Location& loc = cr->Location();
1747         TopLoc_Location L = (Eloc * loc);
1748         if (cr->IsCurve3D()) {
1749           const Handle(Geom_Curve)& C = cr->Curve3D();
1750           if (!C.IsNull()) { // edge non degenerated
1751             p3d = C->Value(par);
1752             p3d.Transform(L.Transformation());
1753             box.Add(p3d);
1754           }
1755         }
1756         else if (cr->IsCurveOnSurface()) {
1757           const Handle(Geom_Surface)& Su = cr->Surface();
1758           const Handle(Geom2d_Curve)& PC = cr->PCurve();
1759           Handle(Geom2d_Curve) PC2;
1760           if (cr->IsCurveOnClosedSurface()) {
1761             PC2 = cr->PCurve2();
1762           }
1763           gp_Pnt2d p2d = PC->Value(par);
1764           p3d = Su->Value(p2d.X(),p2d.Y());
1765           p3d.Transform(L.Transformation());
1766           box.Add(p3d);
1767           if (!PC2.IsNull()) {
1768             p2d = PC2->Value(par);
1769             p3d = Su->Value(p2d.X(),p2d.Y());
1770             p3d.Transform(L.Transformation());
1771             box.Add(p3d);
1772           }
1773         }
1774         itcr.Next();
1775       }
1776     }
1777     Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
1778     box.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
1779     aXmax -= aXmin; aYmax -= aYmin; aZmax -= aZmin;
1780     tol = Max(tol,sqrt(aXmax*aXmax+aYmax*aYmax+aZmax*aZmax));
1781     tol += 2.*Epsilon(tol);
1782     //
1783     Standard_Real aVTol = BRep_Tool::Tolerance(V);
1784     Standard_Boolean anUpdTol = tol > aVTol;
1785     const Handle(BRep_TVertex)& aTV = *((Handle(BRep_TVertex)*)&V.TShape());
1786     Standard_Boolean toAdd = Standard_False;
1787     if (IsVerifyTolerance)
1788     {
1789       // ASet minimum value of the tolerance
1790       // Attention to sharing of the vertex by other shapes
1791       toAdd = Initialized.Add(aTV) && aVTol != tol; //if Vtol == tol => no need to update toler
1792     }
1793     //'Initialized' map is not used anywhere outside this block
1794     if (anUpdTol || toAdd)
1795       aShToTol.Bind(V, tol);
1796   }
1797 
1798   UpdShTol(aShToTol, IsMutableInput, theReshaper, Standard_True);
1799 }
1800 
1801 //=======================================================================
1802 //function : UpdateTolerances
1803 //purpose  :
1804 //=======================================================================
UpdateTolerances(const TopoDS_Shape & S,const Standard_Boolean verifyFaceTolerance)1805 void BRepLib::UpdateTolerances (const TopoDS_Shape& S, const Standard_Boolean verifyFaceTolerance)
1806 {
1807   BRepTools_ReShape aReshaper;
1808   InternalUpdateTolerances(S, verifyFaceTolerance, Standard_True, aReshaper);
1809 }
1810 
1811 //=======================================================================
1812 //function : UpdateTolerances
1813 //purpose  :
1814 //=======================================================================
UpdateTolerances(const TopoDS_Shape & S,BRepTools_ReShape & theReshaper,const Standard_Boolean verifyFaceTolerance)1815 void BRepLib::UpdateTolerances (const TopoDS_Shape& S, BRepTools_ReShape& theReshaper, const Standard_Boolean verifyFaceTolerance )
1816 {
1817   InternalUpdateTolerances(S, verifyFaceTolerance, Standard_False, theReshaper);
1818 }
1819 
1820 //=======================================================================
1821 //function : UpdateInnerTolerances
1822 //purpose  :
1823 //=======================================================================
UpdateInnerTolerances(const TopoDS_Shape & aShape)1824 void  BRepLib::UpdateInnerTolerances(const TopoDS_Shape& aShape)
1825 {
1826   TopTools_IndexedDataMapOfShapeListOfShape EFmap;
1827   TopExp::MapShapesAndAncestors(aShape, TopAbs_EDGE, TopAbs_FACE, EFmap);
1828   BRep_Builder BB;
1829   for (Standard_Integer i = 1; i <= EFmap.Extent(); i++)
1830   {
1831     TopoDS_Edge anEdge = TopoDS::Edge(EFmap.FindKey(i));
1832 
1833     if (!BRep_Tool::IsGeometric(anEdge))
1834     {
1835       continue;
1836     }
1837 
1838     TopoDS_Vertex V1, V2;
1839     TopExp::Vertices(anEdge, V1, V2);
1840     Standard_Real fpar, lpar;
1841     BRep_Tool::Range(anEdge, fpar, lpar);
1842     Standard_Real TolEdge = BRep_Tool::Tolerance(anEdge);
1843     gp_Pnt Pnt1, Pnt2;
1844     Handle(BRepAdaptor_Curve) anHCurve = new BRepAdaptor_Curve();
1845     anHCurve->Initialize(anEdge);
1846     if (!V1.IsNull())
1847       Pnt1 = BRep_Tool::Pnt(V1);
1848     if (!V2.IsNull())
1849       Pnt2 = BRep_Tool::Pnt(V2);
1850 
1851     if (!BRep_Tool::Degenerated(anEdge) &&
1852         EFmap(i).Extent() > 0)
1853     {
1854       NCollection_Sequence<Handle(Adaptor3d_Curve)> theRep;
1855       theRep.Append(anHCurve);
1856       TopTools_ListIteratorOfListOfShape itl(EFmap(i));
1857       for (; itl.More(); itl.Next())
1858       {
1859         const TopoDS_Face& aFace = TopoDS::Face(itl.Value());
1860         Handle(BRepAdaptor_Curve) anHCurvOnSurf = new BRepAdaptor_Curve();
1861         anHCurvOnSurf->Initialize(anEdge, aFace);
1862         theRep.Append(anHCurvOnSurf);
1863       }
1864 
1865       const Standard_Integer NbSamples = (BRep_Tool::SameParameter(anEdge))? 23 : 2;
1866       Standard_Real delta = (lpar - fpar)/(NbSamples-1);
1867       Standard_Real MaxDist = 0.;
1868       for (Standard_Integer j = 2; j <= theRep.Length(); j++)
1869       {
1870         for (Standard_Integer k = 0; k <= NbSamples; k++)
1871         {
1872           Standard_Real ParamOnCenter = (k == NbSamples)? lpar :
1873             fpar + k*delta;
1874           gp_Pnt Center = theRep(1)->Value(ParamOnCenter);
1875           Standard_Real ParamOnCurve = (BRep_Tool::SameParameter(anEdge))? ParamOnCenter
1876             : ((k == 0)? theRep(j)->FirstParameter() : theRep(j)->LastParameter());
1877           gp_Pnt aPoint = theRep(j)->Value(ParamOnCurve);
1878           Standard_Real aDist = Center.Distance(aPoint);
1879           //aDist *= 1.1;
1880           aDist += 2.*Epsilon(aDist);
1881           if (aDist > MaxDist)
1882             MaxDist = aDist;
1883 
1884           //Update tolerances of vertices
1885           if (k == 0 && !V1.IsNull())
1886           {
1887             Standard_Real aDist1 = Pnt1.Distance(aPoint);
1888             aDist1 += 2.*Epsilon(aDist1);
1889             BB.UpdateVertex(V1, aDist1);
1890           }
1891           if (k == NbSamples && !V2.IsNull())
1892           {
1893             Standard_Real aDist2 = Pnt2.Distance(aPoint);
1894             aDist2 += 2.*Epsilon(aDist2);
1895             BB.UpdateVertex(V2, aDist2);
1896           }
1897         }
1898       }
1899       BB.UpdateEdge(anEdge, MaxDist);
1900     }
1901     TolEdge = BRep_Tool::Tolerance(anEdge);
1902     if (!V1.IsNull())
1903     {
1904       gp_Pnt End1 = anHCurve->Value(fpar);
1905       Standard_Real dist1 = Pnt1.Distance(End1);
1906       dist1 += 2.*Epsilon(dist1);
1907       BB.UpdateVertex(V1, Max(dist1, TolEdge));
1908     }
1909     if (!V2.IsNull())
1910     {
1911       gp_Pnt End2 = anHCurve->Value(lpar);
1912       Standard_Real dist2 = Pnt2.Distance(End2);
1913       dist2 += 2.*Epsilon(dist2);
1914       BB.UpdateVertex(V2, Max(dist2, TolEdge));
1915     }
1916   }
1917 }
1918 
1919 //=======================================================================
1920 //function : OrientClosedSolid
1921 //purpose  :
1922 //=======================================================================
OrientClosedSolid(TopoDS_Solid & solid)1923 Standard_Boolean BRepLib::OrientClosedSolid(TopoDS_Solid& solid)
1924 {
1925   // Set material inside the solid
1926   BRepClass3d_SolidClassifier where(solid);
1927   where.PerformInfinitePoint(Precision::Confusion());
1928   if (where.State()==TopAbs_IN) {
1929     solid.Reverse();
1930   }
1931   else if (where.State()==TopAbs_ON || where.State()==TopAbs_UNKNOWN)
1932     return Standard_False;
1933 
1934   return Standard_True;
1935 }
1936 
1937 // Structure for calculation of properties, necessary for decision about continuity
1938 class SurfaceProperties
1939 {
1940 public:
SurfaceProperties(const Handle (Geom_Surface)& theSurface,const gp_Trsf & theSurfaceTrsf,const Handle (Geom2d_Curve)& theCurve2D,const Standard_Boolean theReversed)1941   SurfaceProperties(const Handle(Geom_Surface)& theSurface,
1942                     const gp_Trsf&              theSurfaceTrsf,
1943                     const Handle(Geom2d_Curve)& theCurve2D,
1944                     const Standard_Boolean      theReversed)
1945     : mySurfaceProps(theSurface, 2, Precision::Confusion()),
1946       mySurfaceTrsf(theSurfaceTrsf),
1947       myCurve2d(theCurve2D),
1948       myIsReversed(theReversed)
1949   {}
1950 
1951   // Calculate derivatives on surface related to the point on curve
Calculate(const Standard_Real theParamOnCurve)1952   void Calculate(const Standard_Real theParamOnCurve)
1953   {
1954     gp_Pnt2d aUV;
1955     myCurve2d->D1(theParamOnCurve, aUV, myCurveTangent);
1956     mySurfaceProps.SetParameters(aUV.X(), aUV.Y());
1957   }
1958 
1959   // Returns point just calculated
Value()1960   gp_Pnt Value()
1961   { return mySurfaceProps.Value().Transformed(mySurfaceTrsf); }
1962 
1963   // Calculate a derivative orthogonal to curve's tangent vector
Derivative()1964   gp_Vec Derivative()
1965   {
1966     gp_Vec aDeriv;
1967     // direction orthogonal to tangent vector of the curve
1968     gp_Vec2d anOrtho(-myCurveTangent.Y(), myCurveTangent.X());
1969     Standard_Real aLen = anOrtho.Magnitude();
1970     if (aLen < Precision::Confusion())
1971       return aDeriv;
1972     anOrtho /= aLen;
1973     if (myIsReversed)
1974       anOrtho.Reverse();
1975 
1976     aDeriv.SetLinearForm(anOrtho.X(), mySurfaceProps.D1U(),
1977                          anOrtho.Y(), mySurfaceProps.D1V());
1978     return aDeriv.Transformed(mySurfaceTrsf);
1979   }
1980 
1981   // Calculate principal curvatures, which consist of minimal and maximal normal curvatures and
1982   // the directions on the tangent plane (principal direction) where the extremums are reached
Curvature(gp_Dir & thePrincipalDir1,Standard_Real & theCurvature1,gp_Dir & thePrincipalDir2,Standard_Real & theCurvature2)1983   void Curvature(gp_Dir& thePrincipalDir1, Standard_Real& theCurvature1,
1984                  gp_Dir& thePrincipalDir2, Standard_Real& theCurvature2)
1985   {
1986     mySurfaceProps.CurvatureDirections(thePrincipalDir1, thePrincipalDir2);
1987     theCurvature1 = mySurfaceProps.MaxCurvature();
1988     theCurvature2 = mySurfaceProps.MinCurvature();
1989     if (myIsReversed)
1990     {
1991       theCurvature1 = -theCurvature1;
1992       theCurvature2 = -theCurvature2;
1993     }
1994     if (mySurfaceTrsf.IsNegative())
1995     {
1996       theCurvature1 = -theCurvature1;
1997       theCurvature2 = -theCurvature2;
1998     }
1999 
2000     thePrincipalDir1.Transform(mySurfaceTrsf);
2001     thePrincipalDir2.Transform(mySurfaceTrsf);
2002   }
2003 
2004 private:
2005   GeomLProp_SLProps    mySurfaceProps; // properties calculator
2006   gp_Trsf              mySurfaceTrsf;
2007   Handle(Geom2d_Curve) myCurve2d;
2008   Standard_Boolean     myIsReversed; // the face based on the surface is reversed
2009 
2010   // tangent vector to Pcurve in UV
2011   gp_Vec2d myCurveTangent;
2012 };
2013 
2014 //=======================================================================
2015 //function : tgtfaces
2016 //purpose  : check the angle at the border between two squares.
2017 //           Two shares should have a shared front edge.
2018 //=======================================================================
tgtfaces(const TopoDS_Edge & Ed,const TopoDS_Face & F1,const TopoDS_Face & F2,const Standard_Real theAngleTol)2019 static GeomAbs_Shape tgtfaces(const TopoDS_Edge& Ed,
2020                               const TopoDS_Face& F1,
2021                               const TopoDS_Face& F2,
2022                               const Standard_Real theAngleTol)
2023 {
2024   Standard_Boolean isSeam = F1.IsEqual(F2);
2025 
2026   TopoDS_Edge E = Ed;
2027 
2028   // Check if pcurves exist on both faces of edge
2029   Standard_Real aFirst,aLast;
2030   E.Orientation(TopAbs_FORWARD);
2031   Handle(Geom2d_Curve) aCurve1 = BRep_Tool::CurveOnSurface(E, F1, aFirst, aLast);
2032   if(aCurve1.IsNull())
2033     return GeomAbs_C0;
2034 
2035   if (isSeam)
2036     E.Orientation(TopAbs_REVERSED);
2037   Handle(Geom2d_Curve) aCurve2 = BRep_Tool::CurveOnSurface(E, F2, aFirst, aLast);
2038   if(aCurve2.IsNull())
2039     return GeomAbs_C0;
2040 
2041   TopLoc_Location aLoc1, aLoc2;
2042   Handle(Geom_Surface) aSurface1 = BRep_Tool::Surface(F1, aLoc1);
2043   const gp_Trsf& aSurf1Trsf = aLoc1.Transformation();
2044   Handle(Geom_Surface) aSurface2 = BRep_Tool::Surface(F2, aLoc2);
2045   const gp_Trsf& aSurf2Trsf = aLoc2.Transformation();
2046 
2047   if (aSurface1->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface)))
2048     aSurface1 = Handle(Geom_RectangularTrimmedSurface)::DownCast(aSurface1)->BasisSurface();
2049   if (aSurface2->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface)))
2050     aSurface2 = Handle(Geom_RectangularTrimmedSurface)::DownCast(aSurface2)->BasisSurface();
2051 
2052   // seam edge on elementary surface is always CN
2053   Standard_Boolean isElementary =
2054     (aSurface1->IsKind(STANDARD_TYPE(Geom_ElementarySurface)) &&
2055      aSurface2->IsKind(STANDARD_TYPE(Geom_ElementarySurface)));
2056   if (isSeam && isElementary)
2057   {
2058     return GeomAbs_CN;
2059   }
2060 
2061   SurfaceProperties aSP1(aSurface1, aSurf1Trsf, aCurve1, F1.Orientation() == TopAbs_REVERSED);
2062   SurfaceProperties aSP2(aSurface2, aSurf2Trsf, aCurve2, F2.Orientation() == TopAbs_REVERSED);
2063 
2064   Standard_Real f, l, eps;
2065   BRep_Tool::Range(E,f,l);
2066   Extrema_LocateExtPC ext;
2067   Handle(BRepAdaptor_Curve) aHC2;
2068 
2069   eps = (l - f)/100.;
2070   f += eps; // to avoid calculations on
2071   l -= eps; // points of pointed squares.
2072 
2073   const Standard_Real anAngleTol2 = theAngleTol * theAngleTol;
2074 
2075   gp_Vec aDer1, aDer2;
2076   gp_Vec aNorm1;
2077   Standard_Real aSqLen1, aSqLen2;
2078   gp_Dir aCrvDir1[2], aCrvDir2[2];
2079   Standard_Real aCrvLen1[2], aCrvLen2[2];
2080 
2081   GeomAbs_Shape aCont = (isElementary ? GeomAbs_CN : GeomAbs_C2);
2082   GeomAbs_Shape aCurCont;
2083   Standard_Real u;
2084   for (Standard_Integer i = 0; i <= 20 && aCont > GeomAbs_C0; i++)
2085   {
2086     // First suppose that this is sameParameter
2087     u = f + (l-f)*i/20;
2088 
2089     // Check conditions for G1 and C1 continuity:
2090     // * calculate a derivative in tangent plane of each surface
2091     //   orthogonal to curve's tangent vector
2092     // * continuity is C1 if the vectors are equal
2093     // * continuity is G1 if the vectors are just parallel
2094     aCurCont = GeomAbs_C0;
2095 
2096     aSP1.Calculate(u);
2097     aSP2.Calculate(u);
2098 
2099     aDer1 = aSP1.Derivative();
2100     aSqLen1 = aDer1.SquareMagnitude();
2101     aDer2 = aSP2.Derivative();
2102     aSqLen2 = aDer2.SquareMagnitude();
2103     Standard_Boolean isSmoothSuspect = (aDer1.CrossSquareMagnitude(aDer2) <= anAngleTol2 * aSqLen1 * aSqLen2);
2104     if (!isSmoothSuspect)
2105     {
2106       // Refine by projection
2107       if (aHC2.IsNull())
2108       {
2109         // adaptor for pcurve on the second surface
2110         aHC2 = new BRepAdaptor_Curve (E, F2);
2111         ext.Initialize(*aHC2, f, l, Precision::PConfusion());
2112       }
2113       ext.Perform(aSP1.Value(), u);
2114       if (ext.IsDone() && ext.IsMin())
2115       {
2116         const Extrema_POnCurv& poc = ext.Point();
2117         aSP2.Calculate(poc.Parameter());
2118         aDer2 = aSP2.Derivative();
2119         aSqLen2 = aDer2.SquareMagnitude();
2120       }
2121       isSmoothSuspect = (aDer1.CrossSquareMagnitude(aDer2) <= anAngleTol2 * aSqLen1 * aSqLen2);
2122     }
2123     if (isSmoothSuspect)
2124     {
2125       aCurCont = GeomAbs_G1;
2126       if (Abs(Sqrt(aSqLen1) - Sqrt(aSqLen2)) < Precision::Confusion() &&
2127           aDer1.Dot(aDer2) > Precision::SquareConfusion()) // <= check vectors are codirectional
2128         aCurCont = GeomAbs_C1;
2129     }
2130     else
2131       return GeomAbs_C0;
2132 
2133     if (aCont < GeomAbs_G2)
2134       continue; // no need further processing, because maximal continuity is less than G2
2135 
2136     // Check conditions for G2 and C2 continuity:
2137     // * calculate principal curvatures on each surface
2138     // * continuity is C2 if directions of principal curvatures are equal on different surfaces
2139     // * continuity is G2 if directions of principal curvatures are just parallel
2140     //   and values of curvatures are the same
2141     aSP1.Curvature(aCrvDir1[0], aCrvLen1[0], aCrvDir1[1], aCrvLen1[1]);
2142     aSP2.Curvature(aCrvDir2[0], aCrvLen2[0], aCrvDir2[1], aCrvLen2[1]);
2143     for (Standard_Integer aStep = 0; aStep <= 1; ++aStep)
2144     {
2145       if (aCrvDir1[0].XYZ().CrossSquareMagnitude(aCrvDir2[aStep].XYZ()) <= Precision::SquareConfusion() &&
2146           Abs(aCrvLen1[0] - aCrvLen2[aStep]) < Precision::Confusion() &&
2147           aCrvDir1[1].XYZ().CrossSquareMagnitude(aCrvDir2[1 - aStep].XYZ()) <= Precision::SquareConfusion() &&
2148           Abs(aCrvLen1[1] - aCrvLen2[1 - aStep]) < Precision::Confusion())
2149       {
2150         if (aCurCont == GeomAbs_C1 &&
2151             aCrvDir1[0].Dot(aCrvDir2[aStep]) > Precision::Confusion() &&
2152             aCrvDir1[1].Dot(aCrvDir2[1 - aStep]) > Precision::Confusion())
2153           aCurCont = GeomAbs_C2;
2154         else
2155           aCurCont = GeomAbs_G2;
2156         break;
2157       }
2158     }
2159 
2160     if (aCurCont < aCont)
2161       aCont = aCurCont;
2162   }
2163 
2164   // according to the list of supported elementary surfaces,
2165   // if the continuity is C2, than it is totally CN
2166   if (isElementary && aCont == GeomAbs_C2)
2167     aCont = GeomAbs_CN;
2168   return aCont;
2169 }
2170 
2171 //=======================================================================
2172 // function : EncodeRegularity
2173 // purpose  : Code the regularities on all edges of the shape, boundary of
2174 //            two faces that do not have it.
2175 //            Takes into account that compound may consists of same solid
2176 //            placed with different transformations
2177 //=======================================================================
EncodeRegularity(const TopoDS_Shape & theShape,const Standard_Real theTolAng,TopTools_MapOfShape & theMap,const TopTools_MapOfShape & theEdgesToEncode=TopTools_MapOfShape ())2178 static void EncodeRegularity(const TopoDS_Shape&        theShape,
2179                              const Standard_Real        theTolAng,
2180                              TopTools_MapOfShape&       theMap,
2181                              const TopTools_MapOfShape& theEdgesToEncode = TopTools_MapOfShape())
2182 {
2183   TopoDS_Shape aShape = theShape;
2184   TopLoc_Location aNullLoc;
2185   aShape.Location(aNullLoc); // nullify location
2186   if (!theMap.Add(aShape))
2187     return; // do not need to process shape twice
2188 
2189   if (aShape.ShapeType() == TopAbs_COMPOUND ||
2190       aShape.ShapeType() == TopAbs_COMPSOLID)
2191   {
2192     for (TopoDS_Iterator it(aShape); it.More(); it.Next())
2193       EncodeRegularity(it.Value(), theTolAng, theMap, theEdgesToEncode);
2194     return;
2195   }
2196 
2197   try {
2198     OCC_CATCH_SIGNALS
2199 
2200     TopTools_IndexedDataMapOfShapeListOfShape M;
2201     TopExp::MapShapesAndAncestors(aShape, TopAbs_EDGE, TopAbs_FACE, M);
2202     TopTools_ListIteratorOfListOfShape It;
2203     TopExp_Explorer Ex;
2204     TopoDS_Face F1,F2;
2205     Standard_Boolean found;
2206     for (Standard_Integer i = 1; i <= M.Extent(); i++){
2207       TopoDS_Edge E = TopoDS::Edge(M.FindKey(i));
2208       if (!theEdgesToEncode.IsEmpty())
2209       {
2210         // process only the edges from the list to update their regularity
2211         TopoDS_Shape aPureEdge = E.Located(aNullLoc);
2212         aPureEdge.Orientation(TopAbs_FORWARD);
2213         if (!theEdgesToEncode.Contains(aPureEdge))
2214           continue;
2215       }
2216 
2217       found = Standard_False;
2218       F1.Nullify();
2219       for (It.Initialize(M.FindFromIndex(i)); It.More() && !found; It.Next()){
2220         if (F1.IsNull()) { F1 = TopoDS::Face(It.Value()); }
2221         else {
2222           const TopoDS_Face& aTmpF2 = TopoDS::Face(It.Value());
2223           if (!F1.IsSame(aTmpF2)){
2224             found = Standard_True;
2225             F2 = aTmpF2;
2226           }
2227         }
2228       }
2229       if (!found && !F1.IsNull()){//is it a sewing edge?
2230         TopAbs_Orientation orE = E.Orientation();
2231         TopoDS_Edge curE;
2232         for (Ex.Init(F1, TopAbs_EDGE); Ex.More() && !found; Ex.Next()){
2233           curE = TopoDS::Edge(Ex.Current());
2234           if (E.IsSame(curE) && orE != curE.Orientation()) {
2235             found = Standard_True;
2236             F2 = F1;
2237           }
2238         }
2239       }
2240       if (found)
2241         BRepLib::EncodeRegularity(E, F1, F2, theTolAng);
2242     }
2243   }
2244   catch (Standard_Failure const& anException) {
2245 #ifdef OCCT_DEBUG
2246     std::cout << "Warning: Exception in BRepLib::EncodeRegularity(): ";
2247     anException.Print(std::cout);
2248     std::cout << std::endl;
2249 #endif
2250     (void)anException;
2251   }
2252 }
2253 
2254 //=======================================================================
2255 // function : EncodeRegularity
2256 // purpose  : code the regularities on all edges of the shape, boundary of
2257 //            two faces that do not have it.
2258 //=======================================================================
2259 
EncodeRegularity(const TopoDS_Shape & S,const Standard_Real TolAng)2260 void BRepLib::EncodeRegularity(const TopoDS_Shape& S,
2261   const Standard_Real TolAng)
2262 {
2263   TopTools_MapOfShape aMap;
2264   ::EncodeRegularity(S, TolAng, aMap);
2265 }
2266 
2267 //=======================================================================
2268 // function : EncodeRegularity
2269 // purpose  : code the regularities on all edges in the list that do not
2270 //            have it, and which are boundary of two faces on the shape.
2271 //=======================================================================
2272 
EncodeRegularity(const TopoDS_Shape & S,const TopTools_ListOfShape & LE,const Standard_Real TolAng)2273 void BRepLib::EncodeRegularity(const TopoDS_Shape& S,
2274   const TopTools_ListOfShape& LE,
2275   const Standard_Real TolAng)
2276 {
2277   // Collect edges without location and orientation
2278   TopTools_MapOfShape aPureEdges;
2279   TopLoc_Location aNullLoc;
2280   TopTools_ListIteratorOfListOfShape anEdgeIt(LE);
2281   for (; anEdgeIt.More(); anEdgeIt.Next())
2282   {
2283     TopoDS_Shape anEdge = anEdgeIt.Value();
2284     anEdge.Location(aNullLoc);
2285     anEdge.Orientation(TopAbs_FORWARD);
2286     aPureEdges.Add(anEdge);
2287   }
2288 
2289   TopTools_MapOfShape aMap;
2290   ::EncodeRegularity(S, TolAng, aMap, aPureEdges);
2291 }
2292 
2293 //=======================================================================
2294 // function : EncodeRegularity
2295 // purpose  : code the regularity between 2 faces connected by edge
2296 //=======================================================================
2297 
EncodeRegularity(TopoDS_Edge & E,const TopoDS_Face & F1,const TopoDS_Face & F2,const Standard_Real TolAng)2298 void BRepLib::EncodeRegularity(TopoDS_Edge& E,
2299   const TopoDS_Face& F1,
2300   const TopoDS_Face& F2,
2301   const Standard_Real TolAng)
2302 {
2303   BRep_Builder B;
2304   if(BRep_Tool::Continuity(E,F1,F2)<=GeomAbs_C0){
2305     try {
2306       GeomAbs_Shape aCont = tgtfaces(E, F1, F2, TolAng);
2307       B.Continuity(E,F1,F2,aCont);
2308 
2309     }
2310     catch(Standard_Failure const&)
2311     {
2312 #ifdef OCCT_DEBUG
2313       std::cout << "Failure: Exception in BRepLib::EncodeRegularity" << std::endl;
2314 #endif
2315     }
2316   }
2317 }
2318 
2319 //=======================================================================
2320 // function : EnsureNormalConsistency
2321 // purpose  : Corrects the normals in Poly_Triangulation of faces.
2322 //              Returns TRUE if any correction is done.
2323 //=======================================================================
2324 Standard_Boolean BRepLib::
EnsureNormalConsistency(const TopoDS_Shape & theShape,const Standard_Real theAngTol,const Standard_Boolean theForceComputeNormals)2325             EnsureNormalConsistency(const TopoDS_Shape& theShape,
2326                                     const Standard_Real theAngTol,
2327                                     const Standard_Boolean theForceComputeNormals)
2328 {
2329   const Standard_Real aThresDot = cos(theAngTol);
2330 
2331   Standard_Boolean aRetVal = Standard_False, isNormalsFound = Standard_False;
2332 
2333   // compute normals if they are absent
2334   TopExp_Explorer anExpFace(theShape,TopAbs_FACE);
2335   for (; anExpFace.More(); anExpFace.Next())
2336   {
2337     const TopoDS_Face& aFace = TopoDS::Face(anExpFace.Current());
2338     const Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace);
2339     if(aSurf.IsNull())
2340       continue;
2341     TopLoc_Location aLoc;
2342     const Handle(Poly_Triangulation)& aPT = BRep_Tool::Triangulation(aFace, aLoc);
2343     if(aPT.IsNull())
2344       continue;
2345     if (!theForceComputeNormals && aPT->HasNormals())
2346     {
2347       isNormalsFound = Standard_True;
2348       continue;
2349     }
2350 
2351     aPT->AddNormals();
2352     GeomLProp_SLProps aSLP(aSurf, 2, Precision::Confusion());
2353     for (Standard_Integer i = 1; i <= aPT->NbNodes(); i++)
2354     {
2355       const gp_Pnt2d aP2d = aPT->UVNode (i);
2356       aSLP.SetParameters(aP2d.X(), aP2d.Y());
2357 
2358       if(!aSLP.IsNormalDefined())
2359       {
2360 #ifdef OCCT_DEBUG
2361         std::cout << "BRepLib::EnsureNormalConsistency(): Cannot find normal!" << std::endl;
2362 #endif
2363         aPT->SetNormal (i, gp_Vec3f (0.0f));
2364       }
2365       else
2366       {
2367         gp_Dir aNorm = aSLP.Normal();
2368         if (aFace.Orientation() == TopAbs_REVERSED)
2369         {
2370           aNorm.Reverse();
2371         }
2372         aPT->SetNormal (i, aNorm);
2373       }
2374     }
2375 
2376     aRetVal = Standard_True;
2377     isNormalsFound = Standard_True;
2378   }
2379 
2380   if(!isNormalsFound)
2381   {
2382     return aRetVal;
2383   }
2384 
2385   // loop by edges
2386   TopTools_IndexedDataMapOfShapeListOfShape aMapEF;
2387   TopExp::MapShapesAndAncestors(theShape,TopAbs_EDGE,TopAbs_FACE,aMapEF);
2388   for(Standard_Integer anInd = 1; anInd <= aMapEF.Extent(); anInd++)
2389   {
2390     const TopoDS_Edge& anEdg = TopoDS::Edge(aMapEF.FindKey(anInd));
2391     const TopTools_ListOfShape& anEdgList = aMapEF.FindFromIndex(anInd);
2392     if (anEdgList.Extent() != 2)
2393       continue;
2394     TopTools_ListIteratorOfListOfShape anItF(anEdgList);
2395     const TopoDS_Face aFace1 = TopoDS::Face(anItF.Value());
2396     anItF.Next();
2397     const TopoDS_Face aFace2 = TopoDS::Face(anItF.Value());
2398     TopLoc_Location aLoc1, aLoc2;
2399     const Handle(Poly_Triangulation)& aPT1 = BRep_Tool::Triangulation(aFace1, aLoc1);
2400     const Handle(Poly_Triangulation)& aPT2 = BRep_Tool::Triangulation(aFace2, aLoc2);
2401 
2402     if(aPT1.IsNull() || aPT2.IsNull())
2403       continue;
2404 
2405     if(!aPT1->HasNormals() || !aPT2->HasNormals())
2406       continue;
2407 
2408     const Handle(Poly_PolygonOnTriangulation)& aPTEF1 =
2409                                 BRep_Tool::PolygonOnTriangulation(anEdg, aPT1, aLoc1);
2410     const Handle(Poly_PolygonOnTriangulation)& aPTEF2 =
2411                                 BRep_Tool::PolygonOnTriangulation(anEdg, aPT2, aLoc2);
2412 
2413     if (aPTEF1->Nodes().Lower() != aPTEF2->Nodes().Lower() ||
2414         aPTEF1->Nodes().Upper() != aPTEF2->Nodes().Upper())
2415       continue;
2416 
2417     for(Standard_Integer anEdgNode = aPTEF1->Nodes().Lower();
2418                          anEdgNode <= aPTEF1->Nodes().Upper(); anEdgNode++)
2419     {
2420       //Number of node
2421       const Standard_Integer aFNodF1 = aPTEF1->Nodes().Value(anEdgNode);
2422       const Standard_Integer aFNodF2 = aPTEF2->Nodes().Value(anEdgNode);
2423 
2424       gp_Vec3f aNorm1f, aNorm2f;
2425       aPT1->Normal (aFNodF1, aNorm1f);
2426       aPT1->Normal (aFNodF2, aNorm2f);
2427       const gp_XYZ aNorm1 (aNorm1f.x(), aNorm1f.y(), aNorm1f.z());
2428       const gp_XYZ aNorm2 (aNorm2f.x(), aNorm2f.y(), aNorm2f.z());
2429       const Standard_Real aDot = aNorm1 * aNorm2;
2430       if (aDot > aThresDot)
2431       {
2432         gp_XYZ aNewNorm = (aNorm1 + aNorm2).Normalized();
2433         aPT1->SetNormal (aFNodF1, aNewNorm);
2434         aPT2->SetNormal (aFNodF2, aNewNorm);
2435         aRetVal = Standard_True;
2436       }
2437     }
2438   }
2439 
2440   return aRetVal;
2441 }
2442 
2443 //=======================================================================
2444 //function : UpdateDeflection
2445 //purpose  :
2446 //=======================================================================
2447 namespace
2448 {
2449   //! Tool to estimate deflection of the given UV point
2450   //! with regard to its representation in 3D space.
2451   struct EvalDeflection
2452   {
2453     BRepAdaptor_Surface Surface;
2454 
2455     //! Initializes tool with the given face.
EvalDeflection__anon4a4e77d80111::EvalDeflection2456     EvalDeflection (const TopoDS_Face& theFace)
2457       : Surface (theFace)
2458     {
2459     }
2460 
2461     //! Evaluates deflection of the given 2d point from its 3d representation.
Eval__anon4a4e77d80111::EvalDeflection2462     Standard_Real Eval (const gp_Pnt2d& thePoint2d, const gp_Pnt& thePoint3d)
2463     {
2464       gp_Pnt aPnt;
2465       Surface.D0 (thePoint2d.X (), thePoint2d.Y (), aPnt);
2466       return (thePoint3d.XYZ () - aPnt.XYZ ()).SquareModulus ();
2467     }
2468   };
2469 
2470   //! Represents link of triangulation.
2471   struct Link
2472   {
2473     Standard_Integer Node[2];
2474 
2475     //! Constructor
Link__anon4a4e77d80111::Link2476     Link (const Standard_Integer theNode1, const Standard_Integer theNode2)
2477     {
2478       Node[0] = theNode1;
2479       Node[1] = theNode2;
2480     }
2481 
2482     //! Computes a hash code for the this link
HashCode__anon4a4e77d80111::Link2483     Standard_Integer HashCode (const Standard_Integer theUpperBound) const
2484     {
2485       return ::HashCode (Node[0] + Node[1], theUpperBound);
2486     }
2487 
2488     //! Returns true if this link has the same nodes as the other.
IsEqual__anon4a4e77d80111::Link2489     Standard_Boolean IsEqual (const Link& theOther) const
2490     {
2491       return ((Node[0] == theOther.Node[0] && Node[1] == theOther.Node[1]) ||
2492               (Node[0] == theOther.Node[1] && Node[1] == theOther.Node[0]));
2493     }
2494 
2495     //! Alias for IsEqual.
operator ==__anon4a4e77d80111::Link2496     Standard_Boolean operator ==(const Link& theOther) const
2497     {
2498       return IsEqual (theOther);
2499     }
2500   };
2501 
2502   //! Computes a hash code for the given link
HashCode(const Link & theLink,const Standard_Integer theUpperBound)2503   inline Standard_Integer HashCode (const Link& theLink, const Standard_Integer theUpperBound)
2504   {
2505     return theLink.HashCode (theUpperBound);
2506   }
2507 }
2508 
UpdateDeflection(const TopoDS_Shape & theShape)2509 void BRepLib::UpdateDeflection (const TopoDS_Shape& theShape)
2510 {
2511   TopExp_Explorer anExpFace (theShape, TopAbs_FACE);
2512   for (; anExpFace.More(); anExpFace.Next())
2513   {
2514     const TopoDS_Face& aFace = TopoDS::Face (anExpFace.Current());
2515     const Handle(Geom_Surface) aSurf = BRep_Tool::Surface (aFace);
2516     if (aSurf.IsNull())
2517     {
2518       continue;
2519     }
2520 
2521     TopLoc_Location aLoc;
2522     const Handle(Poly_Triangulation)& aPT = BRep_Tool::Triangulation (aFace, aLoc);
2523     if (aPT.IsNull() || !aPT->HasUVNodes())
2524     {
2525       continue;
2526     }
2527 
2528     // Collect all nodes of degenerative edges and skip elements
2529     // build upon them due to huge distortions introduced by passage
2530     // from UV space to 3D.
2531     NCollection_Map<Standard_Integer> aDegNodes;
2532     TopExp_Explorer anExpEdge (aFace, TopAbs_EDGE);
2533     for (; anExpEdge.More(); anExpEdge.Next())
2534     {
2535       const TopoDS_Edge& aEdge = TopoDS::Edge (anExpEdge.Current());
2536       if (BRep_Tool::Degenerated (aEdge))
2537       {
2538         const Handle(Poly_PolygonOnTriangulation)& aPolygon = BRep_Tool::PolygonOnTriangulation (aEdge, aPT, aLoc);
2539         if (aPolygon.IsNull ())
2540         {
2541           continue;
2542         }
2543 
2544         for (Standard_Integer aNodeIt = aPolygon->Nodes().Lower(); aNodeIt <= aPolygon->Nodes().Upper(); ++aNodeIt)
2545         {
2546           aDegNodes.Add (aPolygon->Node (aNodeIt));
2547         }
2548       }
2549     }
2550 
2551     EvalDeflection aTool (aFace);
2552     NCollection_Map<Link> aLinks;
2553     Standard_Real aSqDeflection = 0.;
2554     const gp_Trsf& aTrsf = aLoc.Transformation();
2555     for (Standard_Integer aTriIt = 1; aTriIt <= aPT->NbTriangles(); ++aTriIt)
2556     {
2557       const Poly_Triangle& aTriangle = aPT->Triangle (aTriIt);
2558 
2559       int aNode[3];
2560       aTriangle.Get (aNode[0], aNode[1], aNode[2]);
2561       if (aDegNodes.Contains (aNode[0]) ||
2562           aDegNodes.Contains (aNode[1]) ||
2563           aDegNodes.Contains (aNode[2]))
2564       {
2565         continue;
2566       }
2567 
2568       const gp_Pnt aP3d[3] = {
2569         aPT->Node (aNode[0]).Transformed (aTrsf),
2570         aPT->Node (aNode[1]).Transformed (aTrsf),
2571         aPT->Node (aNode[2]).Transformed (aTrsf)
2572       };
2573 
2574       const gp_Pnt2d aP2d[3] = {
2575         aPT->UVNode (aNode[0]),
2576         aPT->UVNode (aNode[1]),
2577         aPT->UVNode (aNode[2])
2578       };
2579 
2580       // Check midpoint of triangle.
2581       const gp_Pnt   aMid3d_t = (aP3d[0].XYZ() + aP3d[1].XYZ() + aP3d[2].XYZ()) / 3.;
2582       const gp_Pnt2d aMid2d_t = (aP2d[0].XY () + aP2d[1].XY () + aP2d[2].XY ()) / 3.;
2583 
2584       aSqDeflection = Max (aSqDeflection, aTool.Eval (aMid2d_t, aMid3d_t));
2585 
2586       for (Standard_Integer i = 0; i < 3; ++i)
2587       {
2588         const Standard_Integer j = (i + 1) % 3;
2589         const Link aLink (aNode[i], aNode[j]);
2590         if (!aLinks.Add (aLink))
2591         {
2592           // Do not estimate boundary links due to high distortions at the edge.
2593           const gp_Pnt&   aP3d1 = aP3d[i];
2594           const gp_Pnt&   aP3d2 = aP3d[j];
2595 
2596           const gp_Pnt2d& aP2d1 = aP2d[i];
2597           const gp_Pnt2d& aP2d2 = aP2d[j];
2598 
2599           const gp_Pnt   aMid3d_l = (aP3d1.XYZ() + aP3d2.XYZ()) / 2.;
2600           const gp_Pnt2d aMid2d_l = (aP2d1.XY () + aP2d2.XY ()) / 2.;
2601 
2602           aSqDeflection = Max (aSqDeflection, aTool.Eval (aMid2d_l, aMid3d_l));
2603         }
2604       }
2605     }
2606 
2607     aPT->Deflection (Sqrt (aSqDeflection));
2608   }
2609 }
2610 
2611 //=======================================================================
2612 //function : SortFaces
2613 //purpose  :
2614 //=======================================================================
2615 
SortFaces(const TopoDS_Shape & Sh,TopTools_ListOfShape & LF)2616 void  BRepLib::SortFaces (const TopoDS_Shape& Sh,
2617   TopTools_ListOfShape& LF)
2618 {
2619   LF.Clear();
2620   TopTools_ListOfShape LTri,LPlan,LCyl,LCon,LSphere,LTor,LOther;
2621   TopExp_Explorer exp(Sh,TopAbs_FACE);
2622   TopLoc_Location l;
2623   Handle(Geom_Surface) S;
2624 
2625   for (; exp.More(); exp.Next()) {
2626     const TopoDS_Face&   F = TopoDS::Face(exp.Current());
2627     S = BRep_Tool::Surface(F, l);
2628     if (!S.IsNull()) {
2629       if (S->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
2630         S = Handle(Geom_RectangularTrimmedSurface)::DownCast (S)->BasisSurface();
2631       }
2632       GeomAdaptor_Surface AS(S);
2633       switch (AS.GetType()) {
2634       case GeomAbs_Plane:
2635         {
2636           LPlan.Append(F);
2637           break;
2638         }
2639       case GeomAbs_Cylinder:
2640         {
2641           LCyl.Append(F);
2642           break;
2643         }
2644       case GeomAbs_Cone:
2645         {
2646           LCon.Append(F);
2647           break;
2648         }
2649       case GeomAbs_Sphere:
2650         {
2651           LSphere.Append(F);
2652           break;
2653         }
2654       case GeomAbs_Torus:
2655         {
2656           LTor.Append(F);
2657           break;
2658         }
2659       default:
2660         LOther.Append(F);
2661       }
2662     }
2663     else LTri.Append(F);
2664   }
2665   LF.Append(LPlan); LF.Append(LCyl  ); LF.Append(LCon); LF.Append(LSphere);
2666   LF.Append(LTor ); LF.Append(LOther); LF.Append(LTri);
2667 }
2668 
2669 //=======================================================================
2670 //function : ReverseSortFaces
2671 //purpose  :
2672 //=======================================================================
2673 
ReverseSortFaces(const TopoDS_Shape & Sh,TopTools_ListOfShape & LF)2674 void  BRepLib::ReverseSortFaces (const TopoDS_Shape& Sh,
2675   TopTools_ListOfShape& LF)
2676 {
2677   LF.Clear();
2678   // Use the allocator of the result LF for intermediate results
2679   TopTools_ListOfShape LTri(LF.Allocator()), LPlan(LF.Allocator()),
2680     LCyl(LF.Allocator()), LCon(LF.Allocator()), LSphere(LF.Allocator()),
2681     LTor(LF.Allocator()), LOther(LF.Allocator());
2682   TopExp_Explorer exp(Sh,TopAbs_FACE);
2683   TopLoc_Location l;
2684 
2685   for (; exp.More(); exp.Next()) {
2686     const TopoDS_Face&   F = TopoDS::Face(exp.Current());
2687     const Handle(Geom_Surface)& S = BRep_Tool::Surface(F, l);
2688     if (!S.IsNull()) {
2689       GeomAdaptor_Surface AS(S);
2690       switch (AS.GetType()) {
2691       case GeomAbs_Plane:
2692         {
2693           LPlan.Append(F);
2694           break;
2695         }
2696       case GeomAbs_Cylinder:
2697         {
2698           LCyl.Append(F);
2699           break;
2700         }
2701       case GeomAbs_Cone:
2702         {
2703           LCon.Append(F);
2704           break;
2705         }
2706       case GeomAbs_Sphere:
2707         {
2708           LSphere.Append(F);
2709           break;
2710         }
2711       case GeomAbs_Torus:
2712         {
2713           LTor.Append(F);
2714           break;
2715         }
2716       default:
2717         LOther.Append(F);
2718       }
2719     }
2720     else LTri.Append(F);
2721   }
2722   LF.Append(LTri); LF.Append(LOther); LF.Append(LTor ); LF.Append(LSphere);
2723   LF.Append(LCon); LF.Append(LCyl  ); LF.Append(LPlan);
2724 
2725 }
2726 
2727 //=======================================================================
2728 // function: BoundingVertex
2729 // purpose :
2730 //=======================================================================
BoundingVertex(const NCollection_List<TopoDS_Shape> & theLV,gp_Pnt & theNewCenter,Standard_Real & theNewTol)2731 void BRepLib::BoundingVertex(const NCollection_List<TopoDS_Shape>& theLV,
2732                              gp_Pnt& theNewCenter, Standard_Real& theNewTol)
2733 {
2734   Standard_Integer aNb;
2735   //
2736   aNb=theLV.Extent();
2737   if (aNb < 2) {
2738     return;
2739   }
2740   //
2741   else if (aNb==2) {
2742     Standard_Integer m, n;
2743     Standard_Real aR[2], dR, aD, aEps;
2744     TopoDS_Vertex aV[2];
2745     gp_Pnt aP[2];
2746     //
2747     aEps=RealEpsilon();
2748     for (m=0; m<aNb; ++m) {
2749       aV[m]=(!m)?
2750         *((TopoDS_Vertex*)(&theLV.First())):
2751         *((TopoDS_Vertex*)(&theLV.Last()));
2752       aP[m]=BRep_Tool::Pnt(aV[m]);
2753       aR[m]=BRep_Tool::Tolerance(aV[m]);
2754     }
2755     //
2756     m=0; // max R
2757     n=1; // min R
2758     if (aR[0]<aR[1]) {
2759       m=1;
2760       n=0;
2761     }
2762     //
2763     dR=aR[m]-aR[n]; // dR >= 0.
2764     gp_Vec aVD(aP[m], aP[n]);
2765     aD=aVD.Magnitude();
2766     //
2767     if (aD<=dR || aD<aEps) {
2768       theNewCenter = aP[m];
2769       theNewTol = aR[m];
2770     }
2771     else {
2772       Standard_Real aRr;
2773       gp_XYZ aXYZr;
2774       gp_Pnt aPr;
2775       //
2776       aRr=0.5*(aR[m]+aR[n]+aD);
2777       aXYZr=0.5*(aP[m].XYZ()+aP[n].XYZ()-aVD.XYZ()*(dR/aD));
2778       aPr.SetXYZ(aXYZr);
2779       //
2780       theNewCenter = aPr;
2781       theNewTol = aRr;
2782       //aBB.MakeVertex (aVnew, aPr, aRr);
2783     }
2784     return;
2785   }// else if (aNb==2) {
2786   //
2787   else { // if (aNb>2)
2788     // compute the point
2789     //
2790     // issue 0027540 - sum of doubles may depend on the order
2791     // of addition, thus sort the coordinates for stable result
2792     Standard_Integer i;
2793     NCollection_Array1<gp_Pnt> aPoints(0, aNb-1);
2794     NCollection_List<TopoDS_Edge>::Iterator aIt(theLV);
2795     for (i = 0; aIt.More(); aIt.Next(), ++i) {
2796       const TopoDS_Vertex& aVi = *((TopoDS_Vertex*)(&aIt.Value()));
2797       gp_Pnt aPi = BRep_Tool::Pnt(aVi);
2798       aPoints(i) = aPi;
2799     }
2800     //
2801     std::sort(aPoints.begin(), aPoints.end(), BRepLib_ComparePoints());
2802     //
2803     gp_XYZ aXYZ(0., 0., 0.);
2804     for (i = 0; i < aNb; ++i) {
2805       aXYZ += aPoints(i).XYZ();
2806     }
2807     aXYZ.Divide((Standard_Real)aNb);
2808     //
2809     gp_Pnt aP(aXYZ);
2810     //
2811     // compute the tolerance for the new vertex
2812     Standard_Real aTi, aDi, aDmax;
2813     //
2814     aDmax=-1.;
2815     aIt.Initialize(theLV);
2816     for (; aIt.More(); aIt.Next()) {
2817       TopoDS_Vertex& aVi=*((TopoDS_Vertex*)(&aIt.Value()));
2818       gp_Pnt aPi=BRep_Tool::Pnt(aVi);
2819       aTi=BRep_Tool::Tolerance(aVi);
2820       aDi=aP.SquareDistance(aPi);
2821       aDi=sqrt(aDi);
2822       aDi=aDi+aTi;
2823       if (aDi > aDmax) {
2824         aDmax=aDi;
2825       }
2826     }
2827     //
2828     theNewCenter = aP;
2829     theNewTol = aDmax;
2830   }
2831 }
2832 
2833 //=======================================================================
2834 //function : ExtendFace
2835 //purpose  :
2836 //=======================================================================
ExtendFace(const TopoDS_Face & theF,const Standard_Real theExtVal,const Standard_Boolean theExtUMin,const Standard_Boolean theExtUMax,const Standard_Boolean theExtVMin,const Standard_Boolean theExtVMax,TopoDS_Face & theFExtended)2837 void BRepLib::ExtendFace(const TopoDS_Face& theF,
2838                          const Standard_Real theExtVal,
2839                          const Standard_Boolean theExtUMin,
2840                          const Standard_Boolean theExtUMax,
2841                          const Standard_Boolean theExtVMin,
2842                          const Standard_Boolean theExtVMax,
2843                          TopoDS_Face& theFExtended)
2844 {
2845   // Get face bounds
2846   BRepAdaptor_Surface aBAS(theF);
2847   Standard_Real aFUMin = aBAS.FirstUParameter(),
2848                 aFUMax = aBAS.LastUParameter(),
2849                 aFVMin = aBAS.FirstVParameter(),
2850                 aFVMax = aBAS.LastVParameter();
2851   const Standard_Real aTol = BRep_Tool::Tolerance(theF);
2852 
2853   // Surface to build the face
2854   Handle(Geom_Surface) aS;
2855 
2856   const GeomAbs_SurfaceType aType = aBAS.GetType();
2857   // treat analytical surfaces first
2858   if (aType == GeomAbs_Plane ||
2859       aType == GeomAbs_Sphere ||
2860       aType == GeomAbs_Cylinder ||
2861       aType == GeomAbs_Torus ||
2862       aType == GeomAbs_Cone)
2863   {
2864     // Get basis transformed basis surface
2865     Handle(Geom_Surface) aSurf = Handle(Geom_Surface)::
2866       DownCast(aBAS.Surface().Surface()->Transformed(aBAS.Trsf()));
2867 
2868     // Get bounds of the basis surface
2869     Standard_Real aSUMin, aSUMax, aSVMin, aSVMax;
2870     aSurf->Bounds(aSUMin, aSUMax, aSVMin, aSVMax);
2871 
2872     Standard_Boolean isUPeriodic = aBAS.IsUPeriodic();
2873     Standard_Real anUPeriod = isUPeriodic ? aBAS.UPeriod() : 0.0;
2874     if (isUPeriodic)
2875     {
2876       // Adjust face bounds to first period
2877       Standard_Real aDelta = aFUMax - aFUMin;
2878       aFUMin = Max(aSUMin, aFUMin + anUPeriod*Ceiling((aSUMin - aFUMin) / anUPeriod));
2879       aFUMax = aFUMin + aDelta;
2880     }
2881 
2882     Standard_Boolean isVPeriodic = aBAS.IsVPeriodic();
2883     Standard_Real aVPeriod = isVPeriodic ? aBAS.VPeriod() : 0.0;
2884     if (isVPeriodic)
2885     {
2886       // Adjust face bounds to first period
2887       Standard_Real aDelta = aFVMax - aFVMin;
2888       aFVMin = Max(aSVMin, aFVMin + aVPeriod*Ceiling((aSVMin - aFVMin) / aVPeriod));
2889       aFVMax = aFVMin + aDelta;
2890     }
2891 
2892     // Enlarge the face
2893     Standard_Real anURes = 0., aVRes = 0.;
2894     if (theExtUMin || theExtUMax)
2895       anURes = aBAS.UResolution(theExtVal);
2896     if (theExtVMin || theExtVMax)
2897       aVRes = aBAS.VResolution(theExtVal);
2898 
2899     if (theExtUMin) aFUMin = Max(aSUMin, aFUMin - anURes);
2900     if (theExtUMax) aFUMax = Min(isUPeriodic ? aFUMin + anUPeriod : aSUMax, aFUMax + anURes);
2901     if (theExtVMin) aFVMin = Max(aSVMin, aFVMin - aVRes);
2902     if (theExtVMax) aFVMax = Min(isVPeriodic ? aFVMin + aVPeriod : aSVMax, aFVMax + aVRes);
2903 
2904     // Check if the periodic surface should become closed.
2905     // In this case, use the basis surface with basis bounds.
2906     const Standard_Real anEps = Precision::PConfusion();
2907     if (isUPeriodic && Abs(aFUMax - aFUMin - anUPeriod) < anEps)
2908     {
2909       aFUMin = aSUMin;
2910       aFUMax = aSUMax;
2911     }
2912     if (isVPeriodic && Abs(aFVMax - aFVMin - aVPeriod) < anEps)
2913     {
2914       aFVMin = aSVMin;
2915       aFVMax = aSVMax;
2916     }
2917 
2918     aS = aSurf;
2919   }
2920   else
2921   {
2922     // General case
2923 
2924     Handle(Geom_BoundedSurface) aSB =
2925       Handle(Geom_BoundedSurface)::DownCast(BRep_Tool::Surface(theF));
2926     if (aSB.IsNull())
2927     {
2928       theFExtended = theF;
2929       return;
2930     }
2931 
2932     // Get surfaces bounds
2933     Standard_Real aSUMin, aSUMax, aSVMin, aSVMax;
2934     aSB->Bounds(aSUMin, aSUMax, aSVMin, aSVMax);
2935 
2936     Standard_Boolean isUClosed = aSB->IsUClosed();
2937     Standard_Boolean isVClosed = aSB->IsVClosed();
2938 
2939     // Check if the extension in necessary directions is done
2940     Standard_Boolean isExtUMin = Standard_False,
2941                      isExtUMax = Standard_False,
2942                      isExtVMin = Standard_False,
2943                      isExtVMax = Standard_False;
2944 
2945     // UMin
2946     if (theExtUMin && !isUClosed && !Precision::IsInfinite(aSUMin)) {
2947       GeomLib::ExtendSurfByLength(aSB, theExtVal, 1, Standard_True, Standard_False);
2948       isExtUMin = Standard_True;
2949     }
2950     // UMax
2951     if (theExtUMax && !isUClosed && !Precision::IsInfinite(aSUMax)) {
2952       GeomLib::ExtendSurfByLength(aSB, theExtVal, 1, Standard_True, Standard_True);
2953       isExtUMax = Standard_True;
2954     }
2955     // VMin
2956     if (theExtVMin && !isVClosed && !Precision::IsInfinite(aSVMax)) {
2957       GeomLib::ExtendSurfByLength(aSB, theExtVal, 1, Standard_False, Standard_False);
2958       isExtVMin = Standard_True;
2959     }
2960     // VMax
2961     if (theExtVMax && !isVClosed && !Precision::IsInfinite(aSVMax)) {
2962       GeomLib::ExtendSurfByLength(aSB, theExtVal, 1, Standard_False, Standard_True);
2963       isExtVMax = Standard_True;
2964     }
2965 
2966     aS = aSB;
2967 
2968     // Get new bounds
2969     aS->Bounds(aSUMin, aSUMax, aSVMin, aSVMax);
2970     if (isExtUMin) aFUMin = aSUMin;
2971     if (isExtUMax) aFUMax = aSUMax;
2972     if (isExtVMin) aFVMin = aSVMin;
2973     if (isExtVMax) aFVMax = aSVMax;
2974   }
2975 
2976   BRepLib_MakeFace aMF(aS, aFUMin, aFUMax, aFVMin, aFVMax, aTol);
2977   theFExtended = *(TopoDS_Face*)&aMF.Shape();
2978   if (theF.Orientation() == TopAbs_REVERSED)
2979     theFExtended.Reverse();
2980 }
2981