b492bfcd179cf986068d2aca7c6fc6b3c96ed814
[occt.git] / src / BRepFeat / BRepFeat.cxx
1 // File:        BRepFeat.cxx
2 // Created:     Tue Apr 23 16:07:45 1996
3 // Author:      Jacques GOUSSARD
4 //              <jag@bravox>
5
6
7 #include <BRepFeat.ixx>
8
9 //#include <BRepAlgo_Cut.hxx>
10
11 #include <BRepBuilderAPI.hxx>
12 #include <BRepAdaptor_Curve.hxx>
13 #include <TopExp_Explorer.hxx>
14 #include <TopTools_MapOfShape.hxx>
15 #include <BRep_Tool.hxx>
16 #include <BRep_Builder.hxx>
17 #include <Geom_Curve.hxx>
18 #include <Geom_TrimmedCurve.hxx>
19 #include <Geom2d_TrimmedCurve.hxx>
20 #include <Extrema_ExtPC.hxx>
21 #include <GeomAdaptor_Curve.hxx>
22 #include <BRepLProp.hxx>
23 #include <TopoDS.hxx>
24 #include <TopoDS_Vertex.hxx>
25 #include <TopoDS_Face.hxx>
26 #include <TopoDS_Edge.hxx>
27 #include <TopoDS_Shell.hxx>
28 #include <TopoDS_Solid.hxx>
29 #include <Precision.hxx>
30 #include <GCPnts_QuasiUniformDeflection.hxx>
31 #include <BRepTopAdaptor_FClass2d.hxx>
32 #include <Geom2dAdaptor_Curve.hxx>
33 #include <GeomProjLib.hxx>
34 #include <gp_Vec2d.hxx>
35 #include <BRepTools.hxx>
36 #include <Geom_Surface.hxx>
37 #include <Bnd_Box.hxx>
38 #include <BRepBndLib.hxx>
39 #include <BRepLib_MakeFace.hxx>
40 #include <Geom_RectangularTrimmedSurface.hxx>
41 #include <Geom_Plane.hxx>
42 #include <Geom_CylindricalSurface.hxx>
43 #include <Geom_ConicalSurface.hxx>
44 #include <LocOpe_CSIntersector.hxx>
45 #include <LocOpe_PntFace.hxx>
46 #include <LocOpe_BuildShape.hxx> 
47
48 #include <TColGeom_SequenceOfCurve.hxx>
49
50
51 #include <LocOpe.hxx>
52
53 #define NECHANTBARYC 11
54
55 //=======================================================================
56 //function : SampleEdges
57 //purpose  : 
58 //=======================================================================
59
60 void BRepFeat::SampleEdges(const TopoDS_Shape& theShape,
61                            TColgp_SequenceOfPnt& theSeq)
62 {
63   LocOpe::SampleEdges(theShape,theSeq);
64 }
65
66
67
68 //=======================================================================
69 //function : Barycenter
70 //purpose  : Calcul du barycentre des edges d'un shape
71 //=======================================================================
72
73 void BRepFeat::Barycenter(const TopoDS_Shape& S, 
74                           gp_Pnt& B)
75 {
76   TopTools_MapOfShape theMap;
77   TopExp_Explorer exp(S,TopAbs_EDGE);
78   TopLoc_Location Loc;
79   Handle(Geom_Curve) C;
80   Standard_Real f,l,prm;
81   gp_XYZ Bar(0.,0.,0.);
82   Standard_Integer i, nbp= 0;
83
84   for (; exp.More(); exp.Next()) {
85     const TopoDS_Edge& edg = TopoDS::Edge(exp.Current());
86     if (!theMap.Add(edg)) {
87       continue;
88     }
89     if (!BRep_Tool::Degenerated(edg)) {
90       C = BRep_Tool::Curve(edg,Loc,f,l);
91       C = Handle(Geom_Curve)::DownCast(C->Transformed(Loc.Transformation()));
92       for (i=1;i<NECHANTBARYC; i++) {
93         prm = ((NECHANTBARYC-i)*f + i*l)/NECHANTBARYC;
94         Bar += C->Value(prm).XYZ();
95         nbp++;
96       }
97     }
98   }
99   // Adds every vertex
100   for (exp.Init(S,TopAbs_VERTEX); exp.More(); exp.Next()) {
101     if (theMap.Add(exp.Current())) {
102       Bar += (BRep_Tool::Pnt(TopoDS::Vertex(exp.Current()))).XYZ();
103       nbp++;
104     }
105   }
106
107   Bar.Divide((Standard_Real)nbp);
108   B.SetXYZ(Bar);
109 }
110
111
112 //=======================================================================
113 //function : ParametricBarycenter
114 //purpose  : Calcul du barycentre "parametrique" shape sur une courbe
115 //=======================================================================
116
117 Standard_Real BRepFeat::ParametricBarycenter(const TopoDS_Shape& S, 
118                                              const Handle(Geom_Curve)& CC)
119 {
120   TopTools_MapOfShape theMap;
121   TopExp_Explorer exp(S,TopAbs_EDGE);
122   TopLoc_Location Loc;
123   Handle(Geom_Curve) C;
124   Standard_Real f,l,prm;
125   Standard_Integer i, nbp= 0;
126   GeomAdaptor_Curve TheCurve(CC);
127   Extrema_ExtPC extpc;
128   extpc.Initialize(TheCurve,CC->FirstParameter(),CC->LastParameter());
129   Standard_Real parbar = 0;
130
131   for (; exp.More(); exp.Next()) {
132     const TopoDS_Edge& edg = TopoDS::Edge(exp.Current());
133     if (!theMap.Add(edg)) {
134       continue;
135     }
136     if (!BRep_Tool::Degenerated(edg)) {
137       C = BRep_Tool::Curve(edg,Loc,f,l);
138       C = Handle(Geom_Curve)::DownCast(C->Transformed(Loc.Transformation()));
139       for (i=1;i<NECHANTBARYC; i++) {
140         prm = ((NECHANTBARYC-i)*f + i*l)/NECHANTBARYC;
141         gp_Pnt pone = C->Value(prm);
142         // On projette sur CC
143         extpc.Perform(pone);
144         if (extpc.IsDone() && extpc.NbExt() >= 1) {
145           Standard_Real Dist2Min = extpc.SquareDistance(1);
146           Standard_Integer kmin = 1;
147           for (Standard_Integer k=2; k<=extpc.NbExt(); k++) {
148             Standard_Real Dist2 = extpc.SquareDistance(k);
149             if (Dist2 < Dist2Min) {
150               Dist2Min = Dist2;
151               kmin = k;
152             }
153           }
154           nbp++;
155           Standard_Real prmp = extpc.Point(kmin).Parameter();
156           parbar += prmp;
157         }         
158       }
159     }
160   }
161   // Adds every vertex
162   for (exp.Init(S,TopAbs_VERTEX); exp.More(); exp.Next()) {
163     if (theMap.Add(exp.Current())) {
164       gp_Pnt pone = BRep_Tool::Pnt(TopoDS::Vertex(exp.Current()));
165       // On projette sur CC
166       extpc.Perform(pone);
167       if (extpc.IsDone() && extpc.NbExt() >= 1) {
168         Standard_Real Dist2Min = extpc.SquareDistance(1);
169         Standard_Integer kmin = 1;
170         for (Standard_Integer k=2; k<=extpc.NbExt(); k++) {
171           Standard_Real Dist2 = extpc.SquareDistance(k);
172           if (Dist2 < Dist2Min) {
173             Dist2Min = Dist2;
174             kmin = k;
175           }
176         }
177         nbp++;
178 #ifdef DEB
179         Standard_Real prmp = extpc.Point(kmin).Parameter();
180 #else
181         extpc.Point(kmin).Parameter();
182 #endif
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 Ori)
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 (!Ori) {
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      break;
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       break;
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 c[6], bnd;
493   B.Get(c[0],c[2],c[4],c[1],c[3],c[5]);
494   bnd = c[0];
495   for(Standard_Integer i = 1 ; i < 6; i++) {
496     if(c[i] > bnd) bnd = c[i];
497   }
498   bnd = 10*bnd;
499
500   
501   Handle(Geom_Surface) s = BRep_Tool::Surface(FUntil);
502   Handle(Standard_Type) styp = s->DynamicType();
503   if (styp == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
504     s = Handle(Geom_RectangularTrimmedSurface)::DownCast(s)->BasisSurface();
505     styp = s->DynamicType();
506   }
507   Handle(Geom_RectangularTrimmedSurface) str;
508   if (styp == STANDARD_TYPE(Geom_Plane)) {
509     str = new Geom_RectangularTrimmedSurface
510       (s, bnd, -bnd, bnd, -bnd, Standard_True, Standard_True);
511   }
512   else if (styp == STANDARD_TYPE(Geom_CylindricalSurface)) {
513     str = new Geom_RectangularTrimmedSurface
514       (s, 0., 2.*M_PI, bnd, -bnd, Standard_True, Standard_True);
515   }
516   else if (styp == STANDARD_TYPE(Geom_ConicalSurface)) {
517     str = new Geom_RectangularTrimmedSurface
518       (s, 0., 2.*M_PI, bnd, -bnd, Standard_True, Standard_True);
519   }
520   else {
521     FUntil.Nullify();
522     return;
523   }
524
525   FUntil = BRepLib_MakeFace(str, Precision::Confusion());
526 }
527
528
529
530 //=======================================================================
531 //function : Tool
532 //purpose  : 
533 //=======================================================================
534
535 TopoDS_Solid BRepFeat::Tool(const TopoDS_Shape& SRef,
536                             const TopoDS_Face& Fac,
537                             const TopAbs_Orientation Orf)
538 {
539   TopTools_ListOfShape lfaces;
540 //  for (TopExp_Explorer exp(SRef,TopAbs_FACE); exp.More(); exp.Next()) {
541   TopExp_Explorer exp(SRef,TopAbs_FACE) ;
542   for ( ; exp.More(); exp.Next()) {
543     if (exp.Current().ShapeType() == TopAbs_FACE) {
544       lfaces.Append(exp.Current());
545     }
546   }
547    
548   LocOpe_BuildShape bs(lfaces);
549   const TopoDS_Shape& Res = bs.Shape();
550   TopoDS_Shell Sh;
551   if (Res.ShapeType() == TopAbs_SHELL) {
552     // faire un solide
553     Sh = TopoDS::Shell(Res);
554   }
555   else if (Res.ShapeType() == TopAbs_SOLID) {
556     exp.Init(Res,TopAbs_SHELL);
557     Sh = TopoDS::Shell(exp.Current());
558     exp.Next();
559     if (exp.More()) {
560       Sh.Nullify();
561     }
562   }
563
564   if (Sh.IsNull()) {
565     TopoDS_Solid So;
566     return So;
567   }
568
569
570   Sh.Orientation(TopAbs_FORWARD);
571 #ifdef DEB
572   TopAbs_Orientation orient;
573 #else
574   TopAbs_Orientation orient = TopAbs_FORWARD;
575 #endif
576   for (exp.Init(Sh,TopAbs_FACE); exp.More(); exp.Next()) {
577     if (exp.Current().IsSame(Fac)) {
578       orient = exp.Current().Orientation();
579       break;
580     }
581   }
582   
583   Standard_Boolean reverse = Standard_False;
584   if ((orient == Fac.Orientation() && Orf == TopAbs_REVERSED) ||
585       (orient != Fac.Orientation() && Orf == TopAbs_FORWARD)) {
586     reverse = Standard_True;
587   }
588
589   if (reverse) {
590     Sh.Reverse();
591   }
592
593   BRep_Builder B;
594   TopoDS_Solid Soc;
595   B.MakeSolid(Soc);
596   B.Add(Soc,Sh);
597   return Soc;
598 }
599
600
601 //=======================================================================
602 //function : Print
603 //purpose  : Print the error Description of a StatusError on a stream.
604 //=======================================================================
605         
606 Standard_OStream& BRepFeat::Print(const BRepFeat_StatusError se, 
607                                   Standard_OStream& s)
608 {
609   switch(se) {
610   case BRepFeat_OK :
611     s << "No error";
612     break;
613   case BRepFeat_BadDirect :
614     s << "Directions must be opposite";
615     break;
616   case BRepFeat_BadIntersect :
617     s << "Intersection failure";
618     break;
619   case BRepFeat_EmptyBaryCurve :
620     s << "Empty BaryCurve";
621     break;
622   case BRepFeat_EmptyCutResult :
623     s << "Failure in Cut : Empty resulting shape";
624     break;;
625   case BRepFeat_FalseSide :
626     s << "Verify plane and wire orientation";
627     break;
628   case BRepFeat_IncDirection : 
629     s << "Incoherent Direction for shapes From and Until";
630     break;
631   case BRepFeat_IncSlidFace : 
632     s << "Sliding face not in Base shape";
633     break;
634   case BRepFeat_IncParameter :
635     s << "Incoherent Parameter : shape Until before shape From";
636     break;
637   case BRepFeat_IncTypes : 
638     s << "Invalid option for faces From and Until : 1 Support and 1 not";
639     break;
640   case BRepFeat_IntervalOverlap :
641     s << "Shapes From and Until overlap";
642     break;
643   case BRepFeat_InvFirstShape :
644     s << "Invalid First shape : more than 1 face";
645     break;
646   case BRepFeat_InvOption :
647     s << "Invalid option";
648     break;
649   case BRepFeat_InvShape :
650     s << "Invalid shape";
651     break;
652   case BRepFeat_LocOpeNotDone :
653     s << "Local Operation not done";
654     break;
655   case BRepFeat_LocOpeInvNotDone :
656     s << "Local Operation : intersection line conflict";
657     break;
658   case BRepFeat_NoExtFace :
659     s << "No Extreme faces";
660     break;
661   case BRepFeat_NoFaceProf :
662     s << "No Face Profile";
663     break;
664   case BRepFeat_NoGluer :
665     s << "Gluer Failure";
666     break;
667   case BRepFeat_NoIntersectF :
668     s << "No intersection between Feature and shape From";
669     break;
670   case BRepFeat_NoIntersectU :
671     s << "No intersection between Feature and shape Until";
672     break;
673   case BRepFeat_NoParts :
674     s << "No parts of tool kept";
675     break;
676   case BRepFeat_NoProjPt :
677     s << "No projection points";
678     break;
679   case BRepFeat_NotInitialized :
680     s << "Fields not initialized";
681     break;
682   case BRepFeat_NotYetImplemented : 
683     s << "Not yet implemented";
684     break;
685   case BRepFeat_NullRealTool :
686     s << "Real Tool : Null DPrism";
687     break;
688   case BRepFeat_NullToolF :
689     s << "Null Tool : Invalid type for shape Form";
690     break;
691   case BRepFeat_NullToolU :
692     s << "Null Tool : Invalid type for shape Until";
693     break;
694   }
695   return s;
696 }
697