0030346: Modeling Algorithms - BRepPrimAPI_MakeRevol throws "BRepSweep_Translation...
[occt.git] / src / BRepTest / BRepTest_CurveCommands.cxx
1 // Created on: 1993-07-22
2 // Created by: Remi LEQUETTE
3 // Copyright (c) 1993-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 <BRepTest.hxx>
18 #include <GeometryTest.hxx>
19 #include <gp_Pnt2d.hxx>
20 #include <gp_Pln.hxx>
21 #include <gp_Ax2.hxx>
22 #include <gp_Vec.hxx>
23 #include <gp_Vec2d.hxx>
24 #include <TColgp_HArray1OfPnt2d.hxx>
25 #include <TColgp_Array1OfPnt2d.hxx>
26 #include <BRepBuilderAPI.hxx>
27 #include <BRepBuilderAPI_MakeVertex.hxx>
28 #include <BRepBuilderAPI_MakeEdge.hxx>
29 #include <BRepBuilderAPI_MakeEdge2d.hxx>
30 #include <BRepBuilderAPI_MakeFace.hxx>
31 #include <BRepBuilderAPI_MakeWire.hxx>
32 #include <BRepBuilderAPI_MakePolygon.hxx>
33 #include <BRepOffsetAPI_MakeOffset.hxx>
34 #include <BRepLib.hxx>
35 #include <BRepAlgo.hxx>
36 #include <BRepAdaptor_Curve.hxx>
37 #include <BRep_Builder.hxx>
38 #include <BRep_Tool.hxx>
39 #include <BRepTools.hxx>
40 #include <Geom_Curve.hxx>
41 #include <Geom_TrimmedCurve.hxx>
42 #include <Geom2d_BSplineCurve.hxx>
43 #include <Geom_Surface.hxx>
44 #include <Geom_RectangularTrimmedSurface.hxx>
45 #include <Geom_Plane.hxx>
46 #include <Geom2d_Line.hxx>
47 #include <Geom2d_Circle.hxx>
48 #include <Geom2dAPI_Interpolate.hxx>
49 #include <Geom2d_TrimmedCurve.hxx>
50 #include <TopoDS.hxx>
51 #include <TopoDS_Shape.hxx>
52 #include <TopoDS_Wire.hxx>
53
54 #include <DBRep.hxx>
55 #include <DBRep_DrawableShape.hxx>
56 #include <Draw_Interpretor.hxx>
57 #include <Draw_Appli.hxx>
58 #include <DrawTrSurf.hxx>
59 #include <DrawTrSurf_BSplineCurve2d.hxx>
60 #include <DrawTrSurf_Point.hxx>
61
62 #include <gp.hxx>
63 #include <Precision.hxx>
64 #include <GeomAPI.hxx>
65 #include <TopAbs_Orientation.hxx>
66 #include <TopExp_Explorer.hxx>
67 #include <TopOpeBRep_EdgesIntersector.hxx>
68 #include <TopOpeBRep_Point2d.hxx>
69 #include <TopOpeBRepDS_Transition.hxx>
70
71 #include <stdio.h>
72 #ifdef _WIN32
73 Standard_IMPORT Draw_Viewer dout;
74 #endif
75
76 //=======================================================================
77 // vertex
78 //=======================================================================
79
80 static Standard_Integer vertex(Draw_Interpretor& , Standard_Integer n, const char** a)
81 {
82   if (n < 3) return 1;
83   if (n >= 5) {
84     DBRep::Set(a[1],
85       BRepBuilderAPI_MakeVertex(gp_Pnt(Draw::Atof(a[2]),Draw::Atof(a[3]),Draw::Atof(a[4]))));
86   }
87   else if (n == 4)
88   {
89     TopoDS_Shape S = DBRep::Get(a[3]);
90     if (S.IsNull()) return 0;
91     if (S.ShapeType() != TopAbs_EDGE) return 0;
92     BRepAdaptor_Curve C(TopoDS::Edge(S));
93     gp_Pnt P;
94     C.D0(Draw::Atof(a[2]),P);
95     DBRep::Set(a[1], BRepBuilderAPI_MakeVertex(P));
96   }
97   else
98   {
99     Handle(DrawTrSurf_Point) aP =
100       Handle(DrawTrSurf_Point)::DownCast(Draw::Get(a[2]));
101     DBRep::Set(a[1], BRepBuilderAPI_MakeVertex(aP->Point()));
102   }
103   return 0;
104 }
105
106 //=======================================================================
107 // range
108 //=======================================================================
109
110 static Standard_Integer range(Draw_Interpretor& , Standard_Integer n, const char** a)
111 {
112   if (n < 4) return 1;
113   TopoDS_Shape aLocalShape(DBRep::Get(a[1],TopAbs_EDGE));
114   TopoDS_Edge E = TopoDS::Edge(aLocalShape);
115 //  TopoDS_Edge E = TopoDS::Edge(DBRep::Get(a[1],TopAbs_EDGE));
116   if (E.IsNull()) return 1;
117   Standard_Real f = Draw::Atof(a[n-2]);
118   Standard_Real l = Draw::Atof(a[n-1]);
119   BRep_Builder B;
120   if (n == 4)
121     B.Range(E,f,l);
122   else {
123     aLocalShape = DBRep::Get(a[2],TopAbs_FACE);
124     TopoDS_Face F = TopoDS::Face(aLocalShape);
125 //    TopoDS_Face F = TopoDS::Face(DBRep::Get(a[2],TopAbs_FACE));
126     if (F.IsNull()) return 1;
127     B.Range(E,F,f,l);
128   }
129   return 0;
130 }
131
132 //=======================================================================
133 // trim
134 //=======================================================================
135
136 static Standard_Integer trim(Draw_Interpretor& di, Standard_Integer n, const char** a)
137 {
138   if (n < 3) return 1;
139   TopoDS_Shape e = DBRep::Get(a[1]);
140   if (e.IsNull()) return 1;
141   if (e.ShapeType() != TopAbs_EDGE) return 1;
142   TopoDS_Shape v1 = DBRep::Get(a[2]);
143   if (v1.IsNull()) return 1;
144   if (v1.ShapeType() != TopAbs_VERTEX) return 1;
145   TopoDS_Shape v2;
146   if (n > 3) {
147     v2 = DBRep::Get(a[3]);
148     if (v2.IsNull()) return 1;
149     if (v2.ShapeType() != TopAbs_VERTEX) return 1;
150   }
151   TopLoc_Location L;
152   Standard_Real f,l;
153   const Handle(Geom_Curve) C = BRep_Tool::Curve(TopoDS::Edge(e),L,f,l);
154   TopLoc_Location LI = L.Inverted();
155   e.Orientation(TopAbs_FORWARD);
156   e.Move(LI);
157   v1.Move(LI);
158   v2.Move(LI);
159   TopoDS_Edge ne;
160   if (v2.IsNull()) {
161     if (v1.Orientation() == TopAbs_REVERSED) {
162       v2 = v1;
163       v1 = TopoDS_Shape();
164     }
165   }
166   BRepBuilderAPI_MakeEdge ME(C,TopoDS::Vertex(v1),TopoDS::Vertex(v2));
167   if (ME.IsDone()) {
168     ne = ME;
169     ne.Move(L);
170     DBRep::Set(a[1],ne);
171   }
172   else {
173     //cout <<"Error creating edge"<<endl;
174     di <<"Error creating edge\n";
175   }
176   return 0;
177 }
178
179
180 //=======================================================================
181 // polyline
182 //=======================================================================
183
184 static Standard_Integer polyline(Draw_Interpretor& , Standard_Integer n, const char** a)
185 {
186   if (n < 8) return 1;
187   if (((n-2) % 3) != 0) return 1;
188   Standard_Integer i, j, np = (n-2) / 3;
189   BRepBuilderAPI_MakePolygon W;
190   j = 2;
191   for (i = 1; i <= np; i ++) {
192     W.Add(gp_Pnt(Draw::Atof(a[j]),Draw::Atof(a[j+1]),Draw::Atof(a[j+2])));
193     j += 3;
194   }
195   DBRep::Set(a[1],W.Wire());
196   return 0;
197 }
198
199 //=======================================================================
200 // polyvertex
201 //=======================================================================
202
203 static Standard_Integer polyvertex(Draw_Interpretor& , Standard_Integer n, const char** a)
204 {
205   if (n < 4) return 1;
206   Standard_Integer i;
207   BRepBuilderAPI_MakePolygon W;
208   for (i = 2; i < n; i ++) {
209     TopoDS_Shape S = DBRep::Get(a[i]);
210     if (S.IsNull()) return 1;
211     if (S.ShapeType() != TopAbs_VERTEX) return 1;
212     W.Add(TopoDS::Vertex(S));
213   }
214   DBRep::Set(a[1],W.Wire());
215   return 0;
216 }
217
218 //=======================================================================
219 // wire
220 //=======================================================================
221
222 static Standard_Integer wire(Draw_Interpretor& di, Standard_Integer n, const char** a)
223 {
224   if (n < 3) return 1;
225   Standard_Integer i;
226   BRepBuilderAPI_MakeWire MW;
227   Standard_Boolean IsUnsorted = !strcmp(a[2], "-unsorted");
228
229   if (!IsUnsorted)
230     for (i = 2; i < n; i ++) {
231       TopoDS_Shape S = DBRep::Get(a[i]);
232       if (S.IsNull()) continue;
233       if (S.ShapeType() == TopAbs_EDGE)
234         MW.Add(TopoDS::Edge(S));
235       else if (S.ShapeType() == TopAbs_WIRE)
236         MW.Add(TopoDS::Wire(S));
237       else
238         continue;
239     }
240   else
241   {
242     TopTools_ListOfShape aLE;
243     for (i = 3; i < n; i ++) 
244     {
245       TopoDS_Shape S = DBRep::Get(a[i]);
246       TopExp_Explorer Exp(S, TopAbs_EDGE);
247       for (;Exp.More();Exp.Next())
248       {
249         const TopoDS_Edge& anE = TopoDS::Edge(Exp.Current()); 
250         if (!anE.IsNull())
251           aLE.Append(anE);
252       }
253     }
254     MW.Add(aLE);
255   }
256
257   if (!MW.IsDone()) {
258     //cout << "Wire not done" << endl;
259     di << "Wire not done with an error:\n";
260     switch (MW.Error()) 
261     {
262     case BRepBuilderAPI_EmptyWire:
263       di << "BRepBuilderAPI_EmptyWire\n";
264       break;
265     case BRepBuilderAPI_DisconnectedWire:
266       di << "BRepBuilderAPI_DisconnectedWire\n";
267       break;
268     case BRepBuilderAPI_NonManifoldWire:
269       di << "BRepBuilderAPI_NonManifoldWire\n";
270       break;
271     default:
272       break;
273     }
274   }
275   else   
276     DBRep::Set(a[1],MW);
277   return 0;
278 }
279
280 //=======================================================================
281 // mkedge
282 //=======================================================================
283
284 static Standard_Integer mkedge(Draw_Interpretor& di, Standard_Integer n, const char** a)
285 {
286   if (n < 3) return 1;
287
288   Handle(Geom_Curve)   C   = DrawTrSurf::GetCurve(a[2]);
289   Handle(Geom2d_Curve) C2d = DrawTrSurf::GetCurve2d(a[2]);
290   if (C.IsNull() && C2d.IsNull()) {
291     //cout << a[2] << " is not a curve" << endl;
292     di << a[2] << " is not a curve\n";
293     return 1;
294   }
295
296   TopoDS_Edge edge;
297
298   if (n == 3) {
299     if (!C.IsNull())   edge = BRepBuilderAPI_MakeEdge(C);
300     else               edge = BRepBuilderAPI_MakeEdge2d(C2d);
301   }
302   else {
303     Handle(Geom_Surface) S;
304     Standard_Integer i = 0;
305     if (!C2d.IsNull()) {
306       S = DrawTrSurf::GetSurface(a[3]);
307       if (!S.IsNull()) i = 1;
308     }
309     TopoDS_Shape aLocalShape(DBRep::Get(a[3+i],TopAbs_VERTEX));
310     TopoDS_Vertex V1 = TopoDS::Vertex(aLocalShape);
311 //    TopoDS_Vertex V1 = TopoDS::Vertex(DBRep::Get(a[3+i],TopAbs_VERTEX));
312     if (n == 5+i) {
313       if (V1.IsNull()) {
314         if (!C.IsNull())   
315           edge = BRepBuilderAPI_MakeEdge(C,Draw::Atof(a[3]),Draw::Atof(a[4]));
316         else if (S.IsNull())              
317           edge = BRepBuilderAPI_MakeEdge2d(C2d,Draw::Atof(a[3]),Draw::Atof(a[4]));
318         else
319           edge = BRepBuilderAPI_MakeEdge(C2d,S,Draw::Atof(a[4]),Draw::Atof(a[5]));
320       }
321       else {
322         aLocalShape = DBRep::Get(a[4+i],TopAbs_VERTEX);
323         TopoDS_Vertex V2 = TopoDS::Vertex(aLocalShape);
324 //  TopoDS_Vertex V2 = TopoDS::Vertex(DBRep::Get(a[4+i],TopAbs_VERTEX));
325         if (!C.IsNull())   
326           edge = BRepBuilderAPI_MakeEdge(C,V1,V2);
327         else if (S.IsNull())              
328           edge = BRepBuilderAPI_MakeEdge2d(C2d,V1,V2);
329         else
330           edge = BRepBuilderAPI_MakeEdge(C2d,S,V1,V2);
331       }
332     }  
333     else if (n == 7+i) {
334       aLocalShape = DBRep::Get(a[5+i],TopAbs_VERTEX);
335       TopoDS_Vertex V2 = TopoDS::Vertex(aLocalShape);
336 //      TopoDS_Vertex V2 = TopoDS::Vertex(DBRep::Get(a[5+i],TopAbs_VERTEX));
337       if (!C.IsNull())   
338         edge = BRepBuilderAPI_MakeEdge(C,V1,V2,Draw::Atof(a[4]),Draw::Atof(a[6]));
339       else if (S.IsNull())         
340         edge = BRepBuilderAPI_MakeEdge2d(C2d,V1,V2,Draw::Atof(a[4]),Draw::Atof(a[6]));
341       else              
342         edge = BRepBuilderAPI_MakeEdge(C2d,S,V1,V2,Draw::Atof(a[5]),Draw::Atof(a[7]));
343     }
344     else
345       return 1;
346   }
347
348   DBRep::Set(a[1],edge);
349   return 0;
350 }
351
352 //=======================================================================
353 // mkcurve
354 //=======================================================================
355 Standard_IMPORT Draw_Color DrawTrSurf_CurveColor(const Draw_Color col);
356 Standard_IMPORT void DBRep_WriteColorOrientation ();
357 Standard_IMPORT Draw_Color DBRep_ColorOrientation (const TopAbs_Orientation Or);
358
359 static Standard_Integer mkcurve(Draw_Interpretor& di, Standard_Integer n, const char** a)
360 {
361   if (n < 3) return 1;
362
363   Standard_Boolean DispOrientation = !strcmp(a[0],"mkoricurve");
364
365   TopoDS_Shape S = DBRep::Get(a[2],TopAbs_EDGE);
366   if (S.IsNull()) return 1;
367   TopLoc_Location L;
368   Standard_Real f,l;
369
370   Handle(Geom_Curve) C = BRep_Tool::Curve(TopoDS::Edge(S),L,f,l);
371   if (C.IsNull()) {
372     //cout << a[2] << " has no 3d curve" << endl;
373     di << a[2] << " has no 3d curve\n";
374     return 1;
375   }
376   C = new Geom_TrimmedCurve(C,f,l);
377
378   Draw_Color col,savecol;
379
380   if ( DispOrientation) {
381     DBRep_WriteColorOrientation ();
382     col = DBRep_ColorOrientation(TopoDS::Edge(S).Orientation());
383     savecol = DrawTrSurf_CurveColor(col);
384   }
385   DrawTrSurf::Set(a[1],C->Transformed(L.Transformation()));
386   if ( DispOrientation) {
387     DrawTrSurf_CurveColor(savecol);
388   }
389
390   return 0;
391 }
392
393 //=======================================================================
394 //function : mkpoint
395 //purpose  : 
396 //=======================================================================
397
398 static Standard_Integer mkpoint(Draw_Interpretor& , 
399   Standard_Integer n, const char** a)
400 {
401   if (n < 3) return 1;
402
403   TopoDS_Shape S = DBRep::Get(a[2],TopAbs_VERTEX);
404   if ( S.IsNull()) return 1;
405
406   TopoDS_Vertex V = TopoDS::Vertex(S);
407
408   gp_Pnt P = BRep_Tool::Pnt(V);
409   DrawTrSurf::Set(a[1],P);
410
411   return 0;
412 }
413
414 //=======================================================================
415 // mk2dcurve
416 //=======================================================================
417
418 static Standard_Integer mk2dcurve(Draw_Interpretor& di, 
419   Standard_Integer na, const char** a)
420 {
421   if (na < 3) return 1;
422
423   TopoDS_Shape S;
424   S = DBRep::Get(a[2],TopAbs_EDGE);
425   if (S.IsNull())
426     return 1;
427
428   TopoDS_Edge E = TopoDS::Edge(S);
429
430   TopLoc_Location L;
431   Standard_Real f = 0., l = 0.;
432   Handle(Geom2d_Curve) C;
433   Handle(Geom_Surface) Surf;
434
435   Standard_Boolean hasFace = Standard_False;
436
437   if ( na == 3 ) {
438     // get the first PCurve connected to edge E
439     BRep_Tool::CurveOnSurface(E,C,Surf,L,f,l);
440   }
441   else if ( na == 4 )
442   {
443     S = DBRep::Get(a[3],TopAbs_FACE);
444     if (S.IsNull())
445     {
446       Standard_Integer ind = Draw::Atoi(a[3]);
447       BRep_Tool::CurveOnSurface(E,C,Surf,L,f,l,ind);
448     }
449     else
450     {
451       hasFace = Standard_True;
452       TopoDS_Face F = TopoDS::Face(S);
453       C = BRep_Tool::CurveOnSurface(E,F,f,l);
454     }
455   }
456
457   if (C.IsNull()) {
458     //cout << a[2] << " has no 2d curve"; if (na == 4) cout << " on " << a[3];
459     //cout << endl;
460     di << a[2] << " has no 2d curve";
461     
462     if (hasFace)
463     {
464       di << " on " << a[3];
465     }
466
467     di << "\n";
468     return 1;
469   }
470   C = new Geom2d_TrimmedCurve(C,f,l);
471   DrawTrSurf::Set(a[1],C);
472
473   return 0;
474 }
475
476 //=======================================================================
477 // edge
478 //=======================================================================
479
480 static Standard_Integer edge(Draw_Interpretor& , Standard_Integer n, const char** a)
481 {
482   if (n < 4) return 1;
483   TopoDS_Shape V1 = DBRep::Get(a[2],TopAbs_VERTEX);
484   TopoDS_Shape V2 = DBRep::Get(a[3],TopAbs_VERTEX);
485   if (V1.IsNull() || V2.IsNull()) return 1;
486   TopoDS_Edge E = BRepBuilderAPI_MakeEdge(TopoDS::Vertex(V1),
487     TopoDS::Vertex(V2));
488   DBRep::Set(a[1],E);
489   return 0;
490 }
491
492 //=======================================================================
493 // isoedge
494 //=======================================================================
495
496 static Standard_Integer isoedge(Draw_Interpretor& , Standard_Integer n, const char** a)
497 {
498   if (n < 6) return 1;
499
500   Standard_Boolean uiso = *a[0] == 'u';
501   Standard_Real p = Draw::Atof(a[3]);
502   Standard_Real p1 = Draw::Atof(a[4]);
503   Standard_Real p2 = Draw::Atof(a[5]);
504   TopoDS_Shape Sh = DBRep::Get(a[2],TopAbs_FACE);
505   if (Sh.IsNull()) return 1;
506   TopLoc_Location Loc;
507   const Handle(Geom_Surface)& S = BRep_Tool::Surface(TopoDS::Face(Sh),Loc);
508   Standard_Real UMin,UMax,VMin,VMax;
509   BRepTools::UVBounds(TopoDS::Face(Sh),UMin,UMax,VMin,VMax);
510   if (uiso) {
511     VMin = Min (VMin , Min (p1,p2));
512     VMax = Max (VMax , Max (p1,p2));
513   }
514   else{
515     UMin = Min (UMin , Min (p1,p2));
516     UMax = Max (VMax , Max (p1,p2));
517   }
518
519   Handle(Geom_RectangularTrimmedSurface) TS = new Geom_RectangularTrimmedSurface(S,UMin,UMax,VMin,VMax);
520   Handle(Geom_Curve) C;
521   Handle(Geom2d_Line) L;
522   if (uiso) {
523     C = TS->UIso(p);
524     L = new Geom2d_Line(gp_Pnt2d(p,0),gp_Dir2d(0,1));
525   }
526   else {
527     C = TS->VIso(p);
528     L = new Geom2d_Line(gp_Pnt2d(0,p),gp_Dir2d(1,0));
529   }
530
531   TopoDS_Edge E = BRepBuilderAPI_MakeEdge(C,p1,p2);
532   E.Location(Loc);
533   BRep_Builder B;
534   B.UpdateEdge(E,L,TopoDS::Face(Sh),0.);
535
536   DBRep::Set(a[1],E);
537   return 0;
538 }
539
540 //=======================================================================
541 // transfert
542 //=======================================================================
543
544 static Standard_Integer transfert(Draw_Interpretor& , Standard_Integer n, const char** a)
545 {
546   if (n < 3) return 1;
547
548   TopoDS_Shape E1 = DBRep::Get(a[1],TopAbs_EDGE);
549   TopoDS_Shape E2 = DBRep::Get(a[2],TopAbs_EDGE);
550   if (E1.IsNull() || E2.IsNull()) return 1;
551
552   BRep_Builder B;
553   B.Transfert(TopoDS::Edge(E1),TopoDS::Edge(E2));
554   return 0;
555 }
556
557 //=======================================================================
558 // profile
559 // command to build a profile
560 //=======================================================================
561
562 static Standard_Integer profile(Draw_Interpretor& di,
563   Standard_Integer n,
564   const char** a)
565 {
566   // this command build a profile
567   // from a moving point
568
569   if (n == 1) {
570     // print help
571
572     //cout << "profile name [code values] [code values] ...\n";
573     //cout << "  Build a profile in the XY plane from a moving point and direction\n";
574     //cout << "  The original point and direction are 0 0 and 1 0\n";
575     //cout << "  Codes and values describe the point or direction change\n";
576     //cout << "  When the point change the direction becomes the tangent\n";
577     //cout << "  All angles are in degree (may be negative)\n";
578     //cout << "  By default the profile is closed and a face is built\n";
579     //cout << "\n";
580     //cout << "  Instruction Parameters         Action\n";
581     //cout << "  O           X Y Z              Set the origin of the plane\n";
582     //cout << "  P           DX DY DZ UX UY UZ  Set the normal and X of the plane\n";
583     //cout << "  S           Face               Set the Plane (Face must be a Face)\n";
584     //cout << "  F           X Y                Set the first point\n";
585     //cout << "  X           DX                 Translate point along X\n";
586     //cout << "  Y           DY                 Translate point along Y\n";
587     //cout << "  L           DL                 Translate point along direction\n";
588     //cout << "  XX          X                  Set point X coordinate\n";
589     //cout << "  YY          Y                  Set point Y coordinate\n";
590     //cout << "  T           DX DY              Translate point\n";
591     //cout << "  TT          X Y                Set point\n";
592     //cout << "  R           Angle              Rotate direction\n";
593     //cout << "  RR          Angle              Set direction\n";
594     //cout << "  D           DX DY              Set direction\n";
595     //cout << "  IX          X                  Intersect with vertical\n";
596     //cout << "  IY          Y                  Intersect with horizontal\n";
597     //cout << "  C           Radius Angle       Arc of circle tangent to direction\n";
598     //cout << "  W                              Make a closed wire\n";
599     //cout << "  WW                             Make an open wire\n";
600     //cout << endl;
601     di << "profile name [code values] [code values] ...\n";
602     di << "  Build a profile in the XY plane from a moving point and direction\n";
603     di << "  The original point and direction are 0 0 and 1 0\n";
604     di << "  Codes and values describe the point or direction change\n";
605     di << "  When the point change the direction becomes the tangent\n";
606     di << "  All angles are in degree (may be negative)\n";
607     di << "  By default the profile is closed and a face is built\n";
608     di << "\n";
609     di << "  Instruction Parameters         Action\n";
610     di << "  O           X Y Z              Set the origin of the plane\n";
611     di << "  P           DX DY DZ UX UY UZ  Set the normal and X of the plane\n";
612     di << "  S           Face               Set the Plane (Face must be a Face)\n";
613     di << "  F           X Y                Set the first point\n";
614     di << "  X           DX                 Translate point along X\n";
615     di << "  Y           DY                 Translate point along Y\n";
616     di << "  L           DL                 Translate point along direction\n";
617     di << "  XX          X                  Set point X coordinate\n";
618     di << "  YY          Y                  Set point Y coordinate\n";
619     di << "  T           DX DY              Translate point\n";
620     di << "  TT          X Y                Set point\n";
621     di << "  R           Angle              Rotate direction\n";
622     di << "  RR          Angle              Set direction\n";
623     di << "  D           DX DY              Set direction\n";
624     di << "  IX          X                  Intersect with vertical\n";
625     di << "  IY          Y                  Intersect with horizontal\n";
626     di << "  C           Radius Angle       Arc of circle tangent to direction\n";
627     di << "  W                              Make a closed wire\n";
628     di << "  WW                             Make an open wire\n";
629     di << "\n";
630     return 0;
631   }
632
633   Standard_Integer i = 2;
634   Standard_Real x0 = 0, y0 = 0, x = 0, y = 0, dx = 1, dy = 0;
635   BRepBuilderAPI_MakeWire MW;
636   gp_Ax3 DummyHP(gp::XOY());
637   gp_Pln P(DummyHP);
638   enum {line , circle, none} move;
639   Standard_Boolean face  = Standard_True;
640   Standard_Boolean close = Standard_True;
641   Standard_Boolean first = Standard_True;
642   Standard_Boolean stayfirst = Standard_False;
643   Standard_Boolean isplanar  = Standard_True;
644   TopoDS_Shape S;
645   TopLoc_Location TheLocation;
646   Handle(Geom_Surface) Surface;
647   while (i < n) {
648
649     Standard_Real length=0,radius=0,angle=0;
650     move = none;
651
652     switch (a[i][0]) {
653
654     case 'F':
655     case 'f':
656       i += 2;
657       if (i >= n) goto badargs;
658       if (!first) {
659         di << "profile: The F instruction must precede all moves";
660         return 1;
661       }
662       x0 = x = Draw::Atof(a[i-1]);
663       y0 = y = Draw::Atof(a[i]);
664       stayfirst = Standard_True;
665       break;
666
667     case 'O':
668     case 'o':
669       i += 3;
670       if (i >= n) goto badargs;
671       P.SetLocation(gp_Pnt(Draw::Atof(a[i-2]),Draw::Atof(a[i-1]),Draw::Atof(a[i])));
672       stayfirst = Standard_True;
673       break;
674
675     case 'P':
676     case 'p':
677       i += 6;
678       if (i >= n) goto badargs;
679       {
680         gp_Vec vn(Draw::Atof(a[i-5]),Draw::Atof(a[i-4]),Draw::Atof(a[i-3]));
681         gp_Vec vx(Draw::Atof(a[i-2]),Draw::Atof(a[i-1]),Draw::Atof(a[i]));
682         if (vn.Magnitude() <= Precision::Confusion()) {
683           di << "profile : null direction";
684           return 1;
685         }
686         if (vx.Magnitude() <= Precision::Confusion()) {
687           di << "profile : null direction";
688           return 1;
689         }
690         gp_Ax2 ax(P.Location(),vn,vx);
691         P.SetPosition(ax);
692       }
693       stayfirst = Standard_True;
694       break;
695
696     case 'S':
697     case 's':
698       i += 1;
699       if (i >= n) goto badargs;
700       {
701         TopoDS_Shape aLocalShape(DBRep::Get(a[i],TopAbs_FACE));
702         TopoDS_Face Face = TopoDS::Face(aLocalShape);
703 //  TopoDS_Face Face = TopoDS::Face(DBRep::Get(a[i],TopAbs_FACE));
704         if (Face.IsNull()) {
705           di << "profile : no face found";
706           return 1;
707         }
708         Surface = BRep_Tool::Surface(Face,TheLocation);
709         Handle(Geom_Plane) Plane = Handle(Geom_Plane)::DownCast(Surface);
710         if ( Plane.IsNull()) {
711           isplanar = Standard_False;
712         }
713         else 
714           P = Plane->Pln();
715       }
716       stayfirst = Standard_True;
717       break;
718
719     case 'X':
720     case 'x':
721       i++;
722       if (i >= n) goto badargs;
723       length = Draw::Atof(a[i]);
724       if ((a[i-1][1] == 'X') || (a[i-1][1] == 'x')) {
725         length -= x;
726       }
727       dx = 1; dy = 0;
728       move = line;
729       break;
730
731     case 'Y':
732     case 'y':
733       i++;
734       if (i >= n) goto badargs;
735       length = Draw::Atof(a[i]);
736       if ((a[i-1][1] == 'Y') || (a[i-1][1] == 'y')) {
737         length -= y;
738       }
739       dx = 0; dy = 1;
740       move = line;
741       break;
742
743     case 'L':
744     case 'l':
745       i++;
746       if (i >= n) goto badargs;
747       length = Draw::Atof(a[i]);
748       move = line;
749       break;
750
751     case 'T':
752     case 't':
753       i += 2;
754       if (i >= n) goto badargs;
755       {
756         Standard_Real vx = Draw::Atof(a[i-1]);
757         Standard_Real vy = Draw::Atof(a[i]);
758         if ((a[i-2][1] == 'T') || (a[i-2][1] == 't')) {
759           vx -= x;
760           vy -= y;
761         }
762         length = Sqrt(vx*vx+vy*vy);
763         if (length > Precision::Confusion()) {
764           move = line;
765           dx = vx / length;
766           dy = vy / length;
767         }
768       }
769       break;
770
771     case 'R':
772     case 'r':
773       i++;
774       if (i >= n) goto badargs;
775       angle = Draw::Atof(a[i]) * (M_PI / 180.0);
776       if ((a[i-1][1] == 'R') || (a[i-1][1] == 'r')) {
777         dx = Cos(angle);
778         dy = Sin(angle);
779       }
780       else {
781         Standard_Real c = Cos(angle);
782         Standard_Real s = Sin(angle);
783         Standard_Real t = c * dx - s * dy;
784         dy = s * dx + c * dy;
785         dx = t;
786       }
787       break;
788
789     case 'D':
790     case 'd':
791       i += 2;
792       if (i >= n) goto badargs;
793       {
794         Standard_Real vx = Draw::Atof(a[i-1]);
795         Standard_Real vy = Draw::Atof(a[i]);
796         length = Sqrt(vx*vx+vy*vy);
797         if (length > Precision::Confusion()) {
798           // move = line; DUB
799           dx = vx / length;
800           dy = vy / length;
801         }
802       }
803       break;
804
805     case 'C':
806     case 'c':
807       i += 2;
808       if (i >= n) goto badargs;
809       radius = Draw::Atof(a[i-1]);
810       if (Abs(radius) > Precision::Confusion()) {
811         angle = Draw::Atof(a[i]) * (M_PI / 180.0);
812         move = circle;
813       }
814       break;
815
816     case 'I':
817     case 'i':
818       i++;
819       if (i >= n) goto badargs;
820       length = Draw::Atof(a[i]);
821       if ((a[i-1][1] == 'X') || (a[i-1][1] == 'x')) {
822         if (Abs(dx) < Precision::Confusion()) {
823           di << "Profile : cannot intersect, arg " << i-1;
824           return 1;
825         }
826         length = (length - x) / dx;
827         move = line;
828       }
829       else if ((a[i-1][1] == 'Y') || (a[i-1][1] == 'y')) {
830         if (Abs(dy) < Precision::Confusion()) {
831           di << "Profile : cannot intersect, arg " << i-1;
832           return 1;
833         }
834         length = (length - y) / dy;
835         move = line;
836       }
837
838       break;
839
840     case 'W':
841     case 'w':
842       face = Standard_False;
843       if ((a[i][1] == 'W') || (a[i][1] == 'w')) {
844         close = Standard_False;
845       }
846       i = n-1;
847       break;
848
849     default:
850       di <<"profile : unknown code " << a[i];
851       return 1;
852     }
853
854 again:
855
856     switch (move) {
857
858     case line :
859       {
860         if (length < 0) {
861           length = -length;
862           dx = -dx;
863           dy = -dy;
864         }
865         Handle(Geom2d_Line) l = 
866           new Geom2d_Line(gp_Pnt2d(x,y),gp_Dir2d(dx,dy));
867         if (isplanar)
868           MW.Add(BRepBuilderAPI_MakeEdge(GeomAPI::To3d(l,P),0,length));
869         else 
870           MW.Add(BRepBuilderAPI_MakeEdge(l,Surface,0,length));
871         x += length*dx;
872         y += length*dy;
873       }
874       break;
875
876     case circle :
877       {
878         Standard_Boolean sense = Standard_True;
879         if (radius < 0) {
880           radius = -radius;
881           sense = !sense;
882           dx = -dx;
883           dy = -dy;
884         }
885         gp_Ax2d ax(gp_Pnt2d(x-radius*dy,y+radius*dx),gp_Dir2d(dy,-dx));
886         if (angle < 0) {
887           angle = -angle;
888           sense = !sense;
889         }
890         Handle(Geom2d_Circle) c = new Geom2d_Circle(ax,radius,sense);
891         if (isplanar)
892           MW.Add(BRepBuilderAPI_MakeEdge(GeomAPI::To3d(c,P),0,angle));
893         else
894           MW.Add(BRepBuilderAPI_MakeEdge(c,Surface,0,angle));
895         gp_Pnt2d p;
896         gp_Vec2d v;
897         c->D1(angle,p,v);
898         x = p.X();
899         y = p.Y();
900         dx = v.X() / radius;
901         dy = v.Y() / radius;
902       }
903       break;
904
905     case none:
906       break;
907     }
908
909     // update first
910     first = stayfirst;
911     stayfirst = Standard_False;
912
913     // next segment....
914     i++;
915     if ((i == n) && close) {
916       // the closing segment
917       dx = x0-x;
918       dy = y0-y;
919       length = Sqrt(dx*dx+dy*dy);
920       if (length > Precision::Confusion()) {
921         move = line;
922         dx = dx / length;
923         dy = dy / length;
924         goto again;
925       }
926     }
927   }
928
929
930   // get the result, face or wire
931
932   if (face) {
933     if ( isplanar)
934       S = BRepBuilderAPI_MakeFace(P,MW.Wire());
935     else {
936       BRepBuilderAPI_MakeFace MFace;
937       MFace.Init(Surface,Standard_False,Precision::Confusion());
938       MFace.Add(MW.Wire());
939       S = MFace.Face();
940     }
941   }
942   else {
943     S = MW;
944   }
945
946   if (!TheLocation.IsIdentity())
947     S.Move(TheLocation);
948
949   if ( !isplanar) {
950     Standard_Real Tol = 1.e-5;
951     BRepLib::BuildCurves3d(S,Tol);
952   }
953
954   DBRep::Set(a[1],S);
955
956   return 0;
957
958 badargs:
959   di << "profile : bad number of arguments";
960   return 1;
961 }
962 //=======================================================================
963 // profile
964 // command to build a profile
965 //=======================================================================
966
967 static Standard_Integer bsplineprof(Draw_Interpretor& di,
968   Standard_Integer n,
969   const char** a)
970 {
971   // this command build a profile
972   // from a moving point
973
974   if (n == 1) {
975     // print help
976
977     //cout << " bsplineprof name [S face] [W WW]  "              << endl;
978     //cout << " for an edge : <digitizes> ... <mouse button 2> " << endl ;
979     //cout << " to end profile : <mouse button 3> "              << endl ;
980     //cout << "  Build a profile in the XY plane from digitizes" << endl ;
981     //cout << "  By default the profile is closed and a face is built\n";
982     //cout << "\n";
983     //cout << "  W                              Make a closed wire\n";
984     //cout << "  WW                             Make an open wire\n";
985     //cout << endl;
986     di << " bsplineprof name [S face] [W WW]  "              << "\n";
987     di << " for an edge : <digitizes> ... <mouse button 2> " <<  "\n";
988     di << " to end profile : <mouse button 3> "              <<  "\n";
989     di << "  Build a profile in the XY plane from digitizes" <<  "\n";
990     di << "  By default the profile is closed and a face is built\n";
991     di << "\n";
992     di << "  W                              Make a closed wire\n";
993     di << "  WW                             Make an open wire\n";
994     di << "\n";
995     return 0;
996   }
997
998   gp_Pnt2d last_point(0.0e0,
999     0.0e0) ;
1000   gp_Pnt2d first_point(0.0e0,
1001     0.0e0) ;
1002   Standard_Integer i = 2;
1003   Standard_Boolean wait = Standard_True;
1004 //  Standard_Real x0 = 0, y0 = 0, x = 0, y = 0, dx = 1, dy = 0;
1005   Standard_Real x = 0, y = 0, dx = 1, dy = 0;
1006   BRepBuilderAPI_MakeWire MW;
1007   gp_Ax3 DummyHP(gp::XOY());
1008   gp_Pln P(DummyHP);
1009   Standard_Boolean face  = Standard_True;
1010   Standard_Boolean close = Standard_True;
1011 //  Standard_Boolean first = Standard_True;
1012   Standard_Boolean isplanar  = Standard_True;
1013   Standard_Real  length ; 
1014   TopoDS_Shape S;
1015   TopLoc_Location TheLocation;
1016   Handle(Geom_Surface) Surface;
1017   if (n > 2) {
1018     while (i < n) {
1019
1020       switch (a[i][0]) {
1021
1022       case 'S':
1023       case 's':
1024         i += 1;
1025         {
1026           TopoDS_Shape aLocalShape(DBRep::Get(a[i],TopAbs_FACE));
1027           TopoDS_Face Face = TopoDS::Face(aLocalShape);
1028 //    TopoDS_Face Face = TopoDS::Face(DBRep::Get(a[i],TopAbs_FACE));
1029           if (Face.IsNull()) {
1030             di << "profile : no face found";
1031             return 1;
1032           }
1033           Surface = BRep_Tool::Surface(Face,TheLocation);
1034           Handle(Geom_Plane) Plane = Handle(Geom_Plane)::DownCast(Surface);
1035           if ( Plane.IsNull()) {
1036             isplanar = Standard_False;
1037           }
1038           else 
1039             P = Plane->Pln();
1040         }
1041         i += 1 ;
1042         break;
1043
1044       case 'W':
1045       case 'w':
1046         face = Standard_False;
1047         if ((a[i][1] == 'W') || (a[i][1] == 'w')) {
1048           close = Standard_False;
1049         }
1050         i = n-1;
1051         break;
1052
1053       default:
1054         di <<"profile : unknown code " << a[i];
1055         return 1;
1056       }
1057     }
1058   }
1059 //
1060 //  to be done : close the profile using the first point of the contour
1061 //               and the point taken with mouse button 3 
1062 //
1063   Handle(Geom2d_BSplineCurve) C ;
1064   Handle(Geom_Curve) curve3d_ptr ;
1065   Standard_Integer id, ii;
1066   Standard_Integer X,Y,b, not_done;
1067   Standard_Integer num_points = 0  ;
1068   gp_Pnt2d a_point(  0.0e0,
1069     0.0e0) ;
1070   Handle(TColgp_HArray1OfPnt2d) points_array_ptr = 
1071     new TColgp_HArray1OfPnt2d(1, 1);               
1072   Handle(TColgp_HArray1OfPnt2d) new_points_array_ptr ;
1073
1074   not_done = 1 ;
1075   while (not_done) {
1076
1077     dout.Select(id,X,Y,b,wait);
1078     Standard_Real z = dout.Zoom(id);
1079     a_point.SetCoord(1,(Standard_Real)X /z) ;
1080     a_point.SetCoord(2,(Standard_Real)Y /z) ;
1081     if (num_points == 0) {
1082       points_array_ptr = 
1083         new TColgp_HArray1OfPnt2d(1, 1); 
1084       points_array_ptr->ChangeArray1()(1) = a_point ;
1085       first_point = a_point ;
1086
1087     }
1088     num_points += 1 ;
1089     if (num_points >= 2) {
1090       new_points_array_ptr = 
1091         new TColgp_HArray1OfPnt2d(1, num_points);
1092       for (ii = 1 ; ii <= num_points -1 ; ii++) {
1093         new_points_array_ptr->ChangeArray1()(ii) =
1094           points_array_ptr->Array1()(ii) ;
1095       }
1096       new_points_array_ptr->ChangeArray1()(num_points) = a_point ;
1097       Geom2dAPI_Interpolate    a2dInterpolator(new_points_array_ptr,
1098         Standard_False,
1099         1.0e-5) ;
1100       a2dInterpolator.Perform() ;
1101       if (a2dInterpolator.IsDone()) { 
1102         C = a2dInterpolator.Curve() ;
1103         curve3d_ptr =
1104           GeomAPI::To3d(C,P) ;
1105         DrawTrSurf::Set(a[1], curve3d_ptr);
1106         dout.RepaintView(id);
1107       }
1108       points_array_ptr = new_points_array_ptr ;
1109
1110     }
1111
1112     if (b == 2 || b == 3) {
1113       if (num_points == 2)  {
1114         x = last_point.Coord(1) ;
1115         y = last_point.Coord(2) ;
1116         dx = a_point.Coord(1) - x ;
1117         dy = a_point.Coord(2) - y ;
1118         gp_Vec2d a_vector(dx,
1119           dy) ;
1120         length = a_vector.Magnitude() ;
1121         Handle(Geom2d_Line) l = 
1122           new Geom2d_Line(gp_Pnt2d(x,y),gp_Dir2d(dx,dy));
1123         if (isplanar) {
1124           MW.Add(BRepBuilderAPI_MakeEdge(GeomAPI::To3d(l,P),0,length));
1125         }
1126         else { 
1127           MW.Add(BRepBuilderAPI_MakeEdge(l,Surface,0,length));
1128         }
1129
1130       }
1131       else if (num_points > 2) {
1132         if (isplanar) {
1133           MW.Add(BRepBuilderAPI_MakeEdge(curve3d_ptr,
1134             curve3d_ptr->FirstParameter(),
1135             curve3d_ptr->LastParameter()));
1136         }
1137         else { 
1138           MW.Add(BRepBuilderAPI_MakeEdge(C,
1139             Surface,
1140             C->FirstParameter(),
1141             C->LastParameter()));
1142         }
1143       }
1144       if (num_points >= 2) {
1145         last_point = a_point ;
1146         points_array_ptr->ChangeArray1()(1) = a_point ;
1147         num_points = 1 ;
1148         DBRep::Set(a[1], MW.Wire()) ;
1149       }      
1150
1151
1152     }
1153     if (b == 3) {
1154       not_done = 0 ; 
1155     }
1156   }
1157   a_point = first_point ;
1158   if (close) {
1159
1160     x = last_point.Coord(1) ;
1161     y = last_point.Coord(2) ;
1162     dx = a_point.Coord(1) - x ;
1163     dy = a_point.Coord(2) - y ;
1164     gp_Vec2d a_vector(dx,
1165       dy) ;
1166     length = a_vector.Magnitude() ;
1167     Handle(Geom2d_Line) l = 
1168       new Geom2d_Line(gp_Pnt2d(x,y),gp_Dir2d(dx,dy));
1169     if (isplanar)
1170       MW.Add(BRepBuilderAPI_MakeEdge(GeomAPI::To3d(l,P),0,length));
1171     else 
1172       MW.Add(BRepBuilderAPI_MakeEdge(l,Surface,0,length));
1173   }
1174   if (face) {
1175     if ( isplanar)
1176       S = BRepBuilderAPI_MakeFace(P,MW.Wire());
1177     else {
1178       BRepBuilderAPI_MakeFace MFace;
1179       MFace.Init(Surface,Standard_False,Precision::Confusion());
1180       MFace.Add(MW.Wire());
1181       S = MFace.Face();
1182     }
1183   }
1184   else {
1185     S = MW;
1186   }
1187
1188   if (!TheLocation.IsIdentity())
1189     S.Move(TheLocation);
1190
1191   if ( !isplanar) {
1192     Standard_Real Tol = 1.e-5;
1193     BRepLib::BuildCurves3d(S,Tol);
1194   }
1195
1196   DBRep::Set(a[1],S);
1197
1198   return 0;
1199 }
1200
1201
1202
1203 //=======================================================================
1204 // 2dprofile
1205 // command to build a profile
1206 //=======================================================================
1207
1208 static Standard_Integer profile2d(Draw_Interpretor& di, 
1209   Standard_Integer n, 
1210   const char** a)
1211 {
1212   // this command build a profile with 2d curves.
1213   // from a moving point
1214
1215   if (n == 1) {
1216     // print help
1217
1218     //cout << "profile name [code values] [code values] ...\n";
1219     //cout << "  Build a profile in the UV plane from a moving point and direction\n";
1220     //cout << "  The original point and direction are 0 0 and 1 0\n";
1221     //cout << "  Codes and values describe the point or direction change\n";
1222     //cout << "  When the point change the direction becomes the tangent\n";
1223     //cout << "  All angles are in degree (may be negative)\n";
1224     //cout << "  By default the profile is closed \n";
1225     //cout << "\n";
1226     //cout << "  Instruction Parameters         Action\n";
1227     //cout << "  F           X Y                Set the first point\n";
1228     //cout << "  X           DX                 Translate point along X\n";
1229     //cout << "  Y           DY                 Translate point along Y\n";
1230     //cout << "  L           DL                 Translate point along direction\n";
1231     //cout << "  XX          X                  Set point X coordinate\n";
1232     //cout << "  YY          Y                  Set point Y coordinate\n";
1233     //cout << "  T           DX DY              Translate point\n";
1234     //cout << "  TT          X Y                Set point\n";
1235     //cout << "  R           Angle              Rotate direction\n";
1236     //cout << "  RR          Angle              Set direction\n";
1237     //cout << "  D           DX DY              Set direction\n";
1238     //cout << "  IX          X                  Intersect with vertical\n";
1239     //cout << "  IY          Y                  Intersect with horizontal\n";
1240     //cout << "  C           Radius Angle       Arc of circle tangent to direction\n";
1241     //cout << "  W                              Make a closed wire\n";
1242     //cout << endl;
1243     di << "profile name [code values] [code values] ...\n";
1244     di << "  Build a profile in the UV plane from a moving point and direction\n";
1245     di << "  The original point and direction are 0 0 and 1 0\n";
1246     di << "  Codes and values describe the point or direction change\n";
1247     di << "  When the point change the direction becomes the tangent\n";
1248     di << "  All angles are in degree (may be negative)\n";
1249     di << "  By default the profile is closed \n";
1250     di << "\n";
1251     di << "  Instruction Parameters         Action\n";
1252     di << "  F           X Y                Set the first point\n";
1253     di << "  X           DX                 Translate point along X\n";
1254     di << "  Y           DY                 Translate point along Y\n";
1255     di << "  L           DL                 Translate point along direction\n";
1256     di << "  XX          X                  Set point X coordinate\n";
1257     di << "  YY          Y                  Set point Y coordinate\n";
1258     di << "  T           DX DY              Translate point\n";
1259     di << "  TT          X Y                Set point\n";
1260     di << "  R           Angle              Rotate direction\n";
1261     di << "  RR          Angle              Set direction\n";
1262     di << "  D           DX DY              Set direction\n";
1263     di << "  IX          X                  Intersect with vertical\n";
1264     di << "  IY          Y                  Intersect with horizontal\n";
1265     di << "  C           Radius Angle       Arc of circle tangent to direction\n";
1266     di << "  W                              Make a closed wire\n";
1267     di << "\n";
1268     return 0;
1269   }
1270
1271   Standard_Integer i = 2, NbCurves = 0;
1272   Standard_Real x0 = 0, y0 = 0, x = 0, y = 0, dx = 1, dy = 0;
1273   enum {line , circle, none} move;
1274   Standard_Boolean close = Standard_True;
1275   Standard_Boolean first = Standard_True;
1276   Standard_Boolean stayfirst = Standard_False;
1277   char*  name = new char[100];
1278
1279   while (i < n) {
1280
1281     Standard_Real length=0,radius=0,angle=0;
1282     move = none;
1283
1284     switch (a[i][0]) {
1285
1286     case 'F':
1287     case 'f':
1288       i += 2;
1289       if (i >= n) goto badargs;
1290       if (!first) {
1291         di << "profile: The F instruction must precede all moves";
1292         return 1;
1293       }
1294       x0 = x = Draw::Atof(a[i-1]);
1295       y0 = y = Draw::Atof(a[i]);
1296       stayfirst = Standard_True;
1297       break;
1298
1299     case 'X':
1300     case 'x':
1301       i++;
1302       if (i >= n) goto badargs;
1303       length = Draw::Atof(a[i]);
1304       if ((a[i-1][1] == 'X') || (a[i-1][1] == 'x')) {
1305         length -= x;
1306       }
1307       dx = 1; dy = 0;
1308       move = line;
1309       break;
1310
1311     case 'Y':
1312     case 'y':
1313       i++;
1314       if (i >= n) goto badargs;
1315       length = Draw::Atof(a[i]);
1316       if ((a[i-1][1] == 'Y') || (a[i-1][1] == 'y')) {
1317         length -= y;
1318       }
1319       dx = 0; dy = 1;
1320       move = line;
1321       break;
1322
1323     case 'L':
1324     case 'l':
1325       i++;
1326       if (i >= n) goto badargs;
1327       length = Draw::Atof(a[i]);
1328       move = line;
1329       break;
1330
1331     case 'T':
1332     case 't':
1333       i += 2;
1334       if (i >= n) goto badargs;
1335       {
1336         Standard_Real vx = Draw::Atof(a[i-1]);
1337         Standard_Real vy = Draw::Atof(a[i]);
1338         if ((a[i-2][1] == 'T') || (a[i-2][1] == 't')) {
1339           vx -= x;
1340           vy -= y;
1341         }
1342         length = Sqrt(vx*vx+vy*vy);
1343         if (length > Precision::Confusion()) {
1344           move = line;
1345           dx = vx / length;
1346           dy = vy / length;
1347         }
1348       }
1349       break;
1350
1351     case 'R':
1352     case 'r':
1353       i++;
1354       if (i >= n) goto badargs;
1355       angle = Draw::Atof(a[i]) * (M_PI / 180.0);
1356       if ((a[i-1][1] == 'R') || (a[i-1][1] == 'r')) {
1357         dx = Cos(angle);
1358         dy = Sin(angle);
1359       }
1360       else {
1361         Standard_Real c = Cos(angle);
1362         Standard_Real s = Sin(angle);
1363         Standard_Real t = c * dx - s * dy;
1364         dy = s * dx + c * dy;
1365         dx = t;
1366       }
1367       break;
1368
1369     case 'D':
1370     case 'd':
1371       i += 2;
1372       if (i >= n) goto badargs;
1373       {
1374         Standard_Real vx = Draw::Atof(a[i-1]);
1375         Standard_Real vy = Draw::Atof(a[i]);
1376         length = Sqrt(vx*vx+vy*vy);
1377         if (length > Precision::Confusion()) {
1378           // move = line; DUB
1379           dx = vx / length;
1380           dy = vy / length;
1381         }
1382       }
1383       break;
1384
1385     case 'C':
1386     case 'c':
1387       i += 2;
1388       if (i >= n) goto badargs;
1389       radius = Draw::Atof(a[i-1]);
1390       if (Abs(radius) > Precision::Confusion()) {
1391         angle = Draw::Atof(a[i]) * (M_PI / 180.0);
1392         move = circle;
1393       }
1394       break;
1395
1396     case 'I':
1397     case 'i':
1398       i++;
1399       if (i >= n) goto badargs;
1400       length = Draw::Atof(a[i]);
1401       if ((a[i-1][1] == 'X') || (a[i-1][1] == 'x')) {
1402         if (Abs(dx) < Precision::Confusion()) {
1403           di << "Profile : cannot intersect, arg " << i-1;
1404           return 1;
1405         }
1406         length = (length - x) / dx;
1407         move = line;
1408       }
1409       else if ((a[i-1][1] == 'Y') || (a[i-1][1] == 'y')) {
1410         if (Abs(dy) < Precision::Confusion()) {
1411           di << "Profile : cannot intersect, arg " << i-1;
1412           return 1;
1413         }
1414         length = (length - y) / dy;
1415         move = line;
1416       }
1417
1418       break;
1419
1420     case 'W':
1421     case 'w':
1422       close = Standard_False;
1423       i = n-1;
1424       break;
1425
1426     default:
1427       di <<"profile : unknown code " << a[i];
1428       return 1;
1429     }
1430
1431 again:
1432
1433     switch (move) {
1434
1435     case line :
1436       {
1437         if (length < 0) {
1438           length = -length;
1439           dx = -dx;
1440           dy = -dy;
1441         }
1442         Handle(Geom2d_Line) l = new Geom2d_Line(gp_Pnt2d(x,y),gp_Dir2d(dx,dy));
1443         Handle(Geom2d_TrimmedCurve) ct = 
1444           new Geom2d_TrimmedCurve(l,0,length);
1445         NbCurves++;
1446         Sprintf(name,"%s_%d",a[1],NbCurves);
1447         DrawTrSurf::Set(name,ct);
1448         di.AppendElement(name);
1449         x += length*dx;
1450         y += length*dy;
1451       }
1452       break;
1453
1454     case circle :
1455       {
1456         Standard_Boolean sense = Standard_True;
1457         if (radius < 0) {
1458           radius = -radius;
1459           sense = !sense;
1460           dx = -dx;
1461           dy = -dy;
1462         }
1463         gp_Ax2d ax(gp_Pnt2d(x-radius*dy,y+radius*dx),gp_Dir2d(dy,-dx));
1464         if (angle < 0) {
1465           angle = -angle;
1466           sense = !sense;
1467         }
1468         Handle(Geom2d_Circle) c = new Geom2d_Circle(ax,radius,sense);
1469         Handle(Geom2d_TrimmedCurve) ct = 
1470           new Geom2d_TrimmedCurve(c,0,angle);
1471         NbCurves++;
1472         Sprintf(name,"%s_%d",a[1],NbCurves);
1473         DrawTrSurf::Set(name,ct);       
1474         di.AppendElement(name);
1475         gp_Pnt2d p;
1476         gp_Vec2d v;
1477         c->D1(angle,p,v);
1478         x = p.X();
1479         y = p.Y();
1480         dx = v.X() / radius;
1481         dy = v.Y() / radius;
1482       }
1483       break;
1484
1485     case none:
1486       break;
1487     }
1488
1489     // update first
1490     first = stayfirst;
1491     stayfirst = Standard_False;
1492
1493     // next segment....
1494     i++;
1495     if ((i == n) && close) {
1496       // the closing segment
1497       dx = x0-x;
1498       dy = y0-y;
1499       length = Sqrt(dx*dx+dy*dy);
1500       if (length > Precision::Confusion()) {
1501         move = line;
1502         dx = dx / length;
1503         dy = dy / length;
1504         goto again;
1505       }
1506     }
1507   }
1508   const char* aName;
1509   aName = "CurX";
1510   Draw::Set(aName, x);
1511   aName = "CurY";
1512   Draw::Set(aName, y);
1513   aName = "CurDX";
1514   Draw::Set(aName, dx);
1515   aName = "CurDY";
1516   Draw::Set(aName, dy);
1517
1518   return 0;
1519
1520 badargs:
1521   di << "profile : bad number of arguments";
1522   return 1;
1523 }
1524
1525
1526
1527 //=======================================================================
1528 //function : mkoffset
1529 //purpose  : 
1530 //=======================================================================
1531
1532 Standard_Integer mkoffset(Draw_Interpretor& di, 
1533   Standard_Integer n, const char** a)
1534 {
1535   if (n < 5) return 1;
1536   char name[100];
1537
1538   BRepOffsetAPI_MakeOffset Paral;
1539   GeomAbs_JoinType theJoinType = GeomAbs_Arc;
1540   if (n >= 6 && strcmp(a[5], "i") == 0)
1541     theJoinType = GeomAbs_Intersection;
1542   Paral.Init(theJoinType);
1543   TopoDS_Shape Base = DBRep::Get(a[2],TopAbs_FACE);
1544
1545   if ( Base.IsNull())
1546   {
1547     Base = DBRep::Get(a[2]);
1548     if (Base.IsNull()) return 1;
1549     Paral.Init(theJoinType);
1550     TopExp_Explorer exp;
1551     for (exp.Init(Base,TopAbs_WIRE); exp.More(); exp.Next())
1552     {
1553       TopoDS_Wire aLocalShape = TopoDS::Wire(exp.Current());
1554       Paral.AddWire(aLocalShape);
1555     }
1556   }
1557   else
1558   {
1559     Base.Orientation(TopAbs_FORWARD);
1560     Paral.Init(TopoDS::Face(Base), theJoinType);
1561   }
1562
1563   Standard_Real U, dU;
1564   Standard_Integer Nb;
1565   dU = Draw::Atof(a[4]);
1566   Nb = Draw::Atoi(a[3]);
1567
1568   Standard_Real Alt = 0.;
1569   if ( n == 7)
1570     Alt = Draw::Atof(a[6]);
1571
1572   Standard_Integer Compt = 1;
1573
1574   for ( Standard_Integer i = 1; i <= Nb; i++)
1575   {
1576     U = i * dU;
1577     Paral.Perform(U,Alt);
1578
1579     if ( !Paral.IsDone())
1580     {
1581       di << " Error: Offset is not done.\n";
1582       return 1;
1583     }
1584     else
1585     {
1586       Sprintf(name,"%s_%d", a[1], Compt++);
1587       char* temp = name; // portage WNT
1588       DBRep::Set(temp,Paral.Shape());
1589     }
1590   }
1591
1592   return 0;
1593 }
1594
1595 //=======================================================================
1596 //function : openoffset
1597 //purpose  : 
1598 //=======================================================================
1599
1600 Standard_Integer openoffset(Draw_Interpretor& di, 
1601   Standard_Integer n, const char** a)
1602 {
1603   if (n < 5) return 1;
1604   char name[100];
1605
1606   BRepOffsetAPI_MakeOffset Paral;
1607   GeomAbs_JoinType theJoinType = GeomAbs_Arc;
1608   if (n == 6 && strcmp(a[5], "i") == 0)
1609     theJoinType = GeomAbs_Intersection;
1610   Paral.Init(theJoinType, Standard_True);
1611   TopoDS_Shape Base = DBRep::Get(a[2] ,TopAbs_FACE);
1612
1613   if ( Base.IsNull())
1614   {
1615     Base = DBRep::Get(a[2], TopAbs_WIRE);
1616     if (Base.IsNull()) return 1;
1617     Paral.AddWire(TopoDS::Wire(Base));
1618   }
1619   else
1620   {
1621     Base.Orientation(TopAbs_FORWARD);
1622     Paral.Init(TopoDS::Face(Base), theJoinType, Standard_True);
1623   }
1624
1625   Standard_Real U, dU;
1626   Standard_Integer Nb;
1627   dU = Draw::Atof(a[4]);
1628   Nb = Draw::Atoi(a[3]);
1629
1630   Standard_Real Alt = 0.;
1631
1632   Standard_Integer Compt = 1;
1633
1634   for ( Standard_Integer i = 1; i <= Nb; i++)
1635   {
1636     U = i * dU;
1637     Paral.Perform(U,Alt);
1638
1639     if ( !Paral.IsDone())
1640     {
1641       di << " Error: Offset is not done.\n";
1642       return 1;
1643     }
1644     else
1645     {
1646       Sprintf(name,"%s_%d", a[1], Compt++);
1647       char* temp = name; // portage WNT
1648       DBRep::Set(temp,Paral.Shape());
1649     }
1650   }
1651
1652   return 0;
1653 }
1654
1655 //=======================================================================
1656 //function : pickface
1657 //purpose  : 
1658 //=======================================================================
1659
1660 Standard_Integer pickface(Draw_Interpretor& di, 
1661   Standard_Integer , const char** )
1662 {
1663   Standard_CString pick_name=".";
1664
1665   TopoDS_Shape S = DBRep::Get(pick_name,TopAbs_FACE);
1666   if (S.IsNull()) return 1;
1667
1668   char* name = new char[100];
1669   Sprintf(name,"PickedFace %s",pick_name);
1670   DBRep::Set(name,S);
1671   di.AppendElement(name);
1672   return 0;
1673 }
1674
1675
1676 Standard_Integer edgeintersector(Draw_Interpretor& di,
1677   Standard_Integer n, const char** a)
1678 {
1679   if (n < 5) return 1;
1680
1681   TopoDS_Edge E[2];
1682   TopoDS_Shape aLocalShape(DBRep::Get(a[2],TopAbs_EDGE));
1683   E[0] = TopoDS::Edge(aLocalShape);
1684 //  E[0] = TopoDS::Edge(DBRep::Get(a[2],TopAbs_EDGE));
1685   if ( E[0].IsNull()) return 1;
1686   aLocalShape = DBRep::Get(a[3],TopAbs_EDGE);
1687   E[1] = TopoDS::Edge(aLocalShape);
1688 //  E[1] = TopoDS::Edge(DBRep::Get(a[3],TopAbs_EDGE));
1689   if ( E[1].IsNull()) return 1;
1690   aLocalShape = DBRep::Get(a[4],TopAbs_FACE);
1691   TopoDS_Face F  = TopoDS::Face(aLocalShape);
1692 //  TopoDS_Face F  = TopoDS::Face(DBRep::Get(a[4],TopAbs_FACE));
1693   if ( F.IsNull()) return 1;
1694
1695   TopOpeBRep_EdgesIntersector EInter;
1696   char name[100];
1697   //------------------------------------------------------
1698   // Calculate point of intersection 2D
1699   //-----------------------------------------------------
1700   EInter.SetFaces(F,F);
1701   Standard_Real TolInter = 1.e-7;
1702   if (n == 6) TolInter = Draw::Atof(a[5]);
1703   EInter.ForceTolerances(TolInter,TolInter);
1704   Standard_Boolean reducesegments = Standard_True;
1705   EInter.Perform (E[0],E[1],reducesegments);
1706
1707   if (EInter.IsEmpty()) {
1708     //cout << " No intersection found" << endl;
1709     di << " No intersection found\n";
1710     return 0;
1711   }
1712
1713   BRep_Builder B;
1714
1715   Standard_Integer NbV = 0;
1716   Standard_Real Tol = Precision::PConfusion();
1717
1718   Standard_Boolean rejectreducedsegmentpoints = Standard_True;
1719   EInter.InitPoint(rejectreducedsegmentpoints);
1720   for (;EInter.MorePoint();EInter.NextPoint()) {
1721     const TopOpeBRep_Point2d& P2D = EInter.Point();
1722     gp_Pnt           P    = P2D.Value();
1723     TopoDS_Vertex    V    = BRepLib_MakeVertex(P);
1724     NbV ++;
1725     Sprintf(name,"%s_%d",a[1],NbV);
1726     DBRep::Set(name,V);
1727     for (Standard_Integer i = 1; i <= 2; i++) {
1728       //---------------------------------------------------------------
1729       // to be able to rank parameter on edge
1730       // it is necessary to code it internally
1731       //---------------------------------------------------------------
1732       Standard_Real U = P2D.Parameter(i);
1733
1734       V.Orientation(TopAbs_INTERNAL);
1735       B.UpdateVertex(V,U,E[i-1],Tol);
1736       //      B.UpdateVertex(TopoDS::Vertex(V.Oriented(TopAbs_INTERNAL)),
1737       //                     U,E[i-1],Tol);
1738       //---------------------------------------------------------------
1739       // Orientation of vertex in the transition.
1740       //---------------------------------------------------------------
1741       TopAbs_Orientation OO = TopAbs_REVERSED;
1742       if (P2D.IsVertex(i)) {
1743         OO = P2D.Vertex(i).Orientation();
1744       }
1745       else if (P2D.Transition(i).Before() == TopAbs_OUT) {
1746         OO = TopAbs_FORWARD;
1747       }
1748       //cout << " Orientation of vertex " << NbV << " on " << a[i+1] << ": ";
1749       di << " Orientation of vertex " << NbV << " on " << a[i+1] << ": ";
1750       if (OO == TopAbs_FORWARD) {
1751         //cout << "FORWARD" << endl;
1752         di << "FORWARD\n";
1753       } else {
1754         //cout << "REVERSED" << endl;
1755         di << "REVERSED\n";
1756       }
1757     }
1758   }
1759   //POP pour NT
1760   return 0;
1761
1762 }
1763
1764 //=======================================================================
1765 //function : concatC0wire
1766 //purpose  : 
1767 //=======================================================================
1768
1769 Standard_Integer concatC0wire(Draw_Interpretor&, Standard_Integer n, const char** c)
1770 {
1771   if ( n < 3 ) return 1;                               
1772
1773   TopoDS_Shape S = DBRep::Get(c[2],TopAbs_WIRE) ;
1774
1775   if (S.IsNull())
1776     return 1;                            //test if the shape is empty
1777
1778   TopoDS_Wire W = TopoDS::Wire(S) ;
1779   TopoDS_Shape res;
1780
1781
1782   res = BRepAlgo::ConcatenateWireC0(W);              //treatment
1783   DBRep::Set(c[1], res);
1784   return 0;
1785 }
1786
1787 //=======================================================================
1788 //function : concatwire
1789 //purpose  : reduce the multiply degree of the knots to the minimum without
1790 //           changing the geometry
1791 //=======================================================================
1792
1793 static Standard_Integer concatwire(Draw_Interpretor&, Standard_Integer n, const char** c)
1794 {
1795   GeomAbs_Shape Option=GeomAbs_C1;
1796   if ( n < 3 ) return 1;
1797
1798   if(n==4)                                              //check if it's C1 or G1
1799   if (! strcmp(c[3],"G1"))
1800     Option=GeomAbs_G1;
1801
1802   TopoDS_Shape S = DBRep::Get(c[2],TopAbs_WIRE) ;
1803
1804   if (S.IsNull()) return 1 ;                            //test if the shape is empty
1805   
1806   TopoDS_Wire W = TopoDS::Wire(S) ;
1807   TopoDS_Wire res;
1808   res=BRepAlgo::ConcatenateWire(W,Option);              //processing
1809   DBRep::Set(c[1],res);
1810   return 0;
1811 }
1812
1813 //=======================================================================
1814 //function : build3d
1815 //purpose  : 
1816 //=======================================================================
1817
1818 Standard_Integer  build3d(Draw_Interpretor& di, 
1819   Standard_Integer n, const char** a)
1820 {
1821
1822   if ( (n <2) || (n>3) ) {
1823     //cout << " 1 or 2 arguments expected" << endl;
1824     di << " 1 or 2 arguments expected\n";
1825     return 1;
1826   }
1827
1828   Standard_Boolean Ok;
1829   TopoDS_Shape S = DBRep::Get(a[1]);
1830   if (S.IsNull()) return 1;
1831
1832   if (n==2) { Ok = BRepLib::BuildCurves3d(S); }
1833   else      { Ok = BRepLib::BuildCurves3d(S,Draw::Atof(a[2])); }
1834   //if (!Ok) {cout << " one of the computation failed" << endl;}
1835   if (!Ok) {di << " one of the computation failed\n";}
1836
1837   return 0;
1838 }
1839
1840 //=======================================================================
1841 //function : reducepcurves
1842 //purpose  : remove pcurves that are unused in this shape
1843 //=======================================================================
1844
1845 Standard_Integer reducepcurves(Draw_Interpretor& di, 
1846   Standard_Integer n, const char** a)
1847 {
1848   if (n < 2) return 1;
1849
1850   Standard_Integer i;
1851   for (i = 1; i < n; i++)
1852   {
1853     TopoDS_Shape aShape = DBRep::Get(a[i]);
1854     if (aShape.IsNull())
1855       //cout << a[i] << " is not a valid shape" << endl;
1856       di << a[i] << " is not a valid shape\n";
1857     else
1858       BRepTools::RemoveUnusedPCurves(aShape);
1859   }
1860
1861   return 0;
1862 }
1863
1864 //=======================================================================
1865 //function : CurveCommands
1866 //purpose  : 
1867 //=======================================================================
1868
1869 void  BRepTest::CurveCommands(Draw_Interpretor& theCommands)
1870 {
1871   static Standard_Boolean done = Standard_False;
1872   if (done) return;
1873   done = Standard_True;
1874
1875   DBRep::BasicCommands(theCommands);
1876   GeometryTest::CurveCommands(theCommands);
1877
1878   const char* g = "TOPOLOGY Curve topology commands";
1879
1880   theCommands.Add("vertex",
1881     "vertex name [x y z | p edge | poin]",__FILE__,
1882     vertex,g);
1883
1884   theCommands.Add("etrim",
1885     "etrim edge v1 [v2]",__FILE__,
1886     trim,g);
1887
1888   theCommands.Add("range",
1889     "range edge [face] first last",__FILE__,
1890     range,g);
1891
1892   theCommands.Add("polyline",
1893     "polyline name x1 y1 z1 x2 y2 z2 ...",__FILE__,
1894     polyline,g);
1895
1896   theCommands.Add("polyvertex",
1897     "polyvertex name v1 v2 ...",__FILE__,
1898     polyvertex,g);
1899
1900   theCommands.Add("wire",
1901     "wire wirename [-unsorted] e1/w1 [e2/w2 ...]",__FILE__,
1902     wire,g);
1903
1904   theCommands.Add("profile",
1905     "profile, no args to get help",__FILE__,
1906     profile,g);
1907
1908   theCommands.Add("bsplineprof",
1909     "bsplineprof, no args to get help",__FILE__,
1910     bsplineprof,g);
1911
1912   theCommands.Add("2dprofile",
1913     "2dprofile, no args to get help",__FILE__,
1914     profile2d,g);
1915
1916   theCommands.Add("mkoffset",
1917     "mkoffset result face/compound of wires  nboffset stepoffset [jointype(a/i) [alt]]",__FILE__,
1918     mkoffset);
1919
1920   theCommands.Add("openoffset",
1921     "openoffset result face/wire nboffset stepoffset [jointype(a/i)]",__FILE__,
1922     openoffset);
1923
1924   theCommands.Add("mkedge",
1925     "mkedge edge curve [surface] [pfirst plast] [vfirst [pfirst] vlast [plast]] ",__FILE__,
1926     mkedge,g);
1927
1928   theCommands.Add("mkcurve",
1929     "mkcurve curve edge",__FILE__,
1930     mkcurve,g);
1931
1932   theCommands.Add("mkoricurve",
1933     "mkoricurve curve edge: \n  the curve is colored according to the orientation of the edge",
1934     __FILE__,
1935     mkcurve,g);
1936
1937   theCommands.Add("mk2dcurve",
1938     "mk2dcurve curve edge [face OR index]",__FILE__,
1939     mk2dcurve,g);
1940
1941   theCommands.Add("mkpoint",
1942     "mkpoint point vertex",__FILE__,
1943     mkpoint,g);
1944
1945   theCommands.Add("uisoedge",
1946     "uisoedge edge face u v1 v2",__FILE__,
1947     isoedge,g);
1948
1949   theCommands.Add("edge",
1950     "edge edgename v1 v2",__FILE__,
1951     edge,g);
1952
1953   theCommands.Add("visoedge",
1954     "visoedge edge face v u1 u2",__FILE__,
1955     isoedge,g);
1956
1957   theCommands.Add("transfert",
1958     "transfert edge1 edge2",__FILE__,
1959     transfert,g);
1960
1961   theCommands.Add("pickface",
1962     "pickface",__FILE__,
1963     pickface,g);
1964
1965   theCommands.Add("edgeintersector",
1966     "edgeintersector r E1 E2 F [Tol]",__FILE__,
1967     edgeintersector,g);
1968
1969   theCommands.Add("build3d",
1970     "build3d S [tol]",
1971     build3d, g);
1972
1973   theCommands.Add("reducepcurves",
1974     "reducepcurves shape1 shape2 ...",
1975     reducepcurves, g);
1976
1977   theCommands.Add("concatC0wire",
1978     "concatC0wire result wire",
1979     __FILE__,
1980     concatC0wire,
1981     g);
1982
1983   theCommands.Add("concatwire",
1984     "concatwire result wire [option](G1/C1)",
1985     __FILE__,
1986     concatwire,
1987     g);
1988 }
1989
1990