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