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