0026556: Infinite calculations of BRepOffset_MakeOffset
[occt.git] / src / BRepTest / BRepTest_FeatureCommands.cxx
1 // Created on: 1995-06-16
2 // Created by: Jacques GOUSSARD
3 // Copyright (c) 1995-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 <Draw_Interpretor.hxx>
18 #include <Draw_Appli.hxx>
19 #include <DrawTrSurf.hxx>
20
21 #include <TopTools_ListOfShape.hxx>
22 #include <TopTools_ListIteratorOfListOfShape.hxx>
23 #include <TopTools_MapOfShape.hxx>
24 #include <TopTools_MapIteratorOfMapOfShape.hxx>
25 #include <TopExp_Explorer.hxx>
26 #include <TopoDS_Face.hxx>
27 #include <TopoDS_Wire.hxx>
28 #include <TopoDS_Shell.hxx>
29 #include <TopoDS_Compound.hxx>
30 #include <TopoDS_Edge.hxx>
31 #include <TopoDS.hxx>
32
33 #include <Geom_RectangularTrimmedSurface.hxx>
34 #include <Geom_Plane.hxx>
35 #include <Geom_CylindricalSurface.hxx>
36 #include <gp_Lin.hxx>
37 #include <gp_Pln.hxx>
38 #include <gp_Cylinder.hxx>
39
40 //#include <BRepFeat_LocalOperation.hxx>
41 #include <BRepFeat_Builder.hxx>
42 #include <BRepFeat_MakeCylindricalHole.hxx>
43 #include <BRepFeat_SplitShape.hxx>
44 #include <BRepFeat_Gluer.hxx>
45
46 #include <BRepFeat.hxx>
47 #include <BRepFeat_MakePrism.hxx>
48 #include <BRepFeat_MakeRevol.hxx>
49 #include <BRepFeat_MakePipe.hxx>
50 #include <BRepFeat_MakeDPrism.hxx>
51 #include <BRepFeat_MakeLinearForm.hxx>
52 #include <BRepFeat_MakeRevolutionForm.hxx>
53
54 #include <LocOpe_FindEdges.hxx>
55 #include <LocOpe_FindEdgesInFace.hxx>
56
57 #include <BRepOffsetAPI_MakeOffsetShape.hxx>
58 #include <BRepOffsetAPI_MakeThickSolid.hxx>
59 #include <BRep_Tool.hxx>
60 #include <BRep_Builder.hxx>
61 #include <DBRep.hxx>
62 #include <DBRep_DrawableShape.hxx>
63 #include <BRepTest.hxx>
64
65 #include <BRepFilletAPI_MakeFillet.hxx>
66 #include <ChFi3d_FilletShape.hxx>
67
68 #include <Precision.hxx>
69
70 #ifdef _WIN32
71 //#define strcasecmp _stricmp Already defined
72 Standard_IMPORT Draw_Viewer dout;
73 #endif
74
75 static BRepFeat_MakeCylindricalHole theHole;
76 static Standard_Boolean WithControl = Standard_True;
77
78 Standard_Boolean DownCastingEnforcing = Standard_False;
79
80 static BRepFeat_MakePrism thePrism;
81 static BRepFeat_MakeDPrism theDPrism;
82 static BRepFeat_MakeRevol theRevol;
83 static BRepFeat_MakePipe  thePipe;
84 static BRepFeat_MakeLinearForm  theLF;
85 static BRepFeat_MakeRevolutionForm  theRF;
86
87 static Standard_Boolean dprdef = Standard_False;
88 static Standard_Boolean prdef = Standard_False;
89 static Standard_Boolean rvdef = Standard_False;
90 static Standard_Boolean pidef = Standard_False;
91 static Standard_Boolean lfdef = Standard_False;
92 static Standard_Boolean rfdef = Standard_False;
93
94 static Standard_Real t3d = 1.e-4;
95 static Standard_Real t2d = 1.e-5;
96 static Standard_Real ta  = 1.e-2;
97 static Standard_Real fl  = 1.e-3;
98 static Standard_Real tapp_angle = 1.e-2;
99 static GeomAbs_Shape blend_cont = GeomAbs_C1;
100 static BRepFilletAPI_MakeFillet* Rakk = 0;
101
102
103
104 static void Print(Draw_Interpretor& di,
105                   const BRepFeat_Status St)
106 {
107   di << "  Error Status : ";
108   switch (St) {
109   case BRepFeat_NoError:
110     di << "No error";
111     break;
112
113   case BRepFeat_InvalidPlacement:
114     di << "Invalid placement";
115     break;
116
117   case BRepFeat_HoleTooLong:
118     di << "Hole too long";
119     break;
120   }
121 }
122
123 static Standard_Integer Loc(Draw_Interpretor& theCommands,
124                             Standard_Integer narg, const char** a)
125 {
126   if (narg<6) return 1;
127   TopoDS_Shape S = DBRep::Get(a[2]);
128   TopoDS_Shape T = DBRep::Get(a[3]);
129
130   Standard_Boolean Fuse;
131   if (!strcasecmp("F",a[4])) {
132     Fuse = Standard_True;
133   }
134   else if (!strcasecmp("C",a[4])) {
135     Fuse = Standard_False;
136   }
137   else {
138     return 1;
139   }
140
141   TopTools_ListOfShape LF;
142   for (Standard_Integer i=0; i<= narg-6; i++) {
143     TopoDS_Shape aLocalShape(DBRep::Get(a[i+5],TopAbs_FACE));
144     LF.Append(aLocalShape);
145 //    LF.Append(TopoDS::Face(DBRep::Get(a[i+5],TopAbs_FACE)));
146   }
147
148   //BRepFeat_LocalOperation BLoc(S);
149   //BLoc.Perform(T,LF,Fuse);
150   //BLoc.BuildPartsOfTool();
151   TopTools_ListOfShape parts;
152   BRepFeat_Builder BLoc;
153   BLoc.Init(S,T);
154   BLoc.SetOperation(Fuse);
155   //BRepFeat_LocalOperation BLoc;
156   //BLoc.Init(S,T,Fuse);
157   BLoc.Perform();
158   BLoc.PartsOfTool(parts);
159
160 #if 0
161   char newname[1024];
162   strcpy(newname,a[1]);
163   char* p = newname;
164   while (*p != '\0') p++;
165   *p = '_';
166   p++;
167   TopTools_ListIteratorOfListOfShape its(parts);
168   dout.Clear();
169   i = 0;
170   for (; its.More(); its.Next()) {
171     i++;
172     Sprintf(p,"%d",i);
173     DBRep::Set(newname,its.Value());
174   }
175   if (i >= 2) {
176     dout.Flush();
177     Standard_Integer qq,ww,ee,button;
178     TopoDS_Shell S;
179     do {
180       TopoDS_Shape aLocalShape(DBRep::Get(".",TopAbs_SHELL));
181       S = TopoDS::Shell(aLocalShape);
182 //      S = TopoDS::Shell(DBRep::Get(".",TopAbs_SHELL));
183       Draw::LastPick(qq,ww,ee,button);
184       if (!S.IsNull()) {
185         
186         switch (button) {
187         case 1:
188           //BLoc.RemovePart(S);
189           break;
190         case 2:
191           BLoc.KeepPart(S);
192           break;
193         default:
194           {}
195         }
196       }
197       else {
198         button = 3;
199       }
200
201     } while (button != 3);
202   }
203 #endif
204   BLoc.PerformResult();
205   if (!BLoc.ErrorStatus()) {
206 //    dout.Clear();
207     DBRep::Set(a[1],BLoc.Shape());
208     dout.Flush();
209     return 0;
210   }
211   theCommands << "Local operation not done" ;
212   return 1;
213 }
214
215
216
217 static Standard_Integer HOLE1(Draw_Interpretor& theCommands,
218                               Standard_Integer narg, const char** a)
219 {
220   if (narg<10 || narg == 11) return 1;
221   TopoDS_Shape S = DBRep::Get(a[2]);
222
223   gp_Pnt Or(Draw::Atof(a[3]),Draw::Atof(a[4]),Draw::Atof(a[5]));
224   gp_Dir Di(Draw::Atof(a[6]),Draw::Atof(a[7]),Draw::Atof(a[8]));
225
226   Standard_Real Radius = Draw::Atof(a[9]);
227
228   theHole.Init(S,gp_Ax1(Or,Di));
229
230   if (narg <= 10) {
231     theHole.Perform(Radius);
232   }
233   else {
234     Standard_Real pfrom = Draw::Atof(a[10]);
235     Standard_Real pto   = Draw::Atof(a[11]);
236     theHole.Perform(Radius,pfrom,pto,WithControl);
237   }
238
239   theHole.Build();
240   if (!theHole.ErrorStatus()) {
241 //    dout.Clear();
242     DBRep::Set(a[1],theHole.Shape());
243     dout.Flush();
244     return 0;
245   }
246   theCommands << "Echec de MakeCylindricalHole";
247   Print(theCommands,theHole.Status());
248   return 1;
249 }
250
251 static Standard_Integer HOLE2(Draw_Interpretor& theCommands,
252                               Standard_Integer narg, const char** a)
253 {
254   if (narg<10) return 1;
255   TopoDS_Shape S = DBRep::Get(a[2]);
256
257   gp_Pnt Or(Draw::Atof(a[3]),Draw::Atof(a[4]),Draw::Atof(a[5]));
258   gp_Dir Di(Draw::Atof(a[6]),Draw::Atof(a[7]),Draw::Atof(a[8]));
259
260   Standard_Real Radius = Draw::Atof(a[9]);
261
262   theHole.Init(S,gp_Ax1(Or,Di));
263   theHole.PerformThruNext(Radius,WithControl);
264
265   theHole.Build();
266   if (!theHole.ErrorStatus()) {
267 //    dout.Clear();
268     DBRep::Set(a[1],theHole.Shape());
269     dout.Flush();
270     return 0;
271   }
272   theCommands << "Echec de MakeCylindricalHole";
273   Print(theCommands,theHole.Status());
274   return 1;
275 }
276
277 static Standard_Integer HOLE3(Draw_Interpretor& theCommands,
278                               Standard_Integer narg, const char** a)
279 {
280   if (narg<10) return 1;
281   TopoDS_Shape S = DBRep::Get(a[2]);
282
283   gp_Pnt Or(Draw::Atof(a[3]),Draw::Atof(a[4]),Draw::Atof(a[5]));
284   gp_Dir Di(Draw::Atof(a[6]),Draw::Atof(a[7]),Draw::Atof(a[8]));
285
286   Standard_Real Radius = Draw::Atof(a[9]);
287
288   theHole.Init(S,gp_Ax1(Or,Di));
289   theHole.PerformUntilEnd(Radius,WithControl);
290   theHole.Build();
291   if (!theHole.ErrorStatus()) {
292 //    dout.Clear();
293     DBRep::Set(a[1],theHole.Shape());
294     dout.Flush();
295     return 0;
296   }
297   theCommands << "Echec de MakeCylindricalHole";
298   Print(theCommands,theHole.Status());
299   return 1;
300 }
301
302
303 static Standard_Integer HOLE4(Draw_Interpretor& theCommands,
304                               Standard_Integer narg, const char** a)
305 {
306   if (narg<11) return 1;
307   TopoDS_Shape S = DBRep::Get(a[2]);
308
309   gp_Pnt Or(Draw::Atof(a[3]),Draw::Atof(a[4]),Draw::Atof(a[5]));
310   gp_Dir Di(Draw::Atof(a[6]),Draw::Atof(a[7]),Draw::Atof(a[8]));
311
312   Standard_Real Radius = Draw::Atof(a[9]);
313   Standard_Real Length = Draw::Atof(a[10]);
314
315   theHole.Init(S,gp_Ax1(Or,Di));
316   theHole.PerformBlind(Radius,Length,WithControl);
317   theHole.Build();
318   if (!theHole.ErrorStatus()) {
319 //    dout.Clear();
320     DBRep::Set(a[1],theHole.Shape());
321     dout.Flush();
322     return 0;
323   }
324   theCommands << "Echec de MakeCylindricalHole";
325   Print(theCommands,theHole.Status());
326   return 1;
327 }
328
329 static Standard_Integer CONTROL(Draw_Interpretor& theCommands,
330                                 Standard_Integer narg, const char** a)
331 {
332   if (narg >= 2) {
333     WithControl = strcmp("0",a[1]);
334   }
335   if (WithControl) {
336     theCommands << "Mode avec controle";
337   }
338   else {
339     theCommands << "Mode sans controle";
340   }
341   return 0;
342 }
343
344 //=======================================================================
345 //function : reportOffsetState
346 //purpose  : Print state of offset operation by error code.
347 //=======================================================================
348 static void reportOffsetState(Draw_Interpretor& theCommands,
349                               const BRepOffset_Error theErrorCode)
350 {
351   switch(theErrorCode)
352   {
353   case BRepOffset_NoError:
354     {
355       theCommands << "OK. Offset performed succesfully.";
356       break;
357     }
358   case BRepOffset_BadNormalsOnGeometry:
359     {
360       theCommands << "ERROR. Degenerated normal on input data.";
361       break;
362     }
363   case BRepOffset_C0Geometry:
364     {
365       theCommands << "ERROR. C0 continuity of input data.";
366       break;
367     }
368   case BRepOffset_NullOffset:
369     {
370       theCommands << "ERROR. Null offset of all faces.";
371       break;
372     }
373   case BRepOffset_NotConnectedShell:
374     {
375       theCommands << "ERROR. Incorrect set of faces to remove, the remaining shell is not connected.";
376       break;
377     }
378   default:
379     {
380       theCommands << "ERROR. offsetperform operation not done.";
381       break;
382     }
383   }
384 }
385
386 //=======================================================================
387 //function : PRW
388 //purpose  : 
389 //=======================================================================
390
391 static Standard_Integer PRW(Draw_Interpretor& theCommands,
392                             Standard_Integer narg, const char** a)
393 {
394   if (narg<9) return 1;
395   TopoDS_Shape S = DBRep::Get(a[3]);
396   BRepFeat_MakePrism thePFace;
397   gp_Vec V;
398   TopoDS_Shape FFrom,FUntil;
399   Standard_Integer borne;
400   Standard_Boolean fuse;
401   if (a[1][0] == 'f' || a[1][0] == 'F') {
402     fuse = Standard_True;
403   }
404   else if (a[1][0] == 'c' || a[1][0] == 'C') {
405     fuse = Standard_False;
406   }
407   else {
408     return 1;
409   }
410
411   if (a[4][0] == '.' || IsAlphabetic(a[4][0])) {
412     if (narg < 10) {
413       return 1;
414     }
415     if (a[5][0] == '.' || IsAlphabetic(a[5][0])) {
416       if (narg < 11) {
417         return 1;
418       }
419       V.SetCoord(Draw::Atof(a[6]),Draw::Atof(a[7]),Draw::Atof(a[8]));
420       FFrom   = DBRep::Get(a[4],TopAbs_SHAPE);
421       FUntil  = DBRep::Get(a[5],TopAbs_SHAPE);
422       borne = 9;
423     }
424     else {
425       V.SetCoord(Draw::Atof(a[5]),Draw::Atof(a[6]),Draw::Atof(a[7]));
426       FUntil  = DBRep::Get(a[4],TopAbs_SHAPE);
427       borne = 8;
428     }
429   }
430   else {
431     V.SetCoord(Draw::Atof(a[4]),Draw::Atof(a[5]),Draw::Atof(a[6]));
432     borne = 7;
433   }
434   Standard_Real Length = V.Magnitude();
435   if (Length < Precision::Confusion()) {
436     return 1;
437   }
438
439   TopoDS_Shape aLocalShape(DBRep::Get(a[borne],TopAbs_FACE));
440   TopoDS_Face F  = TopoDS::Face(aLocalShape);
441 //  TopoDS_Face F  = TopoDS::Face(DBRep::Get(a[borne],TopAbs_FACE));
442   BRepFeat_SplitShape Spls(F);
443   for (Standard_Integer i = borne+1; i<narg; i++) {
444     TopoDS_Wire wir;
445     if (a[i][0] !='-') {
446       aLocalShape = DBRep::Get(a[i],TopAbs_WIRE);
447       wir = TopoDS::Wire(aLocalShape);
448 //      wir = TopoDS::Wire(DBRep::Get(a[i],TopAbs_WIRE));
449     }
450     else {
451       if (a[i][1] == '\0')
452         return 1;
453       const char* Temp = a[i]+1;
454       aLocalShape = DBRep::Get(Temp,TopAbs_WIRE);
455       wir = TopoDS::Wire(aLocalShape);
456 //      wir = TopoDS::Wire(DBRep::Get(Temp,TopAbs_WIRE));
457       wir.Reverse();
458     }
459     Spls.Add(wir,F);
460   }
461   Spls.Build();
462
463   TopoDS_Shape ToPrism;
464   const TopTools_ListOfShape& lleft = Spls.DirectLeft();
465   if (lleft.Extent() == 1) {
466     thePFace.Init(S,lleft.First(),F,V,fuse,Standard_True);
467     ToPrism = lleft.First();
468   }
469   else {
470     BRep_Builder B;
471     TopoDS_Shell Sh;
472     B.MakeShell(Sh);
473     TopTools_ListIteratorOfListOfShape it;
474     for (it.Initialize(lleft);it.More();it.Next()) {
475       B.Add(Sh,TopoDS::Face(it.Value()));
476     }
477     Sh.Closed (BRep_Tool::IsClosed (Sh));
478     thePFace.Init(S,Sh,F,V,fuse,Standard_True);
479     ToPrism = Sh;
480   }
481
482   // Recherche des faces de glissement, si on n`a pas sketche sur une face
483   // du shape de depart
484
485 //  for (TopExp_Explorer exp(S,TopAbs_FACE);exp.More();exp.Next()) {
486   TopExp_Explorer exp(S,TopAbs_FACE) ;
487   for ( ;exp.More();exp.Next()) {
488     if (exp.Current().IsSame(F)) {
489       break;
490     }
491   }
492
493   if (!exp.More()) {
494     LocOpe_FindEdgesInFace FEIF;
495     for (exp.Init(S,TopAbs_FACE);exp.More();exp.Next()) {
496       const TopoDS_Face& fac = TopoDS::Face(exp.Current());
497       Handle(Geom_Surface) Su = BRep_Tool::Surface(fac);
498       if (Su->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
499         Su = Handle(Geom_RectangularTrimmedSurface)::
500         DownCast(Su)->BasisSurface();
501       }
502       if (Su->DynamicType() == STANDARD_TYPE(Geom_Plane)) {
503         gp_Pln pl = Handle(Geom_Plane)::DownCast(Su)->Pln();
504         if (pl.Contains(gp_Lin(pl.Location(),V),
505                         Precision::Confusion(),
506                         Precision::Angular())) {
507           FEIF.Set(ToPrism,fac);
508           for (FEIF.Init();FEIF.More();FEIF.Next()) {
509             thePFace.Add(FEIF.Edge(),fac);
510           }
511         }
512       }
513       else if (Su->DynamicType() == STANDARD_TYPE(Geom_CylindricalSurface)) {
514         gp_Cylinder cy = 
515           Handle(Geom_CylindricalSurface)::DownCast(Su)->Cylinder();
516         if (V.IsParallel(cy.Axis().Direction(),Precision::Angular())) {
517           FEIF.Set(ToPrism,fac);
518           for (FEIF.Init();FEIF.More();FEIF.Next()) {
519             thePFace.Add(FEIF.Edge(),fac);
520           }
521         }
522       }
523     }
524   }
525
526   if (borne == 7) {
527     thePFace.Perform(Length);
528   }
529   else if (borne == 8) {
530     thePFace.Perform(FUntil);
531   }
532   else if (borne == 9) {
533     if (!(FFrom.IsNull() || FUntil.IsNull())) {
534       thePFace.Perform(FFrom,FUntil);
535     }
536     else if (FFrom.IsNull()) {
537       if (!FUntil.IsNull()) {
538         thePFace.PerformFromEnd(FUntil);
539       }
540       else {
541         thePFace.PerformThruAll();
542       }
543     }
544     else {
545       // il faudrait inverser V et appeler PerfomFromEnd...
546       //cout << "Not Implemented" << endl;
547       theCommands << "Not Implemented" << "\n";
548     }
549   }
550   if (!thePFace.IsDone()) {
551     theCommands << "Local operation not done";
552     return 1;
553   }
554
555   DBRep::Set(a[2],thePFace);
556   dout.Flush();
557   return 0;
558 }
559
560
561 //=======================================================================
562 //function : PRF
563 //purpose  : 
564 //=======================================================================
565
566 static Standard_Integer PRF(Draw_Interpretor& theCommands,
567                             Standard_Integer narg, const char** a)
568 {
569   if (narg<8) return 1;
570   TopoDS_Shape S = DBRep::Get(a[3]);
571   BRepFeat_MakePrism thePFace;
572   Standard_Integer borne;
573   gp_Vec V;
574   TopoDS_Shape FFrom,FUntil;
575   Standard_Boolean fuse;
576   if (a[1][0] == 'f' || a[1][0] == 'F') {
577     fuse = Standard_True;
578   }
579   else if (a[1][0] == 'c' || a[1][0] == 'C') {
580     fuse = Standard_False;
581   }
582   else {
583     return 1;
584   }
585
586
587   if (a[4][0] == '.' || IsAlphabetic(a[4][0])) {
588     if (narg < 9) {
589       return 1;
590     }
591     if (a[5][0] == '.' || IsAlphabetic(a[5][0])) {
592       if (narg < 10) {
593         return 1;
594       }
595       borne = 9;
596       V.SetCoord(Draw::Atof(a[6]),Draw::Atof(a[7]),Draw::Atof(a[8]));
597       FFrom  = DBRep::Get(a[4],TopAbs_SHAPE);
598       FUntil  = DBRep::Get(a[5],TopAbs_SHAPE);
599     }
600     else {
601       borne = 8;
602       V.SetCoord(Draw::Atof(a[5]),Draw::Atof(a[6]),Draw::Atof(a[7]));
603       FUntil  = DBRep::Get(a[4],TopAbs_SHAPE);
604     }
605   }
606   else {
607     borne = 7;
608     V.SetCoord(Draw::Atof(a[4]),Draw::Atof(a[5]),Draw::Atof(a[6]));
609   }
610   Standard_Real Length = V.Magnitude();
611   if (Length < Precision::Confusion()) {
612     return 1;
613   }
614
615   TopoDS_Shape ToPrism;
616   if (narg == borne+1) {
617     TopoDS_Shape aLocalShape(DBRep::Get(a[borne],TopAbs_FACE));
618     TopoDS_Face F  = TopoDS::Face(aLocalShape);
619 //    TopoDS_Face F  = TopoDS::Face(DBRep::Get(a[borne],TopAbs_FACE));
620     thePFace.Init(S,F,F,V,fuse,Standard_True);
621     ToPrism = F;
622   }
623   else {
624     TopoDS_Shell She;
625     BRep_Builder B;
626     B.MakeShell(She);
627     for (Standard_Integer i=borne; i<narg; i++) {
628       TopoDS_Shape aLocalShape(DBRep::Get(a[i],TopAbs_FACE));
629       TopoDS_Face F  = TopoDS::Face(aLocalShape);
630 //      TopoDS_Face F  = TopoDS::Face(DBRep::Get(a[i],TopAbs_FACE));
631       if (!F.IsNull()) {
632         B.Add(She,F);
633       }
634     }
635     She.Closed (BRep_Tool::IsClosed (She));
636     thePFace.Init(S,She,TopoDS_Face(),V,fuse,Standard_False);
637     ToPrism = She;
638   }
639   
640   // Recherche des faces de glissement, on ne prisme pas une face
641   // du shape de depart
642
643 //  for (TopExp_Explorer exp(ToPrism,TopAbs_FACE);exp.More();exp.Next()) {
644   TopExp_Explorer exp(ToPrism,TopAbs_FACE) ;
645   for ( ;exp.More();exp.Next()) {
646 //    for (TopExp_Explorer exp2(S,TopAbs_FACE);exp2.More();exp2.Next()) {
647     TopExp_Explorer exp2(S,TopAbs_FACE) ;
648     for ( ;exp2.More();exp2.Next()) {
649       if (exp2.Current().IsSame(exp.Current())) {
650         break;
651       }
652     }
653     if (exp2.More()) {
654       break;
655     }
656   }
657
658   if (!exp.More()) {
659     LocOpe_FindEdgesInFace FEIF;
660     for (exp.Init(S,TopAbs_FACE);exp.More();exp.Next()) {
661       const TopoDS_Face& fac = TopoDS::Face(exp.Current());
662       Handle(Geom_Surface) Su = BRep_Tool::Surface(fac);
663       if (Su->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
664         Su = Handle(Geom_RectangularTrimmedSurface)::
665         DownCast(Su)->BasisSurface();
666       }
667       if (Su->DynamicType() == STANDARD_TYPE(Geom_Plane)) {
668         gp_Pln pl = Handle(Geom_Plane)::DownCast(Su)->Pln();
669         if (pl.Contains(gp_Lin(pl.Location(),V),
670                         Precision::Confusion(),
671                         Precision::Angular())) {
672           FEIF.Set(ToPrism,fac);
673           for (FEIF.Init();FEIF.More();FEIF.Next()) {
674             thePFace.Add(FEIF.Edge(),fac);
675           }
676         }
677       }
678       else if (Su->DynamicType() == STANDARD_TYPE(Geom_CylindricalSurface)) {
679         gp_Cylinder cy = 
680           Handle(Geom_CylindricalSurface)::DownCast(Su)->Cylinder();
681         if (V.IsParallel(cy.Axis().Direction(),Precision::Angular())) {
682           FEIF.Set(ToPrism,fac);
683           for (FEIF.Init();FEIF.More();FEIF.Next()) {
684             thePFace.Add(FEIF.Edge(),fac);
685           }
686         }
687       }
688     }
689   }
690
691   if (borne == 7) {
692     thePFace.Perform(Length);
693   }
694   else if (borne == 8) {
695     thePFace.Perform(FUntil);
696   }
697   else if (borne == 9) {
698     if (!(FFrom.IsNull() || FUntil.IsNull())) {
699       thePFace.Perform(FFrom,FUntil);
700     }
701     else if (FFrom.IsNull()) {
702       if (!FUntil.IsNull()) {
703         thePFace.PerformFromEnd(FUntil);
704       }
705       else {
706         thePFace.PerformThruAll();
707       }
708     }
709     else { //FUntil.IsNull()
710       // il faudrait inverser V et appeler PerfomFromEnd...
711       //cout << "Not Implemented" << endl;
712       theCommands << "Not Implemented" << "\n";
713     }
714   }
715   if (!thePFace.IsDone()) {
716     theCommands << "Local operation not done";
717     return 1;
718   }
719
720   DBRep::Set(a[2],thePFace);
721   dout.Flush();
722   return 0;
723 }
724
725
726
727 //=======================================================================
728 //function : SPLS
729 //purpose  : 
730 //=======================================================================
731
732 static Standard_Integer SPLS(Draw_Interpretor& ,
733                              Standard_Integer narg, const char** a)
734 {
735   Standard_Integer newnarg ;
736
737   if (narg<3) return 1;
738   TopoDS_Shape S = DBRep::Get(a[2]);
739   BRepFeat_SplitShape Spls(S);
740   Standard_Boolean pick = Standard_False;
741   TopoDS_Shape EF;
742   Standard_Real u,v;
743   Standard_Integer i = 3;
744
745   for ( newnarg=3; newnarg<narg; newnarg++) {
746     if (a[newnarg][0] == '@') {
747       break;
748     }
749   }
750
751   if (newnarg == 3 || 
752       (newnarg !=narg && ((narg-newnarg)<=2 || (narg-newnarg)%2 != 1))) {
753     return 1;
754   }
755
756   if (i<newnarg) {
757     pick = (a[i][0] == '.');
758     EF = DBRep::Get(a[i],TopAbs_FACE);
759     if (EF.IsNull()) return 1;
760   }
761   
762   while (i < newnarg) {
763     if (pick) {
764       DBRep_DrawableShape::LastPick(EF,u,v);
765     }
766     if (EF.ShapeType() == TopAbs_FACE) {
767       // face wire/edge ...
768       i++;
769       while (i < newnarg) {
770         TopoDS_Shape W;
771         Standard_Boolean rever = Standard_False;
772         if (a[i][0] == '-') {
773           if (a[i][1] == '\0')
774             return 1;
775           pick = (a[i][1] == '.');
776           const char* Temp = a[i]+1;
777           W = DBRep::Get(Temp,TopAbs_SHAPE,Standard_False);
778           rever = Standard_True;
779         }
780         else {
781           pick = (a[i][0] == '.');
782           W = DBRep::Get(a[i],TopAbs_SHAPE,Standard_False);
783         }
784         if (W.IsNull()) {
785           return 1; // on n`a rien recupere
786         }
787         TopAbs_ShapeEnum wtyp = W.ShapeType();
788         if (wtyp != TopAbs_WIRE && wtyp != TopAbs_EDGE && wtyp != TopAbs_COMPOUND && pick) {
789           Standard_Real u,v;
790           DBRep_DrawableShape::LastPick(W,u,v);
791           wtyp = W.ShapeType();
792         }
793         if (wtyp != TopAbs_WIRE && wtyp != TopAbs_EDGE && wtyp != TopAbs_COMPOUND) {
794           EF = DBRep::Get(a[i]);
795           break;
796         }
797         else {
798           if (rever) {
799             W.Reverse();
800           }
801           if (wtyp == TopAbs_WIRE) {
802             Spls.Add(TopoDS::Wire(W),TopoDS::Face(EF));
803           }
804           else if (wtyp == TopAbs_EDGE) {
805             Spls.Add(TopoDS::Edge(W),TopoDS::Face(EF));
806           }
807           else {
808             Spls.Add(TopoDS::Compound(W),TopoDS::Face(EF));
809           }
810         }
811         i++;
812       }
813     }
814     else
815       return 1;
816   }
817   
818   // ici, i vaut newnarg
819   for (i++; i<narg; i+=2) {
820     TopoDS_Shape Ew,Es;
821     TopoDS_Shape aLocalShape(DBRep::Get(a[i],TopAbs_EDGE));
822     Es = TopoDS::Edge(aLocalShape);
823 //    Es = TopoDS::Edge(DBRep::Get(a[i],TopAbs_EDGE));
824     if (Es.IsNull()) {
825       return 1;
826     }
827     aLocalShape = DBRep::Get(a[i+1],TopAbs_EDGE);
828     Ew = TopoDS::Edge(aLocalShape);
829 //    Ew = TopoDS::Edge(DBRep::Get(a[i+1],TopAbs_EDGE));
830     if (Ew.IsNull()) {
831       return 1;
832     }
833     Spls.Add(TopoDS::Edge(Ew),TopoDS::Edge(Es));
834   }
835
836
837   DBRep::Set(a[1],Spls);
838   return 0;
839 }
840
841 //=======================================================================
842 //function : thickshell
843 //purpose  : 
844 //=======================================================================
845 Standard_Integer thickshell(Draw_Interpretor& theCommands,
846   Standard_Integer n, const char** a)
847 {
848   if ( n < 4) return 1;
849   TopoDS_Shape  S  = DBRep::Get(a[2]);
850   if (S.IsNull()) return 1;
851
852   Standard_Real    Of    = Draw::Atof(a[3]);
853
854   GeomAbs_JoinType JT= GeomAbs_Arc;
855   if (n > 4)
856   {
857     if (!strcmp(a[4],"i"))
858       JT = GeomAbs_Intersection;
859     if (!strcmp(a[4],"t"))
860       JT = GeomAbs_Tangent;
861   }
862
863   Standard_Boolean Inter = Standard_False; //Standard_True;
864   Standard_Real    Tol = Precision::Confusion();
865   if (n > 5)
866     Tol = Draw::Atof(a[5]);
867
868   BRepOffset_MakeOffset B;
869   B.Initialize(S,Of,Tol,BRepOffset_Skin,Inter,0,JT, Standard_True);
870
871   B.MakeOffsetShape();
872
873   const BRepOffset_Error aRetCode = B.Error();
874   reportOffsetState(theCommands, aRetCode);
875
876   DBRep::Set(a[1],B.Shape());
877   return 0;
878 }
879
880 //=======================================================================
881 //function : offsetshape
882 //purpose  : 
883 //=======================================================================
884
885 Standard_Integer offsetshape(Draw_Interpretor& theCommands,
886                              Standard_Integer n, const char** a)
887 {
888   if ( n < 4) return 1;
889   TopoDS_Shape  S  = DBRep::Get(a[2]);
890   if (S.IsNull()) return 1;
891
892   Standard_Real    Of    = Draw::Atof(a[3]);
893   Standard_Boolean Inter = (!strcmp(a[0],"offsetcompshape"));
894   GeomAbs_JoinType JT= GeomAbs_Arc;
895   if (!strcmp(a[0],"offsetinter"))
896   {
897     JT    = GeomAbs_Intersection;
898     Inter = Standard_True;
899   }
900   
901   BRepOffset_MakeOffset B;
902   Standard_Integer      IB  = 4;
903   Standard_Real         Tol = Precision::Confusion();
904   if (n > 4)
905   {
906     TopoDS_Shape  SF  = DBRep::Get(a[4],TopAbs_FACE);
907     if (SF.IsNull())
908     {
909       IB  = 5;
910       Tol = Draw::Atof(a[4]);
911     }
912   }
913   B.Initialize(S,Of,Tol,BRepOffset_Skin,Inter,0,JT);
914   //------------------------------------------
915   // recuperation et chargement des bouchons.
916   //----------------------------------------
917   Standard_Boolean YaBouchon = Standard_False;
918
919   for (Standard_Integer i = IB ; i < n; i++)
920   {
921     TopoDS_Shape  SF  = DBRep::Get(a[i],TopAbs_FACE);
922     if (!SF.IsNull())
923     {
924       YaBouchon = Standard_True;
925       B.AddFace(TopoDS::Face(SF));
926     }
927   }
928
929   if (!YaBouchon)  B.MakeOffsetShape();
930   else             B.MakeThickSolid ();
931
932   const BRepOffset_Error aRetCode = B.Error();
933   reportOffsetState(theCommands, aRetCode);
934
935   DBRep::Set(a[1],B.Shape());
936
937   return 0;
938 }
939
940 static BRepOffset_MakeOffset TheOffset;
941 static Standard_Real         TheRadius;
942 static Standard_Boolean      theYaBouchon;
943 static Standard_Real         TheTolerance = Precision::Confusion();
944 static Standard_Boolean      TheInter     = Standard_False;
945 static GeomAbs_JoinType      TheJoin      = GeomAbs_Arc;
946
947 Standard_Integer offsetparameter(Draw_Interpretor& di,
948                                  Standard_Integer n, const char** a)
949 {
950   if ( n == 1 ) { 
951     //cout << " OffsetParameter Tol Inter(c/p) JoinType(a/i)" << endl;
952     //cout << " Current Values" << endl;
953     //cout << "   --> Tolerance :" << TheTolerance << endl;
954     //cout << "   --> TheInter  :";
955     di << " OffsetParameter Tol Inter(c/p) JoinType(a/i)" << "\n";
956     di << " Current Values" << "\n";
957     di << "   --> Tolerance :" << TheTolerance << "\n";
958     di << "   --> TheInter  :";
959     if ( TheInter) {
960       //cout << "Complet" ;
961       di << "Complet" ;
962     } else {
963       //cout << "Partial";
964       di << "Partial";
965     }
966     //cout << endl << "   --> TheJoin   :";
967     di << "\n" << "   --> TheJoin   :";
968     
969     switch (TheJoin) {
970     //case GeomAbs_Arc:          cout << " Arc";          break;
971     //case GeomAbs_Intersection: cout << " Intersection"; break;
972     case GeomAbs_Arc:          di << " Arc";          break;
973     case GeomAbs_Intersection: di << " Intersection"; break;
974     default:
975       break ;
976     }
977     //cout << endl;
978     di << "\n";
979
980     return 0;
981   }
982
983   if ( n < 4 ) return 1;
984   
985   TheTolerance = Draw::Atof(a[1]);
986   TheInter     = strcmp(a[2],"p");
987   
988   if      ( !strcmp(a[3],"a")) TheJoin = GeomAbs_Arc;
989   else if ( !strcmp(a[3],"i")) TheJoin = GeomAbs_Intersection;
990   else if ( !strcmp(a[3],"t")) TheJoin = GeomAbs_Tangent;
991     
992   return 0;    
993 }
994
995
996 //=======================================================================
997 //function : offsetinit
998 //purpose  : 
999 //=======================================================================
1000
1001 Standard_Integer offsetload(Draw_Interpretor& ,
1002                             Standard_Integer n, const char** a)
1003 {
1004   if ( n < 2) return 1;
1005   TopoDS_Shape  S  = DBRep::Get(a[1]);
1006   if (S.IsNull()) return 1;
1007
1008   Standard_Real    Of    = Draw::Atof(a[2]);
1009   TheRadius = Of;
1010 //  Standard_Boolean Inter = Standard_True;
1011   
1012   TheOffset.Initialize(S,Of,TheTolerance,BRepOffset_Skin,TheInter,0,TheJoin);
1013   //------------------------------------------
1014   // recuperation et chargement des bouchons.
1015   //----------------------------------------
1016   for (Standard_Integer i = 3 ; i < n; i++) {
1017     TopoDS_Shape  SF  = DBRep::Get(a[i],TopAbs_FACE);
1018     if (!SF.IsNull()) {
1019       TheOffset.AddFace(TopoDS::Face(SF));
1020     }
1021   }
1022   if (n < 4)  theYaBouchon = Standard_False; //B.MakeOffsetShape();
1023   else        theYaBouchon = Standard_True;  //B.MakeThickSolid ();
1024
1025   return 0;
1026 }
1027
1028
1029 //=======================================================================
1030 //function : offsetonface
1031 //purpose  : 
1032 //=======================================================================
1033
1034 Standard_Integer offsetonface(Draw_Interpretor&, Standard_Integer n, const char** a)
1035 {
1036   if ( n < 3) return 1;
1037
1038   for (Standard_Integer i = 1 ; i < n; i+=2) {
1039     TopoDS_Shape  SF  = DBRep::Get(a[i],TopAbs_FACE);
1040     if (!SF.IsNull()) {
1041       Standard_Real Of = Draw::Atof(a[i+1]);
1042       TheOffset.SetOffsetOnFace(TopoDS::Face(SF),Of);
1043     }
1044   }
1045   
1046   return 0;
1047 }
1048
1049 //=======================================================================
1050 //function : offsetperform
1051 //purpose  : 
1052 //=======================================================================
1053
1054 Standard_Integer offsetperform(Draw_Interpretor& theCommands,
1055                                Standard_Integer theNArg, const char** a)
1056   {
1057   if ( theNArg < 2) return 1;
1058
1059   if (theYaBouchon)
1060     TheOffset.MakeThickSolid ();
1061   else
1062     TheOffset.MakeOffsetShape();
1063
1064   if(TheOffset.IsDone())
1065     {
1066     DBRep::Set(a[1],TheOffset.Shape());
1067     }
1068   else
1069     {
1070       const BRepOffset_Error aRetCode = TheOffset.Error();
1071       reportOffsetState(theCommands, aRetCode);
1072     }
1073
1074   return 0;
1075   }
1076
1077
1078 //=======================================================================
1079 //function : Debou
1080 //purpose  : 
1081 //=======================================================================
1082
1083 static Standard_Integer Debou(Draw_Interpretor& theCommands,
1084                               Standard_Integer narg, const char** a)
1085 {
1086   Standard_Integer i ;
1087   Standard_Integer newnarg ;
1088
1089   if (narg<7) return 1;
1090   
1091   TopoDS_Shape S = DBRep::Get(a[2]);
1092
1093   Standard_Boolean Fuse;
1094   if (!strcasecmp("F",a[3])) {
1095     Fuse = Standard_True;
1096   }
1097   else if (!strcasecmp("C",a[3])) {
1098     Fuse = Standard_False;
1099   }
1100   else {
1101     return 1;
1102   }
1103
1104   for ( newnarg = 4; newnarg < narg; newnarg++) {
1105     if (a[newnarg][0] == '@') {
1106       break;
1107     }
1108   }
1109   if (newnarg >= narg-1 || newnarg == 4) {
1110     return 1;
1111   }
1112
1113
1114   TopTools_ListOfShape LF,LF2;
1115   for ( i=4; i<newnarg; i++) {
1116     TopoDS_Shape aLocalShape(DBRep::Get(a[i],TopAbs_FACE));
1117     LF.Append(aLocalShape);
1118 //    LF.Append(TopoDS::Face(DBRep::Get(a[i],TopAbs_FACE)));
1119   }
1120
1121   for (i=newnarg+1; i<narg; i++) {
1122     TopoDS_Shape aLocalShape(DBRep::Get(a[i],TopAbs_FACE));
1123     LF2.Append(aLocalShape);
1124 //    LF2.Append(TopoDS::Face(DBRep::Get(a[i],TopAbs_FACE)));
1125   }
1126
1127   //BRepFeat_LocalOperation BLoc(S);
1128   //BLoc.Perform(LF,LF2,Fuse);
1129   //BLoc.Build();
1130   BRepFeat_Builder BLoc;
1131   BLoc.Init(S, S);
1132   BLoc.Perform();
1133   BLoc.PerformResult();
1134   if (!BLoc.ErrorStatus()) {
1135 //    dout.Clear();
1136     DBRep::Set(a[1],BLoc.Shape());
1137     dout.Flush();
1138     return 0;
1139   }
1140   theCommands << "Local operation not done" ;
1141   return 1;
1142 }
1143
1144
1145 //=======================================================================
1146 //function : ROW
1147 //purpose  : 
1148 //=======================================================================
1149
1150 static Standard_Integer ROW(Draw_Interpretor& theCommands,
1151                             Standard_Integer narg, const char** a)
1152 {
1153   if (narg<13) return 1;
1154   TopoDS_Shape S = DBRep::Get(a[3]);
1155   BRepFeat_MakeRevol theRFace;
1156   gp_Dir D;
1157   gp_Pnt Or;
1158   Standard_Real Angle=0;
1159   TopoDS_Shape FFrom,FUntil;
1160   Standard_Integer i,borne;
1161   Standard_Boolean fuse;
1162
1163   if (a[1][0] == 'f' || a[1][0] == 'F') {
1164     fuse = Standard_True;
1165   }
1166   else if (a[1][0] == 'c' || a[1][0] == 'C') {
1167     fuse = Standard_False;
1168   }
1169   else {
1170     return 1;
1171   }
1172
1173   FFrom   = DBRep::Get(a[4],TopAbs_SHAPE);
1174   if (FFrom.IsNull()) {
1175     Angle = Draw::Atof(a[4]);
1176     Angle *=M_PI/180.;
1177     i = 5;
1178   }
1179   else {
1180     FUntil = DBRep::Get(a[5],TopAbs_SHAPE);
1181     if (FUntil.IsNull()) {
1182       i = 5;
1183       FUntil = FFrom;
1184       FFrom.Nullify();
1185       
1186     }
1187     else {
1188       if (narg < 14) {
1189         return 1;
1190       }
1191       i = 6;
1192     }
1193   }
1194   borne = i+6;
1195
1196   Or.SetCoord(Draw::Atof(a[i]),Draw::Atof(a[i+1]),Draw::Atof(a[i+2]));
1197   D.SetCoord(Draw::Atof(a[i+3]),Draw::Atof(a[i+4]),Draw::Atof(a[i+5]));
1198   gp_Ax1 theAxis(Or,D);
1199
1200   TopoDS_Shape aLocalShape(DBRep::Get(a[borne],TopAbs_FACE));
1201   TopoDS_Face F  = TopoDS::Face(aLocalShape);
1202 //  TopoDS_Face F  = TopoDS::Face(DBRep::Get(a[borne],TopAbs_FACE));
1203   BRepFeat_SplitShape Spls(F);
1204   for (i = borne+1; i<narg; i++) {
1205     TopoDS_Wire wir;
1206     if (a[i][0] !='-') {
1207       aLocalShape = DBRep::Get(a[i],TopAbs_WIRE);
1208       wir = TopoDS::Wire(aLocalShape);
1209 //      wir = TopoDS::Wire(DBRep::Get(a[i],TopAbs_WIRE));
1210     }
1211     else {
1212       if (a[i][1] == '\0')
1213         return 1;
1214       const char* Temp = a[i]+1;
1215       aLocalShape = DBRep::Get(Temp,TopAbs_WIRE);
1216       wir = TopoDS::Wire(aLocalShape);
1217 //      wir = TopoDS::Wire(DBRep::Get(Temp,TopAbs_WIRE));
1218       wir.Reverse();
1219     }
1220     Spls.Add(wir,F);
1221   }
1222   Spls.Build();
1223
1224   TopoDS_Shape ToRotate;
1225   const TopTools_ListOfShape& lleft = Spls.DirectLeft();
1226   if (lleft.Extent() == 1) {
1227     theRFace.Init(S,lleft.First(),F,theAxis,fuse,Standard_True);
1228     ToRotate = lleft.First();
1229   }
1230   else {
1231     BRep_Builder B;
1232     TopoDS_Shell Sh;
1233     B.MakeShell(Sh);
1234     TopTools_ListIteratorOfListOfShape it;
1235     for (it.Initialize(lleft);it.More();it.Next()) {
1236       B.Add(Sh,TopoDS::Face(it.Value()));
1237     }
1238     Sh.Closed (BRep_Tool::IsClosed (Sh));
1239     theRFace.Init(S,Sh,F,theAxis,fuse,Standard_True);
1240     ToRotate = Sh;
1241   }
1242
1243   // Recherche des faces de glissement
1244 //  for (TopExp_Explorer exp(S,TopAbs_FACE);exp.More();exp.Next()) {
1245   TopExp_Explorer exp(S,TopAbs_FACE) ;
1246   for ( ;exp.More();exp.Next()) {
1247     if (exp.Current().IsSame(F)) {
1248       break;
1249     }
1250   }
1251
1252   if (!exp.More()) {
1253     LocOpe_FindEdgesInFace FEIF;
1254     for (exp.Init(S,TopAbs_FACE);exp.More();exp.Next()) {
1255       const TopoDS_Face& fac = TopoDS::Face(exp.Current());
1256       Handle(Geom_Surface) Su = BRep_Tool::Surface(fac);
1257       if (Su->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
1258         Su = Handle(Geom_RectangularTrimmedSurface)::
1259           DownCast(Su)->BasisSurface();
1260       }
1261       if (Su->DynamicType() == STANDARD_TYPE(Geom_Plane)) {
1262         gp_Pln pl = Handle(Geom_Plane)::DownCast(Su)->Pln();
1263         if (pl.Axis().IsParallel(theAxis,Precision::Angular())) {
1264           FEIF.Set(ToRotate,fac);
1265           for (FEIF.Init();FEIF.More();FEIF.Next()) {
1266             theRFace.Add(FEIF.Edge(),fac);
1267           }
1268         }
1269       }
1270       else if (Su->DynamicType() == STANDARD_TYPE(Geom_CylindricalSurface)) {
1271         gp_Cylinder cy = 
1272           Handle(Geom_CylindricalSurface)::DownCast(Su)->Cylinder();
1273         if (cy.Axis().IsCoaxial(theAxis,
1274                                 Precision::Angular(),Precision::Confusion())) {
1275           FEIF.Set(ToRotate,fac);
1276           for (FEIF.Init();FEIF.More();FEIF.Next()) {
1277             theRFace.Add(FEIF.Edge(),fac);
1278           }
1279         }
1280       }
1281     }
1282   }
1283
1284   if (borne == 11) {
1285     if (FUntil.IsNull()) {
1286       theRFace.Perform(Angle);
1287     }
1288     else {
1289       theRFace.Perform(FUntil);
1290     }
1291   }
1292   else { // borne == 12
1293     theRFace.Perform(FFrom,FUntil);
1294   }
1295
1296   if (!theRFace.IsDone()) {
1297     theCommands << "Local operation not done";
1298     return 1;
1299   }
1300
1301   DBRep::Set(a[2],theRFace);
1302   dout.Flush();
1303   return 0;
1304 }
1305
1306
1307 //=======================================================================
1308 //function : ROF
1309 //purpose  : 
1310 //=======================================================================
1311
1312 static Standard_Integer ROF(Draw_Interpretor& theCommands,
1313                             Standard_Integer narg, const char** a)
1314 {
1315   if (narg<12) return 1;
1316   TopoDS_Shape S = DBRep::Get(a[3]);
1317   BRepFeat_MakeRevol theRFace;
1318   gp_Dir D;
1319   gp_Pnt Or;
1320   Standard_Real Angle=0;
1321   TopoDS_Shape FFrom,FUntil;
1322   Standard_Integer i,borne;
1323   Standard_Boolean fuse;
1324
1325   if (a[1][0] == 'f' || a[1][0] == 'F') {
1326     fuse = Standard_True;
1327   }
1328   else if (a[1][0] == 'c' || a[1][0] == 'C') {
1329     fuse = Standard_False;
1330   }
1331   else {
1332     return 1;
1333   }
1334
1335   FFrom   = DBRep::Get(a[4],TopAbs_SHAPE);
1336   if (FFrom.IsNull()) {
1337     Angle = Draw::Atof(a[4]);
1338     Angle *=M_PI/180.;
1339     i = 5;
1340   }
1341   else {
1342     FUntil = DBRep::Get(a[5],TopAbs_SHAPE);
1343     if (FUntil.IsNull()) {
1344       i = 5;
1345       FUntil = FFrom;
1346       FFrom.Nullify();
1347       
1348     }
1349     else {
1350       if (narg < 13) {
1351         return 1;
1352       }
1353       i = 6;
1354     }
1355   }
1356
1357   borne = i+6;
1358   Or.SetCoord(Draw::Atof(a[i]),Draw::Atof(a[i+1]),Draw::Atof(a[i+2]));
1359   D.SetCoord(Draw::Atof(a[i+3]),Draw::Atof(a[i+4]),Draw::Atof(a[i+5]));
1360   gp_Ax1 theAxis(Or,D);
1361
1362   TopoDS_Shape ToRotate;
1363   if (narg == borne+1) {
1364     TopoDS_Shape aLocalShape(DBRep::Get(a[borne],TopAbs_FACE));
1365     TopoDS_Face F  = TopoDS::Face(aLocalShape);
1366 //    TopoDS_Face F  = TopoDS::Face(DBRep::Get(a[borne],TopAbs_FACE));
1367     theRFace.Init(S,F,F,theAxis,fuse,Standard_True);
1368     ToRotate = F;
1369   }
1370   else {
1371     TopoDS_Shell She;
1372     BRep_Builder B;
1373     B.MakeShell(She);
1374     
1375     for (i=borne; i<narg; i++) {
1376       TopoDS_Shape aLocalShape(DBRep::Get(a[i],TopAbs_FACE));
1377       TopoDS_Face F  = TopoDS::Face(aLocalShape);
1378 //      TopoDS_Face F  = TopoDS::Face(DBRep::Get(a[i],TopAbs_FACE));
1379       if (!F.IsNull()) {
1380         B.Add(She,F);
1381       }
1382     }
1383     She.Closed (BRep_Tool::IsClosed (She));
1384     theRFace.Init(S,She,TopoDS_Face(),theAxis,fuse,Standard_False);
1385     ToRotate = She;
1386   }
1387
1388 //  for (TopExp_Explorer exp(ToRotate,TopAbs_FACE);exp.More();exp.Next()) {
1389   TopExp_Explorer exp(ToRotate,TopAbs_FACE) ;
1390   for ( ;exp.More();exp.Next()) {
1391 //    for (TopExp_Explorer exp2(S,TopAbs_FACE);exp2.More();exp2.Next()) {
1392     TopExp_Explorer exp2(S,TopAbs_FACE) ;
1393     for ( ;exp2.More();exp2.Next()) {
1394       if (exp2.Current().IsSame(exp.Current())) {
1395         break;
1396       }
1397     }
1398     if (exp2.More()) {
1399       break;
1400     }
1401   }
1402
1403   if (!exp.More()) {
1404     LocOpe_FindEdgesInFace FEIF;
1405     for (exp.Init(S,TopAbs_FACE);exp.More();exp.Next()) {
1406       const TopoDS_Face& fac = TopoDS::Face(exp.Current());
1407       Handle(Geom_Surface) Su = BRep_Tool::Surface(fac);
1408       if (Su->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
1409         Su = Handle(Geom_RectangularTrimmedSurface)::
1410           DownCast(Su)->BasisSurface();
1411       }
1412       if (Su->DynamicType() == STANDARD_TYPE(Geom_Plane)) {
1413         gp_Pln pl = Handle(Geom_Plane)::DownCast(Su)->Pln();
1414         if (pl.Axis().IsParallel(theAxis,Precision::Angular())) {
1415           FEIF.Set(ToRotate,fac);
1416           for (FEIF.Init();FEIF.More();FEIF.Next()) {
1417             theRFace.Add(FEIF.Edge(),fac);
1418           }
1419         }
1420       }
1421       else if (Su->DynamicType() == STANDARD_TYPE(Geom_CylindricalSurface)) {
1422         gp_Cylinder cy = 
1423           Handle(Geom_CylindricalSurface)::DownCast(Su)->Cylinder();
1424         if (cy.Axis().IsCoaxial(theAxis,
1425                                 Precision::Angular(),Precision::Confusion())) {
1426           FEIF.Set(ToRotate,fac);
1427           for (FEIF.Init();FEIF.More();FEIF.Next()) {
1428             theRFace.Add(FEIF.Edge(),fac);
1429           }
1430         }
1431       }
1432     }
1433   }
1434
1435   if (borne == 11) {
1436     if (FUntil.IsNull()) {
1437       theRFace.Perform(Angle);
1438     }
1439     else {
1440       theRFace.Perform(FUntil);
1441     }
1442   }
1443   else { // borne == 12
1444     theRFace.Perform(FFrom,FUntil);
1445   }
1446
1447   if (!theRFace.IsDone()) {
1448     theCommands << "Local operation not done";
1449     return 1;
1450   }
1451
1452   DBRep::Set(a[2],theRFace);
1453   dout.Flush();
1454   return 0;
1455 }
1456
1457
1458 //=======================================================================
1459 //function : GLU
1460 //purpose  : Commande glue
1461 //=======================================================================
1462
1463 static Standard_Integer GLU(Draw_Interpretor& ,
1464                             Standard_Integer narg, const char** a)
1465 {
1466   if (narg<6 || narg%2 != 0) return 1;
1467   TopoDS_Shape Sne = DBRep::Get(a[2]);
1468   TopoDS_Shape Sba = DBRep::Get(a[3]);
1469   
1470   Standard_Boolean pick;
1471   
1472   BRepFeat_Gluer theGl(Sne,Sba);
1473   TopoDS_Shape Fne,Fba;
1474   
1475   LocOpe_FindEdges fined;
1476
1477   Standard_Integer i = 4;
1478   Standard_Boolean first = Standard_True;
1479   while (i<narg) {
1480     pick = (a[i][0] == '.');
1481     Fne = DBRep::Get(a[i]);
1482     if (Fne.IsNull()) {
1483       return 1;
1484     }
1485     TopAbs_ShapeEnum sht = Fne.ShapeType();
1486     if (pick && sht != TopAbs_FACE && sht != TopAbs_EDGE) {
1487       Standard_Real u,v;
1488       DBRep_DrawableShape::LastPick(Fne,u,v);
1489       sht = Fne.ShapeType();
1490     }
1491     if (first && sht != TopAbs_FACE) {
1492       return 1;
1493     }
1494     first = Standard_False;
1495     pick = (a[i+1][0] == '.');
1496     Fba = DBRep::Get(a[i+1]);
1497     if (Fba.IsNull()) {
1498       return 1;
1499     }
1500     if (pick && Fba.ShapeType() != sht) {
1501       Standard_Real u,v;
1502       DBRep_DrawableShape::LastPick(Fba,u,v);
1503     }
1504     if (Fba.ShapeType() != sht) {
1505       return 1;
1506     }
1507     if (sht == TopAbs_FACE) {
1508       const TopoDS_Face& f1 = TopoDS::Face(Fne);
1509       const TopoDS_Face& f2 = TopoDS::Face(Fba);
1510       theGl.Bind(f1,f2);
1511       fined.Set(Fne,Fba);
1512       for (fined.InitIterator(); fined.More(); fined.Next()) {
1513         theGl.Bind(fined.EdgeFrom(),fined.EdgeTo());
1514       }
1515     }
1516     else {
1517       theGl.Bind(TopoDS::Edge(Fne),TopoDS::Edge(Fba));
1518     }
1519     i +=2;
1520   }
1521   
1522   DBRep::Set(a[1],theGl);
1523   dout.Flush();
1524   return 0;
1525 }
1526
1527 static Standard_Integer DEFIN(Draw_Interpretor& theCommands,
1528                               Standard_Integer narg, const char** a)
1529 {
1530
1531   if (strcasecmp(a[0],"FEATPRISM") &&
1532       strcasecmp(a[0],"FEATDPRISM") &&
1533       strcasecmp(a[0],"FEATREVOL") &&
1534       strcasecmp(a[0],"FEATPIPE") &&
1535       strcasecmp(a[0],"FEATLF")  &&
1536       strcasecmp(a[0],"FEATRF")) {
1537     return 1;
1538   }
1539
1540   if ((!strcasecmp(a[0],"FEATPRISM") && narg !=9) ||
1541       (!strcasecmp(a[0],"FEATREVOL") && narg != 12) ||
1542       (!strcasecmp(a[0],"FEATDPRISM") && narg != 7) ||
1543       (!strcasecmp(a[0],"FEATPIPE") && narg != 7) ||
1544       (!strcasecmp(a[0],"FEATLF") && narg != 12) ||
1545       (!strcasecmp(a[0],"FEATRF") && narg != 14)) {
1546     theCommands << "invalid number of arguments";
1547     return 1;
1548   }
1549
1550   TopoDS_Shape Sbase = DBRep::Get(a[1]);
1551   if (Sbase.IsNull()) {
1552     theCommands << "null basis shape";
1553     return 1;
1554   }
1555   Standard_Integer Ifuse  = Draw::Atoi(a[narg-2]);
1556   Standard_Integer Imodif = Draw::Atoi(a[narg-1]);
1557   
1558   Standard_Integer Fuse = Ifuse;
1559   Standard_Boolean Modify = (Imodif!=0);
1560
1561   TopoDS_Shape Pbase;
1562   TopoDS_Face Skface;
1563   TopoDS_Wire W;
1564
1565   Handle(Geom_Plane) P;
1566
1567   BRepFeat_StatusError se;
1568
1569   if (strcasecmp(a[0],"FEATLF") && strcasecmp(a[0],"FEATRF")) {
1570     Pbase = DBRep::Get(a[2]);
1571     if (Pbase.IsNull()) {
1572       theCommands << "null shape to transform";
1573       return 1;
1574     }
1575     TopoDS_Shape aLocalShape(DBRep::Get(a[3],TopAbs_FACE));
1576     Skface = TopoDS::Face(aLocalShape);
1577 //    Skface = TopoDS::Face(DBRep::Get(a[3],TopAbs_FACE));
1578     if (Skface.IsNull()) {
1579       theCommands << "null face of Sketch";
1580       return 1;
1581     }
1582   }
1583   else {
1584     TopoDS_Shape aLocalShape(DBRep::Get(a[2], TopAbs_WIRE));
1585     W = TopoDS::Wire(aLocalShape);
1586 //    W = TopoDS::Wire(DBRep::Get(a[2], TopAbs_WIRE));
1587     if(W.IsNull()) {
1588       theCommands << "null profile for rib or slot";
1589       return 1;
1590     }
1591     Handle(Geom_Surface) s = DrawTrSurf::GetSurface(a[3]);
1592     P = Handle(Geom_Plane)::DownCast(s);
1593     if(P.IsNull()) {
1594       theCommands << "null plane to transform";
1595       return 1;
1596     }
1597   }
1598   if (narg == 9 || narg == 12 || narg == 14) {
1599 //    Standard_Real X,Y,Z,X1,Y1,Z1;
1600     Standard_Real X,Y,Z;
1601     X = Draw::Atof(a[4]);
1602     Y = Draw::Atof(a[5]);
1603     Z = Draw::Atof(a[6]);
1604     
1605     if (narg == 9) { // prism
1606       prdef = Standard_True;      
1607       thePrism.Init(Sbase,Pbase,Skface,gp_Dir(X,Y,Z),Fuse,Modify);
1608     }
1609     else if(narg == 14) {
1610       rfdef = Standard_True;
1611       gp_Pnt Or(X, Y, Z);
1612       X = Draw::Atof(a[7]);
1613       Y = Draw::Atof(a[8]);
1614       Z = Draw::Atof(a[9]);
1615       Standard_Real H1 = Draw::Atof(a[10]);
1616       Standard_Real H2 = Draw::Atof(a[11]);
1617       gp_Ax1 ax1(Or, gp_Dir(X, Y, Z));
1618       theRF.Init(Sbase, W, P, ax1, H1, H2, Fuse, Modify);
1619       if (!theRF.IsDone()) {
1620         se = theRF.CurrentStatusError();
1621         //BRepFeat::Print(se,cout) << endl;
1622         Standard_SStream aSStream;
1623         BRepFeat::Print(se,aSStream);
1624         theCommands << aSStream << "\n";
1625         return 1;
1626       }
1627     }
1628     else if(narg == 12 && strcasecmp(a[0],"FEATLF")) {
1629       rvdef = Standard_True;
1630       gp_Pnt Or(X,Y,Z);
1631       X = Draw::Atof(a[7]);
1632       Y = Draw::Atof(a[8]);
1633       Z = Draw::Atof(a[9]);
1634       theRevol.Init(Sbase,Pbase,Skface,gp_Ax1(Or,gp_Dir(X,Y,Z)),
1635                     Fuse,Modify);
1636     }
1637     else {
1638       lfdef = Standard_True;
1639       gp_Vec Direct(X,Y,Z);
1640       X = Draw::Atof(a[7]);
1641       Y = Draw::Atof(a[8]);
1642       Z = Draw::Atof(a[9]);
1643       theLF.Init(Sbase, W, P, Direct, gp_Vec(X,Y,Z), Fuse,Modify);
1644       if (!theLF.IsDone()) {
1645         se = theLF.CurrentStatusError();
1646         //BRepFeat::Print(se,cout) << endl;
1647         Standard_SStream aSStream;
1648         BRepFeat::Print(se,aSStream);
1649         theCommands << aSStream << "\n";
1650         return 1;
1651       }
1652     }
1653   }
1654   else if (narg == 7) {
1655     if (!strcasecmp(a[0],"FEATDPRISM")) {
1656       if (Pbase.ShapeType() != TopAbs_FACE) {
1657         theCommands << "Invalid DPrism base";
1658         return 1;
1659       }
1660       Standard_Real Angle = Draw::Atof(a[4])*M_PI/360; 
1661       dprdef = Standard_True;
1662       theDPrism.Init(Sbase,TopoDS::Face(Pbase),Skface,Angle,Fuse,Modify);
1663     }
1664     else { // FEATPIPE
1665       TopoDS_Shape aLocalShape(DBRep::Get(a[4],TopAbs_WIRE));
1666       TopoDS_Wire Spine = TopoDS::Wire(aLocalShape);
1667 //      TopoDS_Wire Spine = TopoDS::Wire(DBRep::Get(a[4],TopAbs_WIRE));
1668       if (Spine.IsNull()) {
1669         TopoDS_Shape Edspine =DBRep::Get(a[4],TopAbs_EDGE);
1670         if (Edspine.IsNull()) {
1671           theCommands << "null spine";
1672           return 1;
1673         }
1674         BRep_Builder B;
1675         B.MakeWire(Spine);
1676         B.Add(Spine,Edspine);
1677       }
1678       pidef = Standard_True;
1679       thePipe.Init(Sbase,Pbase,Skface,Spine,Fuse,Modify);
1680     }
1681   }
1682   return 0;
1683 }
1684
1685
1686
1687 static Standard_Integer ADD(Draw_Interpretor& ,
1688                             Standard_Integer narg, const char** a)
1689 {
1690   Standard_Integer i ;
1691   if (narg < 4 || narg%2 != 0) {
1692     return 1;
1693   }
1694   if (!strcasecmp("PRISM",a[1])) {
1695     if (!prdef) {
1696       return 1;
1697     }
1698     for ( i=2; i<narg; i+=2) {
1699       TopoDS_Shape aLocalShape(DBRep::Get(a[i],TopAbs_EDGE));
1700       TopoDS_Edge edg = TopoDS::Edge(aLocalShape);
1701 //      TopoDS_Edge edg = TopoDS::Edge(DBRep::Get(a[i],TopAbs_EDGE));
1702       if (edg.IsNull()) {
1703         return 1;
1704       }
1705       aLocalShape = DBRep::Get(a[i+1],TopAbs_FACE);
1706       TopoDS_Face fac = TopoDS::Face(aLocalShape);
1707 //      TopoDS_Face fac = TopoDS::Face(DBRep::Get(a[i+1],TopAbs_FACE));
1708       if (fac.IsNull()) {
1709         return 1;
1710       }
1711       thePrism.Add(edg,fac);
1712     }
1713   }
1714   else if (!strcasecmp("REVOL",a[1])) {
1715     if (!rvdef) {
1716       return 1;
1717     }
1718     for ( i=2; i<narg; i+=2) {
1719       TopoDS_Shape aLocalShape(DBRep::Get(a[i],TopAbs_EDGE));
1720       TopoDS_Edge edg = TopoDS::Edge(aLocalShape);
1721 //      TopoDS_Edge edg = TopoDS::Edge(DBRep::Get(a[i],TopAbs_EDGE));
1722       if (edg.IsNull()) {
1723         return 1;
1724       }
1725       aLocalShape = DBRep::Get(a[i+1],TopAbs_FACE);
1726       TopoDS_Face fac = TopoDS::Face(aLocalShape);
1727 //      TopoDS_Face fac = TopoDS::Face(DBRep::Get(a[i+1],TopAbs_FACE));
1728       if (fac.IsNull()) {
1729         return 1;
1730       }
1731       theRevol.Add(edg,fac);
1732     }
1733   }
1734   else if (!strcasecmp("PIPE",a[1])) {
1735     if (!pidef) {
1736       return 1;
1737     }
1738     for ( i=2; i<narg; i+=2) {
1739       TopoDS_Shape aLocalShape(DBRep::Get(a[i],TopAbs_EDGE));
1740       TopoDS_Edge edg = TopoDS::Edge(aLocalShape);
1741 //      TopoDS_Edge edg = TopoDS::Edge(DBRep::Get(a[i],TopAbs_EDGE));
1742       if (edg.IsNull()) {
1743         return 1;
1744       }
1745       aLocalShape = DBRep::Get(a[i+1],TopAbs_FACE);
1746       TopoDS_Face fac = TopoDS::Face(aLocalShape);
1747 //      TopoDS_Face fac = TopoDS::Face(DBRep::Get(a[i+1],TopAbs_FACE));
1748       if (fac.IsNull()) {
1749         return 1;
1750       }
1751       thePipe.Add(edg,fac);
1752     }
1753   }
1754   else {
1755     return 1;
1756   }
1757   return 0;
1758 }
1759
1760
1761
1762 static Standard_Integer PERF(Draw_Interpretor& theCommands,
1763                             Standard_Integer narg, const char** a)
1764 {
1765   if (narg < 3) {
1766     return 1;
1767   }
1768   if (strcasecmp(a[0],"FEATPERFORM") &&
1769       strcasecmp(a[0],"FEATPERFORMVAL")) {
1770     return 1;
1771   }
1772
1773   Standard_Integer Kas;
1774   if (!strcasecmp("PRISM",a[1])) {
1775     Kas = 1;
1776     if (!prdef) {
1777       theCommands << "prism not defined";
1778       return 1;
1779     }
1780   }
1781   else if (!strcasecmp("REVOL",a[1])) {
1782     Kas = 2;
1783     if (!rvdef) {
1784       theCommands << "revol not defined";
1785       return 1;
1786     }
1787   }
1788   else if (!strcasecmp("PIPE",a[1])) {
1789     Kas = 3;
1790     if (!pidef) {
1791       theCommands << "pipe not defined";
1792       return 1;
1793     }
1794     if (!strcasecmp(a[0],"FEATPERFORMVAL")) {
1795       theCommands << "invalid command for pipe";
1796       return 1;
1797     }
1798   }
1799   else if (!strcasecmp("DPRISM",a[1])) {
1800     Kas = 4;
1801     if (!dprdef) {
1802       theCommands << "dprism not defined";
1803       return 1;
1804     }
1805   }
1806   else if (!strcasecmp("LF",a[1])) {
1807     Kas = 5;
1808     if (!lfdef) {
1809       theCommands << "lf not defined";
1810       return 1;
1811     }
1812     if (!strcasecmp(a[0],"FEATPERFORMVAL")) {
1813       theCommands << "invalid command for lf";
1814       return 1;
1815     }
1816   }
1817   else if (!strcasecmp("RF",a[1])) {
1818     Kas = 6;
1819     if (!rfdef) {
1820       theCommands << "rf not defined";
1821       return 1;
1822     }
1823     if (!strcasecmp(a[0],"FEATPERFORMVAL")) {
1824       theCommands << "invalid command for rf";
1825       return 1;
1826     }
1827   }
1828   else {
1829     theCommands << "unknown argument : " << a[1];
1830     return 1;
1831   }
1832
1833   if (!strcasecmp(a[0],"FEATPERFORMVAL")) {
1834     if (narg !=4 && narg != 5) {
1835       theCommands << "invalid number of arguments";
1836       return 1;
1837     }
1838     if (narg == 4) {
1839       Standard_Real Val = Draw::Atof(a[3]);
1840       if (Kas == 1) {
1841         thePrism.Perform(Val);
1842       }
1843       else if (Kas == 2) {
1844         Val *=(M_PI/180.);
1845         theRevol.Perform(Val);
1846       }
1847       else if (Kas == 4) {
1848         theDPrism.Perform(Val);
1849       }
1850       else if (Kas == 5) {
1851         theCommands << "invalid command for lf";
1852         return 1;
1853       }
1854       else if (Kas == 6) {
1855         theCommands << "invalid command for rf";
1856         return 1;
1857       }
1858     }
1859     else if(narg == 5) {
1860       Standard_Real Val = Draw::Atof(a[3]);
1861       TopoDS_Shape FUntil = DBRep::Get(a[4],TopAbs_SHAPE);
1862       if (Kas == 1) {
1863         thePrism.PerformUntilHeight(FUntil, Val);
1864       }
1865       else if (Kas == 2) {
1866         Val *=(M_PI/180.);
1867         theRevol.PerformUntilAngle(FUntil, Val);
1868       }
1869       else if (Kas == 4) {
1870         theDPrism.PerformUntilHeight(FUntil, Val);
1871       } 
1872       else {
1873         theCommands << "invalid command for ribs or slots";
1874         return 1;
1875       }
1876     }
1877   }
1878   else if (!strcasecmp(a[0],"FEATPERFORM")) {
1879     if (narg == 3) { // Thru all
1880       switch (Kas) {
1881       case 1:
1882         thePrism.PerformThruAll();
1883         break;
1884       case 2:
1885         theRevol.PerformThruAll();
1886         break;
1887       case 3:
1888         thePipe.Perform();
1889         break;
1890       case 4:
1891         theDPrism.PerformThruAll();
1892         break;
1893       case 5:
1894         theLF.Perform();
1895         break;
1896       case 6:
1897         theRF.Perform();
1898         break;
1899       default:
1900
1901         return 1;
1902       }
1903     }
1904     else if (narg == 4) { // Until
1905       TopoDS_Shape Funtil = DBRep::Get(a[3],TopAbs_SHAPE);
1906       switch (Kas) {
1907       case 1:
1908         {
1909           if (Funtil.IsNull()) {
1910             thePrism.PerformUntilEnd();
1911           }
1912           else {
1913             thePrism.Perform(Funtil);
1914           }
1915         }
1916         break;
1917       case 2:
1918         {
1919           if (!Funtil.IsNull()) {
1920             theRevol.Perform(Funtil);
1921           }
1922           else {
1923             return 1;
1924           }
1925         }
1926         break;
1927       case 3:
1928         {
1929           if (!Funtil.IsNull()) {
1930             thePipe.Perform(Funtil);
1931           }
1932           else {
1933             theCommands << "invalid command for ribs pipe";
1934             return 1;
1935           }
1936         }
1937         break;
1938       case 4:
1939         {
1940           if (!Funtil.IsNull()) {
1941             theDPrism.Perform(Funtil);
1942           }
1943           else {
1944             theDPrism.PerformUntilEnd();
1945           }
1946         }
1947         break;
1948       case 5:
1949         {  
1950           theCommands << "invalid command for lf";
1951           return 1;
1952         }
1953         break;
1954       case 6:
1955         {  
1956           theCommands << "invalid command for rf";
1957           return 1;
1958         }
1959         break;
1960       default:
1961         return 1;
1962       }
1963     }
1964     else if (narg == 5) {
1965       TopoDS_Shape Ffrom = DBRep::Get(a[3],TopAbs_SHAPE);
1966       TopoDS_Shape Funtil = DBRep::Get(a[4],TopAbs_SHAPE);
1967       if (Funtil.IsNull()) {
1968         return 1;
1969       }
1970       switch (Kas) {
1971       case 1:
1972         {
1973           if (Ffrom.IsNull()) {
1974             thePrism.PerformFromEnd(Funtil);
1975           }
1976           else {
1977             thePrism.Perform(Ffrom,Funtil);
1978           }
1979         }
1980         break;
1981       case 2:
1982         {
1983           if (Ffrom.IsNull()) {
1984             return 1;
1985           }
1986           theRevol.Perform(Ffrom,Funtil);
1987         }
1988         break;
1989       case 3:
1990         {
1991           if (Ffrom.IsNull()) {
1992             return 1;
1993           }
1994           thePipe.Perform(Ffrom,Funtil);
1995         }
1996         break;
1997       case 4:
1998         {
1999           if (Ffrom.IsNull()) {
2000             theDPrism.PerformFromEnd(Funtil);
2001           }
2002           else {
2003             theDPrism.Perform(Ffrom,Funtil);
2004           }
2005         }
2006         break;
2007
2008       default:
2009         return 1;
2010       }
2011     }
2012   }
2013
2014   BRepFeat_StatusError se;
2015   switch (Kas) {
2016   case 1:
2017     if (!thePrism.IsDone()) {
2018       se = thePrism.CurrentStatusError();
2019       //BRepFeat::Print(se,cout) << endl;
2020       Standard_SStream aSStream;
2021       BRepFeat::Print(se,aSStream);
2022       theCommands << aSStream << "\n";
2023       return 1;
2024     }
2025     DBRep::Set(a[2],thePrism);
2026     dout.Flush();
2027     return 0;
2028   case 2:
2029     if (!theRevol.IsDone()) {
2030       se = theRevol.CurrentStatusError();
2031       //BRepFeat::Print(se,cout) << endl;
2032       Standard_SStream aSStream;
2033       BRepFeat::Print(se,aSStream);
2034       theCommands << aSStream << "\n";
2035       return 1;
2036     }
2037     DBRep::Set(a[2],theRevol);
2038     dout.Flush();
2039     return 0;
2040   case 3:
2041     if (!thePipe.IsDone()) {
2042       se = thePipe.CurrentStatusError();
2043       //BRepFeat::Print(se,cout) << endl;
2044       Standard_SStream aSStream;
2045       BRepFeat::Print(se,aSStream);
2046       theCommands << aSStream << "\n";
2047       return 1;
2048     }
2049     DBRep::Set(a[2],thePipe);
2050     dout.Flush();
2051     return 0;
2052   case 4:
2053     if (!theDPrism.IsDone()) {
2054       se = theDPrism.CurrentStatusError();
2055       //BRepFeat::Print(se,cout) << endl;
2056       Standard_SStream aSStream;
2057       BRepFeat::Print(se,aSStream);
2058       theCommands << aSStream << "\n";
2059       return 1;
2060     }
2061     DBRep::Set(a[2],theDPrism);
2062     dout.Flush();
2063     return 0;
2064   case 5:
2065     if (!theLF.IsDone()) {
2066       se = theLF.CurrentStatusError();
2067       //BRepFeat::Print(se,cout) << endl;
2068       Standard_SStream aSStream;
2069       BRepFeat::Print(se,aSStream);
2070       theCommands << aSStream << "\n";
2071       return 1;
2072     }
2073     DBRep::Set(a[2],theLF);
2074     dout.Flush();
2075     return 0;
2076   case 6:
2077     if (!theRF.IsDone()) {
2078       se = theRF.CurrentStatusError();
2079       //BRepFeat::Print(se,cout) << endl;
2080       Standard_SStream aSStream;
2081       BRepFeat::Print(se,aSStream);
2082       theCommands << aSStream << "\n";
2083       return 1;
2084     }
2085     DBRep::Set(a[2],theRF);
2086     dout.Flush();
2087     return 0;
2088   default:
2089     return 1;
2090   }
2091 }
2092
2093
2094 static Standard_Integer BOSS(Draw_Interpretor& theCommands,
2095                              Standard_Integer narg, const char** a)
2096 {
2097   if (strcasecmp(a[0],"ENDEDGES") && strcasecmp(a[0],"FILLET")
2098       && strcasecmp(a[0],"BOSSAGE")) {
2099     return 1;
2100   }
2101
2102   if ((!strcasecmp(a[0],"ENDEDGES") && narg !=5) ||
2103       (!strcasecmp(a[0],"FILLET") && narg <5 &&  narg%2 != 1) ||
2104       (!strcasecmp(a[0],"BOSSAGE") && narg != 6)) {
2105     theCommands << "invalid number of arguments";
2106     return 1;
2107   }
2108
2109   Standard_Integer Kas=0;
2110   Standard_Integer dprsig=0;
2111   if (!strcasecmp("ENDEDGES",a[0])) {
2112     Kas = 1;
2113     dprsig = Draw::Atoi(a[4]);
2114   }
2115   else if (!strcasecmp("FILLET",a[0])) {
2116     Kas = 2;
2117   }
2118   else if (!strcasecmp("BOSSAGE",a[0])) {
2119     Kas = 3;
2120     dprsig = Draw::Atoi(a[5]);
2121   }
2122  
2123   TopoDS_Shape theShapeTop; 
2124   TopoDS_Shape theShapeBottom;
2125
2126   if (Kas == 1 || Kas == 3) {
2127     if (!strcasecmp("DPRISM",a[1])) {
2128       if (!dprdef) {
2129         theCommands << "dprism not defined";
2130         return 1;
2131       }
2132     }
2133     else {
2134       theCommands << "unknown argument : " << a[1];
2135       return 1;
2136     }
2137
2138     theDPrism.BossEdges(dprsig);
2139    
2140     TopTools_ListOfShape theTopEdges, theLatEdges;
2141     theTopEdges = theDPrism.TopEdges();
2142     theLatEdges = theDPrism.LatEdges();
2143
2144     TopTools_ListIteratorOfListOfShape it;
2145     BRep_Builder B;
2146
2147     B.MakeCompound(TopoDS::Compound(theShapeTop));
2148     it.Initialize(theTopEdges);
2149     for(; it.More(); it.Next()) {
2150       TopExp_Explorer exp;
2151       for (exp.Init(it.Value(),TopAbs_EDGE); exp.More(); exp.Next()) {
2152         B.Add(theShapeTop,exp.Current());
2153       }
2154     }
2155     DBRep::Set(a[2],theShapeTop);
2156     dout.Flush();
2157
2158     B.MakeCompound(TopoDS::Compound(theShapeBottom));
2159     it.Initialize(theLatEdges);
2160     for(; it.More(); it.Next()) {
2161       B.Add(theShapeBottom,it.Value());
2162     }
2163     DBRep::Set(a[3],theShapeBottom);
2164     dout.Flush();
2165     if (Kas == 1) return 0;
2166   }
2167
2168   if (Kas == 2 || Kas == 3) {
2169     
2170 //    Standard_Integer nrad;
2171     TopoDS_Shape V;
2172     if (Kas == 2) {
2173       V = DBRep::Get(a[2],TopAbs_SHAPE);
2174     }
2175     else if (Kas == 3) {
2176       V = theDPrism;
2177     }
2178
2179     if(V.IsNull()) return 1;
2180     ChFi3d_FilletShape FSh = ChFi3d_Rational;
2181     Rakk = new BRepFilletAPI_MakeFillet(V,FSh);
2182     Rakk->SetParams(ta,t3d,t2d,t3d,t2d,fl);
2183     Rakk->SetContinuity(blend_cont, tapp_angle);
2184     Standard_Real Rad;
2185     TopoDS_Shape S;
2186     TopoDS_Edge E;
2187     Standard_Integer nbedge = 0;
2188
2189     if (Kas == 2) {
2190       for (Standard_Integer ii = 1; ii < (narg-1)/2; ii++){
2191         Rad = Draw::Atof(a[2*ii + 1]);
2192         if (Rad == 0.) continue;
2193         S = DBRep::Get(a[(2*ii+2)],TopAbs_SHAPE);
2194         TopExp_Explorer exp;
2195         for (exp.Init(S,TopAbs_EDGE); exp.More(); exp.Next()) {
2196           E = TopoDS::Edge(exp.Current());
2197           if(!E.IsNull()){
2198             Rakk->Add(Rad,E);
2199             nbedge++;
2200           }
2201         }
2202       }
2203     }
2204     else if (Kas == 3) {
2205       Rad = Draw::Atof(a[3]);
2206       if (Rad != 0.) {
2207         S = theShapeTop;
2208         TopExp_Explorer exp;
2209         for (exp.Init(S,TopAbs_EDGE); exp.More(); exp.Next()) {
2210           E = TopoDS::Edge(exp.Current());
2211           if(!E.IsNull()){
2212             Rakk->Add(Rad,E);
2213             nbedge++;
2214           }
2215         } 
2216       }
2217       Rad = Draw::Atof(a[4]);
2218       if (Rad != 0.) {
2219         S = theShapeBottom;
2220         TopExp_Explorer exp;
2221         for (exp.Init(S,TopAbs_EDGE); exp.More(); exp.Next()) {
2222           E = TopoDS::Edge(exp.Current());
2223           if(!E.IsNull()){
2224             Rakk->Add(Rad,E);
2225             nbedge++;
2226           }
2227         } 
2228       }
2229     }
2230     
2231     if(!nbedge) return 1;
2232     Rakk->Build();
2233     if(!Rakk->IsDone()) return 1;
2234     TopoDS_Shape res = Rakk->Shape();
2235
2236     if (Kas == 2) {
2237       DBRep::Set(a[1],res);
2238     } 
2239     else if (Kas == 3) {
2240       DBRep::Set(a[2],res);
2241     }
2242     dout.Flush();
2243     return 0;
2244   }
2245
2246   return 1;
2247 }
2248
2249
2250 //=======================================================================
2251 //function : FeatureCommands
2252 //purpose  : 
2253 //=======================================================================
2254
2255 void BRepTest::FeatureCommands (Draw_Interpretor& theCommands)
2256 {
2257   static Standard_Boolean done = Standard_False;
2258   if (done) return;
2259   done = Standard_True;
2260
2261   DBRep::BasicCommands(theCommands);
2262
2263   const char* g = "TOPOLOGY Feature commands";
2264
2265   theCommands.Add("localope", 
2266                   " Performs a local top. operation : localope result shape tool F/C (fuse/cut) face [face...]",
2267                   __FILE__,Loc,g);
2268
2269   theCommands.Add("hole",
2270                   " Performs a hole : hole result shape Or.X Or.Y Or.Z Dir.X Dir.Y Dir.Z Radius [Pfrom Pto]",
2271                   __FILE__,HOLE1,g);
2272
2273   theCommands.Add("firsthole",
2274                   " Performs the first hole : firsthole result shape Or.X Or.Y Or.Z Dir.X Dir.Y Dir.Z Radius",
2275                   __FILE__,HOLE2,g);
2276
2277   theCommands.Add("holend",
2278                   " Performs the hole til end : holend result shape Or.X Or.Y Or.Z Dir.X Dir.Y Dir.Z Radius",
2279                   __FILE__,HOLE3,g);
2280
2281   theCommands.Add("blindhole", 
2282                   " Performs the blind hole : blindhole result shape Or.X Or.Y Or.Z Dir.X Dir.Y Dir.Z Radius Length",
2283                   __FILE__,HOLE4,g);
2284
2285   theCommands.Add("holecontrol",
2286                   "Sets/Unsets or display controls on holes : holecontrol [0/1]",
2287                   __FILE__,CONTROL,g);
2288
2289   theCommands.Add("wprism",
2290                   "Prisms wires on a face : wprism f[use]/c[ut] result shape [[FaceFrom] FaceUntil] VecX VecY VecZ  SkecthFace wire1 [wire2 ....]",
2291                   __FILE__,PRW,g);
2292
2293
2294   theCommands.Add("fprism", 
2295                   "Prisms a set of faces of a shape : fprism f[use]/c[ut] result shape [[FaceFrom] FaceUntil] VecX VecY VecZ face1 [face2...]",
2296                   __FILE__,PRF,g);
2297
2298
2299   theCommands.Add("wrotate",
2300                   "Rotates wires on a face : wrotate f[use]/c[ut] result shape Angle/[FFrom] FUntil OX OY OZ DX DY DZ SkecthFace wire1 [wire2 ....]",
2301                   __FILE__,ROW,g);
2302
2303
2304   theCommands.Add("frotate", 
2305                   "Rotates a set of faces of a shape : frotate f[use]/c[ut] result shape Angle/[FaceFrom] FaceUntil OX OY OZ DX DY DZ face1 [face2...]",
2306                   __FILE__,ROF,g);
2307
2308
2309   theCommands.Add("splitshape",
2310                   "splitshape result shape face wire/edge/compound [wire/edge/compound ...][face wire/edge/compound [wire/edge/compound...] ...] [@ edgeonshape edgeonwire [edgeonshape edgeonwire...]]",
2311                   __FILE__,SPLS,g);
2312
2313
2314   theCommands.Add("thickshell",
2315                   "thickshell r shape offset [jointype [tol] ]",
2316                   __FILE__,thickshell,g);
2317   
2318   theCommands.Add("offsetshape",
2319                   "offsetshape r shape offset [tol] [face ...]",
2320                   __FILE__,offsetshape,g);
2321   
2322   theCommands.Add("offsetcompshape",
2323                   "offsetcompshape r shape offset [face ...]",
2324                   __FILE__,offsetshape,g);
2325
2326   theCommands.Add("offsetparameter",
2327                   "offsetparameter tol inter(a/i) join(a/i)",
2328                   __FILE__,offsetparameter);
2329
2330   theCommands.Add("offsetload",
2331                   "offsetload shape offset bouchon1 bouchon2 ...",
2332                   __FILE__,offsetload,g);
2333
2334   theCommands.Add("offsetonface",
2335                   "offsetonface face1 offset1 face2 offset2 ...",
2336                   __FILE__,offsetonface,g);
2337
2338   theCommands.Add("offsetperform",
2339                   "offsetperform result",
2340                   __FILE__,offsetperform,g);
2341
2342
2343   theCommands.Add("deboucle", 
2344                   " Essai de debouclage partiel: deboucle result shape F/C face [face...] @ face [face...]",
2345                   __FILE__,Debou,g);
2346
2347
2348   theCommands.Add("glue", 
2349                   "glue result shapenew shapebase facenew facebase [facenew facebase...] [edgenew edgebase [edgenew edgebase...]]",
2350                   __FILE__,GLU,g);
2351
2352
2353   theCommands.Add("featprism", 
2354                   "Defines the arguments for a prism : featprism shape element skface  Dirx Diry Dirz Fuse(0/1/2) Modify(0/1)",
2355                   __FILE__,DEFIN);
2356
2357   theCommands.Add("featrevol", 
2358                   "Defines the arguments for a revol : featrevol shape element skface  Ox Oy Oz Dx Dy Dz Fuse(0/1/2) Modify(0/1)",
2359                   __FILE__,DEFIN);
2360
2361   theCommands.Add("featpipe", 
2362                   "Defines the arguments for a pipe : featpipe shape element skface  spine Fuse(0/1/2) Modify(0/1)",
2363                   __FILE__,DEFIN);
2364
2365   theCommands.Add("featdprism", 
2366                   "Defines the arguments for a drafted prism : featdprism shape face skface angle Fuse(0/1/2) Modify(0/1)",
2367                   __FILE__,DEFIN);
2368
2369   theCommands.Add("featlf", 
2370                   "Defines the arguments for a linear rib or slot : featlf shape wire plane DirX DirY DirZ DirX DirY DirZ Fuse(0/1/2) Modify(0/1)",
2371                   __FILE__,DEFIN);
2372
2373   theCommands.Add("featrf", 
2374                   "Defines the arguments for a rib or slot of revolution : featrf shape wire plane X Y Z DirX DirY DirZ Size Size Fuse(0/1/2) Modify(0/1)",
2375                   __FILE__,DEFIN);
2376
2377   theCommands.Add("addslide", 
2378                   " Adds sliding elements : addslide prism/revol/pipe edge face [edge face...]",
2379                   __FILE__,ADD);
2380
2381   theCommands.Add("featperform", 
2382                   " Performs the prism revol dprism linform or pipe :featperform prism/revol/pipe/dprism/lf result [[Ffrom] Funtil]",
2383                   __FILE__,PERF);
2384
2385   theCommands.Add("featperformval", 
2386                   " Performs the prism revol dprism or linform with a value :featperformval prism/revol/dprism/lf result value",
2387                   __FILE__,PERF);
2388
2389   theCommands.Add("endedges", 
2390                   " Return top and bottom edges of dprism :endedges dprism shapetop shapebottom First/LastShape (1/2)",
2391                   __FILE__,BOSS);
2392
2393   theCommands.Add("fillet", 
2394                   " Perform fillet on compounds of edges :fillet result object rad1 comp1 rad2 comp2 ...",
2395                   __FILE__,BOSS);
2396
2397   theCommands.Add("bossage", 
2398                   " Perform fillet on top and bottom edges of dprism :bossage dprism result radtop radbottom First/LastShape (1/2)",
2399                   __FILE__,BOSS);
2400
2401 }