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