Salome HOME
Merge with version on tag OCC-V2_1_0d
[modules/geom.git] / src / SKETCHER / Sketcher_Profile.cxx
1 //  GEOM SKETCHER : basic sketcher
2 //
3 //  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS 
5 // 
6 //  This library is free software; you can redistribute it and/or 
7 //  modify it under the terms of the GNU Lesser General Public 
8 //  License as published by the Free Software Foundation; either 
9 //  version 2.1 of the License. 
10 // 
11 //  This library is distributed in the hope that it will be useful, 
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of 
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
14 //  Lesser General Public License for more details. 
15 // 
16 //  You should have received a copy of the GNU Lesser General Public 
17 //  License along with this library; if not, write to the Free Software 
18 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA 
19 // 
20 //  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
21 //
22 //
23 //
24 //  File   : Sketcher_Profile.cxx
25 //  Author : Damien COQUERET
26 //  Module : GEOM
27 //  $Header: 
28
29 using namespace std;
30 #include "Sketcher_Profile.hxx"
31
32 #include <TopoDS_Vertex.hxx>
33 #include <TopoDS_Face.hxx>
34 #include <gp_Pln.hxx>
35 #include <gp_Ax2.hxx>
36 #include <BRepLib.hxx>
37 #include <BRepBuilderAPI_MakeVertex.hxx>
38 #include <BRepBuilderAPI_MakeEdge.hxx>
39 #include <BRepBuilderAPI_MakeWire.hxx>
40 #include <BRepBuilderAPI_MakeFace.hxx>
41 #include <Geom2d_Line.hxx>
42 #include <Geom2d_Circle.hxx>
43 #include <Geom_Surface.hxx>
44 #include <Precision.hxx>
45 #include <GeomAPI.hxx>
46
47 #include <TCollection_AsciiString.hxx>
48
49 #include <SALOMEconfig.h>
50 #include CORBA_SERVER_HEADER(SALOMEDS)
51
52 #include "utilities.h"
53
54 //=======================================================================
55 // profile
56 // command to build a profile
57 //=======================================================================
58 Sketcher_Profile::Sketcher_Profile()
59 {
60 }
61
62
63 //=======================================================================
64 // profile
65 // command to build a profile
66 //=======================================================================
67 Sketcher_Profile::Sketcher_Profile(const char* aCmd)
68 {
69   enum {line, circle, point, none} move;
70
71   Standard_Integer i = 1;
72   Standard_Real x0, y0, x, y, dx, dy;
73   x0 = y0 = x = y = dy = 0;
74   dx = 1;
75
76   Standard_Boolean first, stayfirst, face, close;
77   first = Standard_True;
78   stayfirst = face = close = Standard_False;
79
80   TopoDS_Shape S;
81   TopoDS_Vertex MP;
82   BRepBuilderAPI_MakeWire MW;
83   gp_Ax3 DummyHP(gp::XOY());
84   gp_Pln P(DummyHP);
85   TopLoc_Location TheLocation;
86   Handle(Geom_Surface) Surface;
87
88   myOK = Standard_False;
89
90   TCollection_AsciiString aCommand(CORBA::string_dup(aCmd));
91   TCollection_AsciiString aToken = aCommand.Token(":", 1);
92   int n = 0;
93   TCollection_AsciiString aTab[aCommand.Length()];
94   while(aToken.Length() != 0) {
95     if(aCommand.Token(":", n + 1).Length() > 0)
96       aTab[n] = aCommand.Token(":", n + 1);
97     aToken = aCommand.Token(":", ++n);
98   }
99   n = n - 1;
100   
101   while(i < n) {
102     Standard_Real length = 0, radius = 0, angle = 0;
103     move = point;
104
105     int n1 = 0;
106     TCollection_AsciiString a[aTab[0].Length()];
107     aToken = aTab[i].Token(" ", 1);
108     while(aToken.Length() != 0) {
109       if(aTab[i].Token(" ", n1 + 1).Length() > 0)
110         a[n1] = aTab[i].Token(" ", n1 + 1);
111       aToken = aTab[i].Token(" ", ++n1);
112     }
113     n1 = n1 - 1;
114
115     switch(a[0].Value(1))
116     {
117     case 'F':
118       {
119         if (n1 != 3) goto badargs;
120         if (!first) {
121           MESSAGE("profile : The F instruction must precede all moves");
122           return;
123         }
124         x0 = x = a[1].RealValue();
125         y0 = y = a[2].RealValue();
126         stayfirst = Standard_True;
127         break;
128       }
129     case 'O':
130       {
131         if (n1 != 4) goto badargs;
132         P.SetLocation(gp_Pnt(a[1].RealValue(), a[2].RealValue(), a[3].RealValue()));
133         stayfirst = Standard_True;
134         break;
135       }
136     case 'P':
137       {
138         if (n1 != 7) goto badargs;
139         gp_Vec vn(a[1].RealValue(), a[2].RealValue(), a[3].RealValue());
140         gp_Vec vx(a[4].RealValue(), a[5].RealValue(), a[6].RealValue());
141         if (vn.Magnitude() <= Precision::Confusion() || vx.Magnitude() <= Precision::Confusion()) {
142           MESSAGE("profile : null direction");
143           return;
144         }
145         gp_Ax2 ax(P.Location(), vn, vx);
146         P.SetPosition(ax);
147         stayfirst = Standard_True;
148         break;
149       }
150     case 'X':
151       {
152         if (n1 != 2) goto badargs;
153         length = a[1].RealValue();
154         if (a[0] == "XX")
155           length -= x;
156         dx = 1; dy = 0;
157         move = line;
158         break;
159       }
160     case 'Y':
161       {
162         if (n1 != 2) goto badargs;
163         length = a[1].RealValue();
164         if (a[0] == "YY")
165           length -= y;
166         dx = 0; dy = 1;
167         move = line;
168         break;
169       }
170     case 'L':
171       {
172         if (n1 != 2) goto badargs;
173         length = a[1].RealValue();
174         if (Abs(length) > Precision::Confusion())
175           move = line;
176         else
177           move = none;
178         break;
179       }
180     case 'T':
181       {
182         if (n1 != 3) goto badargs;
183         Standard_Real vx = a[1].RealValue();
184         Standard_Real vy = a[2].RealValue();
185         if (a[0] == "TT") {
186           vx -= x;
187           vy -= y;
188         }
189         length = Sqrt(vx * vx + vy * vy);
190         if (length > Precision::Confusion()) {
191           move = line;
192           dx = vx / length;
193           dy = vy / length;
194         }
195         else
196           move = none;
197         break;
198       }
199     case 'R':
200       {
201         if (n1 != 2) goto badargs;
202         angle = a[1].RealValue() * PI180;
203         if (a[0] == "RR") {
204           dx = Cos(angle);
205           dy = Sin(angle);
206         }
207         else {
208           Standard_Real c = Cos(angle);
209           Standard_Real s = Sin(angle);
210           Standard_Real t = c * dx - s * dy;
211           dy = s * dx + c * dy;
212           dx = t;
213         }
214         break;
215       }
216     case 'D':
217       {
218         if (n1 != 3) goto badargs;
219         Standard_Real vx = a[1].RealValue();
220         Standard_Real vy = a[2].RealValue();
221         length = Sqrt(vx * vx + vy * vy);
222         if (length > Precision::Confusion()) {
223           dx = vx / length;
224           dy = vy / length;
225         }
226         else
227           move = none;
228         break;
229       }
230     case 'C':
231       {
232         if (n1 != 3) goto badargs;
233         radius = a[1].RealValue();
234         if (Abs(radius) > Precision::Confusion()) {
235           angle = a[2].RealValue() * PI180;
236           move = circle;
237         }
238         else
239           move = none;
240         break;
241       }
242     case 'I':
243       {
244         if (n1 != 2) goto badargs;
245         length = a[1].RealValue();
246         if (a[0] == "IX") {
247           if (Abs(dx) < Precision::Confusion()) {
248             MESSAGE("profile : cannot intersect, arg "<<i-1);
249             return;
250           }
251           length = (length - x) / dx;
252         }
253         else if (a[0] == "IY") {
254           if (Abs(dy) < Precision::Confusion()) {
255             MESSAGE("profile : cannot intersect, arg "<<i-1);
256             return;
257           }
258           length = (length - y) / dy;
259         }
260         if (Abs(length) > Precision::Confusion())
261           move = line;
262         else
263           move = none;
264         break;
265       }
266     case 'W':
267       {
268         if (a[0] == "WW")
269           close = Standard_True;
270         else if(a[0] == "WF") {
271           close = Standard_True;
272           face = Standard_True;
273         }
274         i = n - 1;
275         break;
276       }
277     default:
278       {
279         MESSAGE("profile : unknown code "<<a[i]);
280         return;
281       }
282     }
283
284   again :
285     switch (move) 
286     {
287     case line :
288       {
289         if (length < 0) {
290           length = -length;
291           dx = -dx;
292           dy = -dy;
293         }
294         Handle(Geom2d_Line) l = new Geom2d_Line(gp_Pnt2d(x,y),gp_Dir2d(dx,dy));
295         BRepBuilderAPI_MakeEdge ME (GeomAPI::To3d(l,P),0,length);
296         if (!ME.IsDone())
297           return;
298         MW.Add(ME);
299         x += length*dx;
300         y += length*dy;
301         break;
302       }
303     case circle :
304       {
305         Standard_Boolean sense = Standard_True;
306         if (radius < 0) {
307           radius = -radius;
308           sense = !sense;
309           dx = -dx;
310           dy = -dy;
311         }
312         gp_Ax2d ax(gp_Pnt2d(x-radius*dy,y+radius*dx),gp_Dir2d(dy,-dx));
313         if (angle < 0) {
314           angle = -angle;
315           sense = !sense;
316         }
317         Handle(Geom2d_Circle) c = new Geom2d_Circle(ax,radius,sense);
318         BRepBuilderAPI_MakeEdge ME (GeomAPI::To3d(c,P),0,angle);
319         if (!ME.IsDone())
320           return;
321         MW.Add(ME);
322         gp_Pnt2d p;
323         gp_Vec2d v;
324         c->D1(angle,p,v);
325         x = p.X();
326         y = p.Y();
327         dx = v.X() / radius;
328         dy = v.Y() / radius;
329         break;
330       }
331     case point:
332       {
333         MP = BRepBuilderAPI_MakeVertex(gp_Pnt(x, y, 0.0));
334         break;
335       }
336     case none:
337       {
338         i = n - 1;
339         break;
340       }
341     }
342
343     // update first
344     first = stayfirst;
345     stayfirst = Standard_False;
346
347     if(!(dx == 0 && dy == 0))
348       myLastDir.SetCoord(dx, dy, 0.0);
349     else
350       return;
351     myLastPoint.SetX(x);
352     myLastPoint.SetY(y);
353
354     // next segment....
355     i++;
356     if ((i == n) && close) {
357       // the closing segment
358       dx = x0 - x;
359       dy = y0 - y;
360       length = Sqrt(dx * dx + dy * dy);
361       move = line;
362       if (length > Precision::Confusion()) {
363         dx = dx / length;
364         dy = dy / length;
365         goto again;
366       }
367     }
368   }
369
370   // get the result, face or wire
371   if (move == none) {
372     return;
373   } else if (move == point) {
374     S = MP;
375   } else if (face) {
376     if (!MW.IsDone()) {
377       return;
378     }
379     BRepBuilderAPI_MakeFace MF (P, MW.Wire());
380     if (!MF.IsDone()) {
381       return;
382     }
383     S = MF;
384   } else {
385     if (!MW.IsDone()) {
386       return;
387     }
388     S = MW;
389   }
390   
391   if(!TheLocation.IsIdentity())
392     S.Move(TheLocation);
393
394   myShape = S;
395   myOK = true;
396   return;
397
398   badargs :
399     MESSAGE("profile : bad number of arguments");
400     return;
401 }