0025021: New option of BRepOffsetAPI_MakeOffset algorithm: open result for open wire
[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   Paral.Init(GeomAbs_Arc);
1506   TopoDS_Shape Base = DBRep::Get(a[2],TopAbs_FACE);
1507
1508   if ( Base.IsNull())
1509   {
1510     Base = DBRep::Get(a[2]);
1511     if (Base.IsNull()) return 1;
1512     Paral.Init(GeomAbs_Arc);
1513     TopExp_Explorer exp;
1514     for (exp.Init(Base,TopAbs_WIRE); exp.More(); exp.Next())
1515     {
1516       TopoDS_Wire aLocalShape = TopoDS::Wire(exp.Current());
1517       Paral.AddWire(aLocalShape);
1518     }
1519   }
1520   else
1521   {
1522     Base.Orientation(TopAbs_FORWARD);
1523     Paral.Init(TopoDS::Face(Base));
1524   }
1525
1526   Standard_Real U, dU;
1527   Standard_Integer Nb;
1528   dU = Draw::Atof(a[4]);
1529   Nb = Draw::Atoi(a[3]);
1530
1531   Standard_Real Alt = 0.;
1532   if ( n == 6)
1533     Alt = Draw::Atof(a[5]);
1534
1535   Standard_Integer Compt = 1;
1536
1537   for ( Standard_Integer i = 1; i <= Nb; i++)
1538   {
1539     U = i * dU;
1540     Paral.Perform(U,Alt);
1541
1542     if ( !Paral.IsDone())
1543     {
1544       di << " Error: Offset is not done." << "\n";
1545       return 1;
1546     }
1547     else
1548     {
1549       Sprintf(name,"%s_%d", a[1], Compt++);
1550       char* temp = name; // portage WNT
1551       DBRep::Set(temp,Paral.Shape());
1552     }
1553   }
1554
1555   return 0;
1556 }
1557
1558 //=======================================================================
1559 //function : openoffset
1560 //purpose  : 
1561 //=======================================================================
1562
1563 Standard_Integer openoffset(Draw_Interpretor& di, 
1564   Standard_Integer n, const char** a)
1565 {
1566   if (n < 5) return 1;
1567   char name[100];
1568
1569   TopoDS_Shape Base = DBRep::Get(a[2], TopAbs_WIRE);
1570
1571   BRepOffsetAPI_MakeOffset Paral(TopoDS::Wire(Base), GeomAbs_Arc, Standard_True);
1572   
1573   Standard_Real U, dU;
1574   Standard_Integer Nb;
1575   dU = Draw::Atof(a[4]);
1576   Nb = Draw::Atoi(a[3]);
1577
1578   Standard_Integer Compt = 1;
1579   
1580   Standard_Real Alt = 0.;
1581   for ( Standard_Integer i = 1; i <= Nb; i++)
1582   {
1583     U = i * dU;
1584     Paral.Perform(U,Alt);
1585
1586     if ( !Paral.IsDone())
1587     {
1588       di << " Error: Offset is not done." << "\n";
1589       return 1;
1590     }
1591     else
1592     {
1593       Sprintf(name,"%s_%d", a[1], Compt++);
1594       char* temp = name; // portage WNT
1595       DBRep::Set(temp,Paral.Shape());
1596     }
1597   }
1598
1599   return 0;
1600 }
1601
1602 //=======================================================================
1603 //function : pickface
1604 //purpose  : 
1605 //=======================================================================
1606
1607 Standard_Integer pickface(Draw_Interpretor& di, 
1608   Standard_Integer , const char** )
1609 {
1610   Standard_CString pick_name=".";
1611
1612   TopoDS_Shape S = DBRep::Get(pick_name,TopAbs_FACE);
1613   if (S.IsNull()) return 1;
1614
1615   char* name = new char[100];
1616   Sprintf(name,"PickedFace %s",pick_name);
1617   DBRep::Set(name,S);
1618   di.AppendElement(name);
1619   return 0;
1620 }
1621
1622
1623 Standard_Integer edgeintersector(Draw_Interpretor& di,
1624   Standard_Integer n, const char** a)
1625 {
1626   if (n < 5) return 1;
1627
1628   TopoDS_Edge E[2];
1629   TopoDS_Shape aLocalShape(DBRep::Get(a[2],TopAbs_EDGE));
1630   E[0] = TopoDS::Edge(aLocalShape);
1631 //  E[0] = TopoDS::Edge(DBRep::Get(a[2],TopAbs_EDGE));
1632   if ( E[0].IsNull()) return 1;
1633   aLocalShape = DBRep::Get(a[3],TopAbs_EDGE);
1634   E[1] = TopoDS::Edge(aLocalShape);
1635 //  E[1] = TopoDS::Edge(DBRep::Get(a[3],TopAbs_EDGE));
1636   if ( E[1].IsNull()) return 1;
1637   aLocalShape = DBRep::Get(a[4],TopAbs_FACE);
1638   TopoDS_Face F  = TopoDS::Face(aLocalShape);
1639 //  TopoDS_Face F  = TopoDS::Face(DBRep::Get(a[4],TopAbs_FACE));
1640   if ( F.IsNull()) return 1;
1641
1642   TopOpeBRep_EdgesIntersector EInter;
1643   char name[100];
1644   //------------------------------------------------------
1645   // Calculate point of intersection 2D
1646   //-----------------------------------------------------
1647   EInter.SetFaces(F,F);
1648   Standard_Real TolInter = 1.e-7;
1649   if (n == 6) TolInter = Draw::Atof(a[5]);
1650   EInter.ForceTolerances(TolInter,TolInter);
1651   Standard_Boolean reducesegments = Standard_True;
1652   EInter.Perform (E[0],E[1],reducesegments);
1653
1654   if (EInter.IsEmpty()) {
1655     //cout << " No intersection found" << endl;
1656     di << " No intersection found" << "\n";
1657     return 0;
1658   }
1659
1660   BRep_Builder B;
1661
1662   Standard_Integer NbV = 0;
1663   Standard_Real Tol = Precision::PConfusion();
1664
1665   Standard_Boolean rejectreducedsegmentpoints = Standard_True;
1666   EInter.InitPoint(rejectreducedsegmentpoints);
1667   for (;EInter.MorePoint();EInter.NextPoint()) {
1668     const TopOpeBRep_Point2d& P2D = EInter.Point();
1669     gp_Pnt           P    = P2D.Value();
1670     TopoDS_Vertex    V    = BRepLib_MakeVertex(P);
1671     NbV ++;
1672     Sprintf(name,"%s_%d",a[1],NbV);
1673     DBRep::Set(name,V);
1674     for (Standard_Integer i = 1; i <= 2; i++) {
1675       //---------------------------------------------------------------
1676       // to be able to rank parameter on edge
1677       // it is necessary to code it internally
1678       //---------------------------------------------------------------
1679       Standard_Real U = P2D.Parameter(i);
1680
1681       V.Orientation(TopAbs_INTERNAL);
1682       B.UpdateVertex(V,U,E[i-1],Tol);
1683       //      B.UpdateVertex(TopoDS::Vertex(V.Oriented(TopAbs_INTERNAL)),
1684       //                     U,E[i-1],Tol);
1685       //---------------------------------------------------------------
1686       // Orientation of vertex in the transition.
1687       //---------------------------------------------------------------
1688       TopAbs_Orientation OO = TopAbs_REVERSED;
1689       if (P2D.IsVertex(i)) {
1690         OO = P2D.Vertex(i).Orientation();
1691       }
1692       else if (P2D.Transition(i).Before() == TopAbs_OUT) {
1693         OO = TopAbs_FORWARD;
1694       }
1695       //cout << " Orientation of vertex " << NbV << " on " << a[i+1] << ": ";
1696       di << " Orientation of vertex " << NbV << " on " << a[i+1] << ": ";
1697       if (OO == TopAbs_FORWARD) {
1698         //cout << "FORWARD" << endl;
1699         di << "FORWARD" << "\n";
1700       } else {
1701         //cout << "REVERSED" << endl;
1702         di << "REVERSED" << "\n";
1703       }
1704     }
1705   }
1706   //POP pour NT
1707   return 0;
1708
1709 }
1710
1711 //=======================================================================
1712 //function : concatC0wire
1713 //purpose  : 
1714 //=======================================================================
1715
1716 Standard_Integer concatC0wire(Draw_Interpretor&, Standard_Integer n, const char** c)
1717 {
1718   if ( n < 3 ) return 1;                               
1719
1720   TopoDS_Shape S = DBRep::Get(c[2],TopAbs_WIRE) ;
1721
1722   if (S.IsNull())
1723     return 1;                            //test if the shape is empty
1724
1725   TopoDS_Wire W = TopoDS::Wire(S) ;
1726   TopoDS_Shape res;
1727
1728
1729   res = BRepAlgo::ConcatenateWireC0(W);              //treatment
1730   DBRep::Set(c[1], res);
1731   return 0;
1732 }
1733
1734 //=======================================================================
1735 //function : concatwire
1736 //purpose  : reduce the multiply degree of the knots to the minimum without
1737 //           changing the geometry
1738 //=======================================================================
1739
1740 static Standard_Integer concatwire(Draw_Interpretor&, Standard_Integer n, const char** c)
1741 {
1742   GeomAbs_Shape Option=GeomAbs_C1;
1743   if ( n < 3 ) return 1;
1744
1745   if(n==4)                                              //check if it's C1 or G1
1746   if (! strcmp(c[3],"G1"))
1747     Option=GeomAbs_G1;
1748
1749   TopoDS_Shape S = DBRep::Get(c[2],TopAbs_WIRE) ;
1750
1751   if (S.IsNull()) return 1 ;                            //test if the shape is empty
1752   
1753   TopoDS_Wire W = TopoDS::Wire(S) ;
1754   TopoDS_Wire res;
1755   res=BRepAlgo::ConcatenateWire(W,Option);              //processing
1756   DBRep::Set(c[1],res);
1757   return 0;
1758 }
1759
1760 //=======================================================================
1761 //function : build3d
1762 //purpose  : 
1763 //=======================================================================
1764
1765 Standard_Integer  build3d(Draw_Interpretor& di, 
1766   Standard_Integer n, const char** a)
1767 {
1768
1769   if ( (n <2) || (n>3) ) {
1770     //cout << " 1 or 2 arguments expected" << endl;
1771     di << " 1 or 2 arguments expected" << "\n";
1772     return 1;
1773   }
1774
1775   Standard_Boolean Ok;
1776   TopoDS_Shape S = DBRep::Get(a[1],TopAbs_FACE);
1777   if (S.IsNull()) return 1;
1778
1779   if (n==2) { Ok = BRepLib::BuildCurves3d(S); }
1780   else      { Ok = BRepLib::BuildCurves3d(S,Draw::Atof(a[2])); }
1781   //if (!Ok) {cout << " one of the computation failed" << endl;}
1782   if (!Ok) {di << " one of the computation failed" << "\n";}
1783
1784   return 0;
1785 }
1786
1787 //=======================================================================
1788 //function : reducepcurves
1789 //purpose  : remove pcurves that are unused in this shape
1790 //=======================================================================
1791
1792 Standard_Integer reducepcurves(Draw_Interpretor& di, 
1793   Standard_Integer n, const char** a)
1794 {
1795   if (n < 2) return 1;
1796
1797   Standard_Integer i;
1798   for (i = 1; i < n; i++)
1799   {
1800     TopoDS_Shape aShape = DBRep::Get(a[i]);
1801     if (aShape.IsNull())
1802       //cout << a[i] << " is not a valid shape" << endl;
1803       di << a[i] << " is not a valid shape" << "\n";
1804     else
1805       BRepTools::RemoveUnusedPCurves(aShape);
1806   }
1807
1808   return 0;
1809 }
1810
1811 //=======================================================================
1812 //function : CurveCommands
1813 //purpose  : 
1814 //=======================================================================
1815
1816 void  BRepTest::CurveCommands(Draw_Interpretor& theCommands)
1817 {
1818   static Standard_Boolean done = Standard_False;
1819   if (done) return;
1820   done = Standard_True;
1821
1822   DBRep::BasicCommands(theCommands);
1823   GeometryTest::CurveCommands(theCommands);
1824
1825   const char* g = "TOPOLOGY Curve topology commands";
1826
1827   theCommands.Add("vertex",
1828     "vertex name [x y z | p edge | poin]",__FILE__,
1829     vertex,g);
1830
1831   theCommands.Add("etrim",
1832     "etrim edge v1 [v2]",__FILE__,
1833     trim,g);
1834
1835   theCommands.Add("range",
1836     "range edge [face] first last",__FILE__,
1837     range,g);
1838
1839   theCommands.Add("polyline",
1840     "polyline name x1 y1 z1 x2 y2 z2 ...",__FILE__,
1841     polyline,g);
1842
1843   theCommands.Add("polyvertex",
1844     "polyvertex name v1 v2 ...",__FILE__,
1845     polyvertex,g);
1846
1847   theCommands.Add("wire",
1848     "wire wirename e1/w1 [e2/w2 ...]",__FILE__,
1849     wire,g);
1850
1851   theCommands.Add("profile",
1852     "profile, no args to get help",__FILE__,
1853     profile,g);
1854
1855   theCommands.Add("bsplineprof",
1856     "bsplineprof, no args to get help",__FILE__,
1857     bsplineprof,g);
1858
1859   theCommands.Add("2dprofile",
1860     "2dprofile, no args to get help",__FILE__,
1861     profile2d,g);
1862
1863   theCommands.Add("mkoffset",
1864     "mkoffset result face/compound of wires  nboffset stepoffset [alt]",__FILE__,
1865     mkoffset);
1866
1867   theCommands.Add("openoffset",
1868     "openoffset result wire nboffset stepoffset",__FILE__,
1869     openoffset);
1870
1871   theCommands.Add("mkedge",
1872     "mkedge edge curve [surface] [pfirst plast] [vfirst [pfirst] vlast [plast]] ",__FILE__,
1873     mkedge,g);
1874
1875   theCommands.Add("mkcurve",
1876     "mkcurve curve edge",__FILE__,
1877     mkcurve,g);
1878
1879   theCommands.Add("mkoricurve",
1880     "mkoricurve curve edge: \n  the curve is colored according to the orientation of the edge",
1881     __FILE__,
1882     mkcurve,g);
1883
1884   theCommands.Add("mk2dcurve",
1885     "mk2dcurve curve edge [face OR index]",__FILE__,
1886     mk2dcurve,g);
1887
1888   theCommands.Add("mkpoint",
1889     "mkpoint point vertex",__FILE__,
1890     mkpoint,g);
1891
1892   theCommands.Add("uisoedge",
1893     "uisoedge edge face u v1 v2",__FILE__,
1894     isoedge,g);
1895
1896   theCommands.Add("edge",
1897     "edge edgename v1 v2",__FILE__,
1898     edge,g);
1899
1900   theCommands.Add("visoedge",
1901     "visoedge edge face v u1 u2",__FILE__,
1902     isoedge,g);
1903
1904   theCommands.Add("transfert",
1905     "transfert edge1 edge2",__FILE__,
1906     transfert,g);
1907
1908   theCommands.Add("pickface",
1909     "pickface",__FILE__,
1910     pickface,g);
1911
1912   theCommands.Add("edgeintersector",
1913     "edgeintersector r E1 E2 F [Tol]",__FILE__,
1914     edgeintersector,g);
1915
1916   theCommands.Add("build3d",
1917     "build3d S [tol]",
1918     build3d, g);
1919
1920   theCommands.Add("reducepcurves",
1921     "reducepcurves shape1 shape2 ...",
1922     reducepcurves, g);
1923
1924   theCommands.Add("concatC0wire",
1925     "concatC0wire result wire",
1926     __FILE__,
1927     concatC0wire,
1928     g);
1929
1930   theCommands.Add("concatwire",
1931     "concatwire result wire [option](G1/C1)",
1932     __FILE__,
1933     concatwire,
1934     g);
1935 }
1936
1937