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