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