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