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