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