0026305: BRepFeat_MakePrism returns inconsistent results && 026315: BRepFeat_MakeRevo...
[occt.git] / src / BRepFeat / BRepFeat.cxx
1 // Created on: 1996-04-23
2 // Created by: Jacques GOUSSARD
3 // Copyright (c) 1996-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 #include <BRepFeat.ixx>
18
19 //#include <BRepAlgo_Cut.hxx>
20
21 #include <BRepBuilderAPI.hxx>
22 #include <BRepAdaptor_Curve.hxx>
23 #include <TopExp_Explorer.hxx>
24 #include <TopTools_MapOfShape.hxx>
25 #include <BRep_Tool.hxx>
26 #include <BRep_Builder.hxx>
27 #include <Geom_Curve.hxx>
28 #include <Geom_TrimmedCurve.hxx>
29 #include <Geom2d_TrimmedCurve.hxx>
30 #include <Extrema_ExtPC.hxx>
31 #include <GeomAdaptor_Curve.hxx>
32 #include <BRepLProp.hxx>
33 #include <TopoDS.hxx>
34 #include <TopoDS_Vertex.hxx>
35 #include <TopoDS_Face.hxx>
36 #include <TopoDS_Edge.hxx>
37 #include <TopoDS_Shell.hxx>
38 #include <TopoDS_Solid.hxx>
39 #include <Precision.hxx>
40 #include <GCPnts_QuasiUniformDeflection.hxx>
41 #include <BRepTopAdaptor_FClass2d.hxx>
42 #include <Geom2dAdaptor_Curve.hxx>
43 #include <GeomProjLib.hxx>
44 #include <gp_Vec2d.hxx>
45 #include <BRepTools.hxx>
46 #include <Geom_Surface.hxx>
47 #include <Bnd_Box.hxx>
48 #include <BRepBndLib.hxx>
49 #include <BRepLib_MakeFace.hxx>
50 #include <Geom_RectangularTrimmedSurface.hxx>
51 #include <Geom_Plane.hxx>
52 #include <Geom_CylindricalSurface.hxx>
53 #include <Geom_ConicalSurface.hxx>
54 #include <LocOpe_CSIntersector.hxx>
55 #include <LocOpe_PntFace.hxx>
56 #include <LocOpe_BuildShape.hxx> 
57 #include <ElSLib.hxx>
58
59 #include <TColGeom_SequenceOfCurve.hxx>
60
61
62 #include <LocOpe.hxx>
63
64 #define NECHANTBARYC 11
65
66 //=======================================================================
67 //function : SampleEdges
68 //purpose  : 
69 //=======================================================================
70
71 void BRepFeat::SampleEdges(const TopoDS_Shape& theShape,
72                            TColgp_SequenceOfPnt& theSeq)
73 {
74   LocOpe::SampleEdges(theShape,theSeq);
75 }
76
77
78
79 //=======================================================================
80 //function : Barycenter
81 //purpose  : Calcul du barycentre des edges d'un shape
82 //=======================================================================
83
84 void BRepFeat::Barycenter(const TopoDS_Shape& S, 
85                           gp_Pnt& B)
86 {
87   TopTools_MapOfShape theMap;
88   TopExp_Explorer exp(S,TopAbs_EDGE);
89   TopLoc_Location Loc;
90   Handle(Geom_Curve) C;
91   Standard_Real f,l,prm;
92   gp_XYZ Bar(0.,0.,0.);
93   Standard_Integer i, nbp= 0;
94
95   for (; exp.More(); exp.Next()) {
96     const TopoDS_Edge& edg = TopoDS::Edge(exp.Current());
97     if (!theMap.Add(edg)) {
98       continue;
99     }
100     if (!BRep_Tool::Degenerated(edg)) {
101       C = BRep_Tool::Curve(edg,Loc,f,l);
102       C = Handle(Geom_Curve)::DownCast(C->Transformed(Loc.Transformation()));
103       for (i=1;i<NECHANTBARYC; i++) {
104         prm = ((NECHANTBARYC-i)*f + i*l)/NECHANTBARYC;
105         Bar += C->Value(prm).XYZ();
106         nbp++;
107       }
108     }
109   }
110   // Adds every vertex
111   for (exp.Init(S,TopAbs_VERTEX); exp.More(); exp.Next()) {
112     if (theMap.Add(exp.Current())) {
113       Bar += (BRep_Tool::Pnt(TopoDS::Vertex(exp.Current()))).XYZ();
114       nbp++;
115     }
116   }
117
118   Bar.Divide((Standard_Real)nbp);
119   B.SetXYZ(Bar);
120 }
121
122
123 //=======================================================================
124 //function : ParametricBarycenter
125 //purpose  : Calcul du barycentre "parametrique" shape sur une courbe
126 //=======================================================================
127
128 Standard_Real BRepFeat::ParametricBarycenter(const TopoDS_Shape& S, 
129                                              const Handle(Geom_Curve)& CC)
130 {
131   TopTools_MapOfShape theMap;
132   TopExp_Explorer exp(S,TopAbs_EDGE);
133   TopLoc_Location Loc;
134   Handle(Geom_Curve) C;
135   Standard_Real f,l,prm;
136   Standard_Integer i, nbp= 0;
137   GeomAdaptor_Curve TheCurve(CC);
138   Extrema_ExtPC extpc;
139   extpc.Initialize(TheCurve,CC->FirstParameter(),CC->LastParameter());
140   Standard_Real parbar = 0;
141
142   for (; exp.More(); exp.Next()) {
143     const TopoDS_Edge& edg = TopoDS::Edge(exp.Current());
144     if (!theMap.Add(edg)) {
145       continue;
146     }
147     if (!BRep_Tool::Degenerated(edg)) {
148       C = BRep_Tool::Curve(edg,Loc,f,l);
149       C = Handle(Geom_Curve)::DownCast(C->Transformed(Loc.Transformation()));
150       for (i=1;i<NECHANTBARYC; i++) {
151         prm = ((NECHANTBARYC-i)*f + i*l)/NECHANTBARYC;
152         gp_Pnt pone = C->Value(prm);
153         // On projette sur CC
154         extpc.Perform(pone);
155         if (extpc.IsDone() && extpc.NbExt() >= 1) {
156           Standard_Real Dist2Min = extpc.SquareDistance(1);
157           Standard_Integer kmin = 1;
158           for (Standard_Integer k=2; k<=extpc.NbExt(); k++) {
159             Standard_Real Dist2 = extpc.SquareDistance(k);
160             if (Dist2 < Dist2Min) {
161               Dist2Min = Dist2;
162               kmin = k;
163             }
164           }
165           nbp++;
166           Standard_Real prmp = extpc.Point(kmin).Parameter();
167           parbar += prmp;
168         }
169       }
170     }
171   }
172   // Adds every vertex
173   for (exp.Init(S,TopAbs_VERTEX); exp.More(); exp.Next()) {
174     if (theMap.Add(exp.Current())) {
175       gp_Pnt pone = BRep_Tool::Pnt(TopoDS::Vertex(exp.Current()));
176       // On projette sur CC
177       extpc.Perform(pone);
178       if (extpc.IsDone() && extpc.NbExt() >= 1) {
179         Standard_Real Dist2Min = extpc.SquareDistance(1);
180         for (Standard_Integer k=2; k<=extpc.NbExt(); k++) {
181           Standard_Real Dist2 = extpc.SquareDistance(k);
182           if (Dist2 < Dist2Min) {
183             Dist2Min = Dist2;
184           }
185         }
186         nbp++;
187       }          
188     }
189   }
190
191   parbar /=((Standard_Real)nbp);
192   return parbar;
193 }
194
195
196 //=======================================================================
197 //function : ParametricBarycenter
198 //purpose  : Calcul du barycentre "parametrique" shape sur une courbe
199 //=======================================================================
200
201 void BRepFeat::ParametricMinMax(const TopoDS_Shape& S, 
202                                 const Handle(Geom_Curve)& CC,
203                                 Standard_Real& prmin,
204                                 Standard_Real& prmax,
205                                 Standard_Real& prbmin,
206                                 Standard_Real& prbmax,
207                                 Standard_Boolean& flag,
208                                 const Standard_Boolean Ori)
209 {
210   LocOpe_CSIntersector ASI(S);
211   TColGeom_SequenceOfCurve scur;
212   scur.Append(CC);
213   ASI.Perform(scur);
214   if(ASI.IsDone() && ASI.NbPoints(1) >=1) {
215     if (!Ori) {
216       prmin = Min(ASI.Point(1,1).Parameter(), 
217                   ASI.Point(1, ASI.NbPoints(1)).Parameter());
218       prmax = Max(ASI.Point(1,1).Parameter(), 
219                   ASI.Point(1, ASI.NbPoints(1)).Parameter());
220     }
221     else {
222       TopAbs_Orientation Ori = ASI.Point(1,1).Orientation();
223       if (Ori ==  TopAbs_FORWARD) {
224         prmin = ASI.Point(1,1).Parameter();
225         prmax = ASI.Point(1, ASI.NbPoints(1)).Parameter();
226       }
227       else {
228         prmax = ASI.Point(1,1).Parameter();
229         prmin = ASI.Point(1, ASI.NbPoints(1)).Parameter();
230       }
231     }
232     flag = Standard_True;
233   }
234   else {
235     prmax = RealFirst();
236     prmin = RealLast();
237     flag = Standard_False; 
238   }
239
240   TopTools_MapOfShape theMap;
241   TopExp_Explorer exp(S,TopAbs_EDGE);
242   TopLoc_Location Loc;
243   Handle(Geom_Curve) C;
244   Standard_Real f,l,prm;
245 //  Standard_Integer i, nbp= 0;
246   Standard_Integer i;
247   GeomAdaptor_Curve TheCurve(CC);
248   Extrema_ExtPC extpc;
249   extpc.Initialize(TheCurve,CC->FirstParameter(),CC->LastParameter());
250   prbmin = RealLast();
251   prbmax = RealFirst();
252   for (; exp.More(); exp.Next()) {
253     const TopoDS_Edge& edg = TopoDS::Edge(exp.Current());
254     if (!theMap.Add(edg)) {
255       continue;
256     }
257     if (!BRep_Tool::Degenerated(edg)) {
258       C = BRep_Tool::Curve(edg,Loc,f,l);
259       C = Handle(Geom_Curve)::DownCast(C->Transformed(Loc.Transformation()));
260       for (i=1;i<NECHANTBARYC; i++) {
261         prm = ((NECHANTBARYC-i)*f + i*l)/NECHANTBARYC;
262         gp_Pnt pone = C->Value(prm);
263         // On projette sur CC
264         extpc.Perform(pone);
265         if (extpc.IsDone() && extpc.NbExt() >= 1) {
266           Standard_Real Dist2Min = extpc.SquareDistance(1);
267           Standard_Integer kmin = 1;
268           for (Standard_Integer k=2; k<=extpc.NbExt(); k++) {
269             Standard_Real Dist2 = extpc.SquareDistance(k);
270             if (Dist2 < Dist2Min) {
271               Dist2Min = Dist2;
272               kmin = k;
273             }
274           }
275           Standard_Real prmp = extpc.Point(kmin).Parameter();
276           if (prmp <= prbmin) {
277             prbmin = prmp;
278           }
279           if (prmp >= prbmax) {
280             prbmax = prmp;
281           }
282         }          
283       }
284     }
285   }
286   // Adds every vertex
287   for (exp.Init(S,TopAbs_VERTEX); exp.More(); exp.Next()) {
288     if (theMap.Add(exp.Current())) {
289       gp_Pnt pone = BRep_Tool::Pnt(TopoDS::Vertex(exp.Current()));
290       // On projette sur CC
291       extpc.Perform(pone);
292       if (extpc.IsDone() && extpc.NbExt() >= 1) {
293         Standard_Real Dist2Min = extpc.SquareDistance(1);
294         Standard_Integer kmin = 1;
295         for (Standard_Integer k=2; k<=extpc.NbExt(); k++) {
296           Standard_Real Dist2 = extpc.SquareDistance(k);
297           if (Dist2 < Dist2Min) {
298             Dist2Min = Dist2;
299             kmin = k;
300           }
301         }
302         Standard_Real prmp = extpc.Point(kmin).Parameter();
303         if (prmp <= prbmin) {
304           prbmin = prmp;
305         }
306         if (prmp >= prbmax) {
307           prbmax = prmp;
308         }
309       }          
310     }
311   }
312 }
313
314
315
316
317 //=======================================================================
318 //function : IsIn
319 //purpose  : 
320 //=======================================================================
321
322 static Standard_Boolean IsIn (BRepTopAdaptor_FClass2d& FC,
323                               Geom2dAdaptor_Curve      AC)
324 {
325  Standard_Real Def = 100*Precision::Confusion();
326  GCPnts_QuasiUniformDeflection QU(AC,Def);
327
328  for (Standard_Integer i = 1; i <= QU.NbPoints(); i++) {
329    gp_Pnt2d P = AC.Value(QU.Parameter(i));
330    if (FC.Perform(P, Standard_False) == TopAbs_OUT) {
331      return Standard_False;
332    } 
333  }
334  return Standard_True;
335 }
336
337
338 //=======================================================================
339 //function : PutInBoundsU
340 //purpose  : Recadre la courbe 2d dans les bounds de la face
341 //=======================================================================
342   //---------------
343   // Recadre en U.
344   //---------------
345
346 static void PutInBoundsU (Standard_Real      umin,
347                           Standard_Real      umax,
348                           Standard_Real      eps,
349                           Standard_Real      period,
350                           Standard_Real      f,
351                           Standard_Real      l,
352                           Handle(Geom2d_Curve)&       C2d)
353 {
354   gp_Pnt2d      Pf      = C2d->Value(f);
355   gp_Pnt2d      Pl      = C2d->Value(l);
356   gp_Pnt2d      Pm      = C2d->Value(0.34*f + 0.66*l);
357   Standard_Real minC    = Min(Pf.X(),Pl.X()); minC = Min(minC,Pm.X());
358   Standard_Real maxC    = Max(Pf.X(),Pl.X()); maxC = Max(maxC,Pm.X());
359   Standard_Real du = 0.;
360   if (minC< umin - eps) {
361     du = (int((umin - minC)/period) + 1)*period;
362   }
363   if (minC > umax + eps) {
364     du = -(int((minC - umax)/period) + 1)*period;
365   }
366   if (du != 0) {
367     gp_Vec2d T1(du,0.);
368     C2d->Translate(T1);
369     minC += du; maxC += du;
370   }
371     // Ajuste au mieux la courbe dans le domaine.
372   if (maxC > umax +100*eps) {
373     Standard_Real d1 = maxC - umax;
374     Standard_Real d2 = umin - minC + period;
375     if (d2 < d1) du =-period;
376     if ( du != 0.) {
377       gp_Vec2d T2(du,0.);
378       C2d->Translate(T2);
379     }
380   }
381
382
383
384 //=======================================================================
385 //function : PutInBoundsU
386 //purpose  : Recadre la courbe 2d dans les bounds de la face
387 //=======================================================================
388   //---------------
389   // Recadre en V.
390   //---------------
391
392 static void PutInBoundsV (Standard_Real     vmin,
393                           Standard_Real      vmax,
394                           Standard_Real      eps,
395                           Standard_Real      period,
396                           Standard_Real      f,
397                           Standard_Real      l,
398                           Handle(Geom2d_Curve)&       C2d)
399 {
400   gp_Pnt2d      Pf      = C2d->Value(f);
401   gp_Pnt2d      Pl      = C2d->Value(l);
402   gp_Pnt2d      Pm      = C2d->Value(0.34*f + 0.66*l);
403   Standard_Real minC    = Min(Pf.Y(),Pl.Y()); minC = Min(minC,Pm.Y());
404   Standard_Real maxC    = Max(Pf.Y(),Pl.Y()); maxC = Max(maxC,Pm.Y());
405   Standard_Real dv = 0.;
406   if (minC< vmin - eps) {
407     dv = (int((vmin - minC)/period) + 1)*period;
408   }
409   if (minC > vmax + eps) {
410     dv = -(int((minC - vmax)/period) + 1)*period;
411   }
412   if (dv != 0) {
413     gp_Vec2d T1(0.,dv);
414     C2d->Translate(T1);
415     minC += dv; maxC += dv;
416   }
417   // Ajuste au mieux la courbe dans le domaine.
418   if (maxC > vmax +100*eps) {
419     Standard_Real d1 = maxC - vmax;
420     Standard_Real d2 = vmin - minC + period;
421     if (d2 < d1) dv =-period;
422     if ( dv != 0.) {
423       gp_Vec2d T2(0.,dv);
424       C2d->Translate(T2);
425     }
426   }
427 }
428
429
430 //=======================================================================
431 //function : IsInside
432 //purpose  : 
433 //=======================================================================
434
435
436 Standard_Boolean BRepFeat::IsInside(const TopoDS_Face& F1,
437                                     const TopoDS_Face& F2)
438 {
439   TopExp_Explorer exp;
440   exp.Init(F1, TopAbs_EDGE);
441
442   Standard_Real   umin,umax,vmin,vmax, uperiod=0, vperiod=0;
443   Standard_Integer flagu = 0, flagv = 0; 
444   TopLoc_Location L; // Recup S avec la location pour eviter la copie.
445   Handle (Geom_Surface) S   = BRep_Tool::Surface(F2);
446 //  Standard_Real periodu, periodv; 
447   BRepTools::UVBounds(F2,umin,umax,vmin,vmax);
448
449   if (S->IsUPeriodic()) {
450     flagu = 1;
451     uperiod = S->UPeriod();
452   }
453
454   if (S->IsVPeriodic()) {
455     flagv = 1;
456     vperiod = S->VPeriod();
457   }
458   TopoDS_Shape aLocalShape = F2.Oriented(TopAbs_FORWARD);
459   BRepTopAdaptor_FClass2d FC (TopoDS::Face(aLocalShape),Precision::Confusion());
460 //  BRepTopAdaptor_FClass2d FC (TopoDS::Face(F2.Oriented(TopAbs_FORWARD)),
461 //                                Precision::Confusion());
462   for(; exp.More(); exp.Next()) {
463     Standard_Real   f1,l1;
464     Handle(Geom_Curve) C0 = BRep_Tool::Curve(TopoDS::Edge(exp.Current()),f1,l1);
465     Handle(Geom2d_Curve) C = GeomProjLib::Curve2d(C0,f1,l1,S);        
466     TopoDS_Edge E = TopoDS::Edge(exp.Current());
467     if(flagu == 1 || flagv == 1) {
468       Standard_Real   eps = BRep_Tool::Tolerance(E);
469       BRep_Tool::Range(E,f1,l1);  
470       if(flagu == 1) PutInBoundsU(umin, umax, eps, uperiod, f1, l1, C); 
471       if(flagv == 1) PutInBoundsV(vmin, vmax, eps, vperiod, f1, l1, C); 
472     }
473     Geom2dAdaptor_Curve  AC(C,f1,l1);
474     if (!IsIn(FC,AC)) {
475       return Standard_False;
476     }
477   }
478   return Standard_True;
479 }
480
481
482
483 //=======================================================================
484 //function : FaceUntil
485 //purpose  : 
486 //=======================================================================
487
488
489 void BRepFeat::FaceUntil(const TopoDS_Shape& Sbase,
490                          TopoDS_Face& FUntil)
491 {
492   Bnd_Box B;
493   BRepBndLib::Add(Sbase,B);
494   Standard_Real x[2], y[2], z[2];
495   B.Get(x[0],y[0],z[0],x[1],y[1],z[1]);
496   Standard_Real diam = 10.*Sqrt(B.SquareExtent());
497   
498   Handle(Geom_Surface) s = BRep_Tool::Surface(FUntil);
499   Handle(Standard_Type) styp = s->DynamicType();
500   if (styp == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
501     s = Handle(Geom_RectangularTrimmedSurface)::DownCast(s)->BasisSurface();
502     styp = s->DynamicType();
503   }
504   Handle(Geom_RectangularTrimmedSurface) str;
505   if (styp == STANDARD_TYPE(Geom_Plane)) {
506     gp_Pln aPln = Handle(Geom_Plane)::DownCast(s)->Pln();
507     Standard_Real u, v, umin = RealLast(), umax = -umin,
508                         vmin = RealLast(), vmax = -vmin;
509     for(Standard_Integer i = 0 ; i < 2; i++) 
510     {
511       for(Standard_Integer j = 0; j < 2; j++)
512       {
513         for(Standard_Integer k = 0; k < 2; k++)
514         {
515           gp_Pnt aP(x[i], y[j], z[k]);
516           ElSLib::Parameters(aPln, aP, u, v);
517           if(u < umin) 
518             umin = u;
519           if(u > umax) 
520             umax = u;
521           if(v < vmin)
522             vmin = v;
523           if(v > vmax)
524             vmax = v;
525         }
526       }
527     }
528     umin -= diam;
529     umax += diam;
530     vmin -= diam;
531     vmax += diam;
532     str = new Geom_RectangularTrimmedSurface
533       (s, umin, umax, vmin, vmax, Standard_True, Standard_True);
534   }
535   else if (styp == STANDARD_TYPE(Geom_CylindricalSurface)) {
536     gp_Cylinder aCyl = Handle(Geom_CylindricalSurface)::DownCast(s)->Cylinder();
537     Standard_Real u, v, vmin = RealLast(), vmax = -vmin;
538     for(Standard_Integer i = 0 ; i < 2; i++) 
539     {
540       for(Standard_Integer j = 0; j < 2; j++)
541       {
542         for(Standard_Integer k = 0; k < 2; k++)
543         {
544           gp_Pnt aP(x[i], y[j], z[k]);
545           ElSLib::Parameters(aCyl, aP, u, v);
546           if(v < vmin)
547             vmin = v;
548           if(v > vmax)
549             vmax = v;
550         }
551       }
552     }
553     vmin -= diam;
554     vmax += diam;
555     str = new Geom_RectangularTrimmedSurface
556       (s, vmin, vmax, Standard_False, Standard_True);
557   }
558   else if (styp == STANDARD_TYPE(Geom_ConicalSurface)) {
559     gp_Cone aCon = Handle(Geom_ConicalSurface)::DownCast(s)->Cone();
560     Standard_Real u, v, vmin = RealLast(), vmax = -vmin;
561     for(Standard_Integer i = 0 ; i < 2; i++) 
562     {
563       for(Standard_Integer j = 0; j < 2; j++)
564       {
565         for(Standard_Integer k = 0; k < 2; k++)
566         {
567           gp_Pnt aP(x[i], y[j], z[k]);
568           ElSLib::Parameters(aCon, aP, u, v);
569           if(v < vmin)
570             vmin = v;
571           if(v > vmax)
572             vmax = v;
573         }
574       }
575     }
576     vmin -= diam;
577     vmax += diam;
578     str = new Geom_RectangularTrimmedSurface
579       (s, vmin, vmax, Standard_False, Standard_True);
580   }
581   else {
582     FUntil.Nullify();
583     return;
584   }
585
586   FUntil = BRepLib_MakeFace(str, Precision::Confusion());
587 }
588
589
590
591 //=======================================================================
592 //function : Tool
593 //purpose  : 
594 //=======================================================================
595
596 TopoDS_Solid BRepFeat::Tool(const TopoDS_Shape& SRef,
597                             const TopoDS_Face& Fac,
598                             const TopAbs_Orientation Orf)
599 {
600   TopTools_ListOfShape lfaces;
601 //  for (TopExp_Explorer exp(SRef,TopAbs_FACE); exp.More(); exp.Next()) {
602   TopExp_Explorer exp(SRef,TopAbs_FACE) ;
603   for ( ; exp.More(); exp.Next()) {
604     if (exp.Current().ShapeType() == TopAbs_FACE) {
605       lfaces.Append(exp.Current());
606     }
607   }
608    
609   LocOpe_BuildShape bs(lfaces);
610   const TopoDS_Shape& Res = bs.Shape();
611   TopoDS_Shell Sh;
612   if (Res.ShapeType() == TopAbs_SHELL) {
613     // faire un solide
614     Sh = TopoDS::Shell(Res);
615   }
616   else if (Res.ShapeType() == TopAbs_SOLID) {
617     exp.Init(Res,TopAbs_SHELL);
618     Sh = TopoDS::Shell(exp.Current());
619     exp.Next();
620     if (exp.More()) {
621       Sh.Nullify();
622     }
623   }
624
625   if (Sh.IsNull()) {
626     TopoDS_Solid So;
627     return So;
628   }
629
630
631   Sh.Orientation(TopAbs_FORWARD);
632
633   TopAbs_Orientation orient = TopAbs_FORWARD;
634
635   for (exp.Init(Sh,TopAbs_FACE); exp.More(); exp.Next()) {
636     if (exp.Current().IsSame(Fac)) {
637       orient = exp.Current().Orientation();
638       break;
639     }
640   }
641   
642   Standard_Boolean reverse = Standard_False;
643   if ((orient == Fac.Orientation() && Orf == TopAbs_REVERSED) ||
644       (orient != Fac.Orientation() && Orf == TopAbs_FORWARD)) {
645     reverse = Standard_True;
646   }
647
648   if (reverse) {
649     Sh.Reverse();
650   }
651
652   BRep_Builder B;
653   TopoDS_Solid Soc;
654   B.MakeSolid(Soc);
655   B.Add(Soc,Sh);
656   return Soc;
657 }
658
659
660 //=======================================================================
661 //function : Print
662 //purpose  : Print the error Description of a StatusError on a stream.
663 //=======================================================================
664             
665 Standard_OStream& BRepFeat::Print(const BRepFeat_StatusError se, 
666                                   Standard_OStream& s)
667 {
668   switch(se) {
669   case BRepFeat_OK :
670     s << "No error";
671     break;
672   case BRepFeat_BadDirect :
673     s << "Directions must be opposite";
674     break;
675   case BRepFeat_BadIntersect :
676     s << "Intersection failure";
677     break;
678   case BRepFeat_EmptyBaryCurve :
679     s << "Empty BaryCurve";
680     break;
681   case BRepFeat_EmptyCutResult :
682     s << "Failure in Cut : Empty resulting shape";
683     break;;
684   case BRepFeat_FalseSide :
685     s << "Verify plane and wire orientation";
686     break;
687   case BRepFeat_IncDirection : 
688     s << "Incoherent Direction for shapes From and Until";
689     break;
690   case BRepFeat_IncSlidFace : 
691     s << "Sliding face not in Base shape";
692     break;
693   case BRepFeat_IncParameter :
694     s << "Incoherent Parameter : shape Until before shape From";
695     break;
696   case BRepFeat_IncTypes : 
697     s << "Invalid option for faces From and Until : 1 Support and 1 not";
698     break;
699   case BRepFeat_IntervalOverlap :
700     s << "Shapes From and Until overlap";
701     break;
702   case BRepFeat_InvFirstShape :
703     s << "Invalid First shape : more than 1 face";
704     break;
705   case BRepFeat_InvOption :
706     s << "Invalid option";
707     break;
708   case BRepFeat_InvShape :
709     s << "Invalid shape";
710     break;
711   case BRepFeat_LocOpeNotDone :
712     s << "Local Operation not done";
713     break;
714   case BRepFeat_LocOpeInvNotDone :
715     s << "Local Operation : intersection line conflict";
716     break;
717   case BRepFeat_NoExtFace :
718     s << "No Extreme faces";
719     break;
720   case BRepFeat_NoFaceProf :
721     s << "No Face Profile";
722     break;
723   case BRepFeat_NoGluer :
724     s << "Gluer Failure";
725     break;
726   case BRepFeat_NoIntersectF :
727     s << "No intersection between Feature and shape From";
728     break;
729   case BRepFeat_NoIntersectU :
730     s << "No intersection between Feature and shape Until";
731     break;
732   case BRepFeat_NoParts :
733     s << "No parts of tool kept";
734     break;
735   case BRepFeat_NoProjPt :
736     s << "No projection points";
737     break;
738   case BRepFeat_NotInitialized :
739     s << "Fields not initialized";
740     break;
741   case BRepFeat_NotYetImplemented : 
742     s << "Not yet implemented";
743     break;
744   case BRepFeat_NullRealTool :
745     s << "Real Tool : Null DPrism";
746     break;
747   case BRepFeat_NullToolF :
748     s << "Null Tool : Invalid type for shape Form";
749     break;
750   case BRepFeat_NullToolU :
751     s << "Null Tool : Invalid type for shape Until";
752     break;
753   }
754   return s;
755 }
756