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