0028661: BRepOffsetAPI_MakePipeShell throws an exception Standard_NoSuchObject: NColl...
[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 <BRepOffset_MakeOffset.hxx>
58 #include <BRepOffset_MakeSimpleOffset.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]) != 0;
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)
738   {
739     cout << "Invalid number of arguments. Should be : splitshape result shape [splitedges] \
740             [face wire/edge/compound [wire/edge/compound ...] \
741             [face wire/edge/compound [wire/edge/compound...] ...] \
742             [@ edgeonshape edgeonwire [edgeonshape edgeonwire...]]" << endl;
743     return 1;
744   }
745   TopoDS_Shape S = DBRep::Get(a[2]);
746   if (S.IsNull())
747   {
748     cout << "Invalid input shape " << a[2]<<endl;
749     return 1;
750   }
751   BRepFeat_SplitShape Spls(S);
752   Standard_Boolean pick = Standard_False;
753   TopoDS_Shape EF;
754   Standard_Real u,v;
755   Standard_Integer i = 3;
756
757   for ( newnarg=3; newnarg<narg; newnarg++) {
758     if (a[newnarg][0] == '@') {
759       break;
760     }
761   }
762
763   if (newnarg == 3 || 
764       (newnarg !=narg && ((narg-newnarg)<=2 || (narg-newnarg)%2 != 1))) {
765     return 1;
766   }
767   Standard_Boolean isSplittingEdges = Standard_False;
768   TopTools_SequenceOfShape aSplitEdges;
769   if (i < newnarg) {
770     pick = (a[i][0] == '.');
771    
772     TopoDS_Shape aSh = DBRep::Get(a[i]);
773     if (aSh.IsNull())
774     {
775       cout << "Invalid input shape " <<a[i]<<endl;
776       return 1;
777     }
778
779
780     if (aSh.ShapeType() == TopAbs_FACE)
781       EF = TopoDS::Face(aSh);
782     else
783     {
784       if (aSh.ShapeType() == TopAbs_COMPOUND || aSh.ShapeType() == TopAbs_WIRE || aSh.ShapeType() == TopAbs_EDGE)
785       {
786         TopExp_Explorer aExpE(aSh, TopAbs_EDGE, TopAbs_FACE);
787         for (; aExpE.More(); aExpE.Next())
788           aSplitEdges.Append(aExpE.Current());
789
790         isSplittingEdges = !aSplitEdges.IsEmpty();
791       }
792     }
793
794   }
795   i++;
796   while (i < newnarg) {
797     if (pick) {
798       DBRep_DrawableShape::LastPick(EF,u,v);
799     }
800     if (!isSplittingEdges  && !EF.IsNull() && EF.ShapeType() == TopAbs_FACE) {
801       // face wire/edge ...
802      
803       while (i < newnarg) {
804         TopoDS_Shape W;
805         Standard_Boolean rever = Standard_False;
806         if (a[i][0] == '-') {
807           if (a[i][1] == '\0')
808             return 1;
809           pick = (a[i][1] == '.');
810           const char* Temp = a[i]+1;
811           W = DBRep::Get(Temp,TopAbs_SHAPE,Standard_False);
812           rever = Standard_True;
813         }
814         else {
815           pick = (a[i][0] == '.');
816           W = DBRep::Get(a[i],TopAbs_SHAPE,Standard_False);
817         }
818         if (W.IsNull()) {
819           return 1; // on n`a rien recupere
820         }
821         TopAbs_ShapeEnum wtyp = W.ShapeType();
822         if (wtyp != TopAbs_WIRE && wtyp != TopAbs_EDGE && wtyp != TopAbs_COMPOUND && pick) {
823           DBRep_DrawableShape::LastPick(W,u,v);
824           wtyp = W.ShapeType();
825         }
826         if (wtyp != TopAbs_WIRE && wtyp != TopAbs_EDGE && wtyp != TopAbs_COMPOUND) {
827           EF = DBRep::Get(a[i]);
828           break;
829         }
830         else {
831           if (rever) {
832             W.Reverse();
833           }
834           if (wtyp == TopAbs_WIRE) {
835             Spls.Add(TopoDS::Wire(W),TopoDS::Face(EF));
836           }
837           else if (wtyp == TopAbs_EDGE) {
838             Spls.Add(TopoDS::Edge(W),TopoDS::Face(EF));
839           }
840           else {
841             Spls.Add(TopoDS::Compound(W),TopoDS::Face(EF));
842           }
843         }
844         i++;
845       }
846     }
847     else
848     {
849       if (isSplittingEdges)
850       {
851         TopoDS_Shape aSh = DBRep::Get(a[i]);
852         if (aSh.IsNull())
853         {
854           cout << "Invalid input shape " <<a[i]<< endl;
855           return 1;
856         }
857         TopExp_Explorer aExpE(aSh, TopAbs_EDGE, TopAbs_FACE);
858         for (; aExpE.More(); aExpE.Next())
859           aSplitEdges.Append(aExpE.Current());
860       }
861       else
862       {
863          cout << "Invalid input arguments. Should be : splitshape result shape [splitedges] \
864             [face wire/edge/compound [wire/edge/compound ...] \
865             [face wire/edge/compound [wire/edge/compound...] ...] \
866             [@ edgeonshape edgeonwire [edgeonshape edgeonwire...]]"<<endl;
867         return 1;
868       }
869     }
870     i++;
871   }
872   
873   if (isSplittingEdges)
874     Spls.Add(aSplitEdges);
875
876   // ici, i vaut newnarg
877   for (; i < narg; i += 2) {
878     TopoDS_Shape Ew,Es;
879     TopoDS_Shape aLocalShape(DBRep::Get(a[i],TopAbs_EDGE));
880     Es = TopoDS::Edge(aLocalShape);
881 //    Es = TopoDS::Edge(DBRep::Get(a[i],TopAbs_EDGE));
882     if (Es.IsNull()) {
883       return 1;
884     }
885     aLocalShape = DBRep::Get(a[i+1],TopAbs_EDGE);
886     Ew = TopoDS::Edge(aLocalShape);
887 //    Ew = TopoDS::Edge(DBRep::Get(a[i+1],TopAbs_EDGE));
888     if (Ew.IsNull()) {
889       cout << "Invalid input shape " <<a[i+1]<< endl;
890       return 1;
891     }
892     Spls.Add(TopoDS::Edge(Ew),TopoDS::Edge(Es));
893   }
894
895
896   DBRep::Set(a[1],Spls);
897   return 0;
898 }
899
900 //=======================================================================
901 //function : thickshell
902 //purpose  : 
903 //=======================================================================
904 Standard_Integer thickshell(Draw_Interpretor& theCommands,
905   Standard_Integer n, const char** a)
906 {
907   if ( n < 4) return 1;
908   TopoDS_Shape  S  = DBRep::Get(a[2]);
909   if (S.IsNull()) return 1;
910
911   Standard_Real    Of    = Draw::Atof(a[3]);
912
913   GeomAbs_JoinType JT= GeomAbs_Arc;
914   if (n > 4)
915   {
916     if (!strcmp(a[4],"i"))
917       JT = GeomAbs_Intersection;
918     if (!strcmp(a[4],"t"))
919       JT = GeomAbs_Tangent;
920   }
921
922   Standard_Boolean Inter = Standard_False; //Standard_True;
923   Standard_Real    Tol = Precision::Confusion();
924   if (n > 5)
925     Tol = Draw::Atof(a[5]);
926
927   BRepOffset_MakeOffset B;
928   B.Initialize(S,Of,Tol,BRepOffset_Skin,Inter,0,JT,Standard_True);
929
930   B.MakeOffsetShape();
931
932   const BRepOffset_Error aRetCode = B.Error();
933   reportOffsetState(theCommands, aRetCode);
934
935   DBRep::Set(a[1],B.Shape());
936   return 0;
937 }
938
939 //=======================================================================
940 //function : offsetshape
941 //purpose  : 
942 //=======================================================================
943
944 Standard_Integer offsetshape(Draw_Interpretor& theCommands,
945                              Standard_Integer n, const char** a)
946 {
947   if ( n < 4) return 1;
948   TopoDS_Shape  S  = DBRep::Get(a[2]);
949   if (S.IsNull()) return 1;
950
951   Standard_Real    Of    = Draw::Atof(a[3]);
952   Standard_Boolean Inter = (!strcmp(a[0],"offsetcompshape"));
953   GeomAbs_JoinType JT= GeomAbs_Arc;
954   if (!strcmp(a[0],"offsetinter"))
955   {
956     JT    = GeomAbs_Intersection;
957     Inter = Standard_True;
958   }
959   
960   BRepOffset_MakeOffset B;
961   Standard_Integer      IB  = 4;
962   Standard_Real         Tol = Precision::Confusion();
963   if (n > 4)
964   {
965     TopoDS_Shape  SF  = DBRep::Get(a[4],TopAbs_FACE);
966     if (SF.IsNull())
967     {
968       IB  = 5;
969       Tol = Draw::Atof(a[4]);
970     }
971   }
972   B.Initialize(S,Of,Tol,BRepOffset_Skin,Inter,0,JT);
973   //------------------------------------------
974   // recuperation et chargement des bouchons.
975   //----------------------------------------
976   Standard_Boolean YaBouchon = Standard_False;
977
978   for (Standard_Integer i = IB ; i < n; i++)
979   {
980     TopoDS_Shape  SF  = DBRep::Get(a[i],TopAbs_FACE);
981     if (!SF.IsNull())
982     {
983       YaBouchon = Standard_True;
984       B.AddFace(TopoDS::Face(SF));
985     }
986   }
987
988   if (!YaBouchon)  B.MakeOffsetShape();
989   else             B.MakeThickSolid ();
990
991   const BRepOffset_Error aRetCode = B.Error();
992   reportOffsetState(theCommands, aRetCode);
993
994   DBRep::Set(a[1],B.Shape());
995
996   return 0;
997 }
998
999 static BRepOffset_MakeOffset TheOffset;
1000 static Standard_Real         TheRadius;
1001 static Standard_Boolean      theYaBouchon;
1002 static Standard_Real         TheTolerance = Precision::Confusion();
1003 static Standard_Boolean      TheInter     = Standard_False;
1004 static GeomAbs_JoinType      TheJoin      = GeomAbs_Arc;
1005 static Standard_Boolean      RemoveIntEdges = Standard_False;
1006
1007 Standard_Integer offsetparameter(Draw_Interpretor& di,
1008                                  Standard_Integer n, const char** a)
1009 {
1010   if ( n == 1 ) { 
1011     di << " offsetparameter Tol Inter(c/p) JoinType(a/i/t) [RemoveInternalEdges(r/k)]\n";
1012     di << " Current Values\n";
1013     di << "   --> Tolerance : " << TheTolerance << "\n";
1014     di << "   --> TheInter  : ";
1015     if ( TheInter) {
1016       di << "Complet" ;
1017     } else {
1018       di << "Partial";
1019     }
1020     di << "\n   --> TheJoin   : ";
1021     
1022     switch (TheJoin) {
1023     case GeomAbs_Arc:          di << "Arc";          break;
1024     case GeomAbs_Intersection: di << "Intersection"; break;
1025     default:
1026       break ;
1027     }
1028     //
1029     di << "\n   --> Internal Edges : ";
1030     if (RemoveIntEdges) {
1031       di << "Remove";
1032     }
1033     else {
1034       di << "Keep";
1035     }
1036     di << "\n";
1037     //
1038     return 0;
1039   }
1040
1041   if ( n < 4 ) return 1;
1042   //
1043   TheTolerance = Draw::Atof(a[1]);
1044   TheInter     = strcmp(a[2],"p") != 0;
1045   //
1046   if      ( !strcmp(a[3],"a")) TheJoin = GeomAbs_Arc;
1047   else if ( !strcmp(a[3],"i")) TheJoin = GeomAbs_Intersection;
1048   else if ( !strcmp(a[3],"t")) TheJoin = GeomAbs_Tangent;
1049   //
1050   RemoveIntEdges = (n >= 5) ? !strcmp(a[4], "r") : Standard_False;
1051   //
1052   return 0;
1053 }
1054
1055 //=======================================================================
1056 //function : offsetinit
1057 //purpose  : 
1058 //=======================================================================
1059
1060 Standard_Integer offsetload(Draw_Interpretor& ,
1061   Standard_Integer n, const char** a)
1062 {
1063   if ( n < 2) return 1;
1064   TopoDS_Shape  S  = DBRep::Get(a[1]);
1065   if (S.IsNull()) return 1;
1066
1067   Standard_Real    Of    = Draw::Atof(a[2]);
1068   TheRadius = Of;
1069 //  Standard_Boolean Inter = Standard_True;
1070   
1071   TheOffset.Initialize(S,Of,TheTolerance,BRepOffset_Skin,TheInter,0,TheJoin,
1072                        Standard_False, RemoveIntEdges);
1073   //------------------------------------------
1074   // recuperation et chargement des bouchons.
1075   //----------------------------------------
1076   for (Standard_Integer i = 3 ; i < n; i++) {
1077     TopoDS_Shape  SF  = DBRep::Get(a[i],TopAbs_FACE);
1078     if (!SF.IsNull()) {
1079       TheOffset.AddFace(TopoDS::Face(SF));
1080     }
1081   }
1082   if (n < 4)  theYaBouchon = Standard_False; //B.MakeOffsetShape();
1083   else        theYaBouchon = Standard_True;  //B.MakeThickSolid ();
1084
1085   return 0;
1086 }
1087
1088
1089 //=======================================================================
1090 //function : offsetonface
1091 //purpose  : 
1092 //=======================================================================
1093
1094 Standard_Integer offsetonface(Draw_Interpretor&, Standard_Integer n, const char** a)
1095 {
1096   if ( n < 3) return 1;
1097
1098   for (Standard_Integer i = 1 ; i < n; i+=2) {
1099     TopoDS_Shape  SF  = DBRep::Get(a[i],TopAbs_FACE);
1100     if (!SF.IsNull()) {
1101       Standard_Real Of = Draw::Atof(a[i+1]);
1102       TheOffset.SetOffsetOnFace(TopoDS::Face(SF),Of);
1103     }
1104   }
1105   
1106   return 0;
1107 }
1108
1109 //=======================================================================
1110 //function : offsetperform
1111 //purpose  : 
1112 //=======================================================================
1113
1114 Standard_Integer offsetperform(Draw_Interpretor& theCommands,
1115                                Standard_Integer theNArg, const char** a)
1116   {
1117   if ( theNArg < 2) return 1;
1118
1119   if (theYaBouchon)
1120     TheOffset.MakeThickSolid ();
1121   else
1122     TheOffset.MakeOffsetShape();
1123
1124   if(TheOffset.IsDone())
1125     {
1126     DBRep::Set(a[1],TheOffset.Shape());
1127     }
1128   else
1129     {
1130       const BRepOffset_Error aRetCode = TheOffset.Error();
1131       reportOffsetState(theCommands, aRetCode);
1132     }
1133
1134   return 0;
1135   }
1136
1137
1138 //=======================================================================
1139 //function : ROW
1140 //purpose  : 
1141 //=======================================================================
1142
1143 static Standard_Integer ROW(Draw_Interpretor& theCommands,
1144                             Standard_Integer narg, const char** a)
1145 {
1146   if (narg<13) return 1;
1147   TopoDS_Shape S = DBRep::Get(a[3]);
1148   BRepFeat_MakeRevol theRFace;
1149   gp_Dir D;
1150   gp_Pnt Or;
1151   Standard_Real Angle=0;
1152   TopoDS_Shape FFrom,FUntil;
1153   Standard_Integer i,borne;
1154   Standard_Boolean fuse;
1155
1156   if (a[1][0] == 'f' || a[1][0] == 'F') {
1157     fuse = Standard_True;
1158   }
1159   else if (a[1][0] == 'c' || a[1][0] == 'C') {
1160     fuse = Standard_False;
1161   }
1162   else {
1163     return 1;
1164   }
1165
1166   FFrom   = DBRep::Get(a[4],TopAbs_SHAPE);
1167   if (FFrom.IsNull()) {
1168     Angle = Draw::Atof(a[4]);
1169     Angle *=M_PI/180.;
1170     i = 5;
1171   }
1172   else {
1173     FUntil = DBRep::Get(a[5],TopAbs_SHAPE);
1174     if (FUntil.IsNull()) {
1175       i = 5;
1176       FUntil = FFrom;
1177       FFrom.Nullify();
1178       
1179     }
1180     else {
1181       if (narg < 14) {
1182         return 1;
1183       }
1184       i = 6;
1185     }
1186   }
1187   borne = i+6;
1188
1189   Or.SetCoord(Draw::Atof(a[i]),Draw::Atof(a[i+1]),Draw::Atof(a[i+2]));
1190   D.SetCoord(Draw::Atof(a[i+3]),Draw::Atof(a[i+4]),Draw::Atof(a[i+5]));
1191   gp_Ax1 theAxis(Or,D);
1192
1193   TopoDS_Shape aLocalShape(DBRep::Get(a[borne],TopAbs_FACE));
1194   TopoDS_Face F  = TopoDS::Face(aLocalShape);
1195 //  TopoDS_Face F  = TopoDS::Face(DBRep::Get(a[borne],TopAbs_FACE));
1196   BRepFeat_SplitShape Spls(F);
1197   for (i = borne+1; i<narg; i++) {
1198     TopoDS_Wire wir;
1199     if (a[i][0] !='-') {
1200       aLocalShape = DBRep::Get(a[i],TopAbs_WIRE);
1201       wir = TopoDS::Wire(aLocalShape);
1202 //      wir = TopoDS::Wire(DBRep::Get(a[i],TopAbs_WIRE));
1203     }
1204     else {
1205       if (a[i][1] == '\0')
1206         return 1;
1207       const char* Temp = a[i]+1;
1208       aLocalShape = DBRep::Get(Temp,TopAbs_WIRE);
1209       wir = TopoDS::Wire(aLocalShape);
1210 //      wir = TopoDS::Wire(DBRep::Get(Temp,TopAbs_WIRE));
1211       wir.Reverse();
1212     }
1213     Spls.Add(wir,F);
1214   }
1215   Spls.Build();
1216
1217   TopoDS_Shape ToRotate;
1218   const TopTools_ListOfShape& lleft = Spls.DirectLeft();
1219   if (lleft.Extent() == 1) {
1220     theRFace.Init(S,lleft.First(),F,theAxis,fuse,Standard_True);
1221     ToRotate = lleft.First();
1222   }
1223   else {
1224     BRep_Builder B;
1225     TopoDS_Shell Sh;
1226     B.MakeShell(Sh);
1227     TopTools_ListIteratorOfListOfShape it;
1228     for (it.Initialize(lleft);it.More();it.Next()) {
1229       B.Add(Sh,TopoDS::Face(it.Value()));
1230     }
1231     Sh.Closed (BRep_Tool::IsClosed (Sh));
1232     theRFace.Init(S,Sh,F,theAxis,fuse,Standard_True);
1233     ToRotate = Sh;
1234   }
1235
1236   // Recherche des faces de glissement
1237 //  for (TopExp_Explorer exp(S,TopAbs_FACE);exp.More();exp.Next()) {
1238   TopExp_Explorer exp(S,TopAbs_FACE) ;
1239   for ( ;exp.More();exp.Next()) {
1240     if (exp.Current().IsSame(F)) {
1241       break;
1242     }
1243   }
1244
1245   if (!exp.More()) {
1246     LocOpe_FindEdgesInFace FEIF;
1247     for (exp.Init(S,TopAbs_FACE);exp.More();exp.Next()) {
1248       const TopoDS_Face& fac = TopoDS::Face(exp.Current());
1249       Handle(Geom_Surface) Su = BRep_Tool::Surface(fac);
1250       if (Su->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
1251         Su = Handle(Geom_RectangularTrimmedSurface)::
1252           DownCast(Su)->BasisSurface();
1253       }
1254       if (Su->DynamicType() == STANDARD_TYPE(Geom_Plane)) {
1255         gp_Pln pl = Handle(Geom_Plane)::DownCast(Su)->Pln();
1256         if (pl.Axis().IsParallel(theAxis,Precision::Angular())) {
1257           FEIF.Set(ToRotate,fac);
1258           for (FEIF.Init();FEIF.More();FEIF.Next()) {
1259             theRFace.Add(FEIF.Edge(),fac);
1260           }
1261         }
1262       }
1263       else if (Su->DynamicType() == STANDARD_TYPE(Geom_CylindricalSurface)) {
1264         gp_Cylinder cy = 
1265           Handle(Geom_CylindricalSurface)::DownCast(Su)->Cylinder();
1266         if (cy.Axis().IsCoaxial(theAxis,
1267                                 Precision::Angular(),Precision::Confusion())) {
1268           FEIF.Set(ToRotate,fac);
1269           for (FEIF.Init();FEIF.More();FEIF.Next()) {
1270             theRFace.Add(FEIF.Edge(),fac);
1271           }
1272         }
1273       }
1274     }
1275   }
1276
1277   if (borne == 11) {
1278     if (FUntil.IsNull()) {
1279       theRFace.Perform(Angle);
1280     }
1281     else {
1282       theRFace.Perform(FUntil);
1283     }
1284   }
1285   else { // borne == 12
1286     theRFace.Perform(FFrom,FUntil);
1287   }
1288
1289   if (!theRFace.IsDone()) {
1290     theCommands << "Local operation not done";
1291     return 1;
1292   }
1293
1294   DBRep::Set(a[2],theRFace);
1295   dout.Flush();
1296   return 0;
1297 }
1298
1299
1300 //=======================================================================
1301 //function : ROF
1302 //purpose  : 
1303 //=======================================================================
1304
1305 static Standard_Integer ROF(Draw_Interpretor& theCommands,
1306                             Standard_Integer narg, const char** a)
1307 {
1308   if (narg<12) return 1;
1309   TopoDS_Shape S = DBRep::Get(a[3]);
1310   BRepFeat_MakeRevol theRFace;
1311   gp_Dir D;
1312   gp_Pnt Or;
1313   Standard_Real Angle=0;
1314   TopoDS_Shape FFrom,FUntil;
1315   Standard_Integer i,borne;
1316   Standard_Boolean fuse;
1317
1318   if (a[1][0] == 'f' || a[1][0] == 'F') {
1319     fuse = Standard_True;
1320   }
1321   else if (a[1][0] == 'c' || a[1][0] == 'C') {
1322     fuse = Standard_False;
1323   }
1324   else {
1325     return 1;
1326   }
1327
1328   FFrom   = DBRep::Get(a[4],TopAbs_SHAPE);
1329   if (FFrom.IsNull()) {
1330     Angle = Draw::Atof(a[4]);
1331     Angle *=M_PI/180.;
1332     i = 5;
1333   }
1334   else {
1335     FUntil = DBRep::Get(a[5],TopAbs_SHAPE);
1336     if (FUntil.IsNull()) {
1337       i = 5;
1338       FUntil = FFrom;
1339       FFrom.Nullify();
1340       
1341     }
1342     else {
1343       if (narg < 13) {
1344         return 1;
1345       }
1346       i = 6;
1347     }
1348   }
1349
1350   borne = i+6;
1351   Or.SetCoord(Draw::Atof(a[i]),Draw::Atof(a[i+1]),Draw::Atof(a[i+2]));
1352   D.SetCoord(Draw::Atof(a[i+3]),Draw::Atof(a[i+4]),Draw::Atof(a[i+5]));
1353   gp_Ax1 theAxis(Or,D);
1354
1355   TopoDS_Shape ToRotate;
1356   if (narg == borne+1) {
1357     TopoDS_Shape aLocalShape(DBRep::Get(a[borne],TopAbs_FACE));
1358     TopoDS_Face F  = TopoDS::Face(aLocalShape);
1359 //    TopoDS_Face F  = TopoDS::Face(DBRep::Get(a[borne],TopAbs_FACE));
1360     theRFace.Init(S,F,F,theAxis,fuse,Standard_True);
1361     ToRotate = F;
1362   }
1363   else {
1364     TopoDS_Shell She;
1365     BRep_Builder B;
1366     B.MakeShell(She);
1367     
1368     for (i=borne; i<narg; i++) {
1369       TopoDS_Shape aLocalShape(DBRep::Get(a[i],TopAbs_FACE));
1370       TopoDS_Face F  = TopoDS::Face(aLocalShape);
1371 //      TopoDS_Face F  = TopoDS::Face(DBRep::Get(a[i],TopAbs_FACE));
1372       if (!F.IsNull()) {
1373         B.Add(She,F);
1374       }
1375     }
1376     She.Closed (BRep_Tool::IsClosed (She));
1377     theRFace.Init(S,She,TopoDS_Face(),theAxis,fuse,Standard_False);
1378     ToRotate = She;
1379   }
1380
1381 //  for (TopExp_Explorer exp(ToRotate,TopAbs_FACE);exp.More();exp.Next()) {
1382   TopExp_Explorer exp(ToRotate,TopAbs_FACE) ;
1383   for ( ;exp.More();exp.Next()) {
1384 //    for (TopExp_Explorer exp2(S,TopAbs_FACE);exp2.More();exp2.Next()) {
1385     TopExp_Explorer exp2(S,TopAbs_FACE) ;
1386     for ( ;exp2.More();exp2.Next()) {
1387       if (exp2.Current().IsSame(exp.Current())) {
1388         break;
1389       }
1390     }
1391     if (exp2.More()) {
1392       break;
1393     }
1394   }
1395
1396   if (!exp.More()) {
1397     LocOpe_FindEdgesInFace FEIF;
1398     for (exp.Init(S,TopAbs_FACE);exp.More();exp.Next()) {
1399       const TopoDS_Face& fac = TopoDS::Face(exp.Current());
1400       Handle(Geom_Surface) Su = BRep_Tool::Surface(fac);
1401       if (Su->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
1402         Su = Handle(Geom_RectangularTrimmedSurface)::
1403           DownCast(Su)->BasisSurface();
1404       }
1405       if (Su->DynamicType() == STANDARD_TYPE(Geom_Plane)) {
1406         gp_Pln pl = Handle(Geom_Plane)::DownCast(Su)->Pln();
1407         if (pl.Axis().IsParallel(theAxis,Precision::Angular())) {
1408           FEIF.Set(ToRotate,fac);
1409           for (FEIF.Init();FEIF.More();FEIF.Next()) {
1410             theRFace.Add(FEIF.Edge(),fac);
1411           }
1412         }
1413       }
1414       else if (Su->DynamicType() == STANDARD_TYPE(Geom_CylindricalSurface)) {
1415         gp_Cylinder cy = 
1416           Handle(Geom_CylindricalSurface)::DownCast(Su)->Cylinder();
1417         if (cy.Axis().IsCoaxial(theAxis,
1418                                 Precision::Angular(),Precision::Confusion())) {
1419           FEIF.Set(ToRotate,fac);
1420           for (FEIF.Init();FEIF.More();FEIF.Next()) {
1421             theRFace.Add(FEIF.Edge(),fac);
1422           }
1423         }
1424       }
1425     }
1426   }
1427
1428   if (borne == 11) {
1429     if (FUntil.IsNull()) {
1430       theRFace.Perform(Angle);
1431     }
1432     else {
1433       theRFace.Perform(FUntil);
1434     }
1435   }
1436   else { // borne == 12
1437     theRFace.Perform(FFrom,FUntil);
1438   }
1439
1440   if (!theRFace.IsDone()) {
1441     theCommands << "Local operation not done";
1442     return 1;
1443   }
1444
1445   DBRep::Set(a[2],theRFace);
1446   dout.Flush();
1447   return 0;
1448 }
1449
1450
1451 //=======================================================================
1452 //function : GLU
1453 //purpose  : Commande glue
1454 //=======================================================================
1455
1456 static Standard_Integer GLU(Draw_Interpretor& ,
1457                             Standard_Integer narg, const char** a)
1458 {
1459   if (narg<6 || narg%2 != 0) return 1;
1460   TopoDS_Shape Sne = DBRep::Get(a[2]);
1461   TopoDS_Shape Sba = DBRep::Get(a[3]);
1462   
1463   Standard_Boolean pick;
1464   
1465   BRepFeat_Gluer theGl(Sne,Sba);
1466   TopoDS_Shape Fne,Fba;
1467   
1468   LocOpe_FindEdges fined;
1469
1470   Standard_Integer i = 4;
1471   Standard_Boolean first = Standard_True;
1472   while (i<narg) {
1473     pick = (a[i][0] == '.');
1474     Fne = DBRep::Get(a[i]);
1475     if (Fne.IsNull()) {
1476       return 1;
1477     }
1478     TopAbs_ShapeEnum sht = Fne.ShapeType();
1479     if (pick && sht != TopAbs_FACE && sht != TopAbs_EDGE) {
1480       Standard_Real u,v;
1481       DBRep_DrawableShape::LastPick(Fne,u,v);
1482       sht = Fne.ShapeType();
1483     }
1484     if (first && sht != TopAbs_FACE) {
1485       return 1;
1486     }
1487     first = Standard_False;
1488     pick = (a[i+1][0] == '.');
1489     Fba = DBRep::Get(a[i+1]);
1490     if (Fba.IsNull()) {
1491       return 1;
1492     }
1493     if (pick && Fba.ShapeType() != sht) {
1494       Standard_Real u,v;
1495       DBRep_DrawableShape::LastPick(Fba,u,v);
1496     }
1497     if (Fba.ShapeType() != sht) {
1498       return 1;
1499     }
1500     if (sht == TopAbs_FACE) {
1501       const TopoDS_Face& f1 = TopoDS::Face(Fne);
1502       const TopoDS_Face& f2 = TopoDS::Face(Fba);
1503       theGl.Bind(f1,f2);
1504       fined.Set(Fne,Fba);
1505       for (fined.InitIterator(); fined.More(); fined.Next()) {
1506         theGl.Bind(fined.EdgeFrom(),fined.EdgeTo());
1507       }
1508     }
1509     else {
1510       theGl.Bind(TopoDS::Edge(Fne),TopoDS::Edge(Fba));
1511     }
1512     i +=2;
1513   }
1514   
1515   DBRep::Set(a[1],theGl);
1516   dout.Flush();
1517   return 0;
1518 }
1519
1520 static Standard_Integer DEFIN(Draw_Interpretor& theCommands,
1521                               Standard_Integer narg, const char** a)
1522 {
1523
1524   if (strcasecmp(a[0],"FEATPRISM") &&
1525       strcasecmp(a[0],"FEATDPRISM") &&
1526       strcasecmp(a[0],"FEATREVOL") &&
1527       strcasecmp(a[0],"FEATPIPE") &&
1528       strcasecmp(a[0],"FEATLF")  &&
1529       strcasecmp(a[0],"FEATRF")) {
1530     return 1;
1531   }
1532
1533   if ((!strcasecmp(a[0],"FEATPRISM") && narg !=9) ||
1534       (!strcasecmp(a[0],"FEATREVOL") && narg != 12) ||
1535       (!strcasecmp(a[0],"FEATDPRISM") && narg != 7) ||
1536       (!strcasecmp(a[0],"FEATPIPE") && narg != 7) ||
1537       (!strcasecmp(a[0],"FEATLF") && narg != 12) ||
1538       (!strcasecmp(a[0],"FEATRF") && narg != 14)) {
1539     theCommands << "invalid number of arguments";
1540     return 1;
1541   }
1542
1543   TopoDS_Shape Sbase = DBRep::Get(a[1]);
1544   if (Sbase.IsNull()) {
1545     theCommands << "null basis shape";
1546     return 1;
1547   }
1548   Standard_Integer Ifuse  = Draw::Atoi(a[narg-2]);
1549   Standard_Integer Imodif = Draw::Atoi(a[narg-1]);
1550   
1551   Standard_Integer Fuse = Ifuse;
1552   Standard_Boolean Modify = (Imodif!=0);
1553
1554   TopoDS_Shape Pbase;
1555   TopoDS_Face Skface;
1556   TopoDS_Wire W;
1557
1558   Handle(Geom_Plane) P;
1559
1560   BRepFeat_StatusError se;
1561
1562   if (strcasecmp(a[0],"FEATLF") && strcasecmp(a[0],"FEATRF")) {
1563     Pbase = DBRep::Get(a[2]);
1564     if (Pbase.IsNull()) {
1565       theCommands << "null shape to transform";
1566       return 1;
1567     }
1568     TopoDS_Shape aLocalShape(DBRep::Get(a[3],TopAbs_FACE));
1569     Skface = TopoDS::Face(aLocalShape);
1570 //    Skface = TopoDS::Face(DBRep::Get(a[3],TopAbs_FACE));
1571     if (Skface.IsNull()) {
1572       theCommands << "null face of Sketch";
1573       return 1;
1574     }
1575   }
1576   else {
1577     TopoDS_Shape aLocalShape(DBRep::Get(a[2], TopAbs_WIRE));
1578     W = TopoDS::Wire(aLocalShape);
1579 //    W = TopoDS::Wire(DBRep::Get(a[2], TopAbs_WIRE));
1580     if(W.IsNull()) {
1581       theCommands << "null profile for rib or slot";
1582       return 1;
1583     }
1584     Handle(Geom_Surface) s = DrawTrSurf::GetSurface(a[3]);
1585     P = Handle(Geom_Plane)::DownCast(s);
1586     if(P.IsNull()) {
1587       theCommands << "null plane to transform";
1588       return 1;
1589     }
1590   }
1591   if (narg == 9 || narg == 12 || narg == 14) {
1592 //    Standard_Real X,Y,Z,X1,Y1,Z1;
1593     Standard_Real X,Y,Z;
1594     X = Draw::Atof(a[4]);
1595     Y = Draw::Atof(a[5]);
1596     Z = Draw::Atof(a[6]);
1597     
1598     if (narg == 9) { // prism
1599       prdef = Standard_True;      
1600       thePrism.Init(Sbase,Pbase,Skface,gp_Dir(X,Y,Z),Fuse,Modify);
1601     }
1602     else if(narg == 14) {
1603       rfdef = Standard_True;
1604       gp_Pnt Or(X, Y, Z);
1605       X = Draw::Atof(a[7]);
1606       Y = Draw::Atof(a[8]);
1607       Z = Draw::Atof(a[9]);
1608       Standard_Real H1 = Draw::Atof(a[10]);
1609       Standard_Real H2 = Draw::Atof(a[11]);
1610       gp_Ax1 ax1(Or, gp_Dir(X, Y, Z));
1611       theRF.Init(Sbase, W, P, ax1, H1, H2, Fuse, Modify);
1612       if (!theRF.IsDone()) {
1613         se = theRF.CurrentStatusError();
1614         //BRepFeat::Print(se,cout) << endl;
1615         Standard_SStream aSStream;
1616         BRepFeat::Print(se,aSStream);
1617         theCommands << aSStream << "\n";
1618         return 1;
1619       }
1620     }
1621     else if(narg == 12 && strcasecmp(a[0],"FEATLF")) {
1622       rvdef = Standard_True;
1623       gp_Pnt Or(X,Y,Z);
1624       X = Draw::Atof(a[7]);
1625       Y = Draw::Atof(a[8]);
1626       Z = Draw::Atof(a[9]);
1627       theRevol.Init(Sbase,Pbase,Skface,gp_Ax1(Or,gp_Dir(X,Y,Z)),
1628                     Fuse,Modify);
1629     }
1630     else {
1631       lfdef = Standard_True;
1632       gp_Vec Direct(X,Y,Z);
1633       X = Draw::Atof(a[7]);
1634       Y = Draw::Atof(a[8]);
1635       Z = Draw::Atof(a[9]);
1636       theLF.Init(Sbase, W, P, Direct, gp_Vec(X,Y,Z), Fuse,Modify);
1637       if (!theLF.IsDone()) {
1638         se = theLF.CurrentStatusError();
1639         //BRepFeat::Print(se,cout) << endl;
1640         Standard_SStream aSStream;
1641         BRepFeat::Print(se,aSStream);
1642         theCommands << aSStream << "\n";
1643         return 1;
1644       }
1645     }
1646   }
1647   else if (narg == 7) {
1648     if (!strcasecmp(a[0],"FEATDPRISM")) {
1649       if (Pbase.ShapeType() != TopAbs_FACE) {
1650         theCommands << "Invalid DPrism base";
1651         return 1;
1652       }
1653       Standard_Real Angle = Draw::Atof(a[4])*M_PI/360; 
1654       dprdef = Standard_True;
1655       theDPrism.Init(Sbase,TopoDS::Face(Pbase),Skface,Angle,Fuse,Modify);
1656     }
1657     else { // FEATPIPE
1658       TopoDS_Shape aLocalShape(DBRep::Get(a[4],TopAbs_WIRE));
1659       TopoDS_Wire Spine = TopoDS::Wire(aLocalShape);
1660 //      TopoDS_Wire Spine = TopoDS::Wire(DBRep::Get(a[4],TopAbs_WIRE));
1661       if (Spine.IsNull()) {
1662         TopoDS_Shape Edspine =DBRep::Get(a[4],TopAbs_EDGE);
1663         if (Edspine.IsNull()) {
1664           theCommands << "null spine";
1665           return 1;
1666         }
1667         BRep_Builder B;
1668         B.MakeWire(Spine);
1669         B.Add(Spine,Edspine);
1670       }
1671       pidef = Standard_True;
1672       thePipe.Init(Sbase,Pbase,Skface,Spine,Fuse,Modify);
1673     }
1674   }
1675   return 0;
1676 }
1677
1678
1679
1680 static Standard_Integer ADD(Draw_Interpretor& ,
1681                             Standard_Integer narg, const char** a)
1682 {
1683   Standard_Integer i ;
1684   if (narg < 4 || narg%2 != 0) {
1685     return 1;
1686   }
1687   if (!strcasecmp("PRISM",a[1])) {
1688     if (!prdef) {
1689       return 1;
1690     }
1691     for ( i=2; i<narg; i+=2) {
1692       TopoDS_Shape aLocalShape(DBRep::Get(a[i],TopAbs_EDGE));
1693       TopoDS_Edge edg = TopoDS::Edge(aLocalShape);
1694 //      TopoDS_Edge edg = TopoDS::Edge(DBRep::Get(a[i],TopAbs_EDGE));
1695       if (edg.IsNull()) {
1696         return 1;
1697       }
1698       aLocalShape = DBRep::Get(a[i+1],TopAbs_FACE);
1699       TopoDS_Face fac = TopoDS::Face(aLocalShape);
1700 //      TopoDS_Face fac = TopoDS::Face(DBRep::Get(a[i+1],TopAbs_FACE));
1701       if (fac.IsNull()) {
1702         return 1;
1703       }
1704       thePrism.Add(edg,fac);
1705     }
1706   }
1707   else if (!strcasecmp("REVOL",a[1])) {
1708     if (!rvdef) {
1709       return 1;
1710     }
1711     for ( i=2; i<narg; i+=2) {
1712       TopoDS_Shape aLocalShape(DBRep::Get(a[i],TopAbs_EDGE));
1713       TopoDS_Edge edg = TopoDS::Edge(aLocalShape);
1714 //      TopoDS_Edge edg = TopoDS::Edge(DBRep::Get(a[i],TopAbs_EDGE));
1715       if (edg.IsNull()) {
1716         return 1;
1717       }
1718       aLocalShape = DBRep::Get(a[i+1],TopAbs_FACE);
1719       TopoDS_Face fac = TopoDS::Face(aLocalShape);
1720 //      TopoDS_Face fac = TopoDS::Face(DBRep::Get(a[i+1],TopAbs_FACE));
1721       if (fac.IsNull()) {
1722         return 1;
1723       }
1724       theRevol.Add(edg,fac);
1725     }
1726   }
1727   else if (!strcasecmp("PIPE",a[1])) {
1728     if (!pidef) {
1729       return 1;
1730     }
1731     for ( i=2; i<narg; i+=2) {
1732       TopoDS_Shape aLocalShape(DBRep::Get(a[i],TopAbs_EDGE));
1733       TopoDS_Edge edg = TopoDS::Edge(aLocalShape);
1734 //      TopoDS_Edge edg = TopoDS::Edge(DBRep::Get(a[i],TopAbs_EDGE));
1735       if (edg.IsNull()) {
1736         return 1;
1737       }
1738       aLocalShape = DBRep::Get(a[i+1],TopAbs_FACE);
1739       TopoDS_Face fac = TopoDS::Face(aLocalShape);
1740 //      TopoDS_Face fac = TopoDS::Face(DBRep::Get(a[i+1],TopAbs_FACE));
1741       if (fac.IsNull()) {
1742         return 1;
1743       }
1744       thePipe.Add(edg,fac);
1745     }
1746   }
1747   else {
1748     return 1;
1749   }
1750   return 0;
1751 }
1752
1753
1754
1755 static Standard_Integer PERF(Draw_Interpretor& theCommands,
1756                             Standard_Integer narg, const char** a)
1757 {
1758   if (narg < 3) {
1759     return 1;
1760   }
1761   if (strcasecmp(a[0],"FEATPERFORM") &&
1762       strcasecmp(a[0],"FEATPERFORMVAL")) {
1763     return 1;
1764   }
1765
1766   Standard_Integer Kas;
1767   if (!strcasecmp("PRISM",a[1])) {
1768     Kas = 1;
1769     if (!prdef) {
1770       theCommands << "prism not defined";
1771       return 1;
1772     }
1773   }
1774   else if (!strcasecmp("REVOL",a[1])) {
1775     Kas = 2;
1776     if (!rvdef) {
1777       theCommands << "revol not defined";
1778       return 1;
1779     }
1780   }
1781   else if (!strcasecmp("PIPE",a[1])) {
1782     Kas = 3;
1783     if (!pidef) {
1784       theCommands << "pipe not defined";
1785       return 1;
1786     }
1787     if (!strcasecmp(a[0],"FEATPERFORMVAL")) {
1788       theCommands << "invalid command for pipe";
1789       return 1;
1790     }
1791   }
1792   else if (!strcasecmp("DPRISM",a[1])) {
1793     Kas = 4;
1794     if (!dprdef) {
1795       theCommands << "dprism not defined";
1796       return 1;
1797     }
1798   }
1799   else if (!strcasecmp("LF",a[1])) {
1800     Kas = 5;
1801     if (!lfdef) {
1802       theCommands << "lf not defined";
1803       return 1;
1804     }
1805     if (!strcasecmp(a[0],"FEATPERFORMVAL")) {
1806       theCommands << "invalid command for lf";
1807       return 1;
1808     }
1809   }
1810   else if (!strcasecmp("RF",a[1])) {
1811     Kas = 6;
1812     if (!rfdef) {
1813       theCommands << "rf not defined";
1814       return 1;
1815     }
1816     if (!strcasecmp(a[0],"FEATPERFORMVAL")) {
1817       theCommands << "invalid command for rf";
1818       return 1;
1819     }
1820   }
1821   else {
1822     theCommands << "unknown argument : " << a[1];
1823     return 1;
1824   }
1825
1826   if (!strcasecmp(a[0],"FEATPERFORMVAL")) {
1827     if (narg !=4 && narg != 5) {
1828       theCommands << "invalid number of arguments";
1829       return 1;
1830     }
1831     if (narg == 4) {
1832       Standard_Real Val = Draw::Atof(a[3]);
1833       if (Kas == 1) {
1834         thePrism.Perform(Val);
1835       }
1836       else if (Kas == 2) {
1837         Val *=(M_PI/180.);
1838         theRevol.Perform(Val);
1839       }
1840       else if (Kas == 4) {
1841         theDPrism.Perform(Val);
1842       }
1843       else if (Kas == 5) {
1844         theCommands << "invalid command for lf";
1845         return 1;
1846       }
1847       else if (Kas == 6) {
1848         theCommands << "invalid command for rf";
1849         return 1;
1850       }
1851     }
1852     else if(narg == 5) {
1853       Standard_Real Val = Draw::Atof(a[3]);
1854       TopoDS_Shape FUntil = DBRep::Get(a[4],TopAbs_SHAPE);
1855       if (Kas == 1) {
1856         thePrism.PerformUntilHeight(FUntil, Val);
1857       }
1858       else if (Kas == 2) {
1859         Val *=(M_PI/180.);
1860         theRevol.PerformUntilAngle(FUntil, Val);
1861       }
1862       else if (Kas == 4) {
1863         theDPrism.PerformUntilHeight(FUntil, Val);
1864       } 
1865       else {
1866         theCommands << "invalid command for ribs or slots";
1867         return 1;
1868       }
1869     }
1870   }
1871   else if (!strcasecmp(a[0],"FEATPERFORM")) {
1872     if (narg == 3) { // Thru all
1873       switch (Kas) {
1874       case 1:
1875         thePrism.PerformThruAll();
1876         break;
1877       case 2:
1878         theRevol.PerformThruAll();
1879         break;
1880       case 3:
1881         thePipe.Perform();
1882         break;
1883       case 4:
1884         theDPrism.PerformThruAll();
1885         break;
1886       case 5:
1887         theLF.Perform();
1888         break;
1889       case 6:
1890         theRF.Perform();
1891         break;
1892       default:
1893
1894         return 1;
1895       }
1896     }
1897     else if (narg == 4) { // Until
1898       TopoDS_Shape Funtil = DBRep::Get(a[3],TopAbs_SHAPE);
1899       switch (Kas) {
1900       case 1:
1901         {
1902           if (Funtil.IsNull()) {
1903             thePrism.PerformUntilEnd();
1904           }
1905           else {
1906             thePrism.Perform(Funtil);
1907           }
1908         }
1909         break;
1910       case 2:
1911         {
1912           if (!Funtil.IsNull()) {
1913             theRevol.Perform(Funtil);
1914           }
1915           else {
1916             return 1;
1917           }
1918         }
1919         break;
1920       case 3:
1921         {
1922           if (!Funtil.IsNull()) {
1923             thePipe.Perform(Funtil);
1924           }
1925           else {
1926             theCommands << "invalid command for ribs pipe";
1927             return 1;
1928           }
1929         }
1930         break;
1931       case 4:
1932         {
1933           if (!Funtil.IsNull()) {
1934             theDPrism.Perform(Funtil);
1935           }
1936           else {
1937             theDPrism.PerformUntilEnd();
1938           }
1939         }
1940         break;
1941       case 5:
1942         {  
1943           theCommands << "invalid command for lf";
1944           return 1;
1945         }
1946         break;
1947       case 6:
1948         {  
1949           theCommands << "invalid command for rf";
1950           return 1;
1951         }
1952         break;
1953       default:
1954         return 1;
1955       }
1956     }
1957     else if (narg == 5) {
1958       TopoDS_Shape Ffrom = DBRep::Get(a[3],TopAbs_SHAPE);
1959       TopoDS_Shape Funtil = DBRep::Get(a[4],TopAbs_SHAPE);
1960       if (Funtil.IsNull()) {
1961         return 1;
1962       }
1963       switch (Kas) {
1964       case 1:
1965         {
1966           if (Ffrom.IsNull()) {
1967             thePrism.PerformFromEnd(Funtil);
1968           }
1969           else {
1970             thePrism.Perform(Ffrom,Funtil);
1971           }
1972         }
1973         break;
1974       case 2:
1975         {
1976           if (Ffrom.IsNull()) {
1977             return 1;
1978           }
1979           theRevol.Perform(Ffrom,Funtil);
1980         }
1981         break;
1982       case 3:
1983         {
1984           if (Ffrom.IsNull()) {
1985             return 1;
1986           }
1987           thePipe.Perform(Ffrom,Funtil);
1988         }
1989         break;
1990       case 4:
1991         {
1992           if (Ffrom.IsNull()) {
1993             theDPrism.PerformFromEnd(Funtil);
1994           }
1995           else {
1996             theDPrism.Perform(Ffrom,Funtil);
1997           }
1998         }
1999         break;
2000
2001       default:
2002         return 1;
2003       }
2004     }
2005   }
2006
2007   BRepFeat_StatusError se;
2008   switch (Kas) {
2009   case 1:
2010     if (!thePrism.IsDone()) {
2011       se = thePrism.CurrentStatusError();
2012       //BRepFeat::Print(se,cout) << endl;
2013       Standard_SStream aSStream;
2014       BRepFeat::Print(se,aSStream);
2015       theCommands << aSStream << "\n";
2016       return 1;
2017     }
2018     DBRep::Set(a[2],thePrism);
2019     dout.Flush();
2020     return 0;
2021   case 2:
2022     if (!theRevol.IsDone()) {
2023       se = theRevol.CurrentStatusError();
2024       //BRepFeat::Print(se,cout) << endl;
2025       Standard_SStream aSStream;
2026       BRepFeat::Print(se,aSStream);
2027       theCommands << aSStream << "\n";
2028       return 1;
2029     }
2030     DBRep::Set(a[2],theRevol);
2031     dout.Flush();
2032     return 0;
2033   case 3:
2034     if (!thePipe.IsDone()) {
2035       se = thePipe.CurrentStatusError();
2036       //BRepFeat::Print(se,cout) << endl;
2037       Standard_SStream aSStream;
2038       BRepFeat::Print(se,aSStream);
2039       theCommands << aSStream << "\n";
2040       return 1;
2041     }
2042     DBRep::Set(a[2],thePipe);
2043     dout.Flush();
2044     return 0;
2045   case 4:
2046     if (!theDPrism.IsDone()) {
2047       se = theDPrism.CurrentStatusError();
2048       //BRepFeat::Print(se,cout) << endl;
2049       Standard_SStream aSStream;
2050       BRepFeat::Print(se,aSStream);
2051       theCommands << aSStream << "\n";
2052       return 1;
2053     }
2054     DBRep::Set(a[2],theDPrism);
2055     dout.Flush();
2056     return 0;
2057   case 5:
2058     if (!theLF.IsDone()) {
2059       se = theLF.CurrentStatusError();
2060       //BRepFeat::Print(se,cout) << endl;
2061       Standard_SStream aSStream;
2062       BRepFeat::Print(se,aSStream);
2063       theCommands << aSStream << "\n";
2064       return 1;
2065     }
2066     DBRep::Set(a[2],theLF);
2067     dout.Flush();
2068     return 0;
2069   case 6:
2070     if (!theRF.IsDone()) {
2071       se = theRF.CurrentStatusError();
2072       //BRepFeat::Print(se,cout) << endl;
2073       Standard_SStream aSStream;
2074       BRepFeat::Print(se,aSStream);
2075       theCommands << aSStream << "\n";
2076       return 1;
2077     }
2078     DBRep::Set(a[2],theRF);
2079     dout.Flush();
2080     return 0;
2081   default:
2082     return 1;
2083   }
2084 }
2085
2086
2087 static Standard_Integer BOSS(Draw_Interpretor& theCommands,
2088                              Standard_Integer narg, const char** a)
2089 {
2090   if (strcasecmp(a[0],"ENDEDGES") && strcasecmp(a[0],"FILLET")
2091       && strcasecmp(a[0],"BOSSAGE")) {
2092     return 1;
2093   }
2094
2095   if ((!strcasecmp(a[0],"ENDEDGES") && narg !=5) ||
2096       (!strcasecmp(a[0],"FILLET") && narg <5 &&  narg%2 != 1) ||
2097       (!strcasecmp(a[0],"BOSSAGE") && narg != 6)) {
2098     theCommands << "invalid number of arguments";
2099     return 1;
2100   }
2101
2102   Standard_Integer Kas=0;
2103   Standard_Integer dprsig=0;
2104   if (!strcasecmp("ENDEDGES",a[0])) {
2105     Kas = 1;
2106     dprsig = Draw::Atoi(a[4]);
2107   }
2108   else if (!strcasecmp("FILLET",a[0])) {
2109     Kas = 2;
2110   }
2111   else if (!strcasecmp("BOSSAGE",a[0])) {
2112     Kas = 3;
2113     dprsig = Draw::Atoi(a[5]);
2114   }
2115  
2116   TopoDS_Shape theShapeTop; 
2117   TopoDS_Shape theShapeBottom;
2118
2119   if (Kas == 1 || Kas == 3) {
2120     if (!strcasecmp("DPRISM",a[1])) {
2121       if (!dprdef) {
2122         theCommands << "dprism not defined";
2123         return 1;
2124       }
2125     }
2126     else {
2127       theCommands << "unknown argument : " << a[1];
2128       return 1;
2129     }
2130
2131     theDPrism.BossEdges(dprsig);
2132    
2133     TopTools_ListOfShape theTopEdges, theLatEdges;
2134     theTopEdges = theDPrism.TopEdges();
2135     theLatEdges = theDPrism.LatEdges();
2136
2137     TopTools_ListIteratorOfListOfShape it;
2138     BRep_Builder B;
2139
2140     B.MakeCompound(TopoDS::Compound(theShapeTop));
2141     it.Initialize(theTopEdges);
2142     for(; it.More(); it.Next()) {
2143       TopExp_Explorer exp;
2144       for (exp.Init(it.Value(),TopAbs_EDGE); exp.More(); exp.Next()) {
2145         B.Add(theShapeTop,exp.Current());
2146       }
2147     }
2148     DBRep::Set(a[2],theShapeTop);
2149     dout.Flush();
2150
2151     B.MakeCompound(TopoDS::Compound(theShapeBottom));
2152     it.Initialize(theLatEdges);
2153     for(; it.More(); it.Next()) {
2154       B.Add(theShapeBottom,it.Value());
2155     }
2156     DBRep::Set(a[3],theShapeBottom);
2157     dout.Flush();
2158     if (Kas == 1) return 0;
2159   }
2160
2161   if (Kas == 2 || Kas == 3) {
2162     
2163 //    Standard_Integer nrad;
2164     TopoDS_Shape V;
2165     if (Kas == 2) {
2166       V = DBRep::Get(a[2],TopAbs_SHAPE);
2167     }
2168     else if (Kas == 3) {
2169       V = theDPrism;
2170     }
2171
2172     if(V.IsNull()) return 1;
2173     ChFi3d_FilletShape FSh = ChFi3d_Rational;
2174     Rakk = new BRepFilletAPI_MakeFillet(V,FSh);
2175     Rakk->SetParams(ta,t3d,t2d,t3d,t2d,fl);
2176     Rakk->SetContinuity(blend_cont, tapp_angle);
2177     Standard_Real Rad;
2178     TopoDS_Shape S;
2179     TopoDS_Edge E;
2180     Standard_Integer nbedge = 0;
2181
2182     if (Kas == 2) {
2183       for (Standard_Integer ii = 1; ii < (narg-1)/2; ii++){
2184         Rad = Draw::Atof(a[2*ii + 1]);
2185         if (Rad == 0.) continue;
2186         S = DBRep::Get(a[(2*ii+2)],TopAbs_SHAPE);
2187         TopExp_Explorer exp;
2188         for (exp.Init(S,TopAbs_EDGE); exp.More(); exp.Next()) {
2189           E = TopoDS::Edge(exp.Current());
2190           if(!E.IsNull()){
2191             Rakk->Add(Rad,E);
2192             nbedge++;
2193           }
2194         }
2195       }
2196     }
2197     else if (Kas == 3) {
2198       Rad = Draw::Atof(a[3]);
2199       if (Rad != 0.) {
2200         S = theShapeTop;
2201         TopExp_Explorer exp;
2202         for (exp.Init(S,TopAbs_EDGE); exp.More(); exp.Next()) {
2203           E = TopoDS::Edge(exp.Current());
2204           if(!E.IsNull()){
2205             Rakk->Add(Rad,E);
2206             nbedge++;
2207           }
2208         } 
2209       }
2210       Rad = Draw::Atof(a[4]);
2211       if (Rad != 0.) {
2212         S = theShapeBottom;
2213         TopExp_Explorer exp;
2214         for (exp.Init(S,TopAbs_EDGE); exp.More(); exp.Next()) {
2215           E = TopoDS::Edge(exp.Current());
2216           if(!E.IsNull()){
2217             Rakk->Add(Rad,E);
2218             nbedge++;
2219           }
2220         } 
2221       }
2222     }
2223     
2224     if(!nbedge) return 1;
2225     Rakk->Build();
2226     if(!Rakk->IsDone()) return 1;
2227     TopoDS_Shape res = Rakk->Shape();
2228
2229     if (Kas == 2) {
2230       DBRep::Set(a[1],res);
2231     } 
2232     else if (Kas == 3) {
2233       DBRep::Set(a[2],res);
2234     }
2235     dout.Flush();
2236     return 0;
2237   }
2238
2239   return 1;
2240 }
2241
2242 //=============================================================================
2243 //function : ComputeSimpleOffset
2244 //purpose  : Computes simple offset.
2245 //=============================================================================
2246 static Standard_Integer ComputeSimpleOffset(Draw_Interpretor& theCommands,
2247                                             Standard_Integer narg, 
2248                                             const char** a)
2249 {
2250   if (narg != 4 && narg != 5)
2251   {
2252     theCommands << "offsetshapesimple result shape offsetvalue [solid]\n";
2253     return 1;
2254   }
2255
2256   // Input data.
2257   TopoDS_Shape aShape = DBRep::Get(a[2]);
2258   if (aShape.IsNull())
2259   {
2260     theCommands << "Input shape is null";
2261     return 0;
2262   }
2263   const Standard_Real anOffsetValue = Draw::Atof(a[3]);
2264   if (Abs(anOffsetValue) < gp::Resolution())
2265   {
2266     theCommands << "Null offset value";
2267     return 0;
2268   }
2269
2270   BRepOffset_MakeSimpleOffset aMaker(aShape, anOffsetValue);
2271   if (narg == 5 && !strcasecmp(a[4],"solid") )
2272   {
2273     aMaker.SetBuildSolidFlag(Standard_True);
2274   }
2275
2276   aMaker.Perform();
2277
2278   if (!aMaker.IsDone())
2279   {
2280     theCommands << "ERROR:" << aMaker.GetErrorMessage() << "\n";
2281     return 0;
2282   }
2283
2284   DBRep::Set(a[1], aMaker.GetResultShape());
2285
2286   return 0;
2287 }
2288
2289 //=======================================================================
2290 //function : FeatureCommands
2291 //purpose  : 
2292 //=======================================================================
2293
2294 void BRepTest::FeatureCommands (Draw_Interpretor& theCommands)
2295 {
2296   static Standard_Boolean done = Standard_False;
2297   if (done) return;
2298   done = Standard_True;
2299
2300   DBRep::BasicCommands(theCommands);
2301
2302   const char* g = "TOPOLOGY Feature commands";
2303
2304   theCommands.Add("localope", 
2305                   " Performs a local top. operation : localope result shape tool F/C (fuse/cut) face [face...]",
2306                   __FILE__,Loc,g);
2307
2308   theCommands.Add("hole",
2309                   " Performs a hole : hole result shape Or.X Or.Y Or.Z Dir.X Dir.Y Dir.Z Radius [Pfrom Pto]",
2310                   __FILE__,HOLE1,g);
2311
2312   theCommands.Add("firsthole",
2313                   " Performs the first hole : firsthole result shape Or.X Or.Y Or.Z Dir.X Dir.Y Dir.Z Radius",
2314                   __FILE__,HOLE2,g);
2315
2316   theCommands.Add("holend",
2317                   " Performs the hole til end : holend result shape Or.X Or.Y Or.Z Dir.X Dir.Y Dir.Z Radius",
2318                   __FILE__,HOLE3,g);
2319
2320   theCommands.Add("blindhole", 
2321                   " Performs the blind hole : blindhole result shape Or.X Or.Y Or.Z Dir.X Dir.Y Dir.Z Radius Length",
2322                   __FILE__,HOLE4,g);
2323
2324   theCommands.Add("holecontrol",
2325                   "Sets/Unsets or display controls on holes : holecontrol [0/1]",
2326                   __FILE__,CONTROL,g);
2327
2328   theCommands.Add("wprism",
2329                   "Prisms wires on a face : wprism f[use]/c[ut] result shape [[FaceFrom] FaceUntil] VecX VecY VecZ  SkecthFace wire1 [wire2 ....]",
2330                   __FILE__,PRW,g);
2331
2332
2333   theCommands.Add("fprism", 
2334                   "Prisms a set of faces of a shape : fprism f[use]/c[ut] result shape [[FaceFrom] FaceUntil] VecX VecY VecZ face1 [face2...]",
2335                   __FILE__,PRF,g);
2336
2337
2338   theCommands.Add("wrotate",
2339                   "Rotates wires on a face : wrotate f[use]/c[ut] result shape Angle/[FFrom] FUntil OX OY OZ DX DY DZ SkecthFace wire1 [wire2 ....]",
2340                   __FILE__,ROW,g);
2341
2342
2343   theCommands.Add("frotate", 
2344                   "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...]",
2345                   __FILE__,ROF,g);
2346
2347
2348   theCommands.Add("splitshape",
2349     "splitshape result shape [splitedges] [face wire/edge/compound [wire/edge/compound ...][face wire/edge/compound [wire/edge/compound...] ...] [@ edgeonshape edgeonwire [edgeonshape edgeonwire...]]",
2350     __FILE__, SPLS, g);
2351
2352
2353   theCommands.Add("thickshell",
2354                   "thickshell r shape offset [jointype [tol] ]",
2355                   __FILE__,thickshell,g);
2356   
2357   theCommands.Add("offsetshape",
2358                   "offsetshape r shape offset [tol] [face ...]",
2359                   __FILE__,offsetshape,g);
2360   
2361   theCommands.Add("offsetcompshape",
2362                   "offsetcompshape r shape offset [face ...]",
2363                   __FILE__,offsetshape,g);
2364
2365   theCommands.Add("offsetparameter",
2366                   "offsetparameter Tol Inter(c/p) JoinType(a/i/t) [RemoveInternalEdges(r/k)]",
2367                   __FILE__,offsetparameter);
2368
2369   theCommands.Add("offsetload",
2370                   "offsetload shape offset bouchon1 bouchon2 ...",
2371                   __FILE__,offsetload,g);
2372
2373   theCommands.Add("offsetonface",
2374                   "offsetonface face1 offset1 face2 offset2 ...",
2375                   __FILE__,offsetonface,g);
2376
2377   theCommands.Add("offsetperform",
2378                   "offsetperform result",
2379                   __FILE__,offsetperform,g);
2380
2381   theCommands.Add("glue", 
2382                   "glue result shapenew shapebase facenew facebase [facenew facebase...] [edgenew edgebase [edgenew edgebase...]]",
2383                   __FILE__,GLU,g);
2384
2385
2386   theCommands.Add("featprism", 
2387                   "Defines the arguments for a prism : featprism shape element skface  Dirx Diry Dirz Fuse(0/1/2) Modify(0/1)",
2388                   __FILE__,DEFIN);
2389
2390   theCommands.Add("featrevol", 
2391                   "Defines the arguments for a revol : featrevol shape element skface  Ox Oy Oz Dx Dy Dz Fuse(0/1/2) Modify(0/1)",
2392                   __FILE__,DEFIN);
2393
2394   theCommands.Add("featpipe", 
2395                   "Defines the arguments for a pipe : featpipe shape element skface  spine Fuse(0/1/2) Modify(0/1)",
2396                   __FILE__,DEFIN);
2397
2398   theCommands.Add("featdprism", 
2399                   "Defines the arguments for a drafted prism : featdprism shape face skface angle Fuse(0/1/2) Modify(0/1)",
2400                   __FILE__,DEFIN);
2401
2402   theCommands.Add("featlf", 
2403                   "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)",
2404                   __FILE__,DEFIN);
2405
2406   theCommands.Add("featrf", 
2407                   "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)",
2408                   __FILE__,DEFIN);
2409
2410   theCommands.Add("addslide", 
2411                   " Adds sliding elements : addslide prism/revol/pipe edge face [edge face...]",
2412                   __FILE__,ADD);
2413
2414   theCommands.Add("featperform", 
2415                   " Performs the prism revol dprism linform or pipe :featperform prism/revol/pipe/dprism/lf result [[Ffrom] Funtil]",
2416                   __FILE__,PERF);
2417
2418   theCommands.Add("featperformval", 
2419                   " Performs the prism revol dprism or linform with a value :featperformval prism/revol/dprism/lf result value",
2420                   __FILE__,PERF);
2421
2422   theCommands.Add("endedges", 
2423                   " Return top and bottom edges of dprism :endedges dprism shapetop shapebottom First/LastShape (1/2)",
2424                   __FILE__,BOSS);
2425
2426   theCommands.Add("fillet", 
2427                   " Perform fillet on compounds of edges :fillet result object rad1 comp1 rad2 comp2 ...",
2428                   __FILE__,BOSS);
2429
2430   theCommands.Add("bossage", 
2431                   " Perform fillet on top and bottom edges of dprism :bossage dprism result radtop radbottom First/LastShape (1/2)",
2432                   __FILE__,BOSS);
2433
2434   theCommands.Add("offsetshapesimple", 
2435                   "offsetshapesimple result shape offsetvalue [solid]",
2436                   __FILE__, ComputeSimpleOffset);
2437 }