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