98e3e0c005d77d494fd0aea037d06c1bd377c10e
[occt.git] / src / BRepLib / BRepLib.cxx
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 <Adaptor3d_CurveOnSurface.hxx>
21 #include <AdvApprox_ApproxAFunction.hxx>
22 #include <AppParCurves_MultiBSpCurve.hxx>
23 #include <AppParCurves_MultiCurve.hxx>
24 #include <Approx_CurvilinearParameter.hxx>
25 #include <Approx_SameParameter.hxx>
26 #include <Bnd_Box.hxx>
27 #include <BRep_Builder.hxx>
28 #include <BRep_CurveRepresentation.hxx>
29 #include <BRep_GCurve.hxx>
30 #include <BRep_ListIteratorOfListOfCurveRepresentation.hxx>
31 #include <BRep_ListOfCurveRepresentation.hxx>
32 #include <BRep_TEdge.hxx>
33 #include <BRep_TFace.hxx>
34 #include <BRep_Tool.hxx>
35 #include <BRep_TVertex.hxx>
36 #include <BRepAdaptor_HCurve.hxx>
37 #include <BRepAdaptor_HCurve2d.hxx>
38 #include <BRepAdaptor_HSurface.hxx>
39 #include <BRepAdaptor_Surface.hxx>
40 #include <BRepBndLib.hxx>
41 #include <BRepClass3d_SolidClassifier.hxx>
42 #include <BRepLib.hxx>
43 #include <BSplCLib.hxx>
44 #include <ElSLib.hxx>
45 #include <Extrema_LocateExtPC.hxx>
46 #include <GCPnts_QuasiUniformDeflection.hxx>
47 #include <Geom2d_BSplineCurve.hxx>
48 #include <Geom2d_Curve.hxx>
49 #include <Geom2d_TrimmedCurve.hxx>
50 #include <Geom2dAdaptor.hxx>
51 #include <Geom2dAdaptor_Curve.hxx>
52 #include <Geom2dAdaptor_HCurve.hxx>
53 #include <Geom2dConvert.hxx>
54 #include <Geom_BSplineCurve.hxx>
55 #include <Geom_BSplineSurface.hxx>
56 #include <Geom_Curve.hxx>
57 #include <Geom_Plane.hxx>
58 #include <Geom_RectangularTrimmedSurface.hxx>
59 #include <Geom_Surface.hxx>
60 #include <Geom_TrimmedCurve.hxx>
61 #include <GeomAdaptor_Curve.hxx>
62 #include <GeomAdaptor_HCurve.hxx>
63 #include <GeomAdaptor_HSurface.hxx>
64 #include <GeomAdaptor_Surface.hxx>
65 #include <GeomLib.hxx>
66 #include <GeomLProp_SLProps.hxx>
67 #include <gp.hxx>
68 #include <gp_Ax2.hxx>
69 #include <gp_Pln.hxx>
70 #include <Poly_PolygonOnTriangulation.hxx>
71 #include <Poly_Triangulation.hxx>
72 #include <Precision.hxx>
73 #include <ProjLib_ProjectedCurve.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
92 // TODO - not thread-safe static variables
93 static Standard_Real thePrecision = Precision::Confusion();     
94 static Handle(Geom_Plane) thePlane;
95
96 //=======================================================================
97 //function : Precision
98 //purpose  : 
99 //=======================================================================
100
101 void BRepLib::Precision(const Standard_Real P)
102 {
103   thePrecision = P;
104 }
105
106 //=======================================================================
107 //function : Precision
108 //purpose  : 
109 //=======================================================================
110
111 Standard_Real  BRepLib::Precision()
112 {
113   return thePrecision;
114 }
115
116 //=======================================================================
117 //function : Plane
118 //purpose  : 
119 //=======================================================================
120
121 void  BRepLib::Plane(const Handle(Geom_Plane)& P)
122 {
123   thePlane = P;
124 }
125
126
127 //=======================================================================
128 //function : Plane
129 //purpose  : 
130 //=======================================================================
131
132 const Handle(Geom_Plane)&  BRepLib::Plane()
133 {
134   if (thePlane.IsNull()) thePlane = new Geom_Plane(gp::XOY());
135   return thePlane;
136 }
137 //=======================================================================
138 //function : CheckSameRange
139 //purpose  : 
140 //=======================================================================
141
142 Standard_Boolean  BRepLib::CheckSameRange(const TopoDS_Edge& AnEdge,
143   const Standard_Real Tolerance) 
144 {
145   Standard_Boolean  IsSameRange = Standard_True,
146     first_time_in = Standard_True ;
147
148   BRep_ListIteratorOfListOfCurveRepresentation an_Iterator
149     ((*((Handle(BRep_TEdge)*)&AnEdge.TShape()))->ChangeCurves());
150
151   Standard_Real first, last;
152   Standard_Real current_first =0., current_last =0. ;
153   Handle(BRep_GCurve) geometric_representation_ptr ;
154
155   while (IsSameRange && an_Iterator.More()) {
156     geometric_representation_ptr =
157       Handle(BRep_GCurve)::DownCast(an_Iterator.Value());
158     if (!geometric_representation_ptr.IsNull()) {
159
160       first = geometric_representation_ptr->First();
161       last =  geometric_representation_ptr->Last();
162       if (first_time_in ) {
163         current_first = first ;
164         current_last = last   ;
165         first_time_in = Standard_False ;
166       }
167       else {
168         IsSameRange = (Abs(current_first - first) <= Tolerance) 
169           && (Abs(current_last -last) <= Tolerance ) ;
170       }
171     }
172     an_Iterator.Next() ;
173   }
174   return IsSameRange ;
175 }
176
177 //=======================================================================
178 //function : SameRange
179 //purpose  : 
180 //=======================================================================
181
182 void BRepLib::SameRange(const TopoDS_Edge& AnEdge,
183   const Standard_Real Tolerance) 
184 {
185   BRep_ListIteratorOfListOfCurveRepresentation an_Iterator
186     ((*((Handle(BRep_TEdge)*)&AnEdge.TShape()))->ChangeCurves());
187
188   Handle(Geom2d_Curve) Curve2dPtr, Curve2dPtr2, NewCurve2dPtr, NewCurve2dPtr2;
189   TopLoc_Location LocalLoc ;
190
191   Standard_Boolean first_time_in = Standard_True,
192     has_curve,
193     has_closed_curve ;
194   Handle(BRep_GCurve) geometric_representation_ptr ;
195   Standard_Real first,
196     current_first,
197     last,
198     current_last ;
199
200   const Handle(Geom_Curve) C = BRep_Tool::Curve(AnEdge,
201     LocalLoc,
202     current_first,
203     current_last);
204   if (!C.IsNull()) {
205     first_time_in = Standard_False ;
206   }
207
208   while (an_Iterator.More()) {
209     geometric_representation_ptr =
210       Handle(BRep_GCurve)::DownCast(an_Iterator.Value());
211     if (! geometric_representation_ptr.IsNull()) {
212       has_closed_curve =
213         has_curve = Standard_False ;
214       first = geometric_representation_ptr->First();
215       last =  geometric_representation_ptr->Last();
216       if (geometric_representation_ptr->IsCurveOnSurface()) {
217         Curve2dPtr = geometric_representation_ptr->PCurve() ; 
218         has_curve = Standard_True ;
219       }
220       if (geometric_representation_ptr->IsCurveOnClosedSurface()) {
221         Curve2dPtr2 = geometric_representation_ptr->PCurve2() ;
222         has_closed_curve = Standard_True ;
223       }
224       if (has_curve || has_closed_curve) {
225         if (first_time_in) {
226           current_first = first ;
227           current_last = last ;
228           first_time_in = Standard_False ;
229         }
230
231         if (Abs(first - current_first) > Precision::Confusion() ||
232           Abs(last - current_last) > Precision::Confusion() )
233         {
234           if (has_curve)
235           {
236             GeomLib::SameRange(Tolerance,
237               Curve2dPtr,
238               geometric_representation_ptr->First(),
239               geometric_representation_ptr->Last(),
240               current_first,
241               current_last,
242               NewCurve2dPtr);
243             geometric_representation_ptr->PCurve(NewCurve2dPtr) ;
244           }
245           if (has_closed_curve)
246           {
247             GeomLib::SameRange(Tolerance,
248               Curve2dPtr2,
249               geometric_representation_ptr->First(),
250               geometric_representation_ptr->Last(),
251               current_first,
252               current_last,
253               NewCurve2dPtr2);
254             geometric_representation_ptr->PCurve2(NewCurve2dPtr2) ;
255           }
256         }
257       }
258     }
259     an_Iterator.Next() ;
260   }
261   BRep_Builder B;
262   B.Range(TopoDS::Edge(AnEdge),
263     current_first,
264     current_last) ;
265
266   B.SameRange(AnEdge,
267     Standard_True) ;
268 }
269
270 //=======================================================================
271 //function : EvaluateMaxSegment
272 //purpose  : return MaxSegment to pass in approximation, if MaxSegment==0 provided
273 //=======================================================================
274
275 static Standard_Integer evaluateMaxSegment(const Standard_Integer aMaxSegment,
276   const Adaptor3d_CurveOnSurface& aCurveOnSurface)
277 {
278   if (aMaxSegment != 0) return aMaxSegment;
279
280   Handle(Adaptor3d_HSurface) aSurf   = aCurveOnSurface.GetSurface();
281   Handle(Adaptor2d_HCurve2d) aCurv2d = aCurveOnSurface.GetCurve();
282
283   Standard_Real aNbSKnots = 0, aNbC2dKnots = 0;
284
285   if (aSurf->GetType() == GeomAbs_BSplineSurface) {
286     Handle(Geom_BSplineSurface) aBSpline = aSurf->BSpline();
287     aNbSKnots = Max(aBSpline->NbUKnots(), aBSpline->NbVKnots());
288   }
289   if (aCurv2d->GetType() == GeomAbs_BSplineCurve) {
290     aNbC2dKnots = aCurv2d->NbKnots();
291   }
292   Standard_Integer aReturn = (Standard_Integer) (  30 + Max(aNbSKnots, aNbC2dKnots) ) ;
293   return aReturn;
294 }
295
296 //=======================================================================
297 //function : BuildCurve3d
298 //purpose  : 
299 //=======================================================================
300
301 Standard_Boolean  BRepLib::BuildCurve3d(const TopoDS_Edge& AnEdge,
302   const Standard_Real Tolerance,
303   const GeomAbs_Shape Continuity,
304   const Standard_Integer MaxDegree,
305   const Standard_Integer MaxSegment)
306 {
307   Standard_Integer //ErrorCode,
308     //                   ReturnCode = 0,
309     ii,
310     //                   num_knots,
311     jj;
312
313   TopLoc_Location LocalLoc,L[2],LC;
314   Standard_Real f,l,fc,lc, first[2], last[2],
315     tolerance,
316     max_deviation,
317     average_deviation ;
318   Handle(Geom2d_Curve) Curve2dPtr, Curve2dArray[2]  ;
319   Handle(Geom_Surface) SurfacePtr, SurfaceArray[2]  ;
320
321   Standard_Integer not_done ;
322   // if the edge has a 3d curve returns true
323
324
325   const Handle(Geom_Curve) C = BRep_Tool::Curve(AnEdge,LocalLoc,f,l);
326   if (!C.IsNull()) 
327     return Standard_True;
328   //
329   // this should not exists but UpdateEdge makes funny things 
330   // if the edge is not same range 
331   //
332   if (! CheckSameRange(AnEdge,
333     Precision::Confusion())) {
334       SameRange(AnEdge,
335         Tolerance) ;
336   }
337
338
339
340   // search a curve on a plane
341   Handle(Geom_Surface) S;
342   Handle(Geom2d_Curve) PC;
343   Standard_Integer i = 0;
344   Handle(Geom_Plane) P;
345   not_done = 1 ;
346
347   while (not_done) {
348     i++;
349     BRep_Tool::CurveOnSurface(AnEdge,PC,S,LocalLoc,f,l,i);
350     Handle(Geom_RectangularTrimmedSurface) RT = 
351       Handle(Geom_RectangularTrimmedSurface)::DownCast(S);
352     if ( RT.IsNull()) {
353       P = Handle(Geom_Plane)::DownCast(S);
354     }
355     else {
356       P = Handle(Geom_Plane)::DownCast(RT->BasisSurface());
357     }
358     not_done = ! (S.IsNull() || !P.IsNull()) ;
359   }
360   if (! P.IsNull()) {
361     // compute the 3d curve
362     gp_Ax2 axes = P->Position().Ax2();
363     Handle(Geom_Curve) C3d = GeomLib::To3d(axes,PC);
364     if (C3d.IsNull())
365       return Standard_False;
366     // update the edge
367     Standard_Real First, Last;
368
369     BRep_Builder B;
370     B.UpdateEdge(AnEdge,C3d,LocalLoc,0.0e0);
371     BRep_Tool::Range(AnEdge, S, LC, First, Last);
372     B.Range(AnEdge, First, Last); //Do not forget 3D range.(PRO6412)
373   }
374   else {
375     //
376     // compute the 3d curve using existing surface
377     //
378     fc = f ;
379     lc = l ;
380     if (!BRep_Tool::Degenerated(AnEdge)) {
381       jj = 0 ;
382       for (ii = 0 ; ii < 3 ; ii++ ) {
383         BRep_Tool::CurveOnSurface(TopoDS::Edge(AnEdge),
384           Curve2dPtr,
385           SurfacePtr,
386           LocalLoc,
387           fc,
388           lc,
389           ii) ;
390
391         if (!Curve2dPtr.IsNull() && jj < 2){
392           Curve2dArray[jj] = Curve2dPtr ;
393           SurfaceArray[jj] = SurfacePtr ;
394           L[jj] = LocalLoc ;
395           first[jj] = fc ;
396           last[jj] = lc ;
397           jj += 1 ;
398         }
399       }
400       f = first[0] ;
401       l = last[0] ;
402       Curve2dPtr = Curve2dArray[0] ;
403       SurfacePtr = SurfaceArray[0] ;
404
405       Geom2dAdaptor_Curve     AnAdaptor3dCurve2d (Curve2dPtr, f, l) ;
406       GeomAdaptor_Surface     AnAdaptor3dSurface (SurfacePtr) ;
407       Handle(Geom2dAdaptor_HCurve) AnAdaptor3dCurve2dPtr =
408         new Geom2dAdaptor_HCurve(AnAdaptor3dCurve2d) ;
409       Handle(GeomAdaptor_HSurface) AnAdaptor3dSurfacePtr =
410         new GeomAdaptor_HSurface (AnAdaptor3dSurface) ;
411       Adaptor3d_CurveOnSurface  CurveOnSurface( AnAdaptor3dCurve2dPtr,
412         AnAdaptor3dSurfacePtr) ;
413
414       Handle(Geom_Curve) NewCurvePtr ;
415
416       GeomLib::BuildCurve3d(Tolerance,
417         CurveOnSurface,
418         f,
419         l,
420         NewCurvePtr,
421         max_deviation,
422         average_deviation,
423         Continuity,
424         MaxDegree,
425         evaluateMaxSegment(MaxSegment,CurveOnSurface)) ;
426       BRep_Builder B;   
427       tolerance = BRep_Tool::Tolerance(AnEdge) ;
428       //Patch
429       //max_deviation = Max(tolerance, max_deviation) ;
430       max_deviation = Max( tolerance, Tolerance );
431       if (NewCurvePtr.IsNull())
432         return Standard_False;
433       B.UpdateEdge(TopoDS::Edge(AnEdge),
434         NewCurvePtr,
435         L[0],
436         max_deviation) ;
437       if (jj == 1 ) {
438         //
439         // if there is only one curve on surface attached to the edge
440         // than it can be qualified sameparameter
441         //
442         B.SameParameter(TopoDS::Edge(AnEdge),
443           Standard_True) ;
444       }
445     }
446     else {
447       return Standard_False ;
448     }
449
450   }         
451   return Standard_True;
452 }
453 //=======================================================================
454 //function : BuildCurves3d
455 //purpose  : 
456 //=======================================================================
457
458 Standard_Boolean  BRepLib::BuildCurves3d(const TopoDS_Shape& S) 
459
460 {
461   return BRepLib::BuildCurves3d(S,
462     1.0e-5) ;
463 }
464
465 //=======================================================================
466 //function : BuildCurves3d
467 //purpose  : 
468 //=======================================================================
469
470 Standard_Boolean  BRepLib::BuildCurves3d(const TopoDS_Shape& S,
471   const Standard_Real Tolerance,
472   const GeomAbs_Shape Continuity,
473   const Standard_Integer MaxDegree,
474   const Standard_Integer MaxSegment)
475 {
476   Standard_Boolean boolean_value,
477     ok = Standard_True;
478   TopTools_MapOfShape a_counter ;
479   TopExp_Explorer ex(S,TopAbs_EDGE);
480
481   while (ex.More()) {
482     if (a_counter.Add(ex.Current())) {
483       boolean_value = 
484         BuildCurve3d(TopoDS::Edge(ex.Current()),
485         Tolerance, Continuity,
486         MaxDegree, MaxSegment);
487       ok = ok && boolean_value ;
488     }
489     ex.Next();
490   }
491   return ok;
492 }
493 //=======================================================================
494 //function : UpdateEdgeTolerance
495 //purpose  : 
496 //=======================================================================
497
498 Standard_Boolean  BRepLib::UpdateEdgeTol(const TopoDS_Edge& AnEdge,
499   const Standard_Real MinToleranceRequested,
500   const Standard_Real MaxToleranceToCheck)
501 {
502
503   Standard_Integer curve_on_surface_index,
504     curve_index,
505     not_done,
506     has_closed_curve,
507     has_curve,
508     jj,
509     ii,
510     geom_reference_curve_flag = 0,
511     max_sampling_points = 90,
512     min_sampling_points = 30 ;
513
514   Standard_Real factor = 100.0e0,
515     //     sampling_array[2],
516     safe_factor = 1.4e0,
517     current_last,
518     current_first,
519     max_distance,
520     coded_edge_tolerance,
521     edge_tolerance = 0.0e0 ;
522   Handle(TColStd_HArray1OfReal) parameters_ptr ;
523   Handle(BRep_GCurve) geometric_representation_ptr ;
524
525   if (BRep_Tool::Degenerated(AnEdge)) return Standard_False ;
526   coded_edge_tolerance = BRep_Tool::Tolerance(AnEdge) ;
527   if (coded_edge_tolerance > MaxToleranceToCheck) return Standard_False ;
528
529   const Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*)&AnEdge.TShape());
530   BRep_ListOfCurveRepresentation& list_curve_rep = TE->ChangeCurves() ;
531   BRep_ListIteratorOfListOfCurveRepresentation an_iterator(list_curve_rep),
532     second_iterator(list_curve_rep) ;
533   Handle(Geom2d_Curve) curve2d_ptr, new_curve2d_ptr;
534   Handle(Geom_Surface) surface_ptr ;
535   TopLoc_Location local_location ;
536   GCPnts_QuasiUniformDeflection  a_sampler ;
537   GeomAdaptor_Curve  geom_reference_curve ;
538   Adaptor3d_CurveOnSurface  curve_on_surface_reference ; 
539   Handle(Geom_Curve) C = BRep_Tool::Curve(AnEdge,
540     local_location,
541     current_first,
542     current_last);
543   curve_on_surface_index = -1 ;
544   if (!C.IsNull()) {
545     if (! local_location.IsIdentity()) {
546       C = Handle(Geom_Curve)::
547         DownCast(C-> Transformed(local_location.Transformation()) ) ;
548     }
549     geom_reference_curve.Load(C) ;
550     geom_reference_curve_flag = 1 ;
551     a_sampler.Initialize(geom_reference_curve,
552       MinToleranceRequested * factor,
553       current_first,
554       current_last) ;
555   }
556   else {
557     not_done = 1 ;
558     curve_on_surface_index = 0 ;  
559
560     while (not_done && an_iterator.More()) {
561       geometric_representation_ptr =
562         Handle(BRep_GCurve)::DownCast(second_iterator.Value());
563       if (!geometric_representation_ptr.IsNull() 
564         && geometric_representation_ptr->IsCurveOnSurface()) {
565           curve2d_ptr = geometric_representation_ptr->PCurve() ;
566           local_location = geometric_representation_ptr->Location() ;
567           current_first = geometric_representation_ptr->First();
568           //first = geometric_representation_ptr->First();
569           current_last =  geometric_representation_ptr->Last();
570           // must be inverted 
571           //
572           if (! local_location.IsIdentity() ) {
573             surface_ptr = Handle(Geom_Surface)::
574               DownCast( geometric_representation_ptr->Surface()->
575               Transformed(local_location.Transformation()) ) ;
576           }
577           else {
578             surface_ptr = 
579               geometric_representation_ptr->Surface() ;
580           }
581           not_done = 0 ;
582       }
583       curve_on_surface_index += 1 ;
584     }
585     Geom2dAdaptor_Curve     AnAdaptor3dCurve2d (curve2d_ptr) ;
586     GeomAdaptor_Surface     AnAdaptor3dSurface (surface_ptr) ;
587     Handle(Geom2dAdaptor_HCurve) AnAdaptor3dCurve2dPtr =
588       new Geom2dAdaptor_HCurve(AnAdaptor3dCurve2d) ;
589     Handle(GeomAdaptor_HSurface) AnAdaptor3dSurfacePtr =
590       new GeomAdaptor_HSurface (AnAdaptor3dSurface) ;
591     curve_on_surface_reference.Load (AnAdaptor3dCurve2dPtr, AnAdaptor3dSurfacePtr);
592     a_sampler.Initialize(curve_on_surface_reference,
593       MinToleranceRequested * factor,
594       current_first,
595       current_last) ;
596   }
597   TColStd_Array1OfReal   sampling_parameters(1,a_sampler.NbPoints()) ;
598   for (ii = 1 ; ii <= a_sampler.NbPoints() ; ii++) {
599     sampling_parameters(ii) = a_sampler.Parameter(ii) ;
600   }
601   if (a_sampler.NbPoints() < min_sampling_points) {
602     GeomLib::DensifyArray1OfReal(min_sampling_points,
603       sampling_parameters,
604       parameters_ptr) ;
605   }
606   else if (a_sampler.NbPoints() > max_sampling_points) {
607     GeomLib::RemovePointsFromArray(max_sampling_points,
608       sampling_parameters,
609       parameters_ptr) ; 
610   }
611   else {
612     jj = 1 ;
613     parameters_ptr =
614       new TColStd_HArray1OfReal(1,sampling_parameters.Length()) ;
615     for (ii = sampling_parameters.Lower() ; ii <= sampling_parameters.Upper() ; ii++) {
616       parameters_ptr->ChangeArray1()(jj) =
617         sampling_parameters(ii) ;
618       jj +=1 ;
619     }
620   }
621
622   curve_index = 0 ;
623
624   while (second_iterator.More()) {
625     geometric_representation_ptr =
626       Handle(BRep_GCurve)::DownCast(second_iterator.Value());
627     if (! geometric_representation_ptr.IsNull() && 
628       curve_index != curve_on_surface_index) {
629         has_closed_curve =
630           has_curve = Standard_False ;
631         //      first = geometric_representation_ptr->First();
632         //      last =  geometric_representation_ptr->Last();
633         local_location = geometric_representation_ptr->Location() ;
634         if (geometric_representation_ptr->IsCurveOnSurface()) {
635           curve2d_ptr = geometric_representation_ptr->PCurve() ; 
636           has_curve = Standard_True ;
637         }
638         if (geometric_representation_ptr->IsCurveOnClosedSurface()) {
639           curve2d_ptr = geometric_representation_ptr->PCurve2() ;
640           has_closed_curve = Standard_True ;
641         }
642
643         if (has_curve ||
644           has_closed_curve) {
645             if (! local_location.IsIdentity() ) {
646               surface_ptr = Handle(Geom_Surface)::
647                 DownCast( geometric_representation_ptr->Surface()->
648                 Transformed(local_location.Transformation()) ) ;
649             }
650             else {
651               surface_ptr = 
652                 geometric_representation_ptr->Surface() ;
653             }
654             Geom2dAdaptor_Curve     an_adaptor_curve2d (curve2d_ptr) ;
655             GeomAdaptor_Surface     an_adaptor_surface(surface_ptr) ;
656             Handle(Geom2dAdaptor_HCurve) an_adaptor_curve2d_ptr =
657               new Geom2dAdaptor_HCurve(an_adaptor_curve2d) ;
658             Handle(GeomAdaptor_HSurface) an_adaptor_surface_ptr =
659               new GeomAdaptor_HSurface (an_adaptor_surface) ;
660             Adaptor3d_CurveOnSurface a_curve_on_surface(an_adaptor_curve2d_ptr,
661               an_adaptor_surface_ptr) ;
662
663             if (BRep_Tool::SameParameter(AnEdge)) {
664
665               GeomLib::EvalMaxParametricDistance(a_curve_on_surface,
666                 geom_reference_curve,
667                 MinToleranceRequested,
668                 parameters_ptr->Array1(),
669                 max_distance) ;
670             }
671             else if (geom_reference_curve_flag) {
672               GeomLib::EvalMaxDistanceAlongParameter(a_curve_on_surface,
673                 geom_reference_curve,
674                 MinToleranceRequested,
675                 parameters_ptr->Array1(),
676                 max_distance) ;
677             }
678             else {
679
680               GeomLib::EvalMaxDistanceAlongParameter(a_curve_on_surface,
681                 curve_on_surface_reference,
682                 MinToleranceRequested,
683                 parameters_ptr->Array1(),
684                 max_distance) ;
685             }
686             max_distance *= safe_factor ;
687             edge_tolerance = Max(max_distance, edge_tolerance) ;
688         }
689
690
691     }
692     curve_index += 1 ;
693     second_iterator.Next() ; 
694   }
695
696   TE->Tolerance(edge_tolerance);
697   return Standard_True ;
698
699 }
700 //=======================================================================
701 //function : UpdateEdgeTolerance
702 //purpose  : 
703 //=======================================================================
704
705 Standard_Boolean BRepLib::UpdateEdgeTolerance(const TopoDS_Shape& S,
706   const Standard_Real MinToleranceRequested,
707   const Standard_Real MaxToleranceToCheck) 
708 {
709   TopExp_Explorer ex(S,TopAbs_EDGE);
710   TopTools_MapOfShape  a_counter ;
711
712   Standard_Boolean     return_status = Standard_False,
713     local_flag ;
714
715   while (ex.More()) {
716     if (a_counter.Add(ex.Current())) {
717       local_flag =
718         BRepLib::UpdateEdgeTol(TopoDS::Edge(ex.Current()),
719         MinToleranceRequested,
720         MaxToleranceToCheck) ;
721       if (local_flag && ! return_status) {
722         return_status = Standard_True ;
723       }
724     }
725     ex.Next();
726   }
727   return return_status ;
728 }
729
730 //=======================================================================
731 //function : SetEdgeTol
732 //purpose  : 
733 //=======================================================================
734
735 static void SetEdgeTol(const TopoDS_Edge& E,
736   const TopoDS_Face& F)
737 {
738   TopLoc_Location L;
739   const Handle(Geom_Surface)& S = BRep_Tool::Surface(F,L);
740   TopLoc_Location l = L.Predivided(E.Location());
741
742   const Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*)&E.TShape());
743   BRep_ListIteratorOfListOfCurveRepresentation itcr(TE->ChangeCurves());
744
745   while (itcr.More()) {
746     const Handle(BRep_CurveRepresentation)& cr = itcr.Value();
747     if(cr->IsCurveOnSurface(S,l)) return;
748     itcr.Next();
749   }
750
751   Handle(Geom_Plane) GP;
752   Handle(Geom_RectangularTrimmedSurface) GRTS;
753   GRTS = Handle(Geom_RectangularTrimmedSurface)::DownCast(S);
754   if(!GRTS.IsNull())
755     GP = Handle(Geom_Plane)::DownCast(GRTS->BasisSurface());
756   else
757     GP = Handle(Geom_Plane)::DownCast(S);
758
759   Handle(GeomAdaptor_HCurve) HC = new GeomAdaptor_HCurve();
760   Handle(GeomAdaptor_HSurface) HS = new GeomAdaptor_HSurface();
761
762   TopLoc_Location LC;
763   Standard_Real First, Last;
764   GeomAdaptor_Curve& GAC = HC->ChangeCurve();
765   GAC.Load(BRep_Tool::Curve(E,LC,First,Last));
766   LC = L.Predivided(LC);
767
768   if (!LC.IsIdentity()) {
769     GP = Handle(Geom_Plane)::DownCast(
770       GP->Transformed(LC.Transformation()));
771   }
772   GeomAdaptor_Surface& GAS = HS->ChangeSurface();
773   GAS.Load(GP);
774
775   ProjLib_ProjectedCurve Proj(HS,HC);
776   Handle(Geom2d_Curve) pc = Geom2dAdaptor::MakeCurve(Proj);
777
778   gp_Pln pln = GAS.Plane();
779   Standard_Real d2 = 0.;
780   Standard_Integer nn = 23;
781   Standard_Real unsurnn = 1./nn;
782   for(Standard_Integer i = 0; i <= nn; i++){
783     Standard_Real t = unsurnn*i;
784     Standard_Real u = First*(1.-t) + Last*t;
785     gp_Pnt Pc3d = HC->Value(u);
786     gp_Pnt2d p2d = pc->Value(u);
787     gp_Pnt Pcons = ElSLib::Value(p2d.X(),p2d.Y(),pln);
788     Standard_Real eps = Max(Pc3d.XYZ().SquareModulus(), Pcons.XYZ().SquareModulus());
789     eps = Epsilon(eps);
790     Standard_Real temp = Pc3d.SquareDistance(Pcons);
791     if(temp <= eps)
792     {
793       temp = 0.;
794     }
795     if(temp > d2) d2 = temp;
796   }
797   d2 = 1.5*sqrt(d2);
798   TE->UpdateTolerance(d2);
799 }
800
801 //=======================================================================
802 //function : SameParameter
803 //purpose  : 
804 //=======================================================================
805 void  BRepLib::SameParameter(const TopoDS_Shape& S,
806   const Standard_Real Tolerance,
807   const Standard_Boolean forced) 
808 {
809   TopExp_Explorer ex(S,TopAbs_EDGE);
810   TopTools_MapOfShape  Done;
811   BRep_Builder brB;
812
813   while (ex.More()) {
814     if (Done.Add(ex.Current())) {
815       if (forced) {
816         brB.SameRange(TopoDS::Edge(ex.Current()), Standard_False);
817         brB.SameParameter(TopoDS::Edge(ex.Current()), Standard_False);
818       }
819       BRepLib::SameParameter(TopoDS::Edge(ex.Current()),Tolerance);
820     }
821     ex.Next();
822   }
823
824   Done.Clear();
825   BRepAdaptor_Surface BS;
826   for(ex.Init(S,TopAbs_FACE); ex.More(); ex.Next()){
827     const TopoDS_Face& curface = TopoDS::Face(ex.Current());
828     if(!Done.Add(curface)) continue;
829     BS.Initialize(curface);
830     if(BS.GetType() != GeomAbs_Plane) continue;
831     TopExp_Explorer ex2;
832     for(ex2.Init(curface,TopAbs_EDGE); ex2.More(); ex2.Next()){
833       const TopoDS_Edge& E = TopoDS::Edge(ex2.Current());
834       SetEdgeTol(E,curface);
835     }
836   }
837   BRepLib::UpdateTolerances(S);
838 }
839
840 //================================================================
841 //function : SameParameter
842 //WARNING  : New spec DUB LBO 9/9/97.
843 //  Recode in the edge the best tolerance found, 
844 //  for vertex extremities it is required to find something else
845 //================================================================
846 static Standard_Boolean EvalTol(const Handle(Geom2d_Curve)& pc,
847   const Handle(Geom_Surface)& s,
848   const GeomAdaptor_Curve&    gac,
849   const Standard_Real         tol,
850   Standard_Real&              tolbail)
851 {
852   Standard_Integer ok = 0;
853   Standard_Real f = gac.FirstParameter();
854   Standard_Real l = gac.LastParameter();
855   Extrema_LocateExtPC Projector;
856   Projector.Initialize(gac,f,l,tol);
857   Standard_Real u,v;
858   gp_Pnt p;
859   tolbail = tol;
860   for(Standard_Integer i = 1; i <= 5; i++){
861     Standard_Real t = i/6.;
862     t = (1.-t) * f + t * l;
863     pc->Value(t).Coord(u,v);
864     p = s->Value(u,v);
865     Projector.Perform(p,t);
866     if (Projector.IsDone()) {
867       Standard_Real dist2 = Projector.SquareDistance();
868       if(dist2 > tolbail * tolbail) tolbail = sqrt (dist2);
869       ok++;
870     }
871   }
872   return (ok > 2);
873 }
874
875 static Standard_Real ComputeTol(const Handle(Adaptor3d_HCurve)& c3d,
876   const Handle(Adaptor2d_HCurve2d)& c2d,
877   const Handle(Adaptor3d_HSurface)& surf,
878   const Standard_Integer        nbp)
879
880 {
881
882   TColStd_Array1OfReal dist(1,nbp+10);
883   dist.Init(-1.);
884
885   Adaptor3d_CurveOnSurface  cons(c2d,surf);
886   Standard_Real d2 = 0.;
887   Standard_Real first = c3d->FirstParameter();
888   Standard_Real last  = c3d->LastParameter();
889   Standard_Integer i = 0;
890   for(i = 0; i <= nbp; i++){
891     const Standard_Real t = IntToReal(i)/IntToReal(nbp);
892     const Standard_Real u = first*(1.-t) + last*t;
893     gp_Pnt Pc3d = c3d->Value(u);
894     gp_Pnt Pcons = cons.Value(u);
895     if (Precision::IsInfinite(Pcons.X()) ||
896       Precision::IsInfinite(Pcons.Y()) ||
897       Precision::IsInfinite(Pcons.Z())) {
898         d2=Precision::Infinite();
899         break;
900     }
901     Standard_Real temp = Pc3d.SquareDistance(Pcons);
902
903
904     dist(i+1) = temp;
905
906
907     if(temp > d2) d2 = temp;
908   }
909
910
911   Standard_Boolean ana = Standard_False;
912   Standard_Real D2 = 0;
913   Standard_Integer N1 = 0;
914   Standard_Integer N2 = 0;
915   Standard_Integer N3 = 0;
916
917   for( i = 1; i<= nbp+10; i++)
918     if( dist(i) > 0 ) {
919       if( dist(i) < 1.0 ) N1++;
920       else N2++;
921     }
922
923     if( N1 > N2 && N2 != 0 ) N3 = 100*N2/(N1+N2);
924     if( N3 < 10 && N3 != 0 ) {
925       ana = Standard_True;
926       for( i = 1; i<= nbp+10; i++)
927         if( dist(i) > 0 && dist(i) < 1.0 )
928           if( dist(i) > D2 ) D2 = dist(i);
929     }
930
931     //d2 = 1.5*sqrt(d2);
932     d2 = (!ana) ? 1.5*sqrt(d2) : 1.5*sqrt(D2);
933     if(d2<1.e-7) d2 = 1.e-7;
934
935     return d2;
936 }
937
938 void BRepLib::SameParameter(const TopoDS_Edge&  AnEdge,
939   const Standard_Real Tolerance)
940 {
941   if (BRep_Tool::SameParameter(AnEdge)) return;
942
943   const Standard_Integer NCONTROL = 22;
944
945   Handle(GeomAdaptor_HCurve) HC = new GeomAdaptor_HCurve();
946   Handle(Geom2dAdaptor_HCurve) HC2d = new Geom2dAdaptor_HCurve();
947   Handle(GeomAdaptor_HSurface) HS = new GeomAdaptor_HSurface();
948   GeomAdaptor_Curve& GAC = HC->ChangeCurve();
949   Geom2dAdaptor_Curve& GAC2d = HC2d->ChangeCurve2d();
950   GeomAdaptor_Surface& GAS = HS->ChangeSurface();
951   Standard_Real f3d =0.,l3d =0.;
952   TopLoc_Location L3d;
953   Handle(Geom_Curve) C3d;
954
955   const Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*) &AnEdge.TShape());
956   BRep_ListOfCurveRepresentation& CList = TE->ChangeCurves();
957   BRep_ListIteratorOfListOfCurveRepresentation It(CList);
958
959   Standard_Boolean NotDone = Standard_True;
960
961   while (NotDone && It.More()) {
962     Handle(BRep_GCurve) GCurve = Handle(BRep_GCurve)::DownCast(It.Value());
963     if (!GCurve.IsNull() && GCurve->IsCurve3D()) {
964       C3d = GCurve->Curve3D() ;
965       f3d = GCurve->First();
966       l3d = GCurve->Last();
967       L3d = GCurve->Location() ;
968       NotDone = Standard_False;
969     } 
970     It.Next() ;
971   }
972
973   if(C3d.IsNull()) return;
974
975   // modified by NIZHNY-OCC486  Tue Aug 27 17:15:13 2002 :
976   Standard_Boolean m_TrimmedPeriodical = Standard_False;
977   Handle(Standard_Type) TheType = C3d->DynamicType();
978   if( TheType == STANDARD_TYPE(Geom_TrimmedCurve))
979   {
980     Handle(Geom_Curve) gtC (Handle(Geom_TrimmedCurve)::DownCast (C3d)->BasisCurve());
981     m_TrimmedPeriodical = gtC->IsPeriodic();
982   }
983   // modified by NIZHNY-OCC486  Tue Aug 27 17:15:17 2002 .
984
985   BRep_Builder B;
986   if(!C3d->IsPeriodic()) {
987     Standard_Real Udeb = C3d->FirstParameter();
988     Standard_Real Ufin = C3d->LastParameter();
989     // modified by NIZHNY-OCC486  Tue Aug 27 17:17:14 2002 :
990     //if (Udeb > f3d) f3d = Udeb;
991     //if (l3d > Ufin) l3d = Ufin;
992     if(!m_TrimmedPeriodical)
993     {
994       if (Udeb > f3d) f3d = Udeb;
995       if (l3d > Ufin) l3d = Ufin;
996     }
997     // modified by NIZHNY-OCC486  Tue Aug 27 17:17:55 2002 .
998   }
999   if(!L3d.IsIdentity()){
1000     C3d = Handle(Geom_Curve)::DownCast(C3d->Transformed(L3d.Transformation()));
1001   }
1002   GAC.Load(C3d,f3d,l3d);
1003
1004   Standard_Boolean IsSameP = 1;
1005   Standard_Real maxdist = 0.;
1006
1007   //  Modified by skv - Thu Jun  3 12:39:19 2004 OCC5898 Begin
1008   Standard_Real anEdgeTol = BRep_Tool::Tolerance(AnEdge);
1009   //  Modified by skv - Thu Jun  3 12:39:20 2004 OCC5898 End
1010   Standard_Boolean SameRange = BRep_Tool::SameRange(AnEdge);
1011   Standard_Boolean YaPCu = Standard_False;
1012   It.Initialize(CList);
1013
1014   while (It.More()) {
1015     Standard_Boolean isANA = Standard_False;
1016     Standard_Boolean isBSP = Standard_False;
1017     Handle(BRep_GCurve) GCurve = Handle(BRep_GCurve)::DownCast(It.Value());
1018     Handle(Geom2d_Curve) PC[2];
1019     Handle(Geom_Surface) S;
1020     if (!GCurve.IsNull() && GCurve->IsCurveOnSurface()) {
1021       YaPCu = Standard_True;
1022       PC[0] = GCurve->PCurve();
1023       TopLoc_Location PCLoc = GCurve->Location();
1024       S = GCurve->Surface();
1025       if (!PCLoc.IsIdentity() ) {
1026         S = Handle(Geom_Surface)::DownCast(S->Transformed(PCLoc.Transformation()));
1027       }
1028
1029       GAS.Load(S);
1030       if (GCurve->IsCurveOnClosedSurface()) {
1031         PC[1] = GCurve->PCurve2();
1032       }
1033
1034       // Eval tol2d to compute SameRange
1035       Standard_Real UResol = Max(GAS.UResolution(Tolerance), Precision::PConfusion());
1036       Standard_Real VResol = Max(GAS.VResolution(Tolerance), Precision::PConfusion());
1037       Standard_Real Tol2d  = Min(UResol, VResol);
1038       for(Standard_Integer i = 0; i < 2; i++){
1039         Handle(Geom2d_Curve) curPC = PC[i];
1040         Standard_Boolean updatepc = 0;
1041         if(curPC.IsNull()) break;
1042         if(!SameRange){
1043           GeomLib::SameRange(Tol2d,
1044             PC[i],GCurve->First(),GCurve->Last(),
1045             f3d,l3d,curPC);
1046
1047           updatepc = (curPC != PC[i]);
1048
1049         }
1050         Standard_Boolean goodpc = 1;
1051         GAC2d.Load(curPC,f3d,l3d);
1052
1053         Standard_Real error = ComputeTol(HC, HC2d, HS, NCONTROL);
1054
1055         if(GAC2d.GetType() == GeomAbs_BSplineCurve && 
1056           GAC2d.Continuity() == GeomAbs_C0) {
1057             Handle(Geom2d_BSplineCurve) bs2d = GAC2d.BSpline();
1058             Handle(Geom2d_BSplineCurve) bs2dsov = bs2d;
1059             Standard_Real fC0 = bs2d->FirstParameter(), lC0 = bs2d->LastParameter();
1060             Standard_Boolean repar = Standard_True;
1061             gp_Pnt2d OriginPoint;
1062             bs2d->D0(fC0, OriginPoint);
1063             Geom2dConvert::C0BSplineToC1BSplineCurve(bs2d, Tol2d);
1064             isBSP = Standard_True; 
1065
1066             if(bs2d->IsPeriodic()) { // -------- IFV, Jan 2000
1067               gp_Pnt2d NewOriginPoint;
1068               bs2d->D0(bs2d->FirstParameter(), NewOriginPoint);
1069               if(Abs(OriginPoint.X() - NewOriginPoint.X()) > Precision::PConfusion() ||
1070                 Abs(OriginPoint.Y() - NewOriginPoint.Y()) > Precision::PConfusion()    ) {
1071
1072                   TColStd_Array1OfReal Knotbs2d (1, bs2d->NbKnots());
1073                   bs2d->Knots(Knotbs2d);
1074
1075                   for(Standard_Integer Index = 1; Index <= bs2d->NbKnots(); Index++) {
1076                     bs2d->D0(Knotbs2d(Index), NewOriginPoint);
1077                     if(Abs(OriginPoint.X() - NewOriginPoint.X()) > Precision::PConfusion() ||
1078                       Abs(OriginPoint.Y() - NewOriginPoint.Y()) > Precision::PConfusion()    ) continue;
1079
1080                     bs2d->SetOrigin(Index);
1081                     break;
1082                   }
1083               }
1084             }
1085
1086             if(bs2d->Continuity() == GeomAbs_C0) {
1087               Standard_Real tolbail;
1088               if(EvalTol(curPC,S,GAC,Tolerance,tolbail)){
1089                 bs2d = bs2dsov;
1090                 Standard_Real UResbail = GAS.UResolution(tolbail);
1091                 Standard_Real VResbail = GAS.VResolution(tolbail);
1092                 Standard_Real Tol2dbail  = Min(UResbail,VResbail);
1093                 bs2d->D0(bs2d->FirstParameter(), OriginPoint); 
1094
1095                 Standard_Integer nbp = bs2d->NbPoles();
1096                 TColgp_Array1OfPnt2d poles(1,nbp);
1097                 bs2d->Poles(poles);
1098                 gp_Pnt2d p = poles(1), p1;
1099                 Standard_Real d = Precision::Infinite();
1100                 for(Standard_Integer ip = 2; ip <= nbp; ip++) {
1101                   p1 = poles(ip);
1102                   d = Min(d,p.SquareDistance(p1));
1103                   p = p1;
1104                 }
1105                 d = sqrt(d)*.1;
1106
1107                 Tol2dbail = Max(Min(Tol2dbail,d),Tol2d);
1108
1109                 Geom2dConvert::C0BSplineToC1BSplineCurve(bs2d,Tol2dbail);
1110
1111                 if(bs2d->IsPeriodic()) { // -------- IFV, Jan 2000
1112                   gp_Pnt2d NewOriginPoint;
1113                   bs2d->D0(bs2d->FirstParameter(), NewOriginPoint);
1114                   if(Abs(OriginPoint.X() - NewOriginPoint.X()) > Precision::PConfusion() ||
1115                     Abs(OriginPoint.Y() - NewOriginPoint.Y()) > Precision::PConfusion()    ) {
1116
1117                       TColStd_Array1OfReal Knotbs2d (1, bs2d->NbKnots());
1118                       bs2d->Knots(Knotbs2d);
1119
1120                       for(Standard_Integer Index = 1; Index <= bs2d->NbKnots(); Index++) {
1121                         bs2d->D0(Knotbs2d(Index), NewOriginPoint);
1122                         if(Abs(OriginPoint.X() - NewOriginPoint.X()) > Precision::PConfusion() ||
1123                           Abs(OriginPoint.Y() - NewOriginPoint.Y()) > Precision::PConfusion()    ) continue;
1124
1125                         bs2d->SetOrigin(Index);
1126                         break;
1127                       }
1128                   }
1129                 }
1130
1131
1132                 if(bs2d->Continuity() == GeomAbs_C0) {
1133                   goodpc = 1;
1134                   bs2d = bs2dsov;
1135                   repar = Standard_False;
1136                 }
1137               }
1138               else goodpc = 0;
1139             }
1140
1141             if(goodpc){
1142               if(repar) {
1143                 Standard_Integer NbKnots = bs2d->NbKnots();
1144                 TColStd_Array1OfReal Knots(1,NbKnots);
1145                 bs2d->Knots(Knots);
1146                 //          BSplCLib::Reparametrize(f3d,l3d,Knots);
1147                 BSplCLib::Reparametrize(fC0,lC0,Knots);
1148                 bs2d->SetKnots(Knots);
1149                 GAC2d.Load(bs2d,f3d,l3d);
1150                 curPC = bs2d;
1151                 Standard_Boolean updatepcsov = updatepc;
1152                 updatepc = Standard_True;
1153
1154                 Standard_Real error1 = ComputeTol(HC, HC2d, HS, NCONTROL);
1155                 if(error1 > error) {
1156                   bs2d = bs2dsov;
1157                   GAC2d.Load(bs2d,f3d,l3d);
1158                   curPC = bs2d;
1159                   updatepc = updatepcsov;
1160                   isANA = Standard_True;
1161                 }
1162                 else {
1163                   error = error1;
1164                 }
1165               }
1166
1167               //check, if new BSpline "good" or not --------- IFV, Jan of 2000
1168               GeomAbs_Shape cont = bs2d->Continuity();
1169               Standard_Boolean IsBad = Standard_False;
1170
1171               if(cont > GeomAbs_C0 && error > Max(1.e-3,Tolerance)) {
1172                 Standard_Integer NbKnots = bs2d->NbKnots();
1173                 TColStd_Array1OfReal Knots(1,NbKnots);
1174                 bs2d->Knots(Knots);
1175                 Standard_Real critratio = 10.; 
1176                 Standard_Real dtprev = Knots(2) - Knots(1), dtratio = 1.;
1177                 Standard_Real dtmin = dtprev;
1178                 Standard_Real dtcur;
1179                 for(Standard_Integer j = 2; j < NbKnots; j++) {
1180                   dtcur = Knots(j+1) - Knots(j);
1181                   dtmin = Min(dtmin, dtcur);
1182
1183                   if(IsBad) continue;
1184
1185                   if(dtcur > dtprev) dtratio = dtcur/dtprev;
1186                   else dtratio = dtprev/dtcur;
1187                   if(dtratio > critratio) {IsBad = Standard_True;}
1188                   dtprev = dtcur;
1189
1190                 }
1191                 if(IsBad) {
1192                   // To avoid failures in Approx_CurvilinearParameter 
1193                   bs2d->Resolution(Max(1.e-3,Tolerance), dtcur);
1194                   if(dtmin < dtcur) IsBad = Standard_False;
1195                 }
1196               }
1197
1198
1199               if(IsBad ) { //if BSpline "bad", try to reparametrize it
1200                 // by its curve length
1201
1202                 //            GeomAbs_Shape cont = bs2d->Continuity();
1203                 if(cont > GeomAbs_C2) cont = GeomAbs_C2;
1204                 Standard_Integer maxdeg = bs2d->Degree();
1205                 if(maxdeg == 1) maxdeg = 14;
1206                 Approx_CurvilinearParameter AppCurPar(HC2d, HS, Max(1.e-3,Tolerance),
1207                   cont, maxdeg, 10);
1208                 if(AppCurPar.IsDone() || AppCurPar.HasResult()) {
1209                   bs2d = AppCurPar.Curve2d1();
1210                   GAC2d.Load(bs2d,f3d,l3d);
1211                   curPC = bs2d;
1212
1213                   if(Abs(bs2d->FirstParameter() - fC0) > Tol2d ||
1214                     Abs(bs2d->LastParameter() - lC0) > Tol2d    ) {
1215                       Standard_Integer NbKnots = bs2d->NbKnots();
1216                       TColStd_Array1OfReal Knots(1,NbKnots);
1217                       bs2d->Knots(Knots);
1218                       //                  BSplCLib::Reparametrize(f3d,l3d,Knots);
1219                       BSplCLib::Reparametrize(fC0,lC0,Knots);
1220                       bs2d->SetKnots(Knots);
1221                       GAC2d.Load(bs2d,f3d,l3d);
1222                       curPC = bs2d;
1223
1224                   }
1225                 }
1226               }
1227
1228
1229             }
1230         }
1231
1232
1233         if(goodpc){
1234           //      Approx_SameParameter SameP(HC,HC2d,HS,Tolerance);
1235           Standard_Real aTol = (isANA && isBSP) ? 1.e-7 : Tolerance;
1236           const Handle(Adaptor3d_HCurve)& aHCurv = HC; // to avoid ambiguity
1237           const Handle(Adaptor2d_HCurve2d)& aHCurv2d = HC2d; // to avoid ambiguity
1238           Approx_SameParameter SameP(aHCurv,aHCurv2d,HS,aTol);
1239
1240           if (SameP.IsSameParameter()) {
1241             maxdist = Max(maxdist,SameP.TolReached());
1242             if(updatepc){
1243               if (i == 0) GCurve->PCurve(curPC);
1244               else GCurve->PCurve2(curPC);
1245             }
1246           }
1247           else if (SameP.IsDone()) {
1248             Standard_Real tolreached = SameP.TolReached();
1249             if(tolreached < error) {
1250               curPC = SameP.Curve2d();
1251               updatepc = Standard_True;
1252               maxdist = Max(maxdist,tolreached);
1253             }
1254             else {
1255               maxdist = Max(maxdist, error);
1256             }
1257             if(updatepc){
1258               if (i == 0) GCurve->PCurve(curPC);
1259               else GCurve->PCurve2(curPC);
1260             }
1261           }
1262           else IsSameP = 0;
1263
1264         }
1265         else IsSameP = 0;
1266
1267         //  Modified by skv - Thu Jun  3 12:39:19 2004 OCC5898 Begin
1268         if (!IsSameP) {
1269           if (anEdgeTol > error) {
1270             maxdist = Max(maxdist, anEdgeTol);
1271             IsSameP = Standard_True;
1272           }
1273         }
1274         //  Modified by skv - Thu Jun  3 12:39:20 2004 OCC5898 End
1275       }
1276     }
1277     It.Next() ;
1278   }
1279   B.Range(AnEdge,f3d,l3d);
1280   B.SameRange(AnEdge,Standard_True);
1281   if ( IsSameP) {
1282     // Reduce eventually the tolerance of the edge, as
1283     // all its representations are processed (except for some associated
1284     // to planes and not stored in the edge !) 
1285     // The same cannot be done with vertices that cannot be enlarged 
1286     // or left as is.
1287     if (YaPCu) {
1288       // Avoid setting too small tolerances.
1289       maxdist = Max(maxdist,Precision::Confusion());
1290       TopoDS_Vertex V1,V2;
1291       TopExp::Vertices(AnEdge,V1,V2);
1292       if (!V1.IsNull())
1293         B.UpdateVertex(V1,maxdist);
1294       if (!V2.IsNull())
1295         B.UpdateVertex(V2,maxdist);
1296       TE->Modified(Standard_True);
1297       TE->Tolerance(maxdist);
1298     }
1299     B.SameParameter(AnEdge,Standard_True);
1300   }
1301 }
1302
1303 //=======================================================================
1304 //function : UpdateTolerances
1305 //purpose  : 
1306 //=======================================================================
1307 void  BRepLib::UpdateTolerances(const TopoDS_Shape& aShape,
1308   const Standard_Boolean verifyTolerance) 
1309 {
1310
1311   // Harmonize tolerances
1312   // with rule Tolerance(VERTEX)>=Tolerance(EDGE)>=Tolerance(FACE)
1313   BRep_Builder B;
1314   Standard_Real tol=0;
1315   if (verifyTolerance) {
1316     // Set tolerance to its minimum value
1317     Handle(Geom_Surface) S;
1318     TopLoc_Location l;
1319     TopExp_Explorer ex;
1320     Bnd_Box aB;
1321     Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax, dMax;
1322     for (ex.Init(aShape, TopAbs_FACE); ex.More(); ex.Next()) {
1323       const TopoDS_Face& curf=TopoDS::Face(ex.Current());
1324       S = BRep_Tool::Surface(curf, l);
1325       if (!S.IsNull()) {
1326         aB.SetVoid();
1327         BRepBndLib::Add(curf,aB);
1328         if (S->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
1329           S = Handle(Geom_RectangularTrimmedSurface)::DownCast (S)->BasisSurface();
1330         }
1331         GeomAdaptor_Surface AS(S);
1332         switch (AS.GetType()) {
1333         case GeomAbs_Plane: 
1334         case GeomAbs_Cylinder: 
1335         case GeomAbs_Cone: 
1336           {
1337             tol=Precision::Confusion();
1338             break;
1339           }
1340         case GeomAbs_Sphere: 
1341         case GeomAbs_Torus: 
1342           {
1343             tol=Precision::Confusion()*2;
1344             break;
1345           }
1346         default:
1347           tol=Precision::Confusion()*4;
1348         }
1349         if (!aB.IsWhole()) {
1350           aB.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
1351           dMax=1.;
1352           if (!aB.IsOpenXmin() && !aB.IsOpenXmax()) dMax=aXmax-aXmin;
1353           if (!aB.IsOpenYmin() && !aB.IsOpenYmax()) aYmin=aYmax-aYmin;
1354           if (!aB.IsOpenZmin() && !aB.IsOpenZmax()) aZmin=aZmax-aZmin;
1355           if (aYmin>dMax) dMax=aYmin;
1356           if (aZmin>dMax) dMax=aZmin;
1357           tol=tol*dMax;
1358           // Do not process tolerances > 1.
1359           if (tol>1.) tol=0.99;
1360         }
1361         const Handle(BRep_TFace)& Tf = *((Handle(BRep_TFace)*)&curf.TShape());
1362         Tf->Tolerance(tol);
1363       }
1364     }
1365   }
1366
1367   //Process edges
1368   TopTools_IndexedDataMapOfShapeListOfShape parents;
1369   TopExp::MapShapesAndAncestors(aShape, TopAbs_EDGE, TopAbs_FACE, parents);
1370   TopTools_ListIteratorOfListOfShape lConx;
1371   Standard_Integer iCur;
1372   for (iCur=1; iCur<=parents.Extent(); iCur++) {
1373     tol=0;
1374     for (lConx.Initialize(parents(iCur)); lConx.More(); lConx.Next()) {
1375       tol=Max(tol, BRep_Tool::Tolerance(TopoDS::Face(lConx.Value())));
1376     }
1377     // Update can only increase tolerance, so if the edge has a greater
1378     //  tolerance than its faces it is not concerned
1379     B.UpdateEdge(TopoDS::Edge(parents.FindKey(iCur)), tol);
1380   }
1381
1382   //Vertices are processed
1383   parents.Clear();
1384   TopExp::MapShapesAndAncestors(aShape, TopAbs_VERTEX, TopAbs_EDGE, parents);
1385   TColStd_MapOfTransient Initialized;
1386   TopTools_MapOfShape Done;
1387   Standard_Integer nbV = parents.Extent();
1388   for (iCur=1; iCur<=nbV; iCur++) {
1389     tol=0;
1390     Done.Clear();
1391     const TopoDS_Vertex& V = TopoDS::Vertex(parents.FindKey(iCur));
1392     Bnd_Box box;
1393     box.Add(BRep_Tool::Pnt(V));
1394     gp_Pnt p3d;
1395     for (lConx.Initialize(parents(iCur)); lConx.More(); lConx.Next()) {
1396       const TopoDS_Edge& E = TopoDS::Edge(lConx.Value());
1397       if(!Done.Add(E)) continue;
1398       tol=Max(tol, BRep_Tool::Tolerance(E));
1399       if(!BRep_Tool::SameRange(E)) continue;
1400       Standard_Real par = BRep_Tool::Parameter(V,E);
1401       Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*)&E.TShape());
1402       BRep_ListIteratorOfListOfCurveRepresentation itcr(TE->Curves());
1403       const TopLoc_Location& Eloc = E.Location();
1404       while (itcr.More()) {
1405         // For each CurveRepresentation, check the provided parameter
1406         const Handle(BRep_CurveRepresentation)& cr = itcr.Value();
1407         const TopLoc_Location& loc = cr->Location();
1408         TopLoc_Location L = (Eloc * loc);
1409         if (cr->IsCurve3D()) {
1410           const Handle(Geom_Curve)& C = cr->Curve3D();
1411           if (!C.IsNull()) { // edge non degenerated
1412             p3d = C->Value(par);
1413             p3d.Transform(L.Transformation());
1414             box.Add(p3d);
1415           }
1416         }
1417         else if (cr->IsCurveOnSurface()) {
1418           const Handle(Geom_Surface)& Su = cr->Surface();
1419           const Handle(Geom2d_Curve)& PC = cr->PCurve();
1420           Handle(Geom2d_Curve) PC2;
1421           if (cr->IsCurveOnClosedSurface()) {
1422             PC2 = cr->PCurve2();
1423           }
1424           gp_Pnt2d p2d = PC->Value(par);
1425           p3d = Su->Value(p2d.X(),p2d.Y());
1426           p3d.Transform(L.Transformation());
1427           box.Add(p3d);
1428           if (!PC2.IsNull()) {
1429             p2d = PC2->Value(par);
1430             p3d = Su->Value(p2d.X(),p2d.Y());
1431             p3d.Transform(L.Transformation());
1432             box.Add(p3d);
1433           }
1434         }
1435         itcr.Next();
1436       }
1437     }
1438     Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
1439     box.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
1440     aXmax -= aXmin; aYmax -= aYmin; aZmax -= aZmin;
1441     tol = Max(tol,sqrt(aXmax*aXmax+aYmax*aYmax+aZmax*aZmax));
1442     tol += 2.*Epsilon(tol);
1443     if (verifyTolerance) {
1444       // ASet minimum value of the tolerance 
1445       // Attention to sharing of the vertex by other shapes
1446       const Handle(BRep_TVertex)& TV = *((Handle(BRep_TVertex)*)&V.TShape());
1447       if (Initialized.Add(TV)) 
1448         TV->Tolerance(tol);
1449       else 
1450         B.UpdateVertex(V, tol);
1451     }
1452     else {
1453       // Update can only increase tolerance, so if the edge has a greater
1454       //  tolerance than its faces it is not concerned
1455       B.UpdateVertex(V, tol);
1456     }
1457   }
1458 }
1459
1460 //=======================================================================
1461 //function : UpdateInnerTolerances
1462 //purpose  : 
1463 //=======================================================================
1464 void  BRepLib::UpdateInnerTolerances(const TopoDS_Shape& aShape)
1465 {
1466   TopTools_IndexedDataMapOfShapeListOfShape EFmap;
1467   TopExp::MapShapesAndAncestors(aShape, TopAbs_EDGE, TopAbs_FACE, EFmap);
1468   BRep_Builder BB;
1469   for (Standard_Integer i = 1; i <= EFmap.Extent(); i++)
1470   {
1471     TopoDS_Edge anEdge = TopoDS::Edge(EFmap.FindKey(i));
1472     TopoDS_Vertex V1, V2;
1473     TopExp::Vertices(anEdge, V1, V2);
1474     Standard_Real fpar, lpar;
1475     BRep_Tool::Range(anEdge, fpar, lpar);
1476     Standard_Real TolEdge = BRep_Tool::Tolerance(anEdge);
1477     gp_Pnt Pnt1, Pnt2;
1478     Handle(BRepAdaptor_HCurve) anHCurve = new BRepAdaptor_HCurve();
1479     anHCurve->ChangeCurve().Initialize(anEdge);
1480     if (!V1.IsNull())
1481       Pnt1 = BRep_Tool::Pnt(V1);
1482     if (!V2.IsNull())
1483       Pnt2 = BRep_Tool::Pnt(V2);
1484     
1485     if (!BRep_Tool::Degenerated(anEdge) &&
1486         EFmap(i).Extent() > 0)
1487     {
1488       NCollection_Sequence<Handle(Adaptor3d_HCurve)> theRep;
1489       theRep.Append(anHCurve);
1490       TopTools_ListIteratorOfListOfShape itl(EFmap(i));
1491       for (; itl.More(); itl.Next())
1492       {
1493         const TopoDS_Face& aFace = TopoDS::Face(itl.Value());
1494         Handle(BRepAdaptor_HCurve) anHCurvOnSurf = new BRepAdaptor_HCurve();
1495         anHCurvOnSurf->ChangeCurve().Initialize(anEdge, aFace);
1496         theRep.Append(anHCurvOnSurf);
1497       }
1498       
1499       const Standard_Integer NbSamples = (BRep_Tool::SameParameter(anEdge))? 23 : 2;
1500       Standard_Real delta = (lpar - fpar)/(NbSamples-1);
1501       Standard_Real MaxDist = 0.;
1502       for (Standard_Integer j = 2; j <= theRep.Length(); j++)
1503       {
1504         for (Standard_Integer k = 0; k <= NbSamples; k++)
1505         {
1506           Standard_Real ParamOnCenter = (k == NbSamples)? lpar :
1507             fpar + k*delta;
1508           gp_Pnt Center = theRep(1)->Value(ParamOnCenter);
1509           Standard_Real ParamOnCurve = (BRep_Tool::SameParameter(anEdge))? ParamOnCenter
1510             : ((k == 0)? theRep(j)->FirstParameter() : theRep(j)->LastParameter());
1511           gp_Pnt aPoint = theRep(j)->Value(ParamOnCurve);
1512           Standard_Real aDist = Center.Distance(aPoint);
1513           //aDist *= 1.1;
1514           aDist += 2.*Epsilon(aDist);
1515           if (aDist > MaxDist)
1516             MaxDist = aDist;
1517
1518           //Update tolerances of vertices
1519           if (k == 0 && !V1.IsNull())
1520           {
1521             Standard_Real aDist1 = Pnt1.Distance(aPoint);
1522             aDist1 += 2.*Epsilon(aDist1);
1523             BB.UpdateVertex(V1, aDist1);
1524           }
1525           if (k == NbSamples && !V2.IsNull())
1526           {
1527             Standard_Real aDist2 = Pnt2.Distance(aPoint);
1528             aDist2 += 2.*Epsilon(aDist2);
1529             BB.UpdateVertex(V2, aDist2);
1530           }
1531         }
1532       }
1533       BB.UpdateEdge(anEdge, MaxDist);
1534     }
1535     TolEdge = BRep_Tool::Tolerance(anEdge);
1536     if (!V1.IsNull())
1537     {
1538       gp_Pnt End1 = anHCurve->Value(fpar);
1539       Standard_Real dist1 = Pnt1.Distance(End1);
1540       dist1 += 2.*Epsilon(dist1);
1541       BB.UpdateVertex(V1, Max(dist1, TolEdge));
1542     }
1543     if (!V2.IsNull())
1544     {
1545       gp_Pnt End2 = anHCurve->Value(lpar);
1546       Standard_Real dist2 = Pnt2.Distance(End2);
1547       dist2 += 2.*Epsilon(dist2);
1548       BB.UpdateVertex(V2, Max(dist2, TolEdge));
1549     }
1550   }
1551 }
1552
1553 //=======================================================================
1554 //function : OrientClosedSolid
1555 //purpose  : 
1556 //=======================================================================
1557 Standard_Boolean BRepLib::OrientClosedSolid(TopoDS_Solid& solid) 
1558 {
1559   // Set material inside the solid
1560   BRepClass3d_SolidClassifier where(solid);
1561   where.PerformInfinitePoint(Precision::Confusion());
1562   if (where.State()==TopAbs_IN) {
1563     solid.Reverse();
1564   }
1565   else if (where.State()==TopAbs_ON || where.State()==TopAbs_UNKNOWN) 
1566     return Standard_False;
1567
1568   return Standard_True;
1569 }
1570
1571 //=======================================================================
1572 //function : tgtfaces
1573 //purpose  : check the angle at the border between two squares.
1574 //           Two shares should have a shared front edge.
1575 //=======================================================================
1576
1577 static Standard_Boolean tgtfaces(const TopoDS_Edge& Ed,
1578   const TopoDS_Face& F1,
1579   const TopoDS_Face& F2,
1580   const Standard_Real ta,
1581   const Standard_Boolean couture)
1582 {
1583   // Check if pcurves exist on both faces of edge
1584   Standard_Real aFirst,aLast;
1585   Handle(Geom2d_Curve) aCurve;
1586   aCurve = BRep_Tool::CurveOnSurface(Ed,F1,aFirst,aLast);
1587   if(aCurve.IsNull())
1588     return Standard_False;
1589   aCurve = BRep_Tool::CurveOnSurface(Ed,F2,aFirst,aLast);
1590   if(aCurve.IsNull())
1591     return Standard_False;
1592
1593   Standard_Real u;
1594   TopoDS_Edge E = Ed;
1595   BRepAdaptor_Surface aBAS1(F1,Standard_False);
1596   BRepAdaptor_Surface aBAS2(F2,Standard_False);
1597   Handle(BRepAdaptor_HSurface) HS1 = new BRepAdaptor_HSurface(aBAS1);
1598   Handle(BRepAdaptor_HSurface) HS2;
1599   if(couture) HS2 = HS1;
1600   else HS2 = new BRepAdaptor_HSurface(aBAS2);
1601
1602   E.Orientation(TopAbs_FORWARD);
1603   Handle(BRepAdaptor_HCurve2d) HC2d1 = new BRepAdaptor_HCurve2d();
1604   HC2d1->ChangeCurve2d().Initialize(E,F1);
1605   if(couture) E.Orientation(TopAbs_REVERSED);
1606   Handle(BRepAdaptor_HCurve2d) HC2d2 = new BRepAdaptor_HCurve2d();
1607   HC2d2->ChangeCurve2d().Initialize(E,F2);
1608   Adaptor3d_CurveOnSurface C1(HC2d1,HS1);
1609   Adaptor3d_CurveOnSurface C2(HC2d2,HS2);
1610
1611   Standard_Boolean rev1 = (F1.Orientation() == TopAbs_REVERSED);
1612   Standard_Boolean rev2 = (F2.Orientation() == TopAbs_REVERSED);
1613   Standard_Real f,l,eps, angmax = -M_PI;
1614   Standard_Real ang =0.;
1615   BRep_Tool::Range(E,f,l);
1616   Extrema_LocateExtPC ext;
1617   Standard_Boolean IsInitialized = Standard_False;
1618
1619   eps = (l - f)/100.;
1620   f += eps; // to avoid calculations on  
1621   l -= eps; // points of pointed squares.
1622   gp_Pnt2d p;
1623   gp_Pnt pp1,pp2;//,PP;
1624   gp_Vec du,dv;
1625   gp_Vec d1,d2;
1626   Standard_Real uu, vv, norm;
1627
1628   Standard_Integer i;
1629   Standard_Boolean Nok;
1630   for(i = 0; (i<= 20) && (angmax<=ta) ; i++){
1631     // First suppose that this is sameParameter
1632     Nok = Standard_True;
1633     u = f + (l-f)*i/20;
1634     HC2d1->D0(u,p);
1635     HS1->D1(p.X(),p.Y(),pp1,du,dv);
1636     d1 = (du.Crossed(dv));
1637     norm = d1.Magnitude(); 
1638     if (norm > 1.e-12) d1 /= norm;
1639     else Nok=Standard_False;
1640     if(rev1) d1.Reverse();
1641
1642     HC2d2->D0(u,p);
1643     HS2->D1(p.X(), p.Y(), pp2, du, dv);
1644     d2 = (du.Crossed(dv));
1645     norm = d2.Magnitude();
1646     if (norm> 1.e-12) d2 /= norm;
1647     else Nok=Standard_False;
1648     if(rev2) d2.Reverse();
1649     if (Nok) ang = d1.Angle(d2);
1650
1651     if (Nok &&(ang > ta)) { // Refine by projection
1652       if (! IsInitialized ) {
1653         ext.Initialize(C2,f,l,Precision::PConfusion());
1654         IsInitialized = Standard_True;
1655       }      
1656       ext.Perform(pp1,u);
1657       if(ext.IsDone() && ext.IsMin()){
1658         Extrema_POnCurv poc = ext.Point();
1659         Standard_Real v = poc.Parameter();
1660
1661         HC2d2->D0(v,p);
1662         p.Coord(uu,vv);
1663         HS2->D1(p.X(), p.Y(), pp2, du, dv);
1664         d2 = (du.Crossed(dv));
1665         norm = d2.Magnitude();
1666         if (norm> 1.e-12) d2 /= norm;
1667         else Nok = Standard_False;
1668         if(rev2) d2.Reverse();
1669         if (Nok) ang = d1.Angle(d2);
1670       }
1671     }
1672     if(ang >= angmax) angmax = ang;
1673   }     
1674
1675   return (angmax<=ta);
1676
1677 }
1678
1679
1680 //=======================================================================
1681 // function : EncodeRegularity
1682 // purpose  : code the regularities on all edges of the shape, boundary of 
1683 //            two faces that do not have it.
1684 //=======================================================================
1685
1686 void BRepLib::EncodeRegularity(const TopoDS_Shape& S,
1687   const Standard_Real TolAng)
1688 {
1689   BRep_Builder B;
1690   TopTools_IndexedDataMapOfShapeListOfShape M;
1691   TopExp::MapShapesAndAncestors(S,TopAbs_EDGE,TopAbs_FACE,M);
1692   TopTools_ListIteratorOfListOfShape It;
1693   TopExp_Explorer Ex;
1694   TopoDS_Face F1,F2;
1695   Standard_Boolean found, couture;
1696   for(Standard_Integer i = 1; i <= M.Extent(); i++){
1697     TopoDS_Edge E = TopoDS::Edge(M.FindKey(i));
1698     found = Standard_False; couture = Standard_False;
1699     F1.Nullify();
1700     for(It.Initialize(M.FindFromIndex(i));It.More() && !found;It.Next()){
1701       if(F1.IsNull()) { F1 = TopoDS::Face(It.Value()); }
1702       else {
1703         if(!F1.IsSame(TopoDS::Face(It.Value()))){
1704           found = Standard_True;
1705           F2 = TopoDS::Face(It.Value());
1706         }
1707       }
1708     }
1709     if (!found && !F1.IsNull()){//is it a sewing edge?
1710       TopAbs_Orientation orE = E.Orientation();
1711       TopoDS_Edge curE;
1712       for(Ex.Init(F1,TopAbs_EDGE);Ex.More() && !found;Ex.Next()){
1713         curE= TopoDS::Edge(Ex.Current());
1714         if(E.IsSame(curE) && orE != curE.Orientation()) {
1715           found = Standard_True;
1716           couture = Standard_True;
1717           F2 = F1;
1718         }
1719       }
1720     }
1721     if(found){
1722       if(BRep_Tool::Continuity(E,F1,F2)<=GeomAbs_C0){
1723
1724         try {
1725           if(tgtfaces(E, F1, F2, TolAng, couture)){
1726             B.Continuity(E,F1,F2,GeomAbs_G1);
1727           }
1728         }
1729         catch(Standard_Failure)
1730         {
1731         }
1732       }
1733     }
1734   }
1735 }
1736
1737 //=======================================================================
1738 // function : EncodeRegularity
1739 // purpose  : code the regularity between 2 faces on an edge 
1740 //=======================================================================
1741
1742 void BRepLib::EncodeRegularity(TopoDS_Edge& E,
1743   const TopoDS_Face& F1,
1744   const TopoDS_Face& F2,
1745   const Standard_Real TolAng)
1746 {
1747   BRep_Builder B;
1748   if(BRep_Tool::Continuity(E,F1,F2)<=GeomAbs_C0){
1749     try {
1750       if( tgtfaces(E, F1, F2, TolAng, F1.IsEqual(F2))) {
1751         B.Continuity(E,F1,F2,GeomAbs_G1);
1752       }
1753     }
1754     catch(Standard_Failure)
1755     {
1756     }
1757   }
1758 }
1759
1760 //=======================================================================
1761 // function : EnsureNormalConsistency
1762 // purpose  : Corrects the normals in Poly_Triangulation of faces.
1763 //              Returns TRUE if any correction is done.
1764 //=======================================================================
1765 Standard_Boolean BRepLib::
1766             EnsureNormalConsistency(const TopoDS_Shape& theShape,
1767                                     const Standard_Real theAngTol,
1768                                     const Standard_Boolean theForceComputeNormals)
1769 {
1770   const Standard_Real aThresDot = cos(theAngTol);
1771
1772   Standard_Boolean aRetVal = Standard_False, isNormalsFound = Standard_False;
1773
1774   // compute normals if they are absent
1775   TopExp_Explorer anExpFace(theShape,TopAbs_FACE);
1776   for (; anExpFace.More(); anExpFace.Next())
1777   {
1778     const TopoDS_Face& aFace = TopoDS::Face(anExpFace.Current());
1779     const Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace);
1780     if(aSurf.IsNull())
1781       continue;
1782     TopLoc_Location aLoc;
1783     const Handle(Poly_Triangulation)& aPT = BRep_Tool::Triangulation(aFace, aLoc);
1784     if(aPT.IsNull())
1785       continue;
1786     if (!theForceComputeNormals && aPT->HasNormals())
1787     {
1788       isNormalsFound = Standard_True;
1789       continue;
1790     }
1791
1792     GeomLProp_SLProps aSLP(aSurf, 2, Precision::Confusion());
1793     const Standard_Integer anArrDim = 3*aPT->NbNodes();
1794     Handle(TShort_HArray1OfShortReal) aNormArr = new TShort_HArray1OfShortReal(1, anArrDim);
1795     Standard_Integer anNormInd = aNormArr->Lower();
1796     for(Standard_Integer i = aPT->UVNodes().Lower(); i <= aPT->UVNodes().Upper(); i++)
1797     {
1798       const gp_Pnt2d &aP2d = aPT->UVNodes().Value(i);
1799       aSLP.SetParameters(aP2d.X(), aP2d.Y());
1800
1801       gp_XYZ aNorm(0.,0.,0.);
1802       if(!aSLP.IsNormalDefined())
1803       {
1804 #ifdef OCCT_DEBUG
1805         cout << "BRepLib::EnsureNormalConsistency(): Cannot find normal!" << endl;
1806 #endif
1807       }
1808       else
1809       {
1810         aNorm = aSLP.Normal().XYZ();
1811         if (aFace.Orientation() == TopAbs_REVERSED)
1812           aNorm.Reverse();
1813       }
1814       aNormArr->ChangeValue(anNormInd++) = static_cast<Standard_ShortReal>(aNorm.X());
1815       aNormArr->ChangeValue(anNormInd++) = static_cast<Standard_ShortReal>(aNorm.Y());
1816       aNormArr->ChangeValue(anNormInd++) = static_cast<Standard_ShortReal>(aNorm.Z());
1817     }
1818
1819     aRetVal = Standard_True;
1820     isNormalsFound = Standard_True;
1821     aPT->SetNormals(aNormArr);
1822   }
1823
1824   if(!isNormalsFound)
1825   {
1826     return aRetVal;
1827   }
1828
1829   // loop by edges
1830   TopTools_IndexedDataMapOfShapeListOfShape aMapEF;
1831   TopExp::MapShapesAndAncestors(theShape,TopAbs_EDGE,TopAbs_FACE,aMapEF);
1832   for(Standard_Integer anInd = 1; anInd <= aMapEF.Extent(); anInd++)
1833   {
1834     const TopoDS_Edge& anEdg = TopoDS::Edge(aMapEF.FindKey(anInd));
1835     const TopTools_ListOfShape& anEdgList = aMapEF.FindFromIndex(anInd);
1836     if (anEdgList.Extent() != 2)
1837       continue;
1838     TopTools_ListIteratorOfListOfShape anItF(anEdgList);
1839     const TopoDS_Face aFace1 = TopoDS::Face(anItF.Value());
1840     anItF.Next();
1841     const TopoDS_Face aFace2 = TopoDS::Face(anItF.Value());
1842     TopLoc_Location aLoc1, aLoc2;
1843     const Handle(Poly_Triangulation)& aPT1 = BRep_Tool::Triangulation(aFace1, aLoc1);
1844     const Handle(Poly_Triangulation)& aPT2 = BRep_Tool::Triangulation(aFace2, aLoc2);
1845
1846     if(aPT1.IsNull() || aPT2.IsNull())
1847       continue;
1848
1849     if(!aPT1->HasNormals() || !aPT2->HasNormals())
1850       continue;
1851
1852     const Handle(Poly_PolygonOnTriangulation)& aPTEF1 = 
1853                                 BRep_Tool::PolygonOnTriangulation(anEdg, aPT1, aLoc1);
1854     const Handle(Poly_PolygonOnTriangulation)& aPTEF2 = 
1855                                 BRep_Tool::PolygonOnTriangulation(anEdg, aPT2, aLoc2);
1856
1857     TShort_Array1OfShortReal& aNormArr1 = aPT1->ChangeNormals();
1858     TShort_Array1OfShortReal& aNormArr2 = aPT2->ChangeNormals();
1859
1860     for(Standard_Integer anEdgNode = aPTEF1->Nodes().Lower();
1861                          anEdgNode <= aPTEF1->Nodes().Upper(); anEdgNode++)
1862     {
1863       //Number of node
1864       const Standard_Integer aFNodF1 = aPTEF1->Nodes().Value(anEdgNode);
1865       const Standard_Integer aFNodF2 = aPTEF2->Nodes().Value(anEdgNode);
1866
1867       const Standard_Integer aFNorm1FirstIndex = aNormArr1.Lower() + 3*
1868                                                     (aFNodF1 - aPT1->Nodes().Lower());
1869       const Standard_Integer aFNorm2FirstIndex = aNormArr2.Lower() + 3*
1870                                                     (aFNodF2 - aPT2->Nodes().Lower());
1871
1872       gp_XYZ aNorm1(aNormArr1.Value(aFNorm1FirstIndex),
1873                     aNormArr1.Value(aFNorm1FirstIndex+1),
1874                     aNormArr1.Value(aFNorm1FirstIndex+2));
1875       gp_XYZ aNorm2(aNormArr2.Value(aFNorm2FirstIndex),
1876                     aNormArr2.Value(aFNorm2FirstIndex+1),
1877                     aNormArr2.Value(aFNorm2FirstIndex+2));
1878       const Standard_Real aDot = aNorm1 * aNorm2;
1879
1880       if(aDot > aThresDot)
1881       {
1882         gp_XYZ aNewNorm = (aNorm1 + aNorm2).Normalized();
1883         aNormArr1.ChangeValue(aFNorm1FirstIndex) =
1884           aNormArr2.ChangeValue(aFNorm2FirstIndex) =
1885           static_cast<Standard_ShortReal>(aNewNorm.X());
1886         aNormArr1.ChangeValue(aFNorm1FirstIndex+1) =
1887           aNormArr2.ChangeValue(aFNorm2FirstIndex+1) =
1888           static_cast<Standard_ShortReal>(aNewNorm.Y());
1889         aNormArr1.ChangeValue(aFNorm1FirstIndex+2) =
1890           aNormArr2.ChangeValue(aFNorm2FirstIndex+2) =
1891           static_cast<Standard_ShortReal>(aNewNorm.Z());
1892         aRetVal = Standard_True;
1893       }
1894     }
1895   }
1896
1897   return aRetVal;
1898 }
1899
1900 //=======================================================================
1901 //function : SortFaces
1902 //purpose  : 
1903 //=======================================================================
1904
1905 void  BRepLib::SortFaces (const TopoDS_Shape& Sh,
1906   TopTools_ListOfShape& LF)
1907 {
1908   LF.Clear();
1909   TopTools_ListOfShape LTri,LPlan,LCyl,LCon,LSphere,LTor,LOther;
1910   TopExp_Explorer exp(Sh,TopAbs_FACE);
1911   TopLoc_Location l;
1912   Handle(Geom_Surface) S;
1913
1914   for (; exp.More(); exp.Next()) {
1915     const TopoDS_Face&   F = TopoDS::Face(exp.Current());
1916     S = BRep_Tool::Surface(F, l);
1917     if (!S.IsNull()) {
1918       if (S->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
1919         S = Handle(Geom_RectangularTrimmedSurface)::DownCast (S)->BasisSurface();
1920       }
1921       GeomAdaptor_Surface AS(S);
1922       switch (AS.GetType()) {
1923       case GeomAbs_Plane: 
1924         {
1925           LPlan.Append(F);
1926           break;
1927         }
1928       case GeomAbs_Cylinder: 
1929         {
1930           LCyl.Append(F);
1931           break;
1932         }
1933       case GeomAbs_Cone: 
1934         {
1935           LCon.Append(F);
1936           break;
1937         }
1938       case GeomAbs_Sphere: 
1939         {
1940           LSphere.Append(F);
1941           break;
1942         }
1943       case GeomAbs_Torus: 
1944         {
1945           LTor.Append(F);
1946           break;
1947         }
1948       default:
1949         LOther.Append(F);
1950       }
1951     }
1952     else LTri.Append(F);
1953   }
1954   LF.Append(LPlan); LF.Append(LCyl  ); LF.Append(LCon); LF.Append(LSphere);
1955   LF.Append(LTor ); LF.Append(LOther); LF.Append(LTri); 
1956 }
1957
1958 //=======================================================================
1959 //function : ReverseSortFaces
1960 //purpose  : 
1961 //=======================================================================
1962
1963 void  BRepLib::ReverseSortFaces (const TopoDS_Shape& Sh,
1964   TopTools_ListOfShape& LF)
1965 {
1966   LF.Clear();
1967   TopTools_ListOfShape LTri,LPlan,LCyl,LCon,LSphere,LTor,LOther;
1968   TopExp_Explorer exp(Sh,TopAbs_FACE);
1969   TopLoc_Location l;
1970   Handle(Geom_Surface) S;
1971
1972   for (; exp.More(); exp.Next()) {
1973     const TopoDS_Face&   F = TopoDS::Face(exp.Current());
1974     S = BRep_Tool::Surface(F, l);
1975     if (!S.IsNull()) {
1976       if (S->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
1977         S = Handle(Geom_RectangularTrimmedSurface)::DownCast (S)->BasisSurface();
1978       }
1979       GeomAdaptor_Surface AS(S);
1980       switch (AS.GetType()) {
1981       case GeomAbs_Plane: 
1982         {
1983           LPlan.Append(F);
1984           break;
1985         }
1986       case GeomAbs_Cylinder: 
1987         {
1988           LCyl.Append(F);
1989           break;
1990         }
1991       case GeomAbs_Cone: 
1992         {
1993           LCon.Append(F);
1994           break;
1995         }
1996       case GeomAbs_Sphere: 
1997         {
1998           LSphere.Append(F);
1999           break;
2000         }
2001       case GeomAbs_Torus: 
2002         {
2003           LTor.Append(F);
2004           break;
2005         }
2006       default:
2007         LOther.Append(F);
2008       }
2009     }
2010     else LTri.Append(F);
2011   }
2012   LF.Append(LTri); LF.Append(LOther); LF.Append(LTor ); LF.Append(LSphere);
2013   LF.Append(LCon); LF.Append(LCyl  ); LF.Append(LPlan);
2014
2015 }
2016