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