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