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