0031642: Visualization - crash in Graphic3d_Structure::SetVisual() on redisplaying...
[occt.git] / src / BRepBndLib / BRepBndLib.cxx
1 // Copyright (c) 1995-1999 Matra Datavision
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15
16 #include <Bnd_Box.hxx>
17 #include <BndLib_Add3dCurve.hxx>
18 #include <BndLib_AddSurface.hxx>
19 #include <BRep_Polygon3D.hxx>
20 #include <BRep_Tool.hxx>
21 #include <BRepAdaptor_Curve.hxx>
22 #include <BRepAdaptor_Surface.hxx>
23 #include <BRepBndLib.hxx>
24 #include <Geom_Curve.hxx>
25 #include <Geom_Surface.hxx>
26 #include <GeomAdaptor_Curve.hxx>
27 #include <Poly_Polygon3D.hxx>
28 #include <Poly_PolygonOnTriangulation.hxx>
29 #include <Poly_Triangulation.hxx>
30 #include <TColgp_Array1OfPnt.hxx>
31 #include <TColStd_Array1OfInteger.hxx>
32 #include <TColStd_HArray1OfInteger.hxx>
33 #include <TopExp_Explorer.hxx>
34 #include <TopLoc_Location.hxx>
35 #include <TopoDS.hxx>
36 #include <TopoDS_Shape.hxx>
37 #include <Adaptor3d_HCurve.hxx>
38 #include <Adaptor3d_HSurface.hxx>
39 #include <BRepTools.hxx>
40 #include <Geom_BSplineSurface.hxx>
41 #include <Geom_BezierSurface.hxx>
42 #include <Bnd_Box2d.hxx>
43 #include <BndLib_Add2dCurve.hxx>
44 #include <BRepTopAdaptor_FClass2d.hxx>
45 #include <ElSLib.hxx>
46 #include <ElCLib.hxx>
47 #include <Geom_Plane.hxx>
48 #include <Extrema_ExtSS.hxx>
49 #include <GeomAdaptor_Surface.hxx>
50 //
51 static Standard_Boolean CanUseEdges(const Adaptor3d_Surface& BS);
52 //
53 static void FindExactUVBounds(const TopoDS_Face F, 
54                               Standard_Real& umin, Standard_Real& umax, 
55                               Standard_Real& vmin, Standard_Real& vmax,
56                               const Standard_Real Tol, 
57                               Standard_Boolean& isNaturalRestriction);
58 //
59 static void AdjustFaceBox(const BRepAdaptor_Surface& BS, 
60                           const Standard_Real umin, const Standard_Real umax, 
61                           const Standard_Real vmin, const Standard_Real vmax,
62                           Bnd_Box& FaceBox,
63                           const Bnd_Box& EdgeBox, const Standard_Real Tol);
64 //
65 static Standard_Boolean IsModifySize(const BRepAdaptor_Surface& theBS, 
66                                      const gp_Pln& thePln, const gp_Pnt& theP,
67                                      const Standard_Real umin, const Standard_Real umax,
68                                      const Standard_Real vmin, const Standard_Real vmax,
69                                      const BRepTopAdaptor_FClass2d& theFClass,
70                                      const Standard_Real theTolU, const Standard_Real theTolV);
71
72 //
73 //=======================================================================
74 //function : Add
75 //purpose  : Add a shape bounding to a box
76 //=======================================================================
77 void BRepBndLib::Add(const TopoDS_Shape& S, Bnd_Box& B, Standard_Boolean useTriangulation)
78 {
79   TopExp_Explorer ex;
80
81   // Add the faces
82   BRepAdaptor_Surface BS;
83   TopLoc_Location l, aDummyLoc;
84   Standard_Integer i, nbNodes;
85   BRepAdaptor_Curve BC;
86
87   for (ex.Init(S,TopAbs_FACE); ex.More(); ex.Next()) {
88     const TopoDS_Face& F = TopoDS::Face(ex.Current());
89     const Handle(Poly_Triangulation)& T = BRep_Tool::Triangulation(F, l);
90     const Handle(Geom_Surface)& GS = BRep_Tool::Surface (F, aDummyLoc);
91     if ((useTriangulation || GS.IsNull()) && !T.IsNull())
92     {
93       nbNodes = T->NbNodes();
94       const TColgp_Array1OfPnt& Nodes = T->Nodes();
95       for (i = 1; i <= nbNodes; i++) {
96         if (l.IsIdentity()) B.Add(Nodes(i));
97         else B.Add(Nodes(i).Transformed(l));
98       }
99       //       B.Enlarge(T->Deflection());
100       B.Enlarge(T->Deflection() + BRep_Tool::Tolerance(F));
101     } else
102     {
103       if (!GS.IsNull()) {
104         BS.Initialize(F, Standard_False);
105         if (BS.GetType() != GeomAbs_Plane) {
106           BS.Initialize(F);
107           BndLib_AddSurface::Add(BS, BRep_Tool::Tolerance(F), B);
108         }
109         else {
110           // on travaille directement sur les courbes 3d.
111           TopExp_Explorer ex2(F, TopAbs_EDGE);
112           if (!ex2.More()) {
113             BS.Initialize(F);
114             BndLib_AddSurface::Add(BS, BRep_Tool::Tolerance(F), B);
115           }
116           else {
117             for (;ex2.More();ex2.Next()) {
118               const TopoDS_Edge& anEdge = TopoDS::Edge(ex2.Current());
119               if (BRep_Tool::IsGeometric (anEdge))
120               {
121                 BC.Initialize (anEdge);
122                 BndLib_Add3dCurve::Add (BC, BRep_Tool::Tolerance (anEdge), B);
123               }
124             }
125             B.Enlarge(BRep_Tool::Tolerance(F));
126           }
127         }
128       }
129     }
130   }
131
132   // Add the edges not in faces
133   Handle(TColStd_HArray1OfInteger) HIndices;
134   Handle(Poly_PolygonOnTriangulation) Poly;
135   Handle(Poly_Triangulation) T;
136   for (ex.Init(S,TopAbs_EDGE,TopAbs_FACE); ex.More(); ex.Next())
137   {
138     const TopoDS_Edge& E = TopoDS::Edge(ex.Current());
139     Handle(Poly_Polygon3D) P3d = BRep_Tool::Polygon3D(E, l);
140     if (!P3d.IsNull())
141     {
142       const TColgp_Array1OfPnt& Nodes = P3d->Nodes();
143       nbNodes = P3d->NbNodes();
144       for (i = 1; i <= nbNodes; i++)
145       {
146         if (l.IsIdentity()) B.Add(Nodes(i));
147         else B.Add(Nodes(i).Transformed(l));
148       }
149       //       B.Enlarge(P3d->Deflection());
150       B.Enlarge(P3d->Deflection() + BRep_Tool::Tolerance(E));
151     }
152     else
153     {
154       BRep_Tool::PolygonOnTriangulation(E, Poly, T, l);
155       if (useTriangulation && !Poly.IsNull())
156       {
157         const TColStd_Array1OfInteger& Indices = Poly->Nodes();
158         const TColgp_Array1OfPnt& Nodes = T->Nodes();
159         nbNodes = Indices.Length();
160         for (i = 1; i <= nbNodes; i++)
161         {
162           if (l.IsIdentity()) B.Add(Nodes(Indices(i)));
163           else B.Add(Nodes(Indices(i)).Transformed(l));
164         }
165         //      B.Enlarge(T->Deflection());
166         B.Enlarge(Poly->Deflection() + BRep_Tool::Tolerance(E));
167       }
168       else {
169         if (BRep_Tool::IsGeometric(E))
170         {
171           BC.Initialize(E);
172           BndLib_Add3dCurve::Add(BC, BRep_Tool::Tolerance(E), B);
173         }
174       }
175     }
176   }
177
178   // Add the vertices not in edges
179
180   for (ex.Init(S,TopAbs_VERTEX,TopAbs_EDGE); ex.More(); ex.Next()) {
181     B.Add(BRep_Tool::Pnt(TopoDS::Vertex(ex.Current())));
182     B.Enlarge(BRep_Tool::Tolerance(TopoDS::Vertex(ex.Current())));
183   }
184 }
185
186
187
188 //=======================================================================
189 //function : AddClose
190 //purpose  : Add a precise shape bounding to a box
191 //=======================================================================
192
193 void BRepBndLib::AddClose(const TopoDS_Shape& S, Bnd_Box& B)
194 {
195   TopExp_Explorer ex;
196
197   // No faces
198
199   // Add the edges
200
201   BRepAdaptor_Curve BC;
202
203   for (ex.Init(S,TopAbs_EDGE); ex.More(); ex.Next()) {
204     const TopoDS_Edge& anEdge = TopoDS::Edge (ex.Current());
205     if (BRep_Tool::IsGeometric (anEdge))
206     {
207       BC.Initialize (anEdge);
208       BndLib_Add3dCurve::Add(BC,0.,B);
209     }
210   }
211
212   // Add the vertices not in edges
213
214   for (ex.Init(S,TopAbs_VERTEX,TopAbs_EDGE); ex.More(); ex.Next()) {
215     B.Add(BRep_Tool::Pnt(TopoDS::Vertex(ex.Current())));
216   }
217 }
218
219 //=======================================================================
220 //function : AddOptimal
221 //purpose  : Add a shape bounding to a box
222 //=======================================================================
223 void BRepBndLib::AddOptimal(const TopoDS_Shape& S, Bnd_Box& B, 
224                             const Standard_Boolean useTriangulation, 
225                             const Standard_Boolean useShapeTolerance)
226 {
227   TopExp_Explorer ex;
228
229   // Add the faces
230   BRepAdaptor_Surface BS;
231   Handle(Poly_Triangulation) T;
232   TopLoc_Location l;
233   Standard_Integer i, nbNodes;
234   BRepAdaptor_Curve BC;
235
236   for (ex.Init(S,TopAbs_FACE); ex.More(); ex.Next()) {
237     const TopoDS_Face& F = TopoDS::Face(ex.Current());
238     T = BRep_Tool::Triangulation(F, l);
239     Bnd_Box aLocBox;
240     if (useTriangulation && !T.IsNull())
241     {
242       nbNodes = T->NbNodes();
243       const TColgp_Array1OfPnt& Nodes = T->Nodes();
244       for (i = 1; i <= nbNodes; i++) {
245         if (l.IsIdentity()) aLocBox.Add(Nodes(i));
246         else aLocBox.Add(Nodes(i).Transformed(l));
247       }
248       //       B.Enlarge(T->Deflection());
249       aLocBox.Enlarge(T->Deflection() + BRep_Tool::Tolerance(F));
250       Standard_Real xmin, ymin, zmin, xmax, ymax, zmax;
251       aLocBox.Get(xmin, ymin, zmin, xmax, ymax, zmax);
252       B.Update(xmin, ymin, zmin, xmax, ymax, zmax);
253     } 
254     else
255     {
256       const Handle(Geom_Surface)& GS = BRep_Tool::Surface(F, l);
257       if (!GS.IsNull()) {
258         BS.Initialize(F, Standard_False);
259         if (CanUseEdges(BS)) {
260           TopExp_Explorer ex2(F, TopAbs_EDGE);
261           if (!ex2.More()) {
262             BS.Initialize(F);
263             Standard_Real Tol = useShapeTolerance?  BRep_Tool::Tolerance(F) : 0.;
264             BndLib_AddSurface::AddOptimal(BS, Tol, aLocBox);
265           }
266           else
267           {
268             Standard_Real Tol;
269             for (;ex2.More();ex2.Next()) {
270               Bnd_Box anEBox;
271               const TopoDS_Edge& anE = TopoDS::Edge(ex2.Current());
272               if (BRep_Tool::Degenerated (anE) || !BRep_Tool::IsGeometric (anE))
273               {
274                 continue;
275               }
276               BC.Initialize(anE);
277               Tol = useShapeTolerance?  BRep_Tool::Tolerance(anE) : 0.;
278               BndLib_Add3dCurve::AddOptimal(BC, Tol, anEBox);
279               aLocBox.Add(anEBox);
280             }
281           }
282         }
283         else
284         {
285           Standard_Real umin, umax, vmin, vmax;
286           Standard_Boolean isNaturalRestriction = Standard_False;
287           Standard_Real Tol = useShapeTolerance?  BRep_Tool::Tolerance(F) : 0.;
288           FindExactUVBounds(F, umin, umax, vmin, vmax, Tol, isNaturalRestriction);
289           BndLib_AddSurface::AddOptimal(BS, umin, umax, vmin, vmax, 
290                                         Tol, aLocBox);
291           //
292           if(!isNaturalRestriction)
293           {
294             TopExp_Explorer ex2(F, TopAbs_EDGE);
295             Bnd_Box EBox;
296             for (;ex2.More();ex2.Next()) {
297               Bnd_Box anEBox;
298               const TopoDS_Edge& anE = TopoDS::Edge(ex2.Current());
299               if (BRep_Tool::Degenerated (anE) || !BRep_Tool::IsGeometric (anE))
300               {
301                 continue;
302               }
303               BC.Initialize(anE);
304               Tol = useShapeTolerance?  BRep_Tool::Tolerance(anE) : 0.;
305               BndLib_Add3dCurve::AddOptimal(BC, Tol, anEBox);
306               EBox.Add(anEBox);
307             }
308             Tol = useShapeTolerance?  BRep_Tool::Tolerance(F) : 0.;
309             AdjustFaceBox(BS, umin, umax, vmin, vmax, aLocBox, EBox, 
310                           Tol);
311           }
312         }
313         Standard_Real xmin, ymin, zmin, xmax, ymax, zmax;
314         aLocBox.Get(xmin, ymin, zmin, xmax, ymax, zmax);
315         B.Update(xmin, ymin, zmin, xmax, ymax, zmax);
316       }
317     }
318   }
319
320   // Add the edges not in faces
321   Handle(TColStd_HArray1OfInteger) HIndices;
322   Handle(Poly_PolygonOnTriangulation) Poly;
323
324   for (ex.Init(S,TopAbs_EDGE,TopAbs_FACE); ex.More(); ex.Next())
325   {
326     const TopoDS_Edge& E = TopoDS::Edge(ex.Current());
327     Bnd_Box aLocBox;
328     Handle(Poly_Polygon3D) P3d = BRep_Tool::Polygon3D(E, l);
329     if (useTriangulation && (!P3d.IsNull()))
330     {
331       const TColgp_Array1OfPnt& Nodes = P3d->Nodes();
332       nbNodes = P3d->NbNodes();
333       for (i = 1; i <= nbNodes; i++)
334       {
335         if (l.IsIdentity()) aLocBox.Add(Nodes(i));
336         else aLocBox.Add(Nodes(i).Transformed(l));
337       }
338       Standard_Real Tol = useShapeTolerance?  BRep_Tool::Tolerance(E) : 0.;
339       aLocBox.Enlarge(P3d->Deflection() + Tol);
340     }
341     else
342     {
343       BRep_Tool::PolygonOnTriangulation(E, Poly, T, l);
344       if (useTriangulation && !Poly.IsNull())
345       {
346         const TColStd_Array1OfInteger& Indices = Poly->Nodes();
347         const TColgp_Array1OfPnt& Nodes = T->Nodes();
348         nbNodes = Indices.Length();
349         for (i = 1; i <= nbNodes; i++)
350         {
351           if (l.IsIdentity()) aLocBox.Add(Nodes(Indices(i)));
352           else aLocBox.Add(Nodes(Indices(i)).Transformed(l));
353         }
354         Standard_Real Tol = useShapeTolerance?  BRep_Tool::Tolerance(E) : 0.;
355         aLocBox.Enlarge(Poly->Deflection() + Tol);
356       }
357       else {
358         if (BRep_Tool::IsGeometric(E))
359         {
360           BC.Initialize(E);
361           Standard_Real Tol = useShapeTolerance?  BRep_Tool::Tolerance(E) : 0.;
362           BndLib_Add3dCurve::AddOptimal(BC, Tol, aLocBox);
363         }
364       }
365     }
366     if (!aLocBox.IsVoid())
367     {
368       Standard_Real xmin, ymin, zmin, xmax, ymax, zmax;
369       aLocBox.Get(xmin, ymin, zmin, xmax, ymax, zmax);
370       B.Update(xmin, ymin, zmin, xmax, ymax, zmax);
371     }
372   }
373
374   // Add the vertices not in edges
375
376   for (ex.Init(S,TopAbs_VERTEX,TopAbs_EDGE); ex.More(); ex.Next()) {
377     Bnd_Box aLocBox;
378     const TopoDS_Vertex& aV = TopoDS::Vertex(ex.Current());
379     aLocBox.Add(BRep_Tool::Pnt(aV));
380     Standard_Real Tol = useShapeTolerance?  BRep_Tool::Tolerance(aV) : 0.;
381     aLocBox.Enlarge(Tol);
382     Standard_Real xmin, ymin, zmin, xmax, ymax, zmax;
383     aLocBox.Get(xmin, ymin, zmin, xmax, ymax, zmax);
384     B.Update(xmin, ymin, zmin, xmax, ymax, zmax);
385   }
386 }
387
388 //=======================================================================
389 //function : CanUseEdges
390 //purpose  : Define is it possible using only edges bnd boxes 
391 //           to get face bnd box
392 //=======================================================================
393 Standard_Boolean CanUseEdges(const Adaptor3d_Surface& BS)
394 {
395   GeomAbs_SurfaceType aST = BS.GetType();
396   if(aST == GeomAbs_Plane ||
397      aST == GeomAbs_Cylinder ||
398      aST == GeomAbs_Cone ||
399      aST == GeomAbs_SurfaceOfExtrusion)
400   {
401     return Standard_True;
402   }
403   else if(aST == GeomAbs_SurfaceOfRevolution)
404   {
405     const Handle(Adaptor3d_HCurve)& aBC = BS.BasisCurve();
406     if(aBC->GetType() == GeomAbs_Line)
407     {
408       return Standard_True;
409     }
410     else
411     {
412       return Standard_False;
413     }
414   }
415   else if(aST == GeomAbs_OffsetSurface)
416   {
417     const Handle(Adaptor3d_HSurface)& aS = BS.BasisSurface();
418     return CanUseEdges(aS->Surface());
419   }
420   else if(aST == GeomAbs_BSplineSurface)
421   {
422     Handle(Geom_BSplineSurface) aBSpl = BS.BSpline();
423     if((aBSpl->UDegree() == 1 && aBSpl->NbUKnots() == 2) ||
424        (aBSpl->VDegree() == 1 && aBSpl->NbVKnots() == 2))
425     {
426       return Standard_True;
427     }
428     else
429     {
430       return Standard_False;
431     }
432   }
433   else if(aST == GeomAbs_BezierSurface)
434   {
435     Handle(Geom_BezierSurface) aBz = BS.Bezier();
436     if((aBz->UDegree() == 1 ) ||
437        (aBz->VDegree() == 1 ))
438     {
439       return Standard_True;
440     }
441     else
442     {
443       return Standard_False;
444     }
445   }
446   return Standard_False;
447 }
448
449 //=======================================================================
450 //function : FindExactUVBounds
451 //purpose  : 
452 //=======================================================================
453 void FindExactUVBounds(const TopoDS_Face FF, 
454                        Standard_Real& umin, Standard_Real& umax, 
455                        Standard_Real& vmin, Standard_Real& vmax,
456                        const Standard_Real Tol, 
457                        Standard_Boolean& isNaturalRestriction)
458 {
459   TopoDS_Face F = FF;
460   F.Orientation(TopAbs_FORWARD);
461   TopExp_Explorer ex(F,TopAbs_EDGE);
462   //
463   //Check Natural restriction
464   isNaturalRestriction = BRep_Tool::NaturalRestriction(F); //Can we trust this flag?
465   BRepAdaptor_Surface aBAS(F, Standard_False);
466   if(!isNaturalRestriction)
467   {
468     //Check by comparing pcurves and surface boundaries
469     umin = aBAS.FirstUParameter();
470     umax = aBAS.LastUParameter();
471     vmin = aBAS.FirstVParameter();
472     vmax = aBAS.LastVParameter();
473     Standard_Boolean isUperiodic = aBAS.IsUPeriodic(), isVperiodic = aBAS.IsVPeriodic();
474     Standard_Real aT1, aT2;
475     Standard_Real TolU = Max(aBAS.UResolution(Tol), Precision::PConfusion());
476     Standard_Real TolV = Max(aBAS.VResolution(Tol), Precision::PConfusion());
477     Standard_Integer Nu = 0, Nv = 0, NbEdges = 0;
478     gp_Vec2d Du(1, 0), Dv(0, 1);
479     gp_Pnt2d aP;
480     gp_Vec2d aV;
481     for (;ex.More();ex.Next()) {
482       NbEdges++;
483       if(NbEdges > 4)
484       {
485         break;
486       }
487       const TopoDS_Edge& aE = TopoDS::Edge(ex.Current());
488       const Handle(Geom2d_Curve) aC2D = BRep_Tool::CurveOnSurface(aE, F, aT1, aT2);
489       if (aC2D.IsNull()) 
490       {
491         break;
492       }
493       //
494       aC2D->D1((aT1 + aT2)/2., aP, aV);
495       Standard_Real magn = aV.SquareMagnitude();
496       if(magn < gp::Resolution())
497       {
498         break;
499       }
500       else
501       {
502         aV /= Sqrt(magn);
503       }
504       Standard_Real u = aP.X(), v = aP.Y();
505       if(isUperiodic)
506       {
507         ElCLib::InPeriod(u, umin, umax);
508       }
509       if(isVperiodic)
510       {
511         ElCLib::InPeriod(v, vmin, vmax);
512       }
513       //
514       if(Abs(u - umin) <= TolU || Abs(u - umax) <= TolU)
515       {
516         Standard_Real d = Dv * aV;
517         if(1. - Abs(d) <= Precision::PConfusion())
518         {
519           Nu++;
520           if(Nu > 2)
521           {
522             break;
523           }
524         }
525         else
526         {
527           break;
528         }
529       }
530       else if(Abs(v - vmin) <= TolV || Abs(v - vmax) <= TolV)
531       {
532         Standard_Real d = Du * aV;
533         if(1. - Abs(d) <= Precision::PConfusion())
534         {
535           Nv++;
536           if(Nv > 2)
537           {
538             break;
539           }
540         }
541         else
542         {
543           break;
544         }
545       }
546       else
547       {
548         break;
549       }
550     }
551     if(Nu == 2 && Nv == 2)
552     {
553       isNaturalRestriction = Standard_True;
554     }
555   }
556   //
557   if(isNaturalRestriction)
558   {
559     umin = aBAS.FirstUParameter();
560     umax = aBAS.LastUParameter();
561     vmin = aBAS.FirstVParameter();
562     vmax = aBAS.LastVParameter();
563     return;
564   }
565
566   // fill box for the given face
567   Standard_Real aT1, aT2;
568   Standard_Real TolU = Max(aBAS.UResolution(Tol), Precision::PConfusion());
569   Standard_Real TolV = Max(aBAS.VResolution(Tol), Precision::PConfusion());
570   Standard_Real TolUV = Max(TolU, TolV);
571   Bnd_Box2d aBox;
572   ex.Init(F,TopAbs_EDGE);
573   for (;ex.More();ex.Next()) {
574     const TopoDS_Edge& aE = TopoDS::Edge(ex.Current());
575     const Handle(Geom2d_Curve) aC2D = BRep_Tool::CurveOnSurface(aE, F, aT1, aT2);
576     if (aC2D.IsNull()) 
577     {
578       continue;
579     }
580     //
581     BndLib_Add2dCurve::AddOptimal(aC2D, aT1, aT2, TolUV, aBox);
582     //
583   }
584   //
585   aBox.Get(umin, vmin, umax, vmax);
586   //
587   TopLoc_Location aLoc;
588   Handle(Geom_Surface) aS = BRep_Tool::Surface(FF, aLoc);
589   Standard_Real aUmin, aUmax, aVmin, aVmax;
590   aS->Bounds(aUmin, aUmax, aVmin, aVmax);
591   if(!aS->IsUPeriodic())
592   {
593     umin = Max(aUmin, umin);
594     umax = Min(aUmax, umax);
595   }
596   else
597   {
598     if(umax - umin > aS->UPeriod())
599     {
600       Standard_Real delta = umax - umin - aS->UPeriod();
601       umin += delta/2.;
602       umax -= delta/2;
603     }
604   }
605   //
606   if(!aS->IsVPeriodic())
607   {
608     vmin = Max(aVmin, vmin);
609     vmax = Min(aVmax, vmax);
610   }
611   else
612   {
613     if(vmax - vmin > aS->VPeriod())
614     {
615       Standard_Real delta = vmax - vmin - aS->VPeriod();
616       vmin += delta/2.;
617       vmax -= delta/2;
618     }
619   }
620 }
621 //=======================================================================
622 //function : Reorder
623 //purpose  : 
624 //=======================================================================
625 inline void Reorder(Standard_Real& a, Standard_Real& b)
626 {
627   if(a > b)
628   {
629     Standard_Real t = a;
630     a = b;
631     b = t;
632   }
633 }
634 //=======================================================================
635 //function : IsModifySize
636 //purpose  : 
637 //=======================================================================
638 Standard_Boolean IsModifySize(const BRepAdaptor_Surface& theBS, 
639                               const gp_Pln& thePln, const gp_Pnt& theP,
640                               const Standard_Real umin, const Standard_Real umax,
641                               const Standard_Real vmin, const Standard_Real vmax,
642                               const BRepTopAdaptor_FClass2d& theFClass,
643                               const Standard_Real theTolU, const Standard_Real theTolV)
644 {
645   Standard_Real pu1 = 0, pu2, pv1 = 0, pv2;
646   ElSLib::PlaneParameters(thePln.Position(), theP, pu2, pv2);
647   Reorder(pu1, pu2);
648   Reorder(pv1, pv2);
649   Handle(Geom_Plane) aPlane = new Geom_Plane(thePln);
650   GeomAdaptor_Surface aGAPln(aPlane, pu1, pu2, pv1, pv2);
651   Extrema_ExtSS anExtr(aGAPln, theBS, pu1, pu2, pv1, pv2, umin, umax, vmin, vmax, theTolU, theTolV);
652   if(anExtr.IsDone())
653   {
654     if(anExtr.NbExt() > 0)
655     {
656       Standard_Integer i, imin = 0;
657       Standard_Real dmin = RealLast();
658       Standard_Real uextr = 0., vextr = 0.;
659       Extrema_POnSurf P1, P2;
660       for(i = 1; i <= anExtr.NbExt(); ++i)
661       {
662         Standard_Real d = anExtr.SquareDistance(i);
663         if(d < dmin)
664         {
665           imin = i;
666           dmin = d;
667         }
668       }
669       if(imin > 0)
670       {
671         anExtr.Points(imin, P1, P2);
672         P2.Parameter(uextr, vextr);
673       }
674       else
675       {
676         return Standard_False;
677       }
678       //
679       gp_Pnt2d aP2d(uextr, vextr);
680       TopAbs_State aSt = theFClass.Perform(aP2d);
681       if(aSt != TopAbs_IN)
682       {
683         return Standard_True;
684       }
685     }
686     else
687     {
688       return Standard_True; //extrema point seems to be out of face UV bounds
689     }
690   }
691   //
692   return Standard_False;
693 }
694 //
695 //=======================================================================
696 //function : AdjustFaceBox
697 //purpose  : 
698 //=======================================================================
699 void AdjustFaceBox(const BRepAdaptor_Surface& BS, 
700                    const Standard_Real umin, const Standard_Real umax, 
701                    const Standard_Real vmin, const Standard_Real vmax,
702                    Bnd_Box& FaceBox,
703                    const Bnd_Box& EdgeBox, const Standard_Real Tol)
704 {
705   Standard_Real fxmin, fymin, fzmin, fxmax, fymax, fzmax;
706   Standard_Real exmin, eymin, ezmin, exmax, eymax, ezmax;
707   //
708   FaceBox.Get(fxmin, fymin, fzmin, fxmax, fymax, fzmax);
709   EdgeBox.Get(exmin, eymin, ezmin, exmax, eymax, ezmax);
710   //
711   Standard_Real TolU = Max(BS.UResolution(Tol), Precision::PConfusion());
712   Standard_Real TolV = Max(BS.VResolution(Tol), Precision::PConfusion());
713   BRepTopAdaptor_FClass2d FClass(BS.Face(), Max(TolU, TolV));
714   //
715   Standard_Boolean isModified = Standard_False;
716   if(exmin > fxmin)
717   {
718     //
719     gp_Pln pl(gp_Ax3(gp_Pnt(fxmin, fymin, fzmin), gp::DX()));
720     gp_Pnt aP(fxmin, fymax, fzmax);
721     if(IsModifySize(BS, pl, aP,
722                     umin, umax, vmin, vmax, FClass, TolU, TolV))
723     {
724       fxmin = exmin;
725       isModified = Standard_True;
726     }
727   }
728   if(exmax < fxmax)
729   {
730     //
731     gp_Pln pl(gp_Ax3(gp_Pnt(fxmax, fymax, fzmax), gp::DX()));
732     gp_Pnt aP(fxmax, fymin, fzmin);
733     if(IsModifySize(BS, pl, aP,
734                     umin, umax, vmin, vmax, FClass, TolU, TolV))
735     {
736       fxmax = exmax;
737       isModified = Standard_True;
738     }
739   }
740   //
741   if(eymin > fymin)
742   {
743     //
744     gp_Pln pl(gp_Ax3(gp_Pnt(fxmin, fymin, fzmin), gp::DY()));
745     gp_Pnt aP(fxmax, fymin, fzmax);
746     if(IsModifySize(BS, pl, aP,
747                     umin, umax, vmin, vmax, FClass, TolU, TolV))
748     {
749       fymin = eymin;
750       isModified = Standard_True;
751     }
752   }
753   if(eymax < fymax)
754   {
755     //
756     gp_Pln pl(gp_Ax3(gp_Pnt(fxmax, fymax, fzmax), gp::DY()));
757     gp_Pnt aP(fxmin, fymax, fzmin);
758     if(IsModifySize(BS, pl, aP,
759                     umin, umax, vmin, vmax, FClass, TolU, TolV))
760     {
761       fymax = eymax;
762       isModified = Standard_True;
763     }
764   }
765   //
766   if(ezmin > fzmin)
767   {
768     //
769     gp_Pln pl(gp_Ax3(gp_Pnt(fxmin, fymin, fzmin), gp::DZ()));
770     gp_Pnt aP(fxmax, fymax, fzmin);
771     if(IsModifySize(BS, pl, aP,
772                     umin, umax, vmin, vmax, FClass, TolU, TolV))
773     {
774       fzmin = ezmin;
775       isModified = Standard_True;
776     }
777   }
778   if(ezmax < fzmax)
779   {
780     //
781     gp_Pln pl(gp_Ax3(gp_Pnt(fxmax, fymax, fzmax), gp::DZ()));
782     gp_Pnt aP(fxmin, fymin, fzmax);
783     if(IsModifySize(BS, pl, aP,
784                     umin, umax, vmin, vmax, FClass, TolU, TolV))
785     {
786       fzmax = ezmax;
787       isModified = Standard_True;
788     }
789   }
790   //
791   if(isModified)
792   {
793     FaceBox.SetVoid();
794     FaceBox.Update(fxmin, fymin, fzmin, fxmax, fymax, fzmax);
795   }
796 }
797