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