0031035: Coding - uninitialized class fields reported by Visual Studio Code Analysis
[occt.git] / src / BRepFeat / BRepFeat_MakeCylindricalHole.cxx
1 // Created on: 1995-05-30
2 // Created by: Jacques GOUSSARD
3 // Copyright (c) 1995-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
18 #include <Bnd_Box.hxx>
19 #include <BRep_Builder.hxx>
20 #include <BRep_Tool.hxx>
21 #include <BRepBndLib.hxx>
22 #include <BRepFeat_MakeCylindricalHole.hxx>
23 #include <BRepPrim_Cylinder.hxx>
24 #include <BRepTools.hxx>
25 #include <ElCLib.hxx>
26 #include <Geom_Curve.hxx>
27 #include <gp_Ax1.hxx>
28 #include <LocOpe_CurveShapeIntersector.hxx>
29 #include <LocOpe_PntFace.hxx>
30 #include <Precision.hxx>
31 #include <Standard_ConstructionError.hxx>
32 #include <StdFail_NotDone.hxx>
33 #include <TopExp_Explorer.hxx>
34 #include <TopLoc_Location.hxx>
35 #include <TopoDS.hxx>
36 #include <TopoDS_Shape.hxx>
37 #include <TopoDS_Solid.hxx>
38 #include <TopTools_ListIteratorOfListOfShape.hxx>
39 #include <TopTools_ListOfShape.hxx>
40 #include <BRepAdaptor_Surface.hxx>
41 #include <CSLib.hxx>
42
43 static void Baryc(const TopoDS_Shape&,
44                   gp_Pnt&);
45
46 static void BoxParameters(const TopoDS_Shape&,
47                           const gp_Ax1&,
48                           Standard_Real&,
49                           Standard_Real&);
50
51 static Standard_Boolean GetOffset(const LocOpe_PntFace& PntInfo, 
52                                   const Standard_Real Radius, 
53                                   const gp_Ax1& Axis, 
54                                   Standard_Real& outOff );
55
56 static void CreateCyl(const LocOpe_PntFace& PntInfoFirst, const LocOpe_PntFace& PntInfoLast, const Standard_Real Radius,
57                       const gp_Ax1& Axis, TopoDS_Shell& Cyl, TopoDS_Face& CylTopF, TopoDS_Face& CylBottF );
58
59
60 //=======================================================================
61 //function : Perform
62 //purpose  : 
63 //=======================================================================
64
65 void BRepFeat_MakeCylindricalHole::Perform(const Standard_Real Radius)
66 {
67   const TopoDS_Shape& aObject=myArguments.First();
68   if (aObject.IsNull() || !myAxDef) {
69     throw Standard_ConstructionError();
70   }
71
72   myIsBlind = Standard_False;
73   myStatus = BRepFeat_NoError;
74
75   LocOpe_CurveShapeIntersector theASI(myAxis,aObject);
76   if (!theASI.IsDone() || theASI.NbPoints() <= 0) {
77     myStatus = BRepFeat_InvalidPlacement;
78     return;
79   }
80
81   // It is not possible to use infinite cylinder for topological operations.
82   Standard_Real PMin,PMax;
83   BoxParameters(aObject,myAxis,PMin,PMax);
84   Standard_Real Heigth = 2.*(PMax-PMin);
85   gp_XYZ theOrig = myAxis.Location().XYZ();
86   theOrig += ((3.*PMin-PMax)/2.) * myAxis.Direction().XYZ();
87   gp_Pnt p1_ao1(theOrig); gp_Ax2 a1_ao1(p1_ao1,myAxis.Direction());
88   BRepPrim_Cylinder theCylinder(a1_ao1,
89                                 Radius,
90                                 Heigth);
91
92   // Probably it is better to make cut directly
93
94   BRep_Builder B;
95   TopoDS_Solid theTool;
96   B.MakeSolid(theTool);
97   B.Add(theTool,theCylinder.Shell());
98
99   myTopFace = theCylinder.TopFace();
100   myBotFace = theCylinder.BottomFace();
101   myValidate = Standard_False;
102
103 //  BRepTools::Dump(theTool,std::cout);
104   Standard_Boolean Fuse = Standard_False;
105   //
106   AddTool(theTool);
107   SetOperation(Fuse);
108   BOPAlgo_BOP::Perform();
109 }
110
111
112 //=======================================================================
113 //function : PerformThruNext
114 //purpose  : 
115 //=======================================================================
116
117 void BRepFeat_MakeCylindricalHole::PerformThruNext(const Standard_Real Radius,
118                                                    const Standard_Boolean Cont)
119 {
120   //
121   const TopoDS_Shape& aObject=myArguments.First();
122   if (aObject.IsNull() || !myAxDef) {
123     throw Standard_ConstructionError();
124   }
125
126   myIsBlind = Standard_False;
127   myValidate = Cont;
128   myStatus = BRepFeat_NoError;
129
130   LocOpe_CurveShapeIntersector theASI(myAxis,aObject);
131   if (!theASI.IsDone()) {
132     myStatus = BRepFeat_InvalidPlacement;
133     return;
134   }
135   
136   Standard_Integer IndFrom,IndTo;
137   TopAbs_Orientation theOr;
138   LocOpe_PntFace PntInfoFirst, PntInfoLast;
139   Standard_Boolean ok = theASI.LocalizeAfter(0.,theOr,IndFrom,IndTo);
140   if (ok) {
141     if (theOr == TopAbs_FORWARD) {
142       PntInfoFirst = theASI.Point(IndFrom);
143       ok = theASI.LocalizeAfter(IndTo,theOr,IndFrom,IndTo);
144       if (ok) {
145         if (theOr != TopAbs_REVERSED) {
146           ok = Standard_False;
147         }
148         else {
149           PntInfoLast = theASI.Point(IndTo);
150         }
151       }
152       
153     }
154     else { // TopAbs_REVERSED
155       PntInfoLast = theASI.Point(IndTo);
156       ok = theASI.LocalizeBefore(IndFrom,theOr,IndFrom,IndTo);
157       if (ok) {
158         if (theOr != TopAbs_FORWARD) {
159           ok = Standard_False;
160         }
161         else {
162           PntInfoFirst = theASI.Point(IndFrom);
163         }
164       }
165     }
166   }
167   if (!ok) {
168     myStatus = BRepFeat_InvalidPlacement;
169     return;
170   }
171
172   TopoDS_Shell Cyl;
173   CreateCyl(PntInfoFirst, PntInfoLast, Radius, myAxis, Cyl, myTopFace, myBotFace); 
174
175   BRep_Builder B;
176   TopoDS_Solid theTool;
177   B.MakeSolid(theTool);
178   B.Add(theTool, Cyl);
179
180   Standard_Boolean Fuse = Standard_False;
181   AddTool(theTool);
182   SetOperation(Fuse);
183   BOPAlgo_BOP::Perform();
184   TopTools_ListOfShape parts;
185   PartsOfTool(parts);
186
187   Standard_Integer nbparts = 0;
188   TopTools_ListIteratorOfListOfShape its(parts);
189   for (; its.More(); its.Next()) {
190     nbparts ++;
191   }
192   if (nbparts == 0) {
193     myStatus = BRepFeat_InvalidPlacement;
194     return;
195   }
196
197   if (nbparts >= 2) { // preserve the smallest as parameter 
198                       // along the axis
199
200     Standard_Real First=PntInfoFirst.Parameter();
201     Standard_Real Last=PntInfoLast.Parameter();
202     TopoDS_Shape tokeep;
203     Standard_Real parbar,parmin = Last;
204     gp_Pnt Barycentre;
205     for (its.Initialize(parts); its.More(); its.Next()) {
206       Baryc(its.Value(),Barycentre);
207       parbar = ElCLib::LineParameter(myAxis,Barycentre);
208       if (parbar >= First && parbar <= Last && parbar <= parmin) {
209         parmin = parbar;
210         tokeep = its.Value();
211       }
212     }
213
214     if (tokeep.IsNull()) { // preserve the closest interval
215
216       Standard_Real dmin = RealLast();
217       for (its.Initialize(parts); its.More(); its.Next()) {
218         Baryc(its.Value(),Barycentre);
219         parbar = ElCLib::LineParameter(myAxis,Barycentre);
220         if (parbar < First) {
221           if (First - parbar < dmin ) {
222             dmin = First-parbar;
223             tokeep = its.Value();
224           }
225           else { // parbar > Last
226             if (parbar - Last < dmin) {
227               dmin = parbar-Last;
228               tokeep = its.Value();
229             }
230           }
231         }
232       }
233     }
234     for (its.Initialize(parts); its.More(); its.Next()) {
235       if (tokeep.IsSame(its.Value())) {
236         KeepPart(its.Value());
237         break;
238       }
239     }
240   }
241 }
242
243 //=======================================================================
244 //function : PerformUntilEnd
245 //purpose  : 
246 //=======================================================================
247
248 void BRepFeat_MakeCylindricalHole::PerformUntilEnd(const Standard_Real Radius,
249                                                    const Standard_Boolean Cont)
250 {
251   //
252   const TopoDS_Shape& aObject=myArguments.First();
253   if (aObject.IsNull() || !myAxDef) {
254     throw Standard_ConstructionError();
255   }
256
257   myIsBlind = Standard_False;
258   myValidate = Cont;
259   myStatus = BRepFeat_NoError;
260
261   LocOpe_CurveShapeIntersector theASI(myAxis,aObject);
262   if (!theASI.IsDone()) {
263     myStatus = BRepFeat_InvalidPlacement;
264     return;
265   }
266
267   Standard_Integer IndFrom,IndTo;
268   TopAbs_Orientation theOr;
269   Standard_Boolean ok = theASI.LocalizeAfter(0.,theOr,IndFrom,IndTo);
270   LocOpe_PntFace PntInfoFirst, PntInfoLast;
271
272   if (ok) {
273     if (theOr == TopAbs_REVERSED) {
274       ok = theASI.LocalizeBefore(IndFrom,theOr,IndFrom,IndTo); // on reset
275       // It is possible to search for the next.
276     }
277     if ( ok && theOr == TopAbs_FORWARD) {
278       PntInfoFirst = theASI.Point(IndFrom);
279       ok = theASI.LocalizeBefore(theASI.NbPoints()+1,theOr,IndFrom,IndTo);
280       if (ok) {
281         if (theOr != TopAbs_REVERSED) {
282           ok = Standard_False;
283         }
284         else {
285           PntInfoLast = theASI.Point(IndTo);
286         }
287       }
288     }
289   }
290   if (!ok) {
291     myStatus = BRepFeat_InvalidPlacement;
292     return;
293   }
294
295   TopoDS_Shell Cyl;
296   CreateCyl(PntInfoFirst, PntInfoLast, Radius, myAxis, Cyl, myTopFace, myBotFace); 
297
298   BRep_Builder B;
299   TopoDS_Solid theTool;
300   B.MakeSolid(theTool);
301   B.Add(theTool, Cyl);
302
303   Standard_Boolean Fuse = Standard_False;
304   AddTool(theTool);
305   SetOperation(Fuse);
306   BOPAlgo_BOP::Perform();
307   TopTools_ListOfShape parts;
308   PartsOfTool(parts);
309
310   Standard_Integer nbparts = 0;
311   TopTools_ListIteratorOfListOfShape its(parts);
312   for (; its.More(); its.Next()) {
313     nbparts ++;
314   }
315   if (nbparts == 0) {
316     myStatus = BRepFeat_InvalidPlacement;
317     return;
318   }
319
320   if (nbparts >= 2) { // preserve everything above the First 
321     Standard_Real parbar;
322     gp_Pnt Barycentre;
323     for (its.Initialize(parts); its.More(); its.Next()) {
324       Baryc(its.Value(),Barycentre);
325       parbar = ElCLib::LineParameter(myAxis,Barycentre);
326       if (parbar > PntInfoFirst.Parameter()) {
327         KeepPart(its.Value());
328       }
329     }
330   }
331 }
332
333
334 //=======================================================================
335 //function : Perform
336 //purpose  : 
337 //=======================================================================
338
339 void BRepFeat_MakeCylindricalHole::Perform(const Standard_Real Radius,
340                                            const Standard_Real PFrom,
341                                            const Standard_Real PTo,
342                                            const Standard_Boolean Cont)
343 {
344   //
345   const TopoDS_Shape& aObject=myArguments.First();
346   if (aObject.IsNull() || !myAxDef) {
347     throw Standard_ConstructionError();
348   }
349
350   myIsBlind = Standard_False;
351   myValidate = Cont;
352   myStatus = BRepFeat_NoError;
353
354   LocOpe_CurveShapeIntersector theASI(myAxis,aObject);
355   if (!theASI.IsDone()) {
356     myStatus = BRepFeat_InvalidPlacement;
357     return;
358   }
359
360   Standard_Real thePFrom,thePTo;
361   if (PFrom < PTo) {
362     thePFrom = PFrom;
363     thePTo   = PTo;
364   }
365   else {
366     thePFrom = PTo;
367     thePTo   = PFrom;
368   }
369
370   //Standard_Real First=0,Last=0,prm;
371   LocOpe_PntFace PntInfoFirst, PntInfoLast;
372   Standard_Integer IndFrom,IndTo;
373   TopAbs_Orientation theOr;
374   Standard_Boolean ok = theASI.LocalizeAfter(thePFrom,theOr,IndFrom,IndTo);
375   if (ok) {
376     if (theOr == TopAbs_REVERSED) {
377       ok = theASI.LocalizeBefore(IndFrom,theOr,IndFrom,IndTo); // reset
378       // It is possible to find the next.
379     }
380     if ( ok && theOr == TopAbs_FORWARD) {
381       PntInfoFirst = theASI.Point(IndFrom);
382       ok = theASI.LocalizeBefore(thePTo,theOr,IndFrom,IndTo);
383       if (ok) {
384         if (theOr == TopAbs_FORWARD) {
385           ok = theASI.LocalizeAfter(IndTo,theOr,IndFrom,IndTo);
386         }
387         if (ok && theOr == TopAbs_REVERSED) {
388           PntInfoLast = theASI.Point(IndTo);
389         }
390       }
391     }
392   }
393
394   if (!ok) {
395     myStatus = BRepFeat_InvalidPlacement;
396     return;
397   }
398
399   TopoDS_Shell Cyl;
400   CreateCyl(PntInfoFirst, PntInfoLast, Radius, myAxis, Cyl, myTopFace, myBotFace); 
401
402   BRep_Builder B;
403   TopoDS_Solid theTool;
404   B.MakeSolid(theTool);
405   B.Add(theTool, Cyl);
406
407   Standard_Boolean Fuse = Standard_False;
408   AddTool(theTool);
409   SetOperation(Fuse);
410   BOPAlgo_BOP::Perform();
411   TopTools_ListOfShape parts;
412   PartsOfTool(parts);
413
414   Standard_Integer nbparts = 0;
415   TopTools_ListIteratorOfListOfShape its(parts);
416   for (; its.More(); its.Next()) {
417     nbparts ++;
418   }
419   if (nbparts == 0) {
420     myStatus = BRepFeat_InvalidPlacement;
421     return;
422   }
423
424   if (nbparts >= 2) { // preserve parts between First and Last
425
426     TopoDS_Shape tokeep;
427     Standard_Real parbar;
428     gp_Pnt Barycentre;
429     for (its.Initialize(parts); its.More(); its.Next()) {
430       Baryc(its.Value(),Barycentre);
431       parbar = ElCLib::LineParameter(myAxis,Barycentre);
432       if (!(parbar < PntInfoFirst.Parameter() || parbar > PntInfoLast.Parameter())) {
433         KeepPart(its.Value());
434       }
435     }
436   }
437 }
438
439
440 //=======================================================================
441 //function : PerformBlind
442 //purpose  : 
443 //=======================================================================
444
445 void BRepFeat_MakeCylindricalHole::PerformBlind(const Standard_Real Radius,
446                                                 const Standard_Real Length,
447                                                 const Standard_Boolean Cont)
448 {
449   //
450   const TopoDS_Shape& aObject=myArguments.First();
451   if (aObject.IsNull() || !myAxDef || Length <= 0.) {
452     throw Standard_ConstructionError();
453   }
454
455   myIsBlind = Standard_True;
456   myValidate = Cont;
457   myStatus = BRepFeat_NoError;
458
459   LocOpe_CurveShapeIntersector theASI(myAxis,aObject);
460   if (!theASI.IsDone()) {
461     myStatus = BRepFeat_InvalidPlacement;
462     return;
463   }
464   
465   Standard_Real First;
466   Standard_Integer IndFrom,IndTo;
467   TopAbs_Orientation theOr;
468   Standard_Boolean ok = theASI.LocalizeAfter(0.,theOr,IndFrom,IndTo);
469   
470   if (ok) {
471     if (theOr == TopAbs_REVERSED) {
472       ok = theASI.LocalizeBefore(IndFrom,theOr,IndFrom,IndTo); // reset
473       // it is possible to find the next
474     }
475     ok = ok && theOr == TopAbs_FORWARD;
476   }
477   if (!ok) {
478     myStatus = BRepFeat_InvalidPlacement;
479     return;
480   }
481
482   // check a priori the length of the hole
483   Standard_Integer IFNext,ITNext;
484   ok = theASI.LocalizeAfter(IndTo,theOr,IFNext,ITNext);
485   if (!ok) {
486     myStatus = BRepFeat_InvalidPlacement;
487     return;
488   }
489   if (theASI.Point(IFNext).Parameter() <= Length) {
490     myStatus = BRepFeat_HoleTooLong;
491     return;
492   }
493
494   TopTools_ListOfShape theList;
495
496   // version for advanced control
497   for (Standard_Integer i=IndFrom; i<= ITNext; i++) {
498     theList.Append(theASI.Point(i).Face());
499   }
500
501   First = theASI.Point(IndFrom).Parameter();
502
503   //// It is not possible to use infinite cylinder for topological operations.
504   Standard_Real PMin,PMax;
505   BoxParameters(aObject,myAxis,PMin,PMax);
506   if (PMin > Length) {
507     myStatus = BRepFeat_InvalidPlacement;
508     return;
509   }
510
511   Standard_Real Heigth = 3.*(Length-PMin)/2.;
512   gp_XYZ theOrig = myAxis.Location().XYZ();
513   theOrig += ((3.*PMin-Length)/2.) * myAxis.Direction().XYZ();
514   gp_Pnt p5_ao1(theOrig); gp_Ax2 a5_ao1(p5_ao1,myAxis.Direction());
515   BRepPrim_Cylinder theCylinder(a5_ao1,
516                                 Radius,
517                                 Heigth);
518
519   BRep_Builder B;
520   TopoDS_Solid theTool;
521   B.MakeSolid(theTool);
522   B.Add(theTool,theCylinder.Shell());
523
524   myTopFace = theCylinder.TopFace();
525   myBotFace.Nullify();
526
527   //  BRepTools::Dump(theTool,std::cout);
528   Standard_Boolean Fuse = Standard_False;
529   //myBuilder.Perform(theTool,theList,Fuse);
530   //myBuilder.BuildPartsOfTool();
531   AddTool(theTool);
532   SetOperation(Fuse);
533   BOPAlgo_BOP::Perform();
534   TopTools_ListOfShape parts;
535   PartsOfTool(parts);
536
537   Standard_Integer nbparts = 0;
538   TopTools_ListIteratorOfListOfShape its(parts);
539   for (; its.More(); its.Next()) {
540     nbparts ++;
541   }
542   if (nbparts == 0) {
543     myStatus = BRepFeat_InvalidPlacement;
544     return;
545   }
546
547   if (nbparts >= 2) { // preserve the smallest as parameter along the axis
548     TopoDS_Shape tokeep;
549     Standard_Real parbar,parmin = RealLast();
550     gp_Pnt Barycentre;
551     for (its.Initialize(parts); its.More(); its.Next()) {
552       Baryc(its.Value(),Barycentre);
553       parbar = ElCLib::LineParameter(myAxis,Barycentre);
554       if (parbar >= First && parbar <= parmin) {
555         parmin = parbar;
556         tokeep = its.Value();
557       }
558     }
559
560     if (tokeep.IsNull()) { // preserve the closest interval
561
562       Standard_Real dmin = RealLast();
563       for (its.Initialize(parts); its.More(); its.Next()) {
564         Baryc(its.Value(),Barycentre);
565         parbar = ElCLib::LineParameter(myAxis,Barycentre);
566         if (Abs(First - parbar) < dmin ) {
567           dmin = Abs(First-parbar);
568           tokeep = its.Value();
569         }
570       }
571     }
572     for (its.Initialize(parts); its.More(); its.Next()) {
573       if (tokeep.IsSame(its.Value())) {
574         KeepPart(its.Value());
575         break;
576       }
577     }
578   }
579 }
580
581 //=======================================================================
582 //function : Build
583 //purpose  : 
584 //=======================================================================
585
586 void BRepFeat_MakeCylindricalHole::Build ()
587 {
588   if (myStatus == BRepFeat_NoError) {
589     PerformResult();
590     if (!HasErrors()) {
591       myStatus = (myValidate) ? Validate() : BRepFeat_NoError;
592       if (myStatus == BRepFeat_NoError) {
593         myShape = Shape();
594       }
595     }
596     else {
597       myStatus = BRepFeat_InvalidPlacement; // why not
598     }
599   }
600 }
601
602
603 //=======================================================================
604 //function : Validate
605 //purpose  : 
606 //=======================================================================
607
608 BRepFeat_Status BRepFeat_MakeCylindricalHole::Validate ()
609 {
610   BRepFeat_Status thestat = BRepFeat_NoError;
611   TopExp_Explorer ex(Shape(),TopAbs_FACE);
612   if (myIsBlind) { // limit of the hole
613     for (; ex.More(); ex.Next()) {
614       if (ex.Current().IsSame(myTopFace) ) {
615         break;
616       }
617     }
618     if (!ex.More()) {
619       thestat = BRepFeat_HoleTooLong;
620     }
621   }
622   else {
623     for (; ex.More(); ex.Next()) {
624       if (ex.Current().IsSame(myTopFace) ) {
625         return BRepFeat_InvalidPlacement;
626       }
627     }
628     for (ex.ReInit(); ex.More(); ex.Next()) {
629       if (ex.Current().IsSame(myBotFace) ) {
630         return BRepFeat_InvalidPlacement;
631       }
632     }
633   }
634   return thestat;
635 }
636
637
638
639 void Baryc(const TopoDS_Shape& S, gp_Pnt& B)
640 {
641   TopExp_Explorer exp(S,TopAbs_EDGE);
642   gp_XYZ Bar(0.,0.,0.);
643   TopLoc_Location L;
644   Handle(Geom_Curve) C;
645   Standard_Real prm,First,Last;
646
647   Standard_Integer i, nbp= 0;
648   for (; exp.More(); exp.Next()) {
649     // Calculate points by non-degenerated edges
650     const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
651     if (!BRep_Tool::Degenerated(E)) {
652       C = BRep_Tool::Curve(E,L,First,Last);
653       C = Handle(Geom_Curve)::DownCast(C->Transformed(L.Transformation()));
654       for (i=1;i<=11; i++) {
655         prm = ((11-i)*First + (i-1)*Last)/10.;
656         Bar += C->Value(prm).XYZ();
657         nbp++;
658       }
659     }
660   }
661   Bar.Divide((Standard_Real)nbp);
662   B.SetXYZ(Bar);
663 }
664
665
666 void BoxParameters(const TopoDS_Shape& S,
667                    const gp_Ax1& Axis,
668                    Standard_Real& parmin,
669                    Standard_Real& parmax)
670 {
671
672   // calculate the parameters of a bounding box in the direction of the axis of the hole
673   Bnd_Box B;
674   BRepBndLib::Add(S,B);
675   Standard_Real c[6];
676   B.Get(c[0],c[2],c[4],c[1],c[3],c[5]);
677   gp_Pnt P;
678   Standard_Integer i,j,k;
679   parmin = RealLast();
680   parmax = RealFirst();
681   Standard_Real param;
682   for (i=0; i<=1; i++) {
683     P.SetX(c[i]);
684     for (j=2; j<=3; j++) {
685       P.SetY(c[j]);
686       for (k=4; k<=5; k++) {
687         P.SetZ(c[k]);
688         param = ElCLib::LineParameter(Axis,P);
689         parmin = Min(param,parmin);
690         parmax = Max(param,parmax);
691       }
692     }
693   }
694 }
695
696 Standard_Boolean GetOffset(const LocOpe_PntFace& PntInfo, const Standard_Real Radius, const gp_Ax1& Axis, Standard_Real& outOff )
697
698   const TopoDS_Face& FF = PntInfo.Face();
699   BRepAdaptor_Surface FFA(FF);
700
701   Standard_Real Up = PntInfo.UParameter();
702   Standard_Real Vp = PntInfo.VParameter();
703   gp_Pnt PP;
704   gp_Vec D1U, D1V; 
705   FFA.D1(Up, Vp, PP, D1U, D1V);
706   gp_Dir NormF;
707   CSLib_NormalStatus stat;
708   CSLib::Normal(D1U, D1V, Precision::Angular(), stat, NormF);
709   if (stat != CSLib_Defined)
710     return Standard_False;
711   Standard_Real angle = Axis.Direction().Angle(NormF);
712   if (Abs(M_PI/2. - angle) < Precision::Angular())
713     return Standard_False;
714   outOff = Radius * Abs (tan(angle));
715   return Standard_True;
716 }
717
718 void CreateCyl(const LocOpe_PntFace& PntInfoFirst, const LocOpe_PntFace& PntInfoLast, const Standard_Real Radius,
719                const gp_Ax1& Axis, TopoDS_Shell& Cyl, TopoDS_Face& CylTopF, TopoDS_Face& CylBottF )
720 {
721   Standard_Real First=0, Last=0;
722   double offF = 0., offL = 0.;
723   Last = PntInfoLast.Parameter();
724   First = PntInfoFirst.Parameter();
725   Standard_Real Heigth = Last - First;
726
727   if ( !GetOffset(PntInfoFirst, Radius, Axis, offF))
728     offF = Radius;
729   if ( !GetOffset(PntInfoLast, Radius, Axis, offL))
730     offL = Radius;
731   
732   //create cylinder along the axis (myAxis);
733   //from 'First - offF' to 'Last + offL' params
734   gp_XYZ theOrig = PntInfoFirst.Pnt().XYZ() - offF * Axis.Direction().XYZ();
735   gp_Pnt p2_ao1(theOrig); 
736   gp_Ax2 a2_ao1(p2_ao1, Axis.Direction());
737   BRepPrim_Cylinder theCylinder(a2_ao1, Radius, Heigth + offF + offL);
738   Cyl = theCylinder.Shell();
739   CylTopF = theCylinder.TopFace();
740   CylBottF = theCylinder.BottomFace();
741 }