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