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