Salome HOME
d68ecf4a65928e0f917320ac2ca2e1d07eda9fd8
[modules/geom.git] / src / SKETCHER / Sketcher_Profile.cxx
1 // Copyright (C) 2007-2022  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  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, or (at your option) any later version.
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.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 //  GEOM SKETCHER : basic sketcher
24 //  File   : Sketcher_Profile.cxx
25 //  Author : Damien COQUERET
26 //  Module : GEOM
27
28 #include "Sketcher_Profile.hxx"
29
30 #include <TopoDS_Vertex.hxx>
31 #include <BRepBuilderAPI_MakeVertex.hxx>
32 #include <BRepBuilderAPI_MakeEdge.hxx>
33 #include <BRepBuilderAPI_MakeWire.hxx>
34 #include <BRepBuilderAPI_MakeFace.hxx>
35
36 #include <GeomAPI.hxx>
37 #include <Geom2d_Line.hxx>
38 #include <Geom2d_Circle.hxx>
39
40 #include <Precision.hxx>
41 #include <gp_Pln.hxx>
42 #include <gp_Ax2.hxx>
43
44 #include "utilities.h"
45
46 /*!
47   \class Sketcher_Profile::Functor
48   \brief Generic functor class to process sketcher command
49   \internal
50 */
51
52 class Sketcher_Profile::Functor
53 {
54 public:
55   Functor();
56   virtual ~Functor();
57
58   virtual void init( const TCollection_AsciiString& );
59
60   virtual void initCommand() = 0;
61   virtual void addPoint( const TCollection_AsciiString& x,
62                          const TCollection_AsciiString& y ) = 0;
63   virtual void addAngle( const TCollection_AsciiString& angle ) = 0;
64   virtual void addSegmentParalX( const TCollection_AsciiString& x ) = 0;
65   virtual void addSegmentParalXToZero() = 0;
66   virtual void addSegmentParalY( const TCollection_AsciiString& y ) = 0;
67   virtual void addSegmentParalYToZero() = 0;
68   virtual void addSegmentAbsolute( const TCollection_AsciiString& x,
69                                    const TCollection_AsciiString& y ) = 0;
70   virtual void addSegmentRelative( const TCollection_AsciiString& dx,
71                                    const TCollection_AsciiString& dy ) = 0;
72   virtual void addSegmentLength( const TCollection_AsciiString& length ) = 0;
73   virtual void addSegmentX( const TCollection_AsciiString& x,
74                             int CurrentIndex ) = 0;
75   virtual void addSegmentY( const TCollection_AsciiString& y,
76                             int CurrentIndex ) = 0;
77   virtual void addSegmentAngleLength( const TCollection_AsciiString& angle,
78                                       const TCollection_AsciiString& length,
79                                       int& CurrentIndex ) = 0;
80   virtual void addSegmentAngleX( const TCollection_AsciiString& angle,
81                                  const TCollection_AsciiString& x,
82                                  int& CurrentIndex ) = 0;
83   virtual void addSegmentAngleY( const TCollection_AsciiString& angle,
84                                  const TCollection_AsciiString& y,
85                                  int& CurrentIndex ) = 0;
86   virtual void addSegmentDirectionLength( const TCollection_AsciiString& dx,
87                                           const TCollection_AsciiString& dy,
88                                           const TCollection_AsciiString& length,
89                                           int& CurrentIndex ) = 0;
90   virtual void addSegmentDirectionX( const TCollection_AsciiString& dx,
91                                      const TCollection_AsciiString& dy,
92                                      const TCollection_AsciiString& x,
93                                      int& CurrentIndex ) = 0;
94   virtual void addSegmentDirectionY( const TCollection_AsciiString& dx,
95                                      const TCollection_AsciiString& dy,
96                                      const TCollection_AsciiString& y,
97                                      int& CurrentIndex ) = 0;
98   virtual void addArcAbsolute( const TCollection_AsciiString& x,
99                                const TCollection_AsciiString& y ) = 0;
100   virtual void addArcRelative( const TCollection_AsciiString& dx,
101                                const TCollection_AsciiString& dy ) = 0;
102   virtual void addArcRadiusAbsolute( const TCollection_AsciiString& x,
103                                      const TCollection_AsciiString& y,
104                                      const TCollection_AsciiString& radius,
105                                      const TCollection_AsciiString& flag ) = 0;
106   virtual void addArcRadiusRelative( const TCollection_AsciiString& dx,
107                                      const TCollection_AsciiString& dy,
108                                      const TCollection_AsciiString& radius,
109                                      const TCollection_AsciiString& flag ) = 0;
110   virtual void addArcCenterAbsolute( const TCollection_AsciiString& x,
111                                      const TCollection_AsciiString& y,
112                                      const TCollection_AsciiString& xc,
113                                      const TCollection_AsciiString& yc,
114                                      const TCollection_AsciiString& flag1,
115                                      const TCollection_AsciiString& flag2 ) = 0;
116   virtual void addArcCenterRelative( const TCollection_AsciiString& dx,
117                                      const TCollection_AsciiString& dy,
118                                      const TCollection_AsciiString& xc,
119                                      const TCollection_AsciiString& yc,
120                                      const TCollection_AsciiString& flag1,
121                                      const TCollection_AsciiString& flag2 ) = 0;
122   virtual void addArcRadiusLength( const TCollection_AsciiString& radius,
123                                    const TCollection_AsciiString& length ) = 0;
124   virtual void addArcAngleRadiusLength( const TCollection_AsciiString& angle,
125                                         const TCollection_AsciiString& radius,
126                                         const TCollection_AsciiString& length ,
127                                         int& CurrentIndex ) = 0;
128   virtual void addArcDirectionRadiusLength( const TCollection_AsciiString& dx,
129                                             const TCollection_AsciiString& dy,
130                                             const TCollection_AsciiString& radius,
131                                             const TCollection_AsciiString& length ,
132                                             int& CurrentIndex ) = 0;
133   virtual void closeWire() = 0;
134   virtual void closeWireAndBuildFace() = 0;
135
136   virtual void nextCommand( int& CurrentIndex ) = 0;
137   virtual void makeResult() = 0;
138
139   void setNumberOfCommand( int n );
140   double error();
141   bool isOk();
142
143 protected:
144   int    myNumberOfCommand;
145   double myError;
146   bool   myOk;
147 };
148
149 /*!
150   \class Sketcher_Profile::ShapeFunctor
151   \brief Functor that creates a shape from sketcher command
152   \internal
153 */
154
155 class Sketcher_Profile::ShapeFunctor : public Functor
156 {
157 public:
158   ShapeFunctor();
159
160   virtual void initCommand();
161   virtual void addPoint( const TCollection_AsciiString& x,
162                          const TCollection_AsciiString& y );
163   virtual void addAngle( const TCollection_AsciiString& angle );
164   virtual void addSegmentParalX( const TCollection_AsciiString& x );
165   virtual void addSegmentParalXToZero();
166   virtual void addSegmentParalY( const TCollection_AsciiString& y );
167   virtual void addSegmentParalYToZero();
168   virtual void setAngle( const TCollection_AsciiString& angle );
169   virtual void setDirection( const TCollection_AsciiString& dx,
170                              const TCollection_AsciiString& dy );
171   virtual void addSegmentAbsolute( const TCollection_AsciiString& x,
172                                    const TCollection_AsciiString& y );
173   virtual void addSegmentRelative( const TCollection_AsciiString& dx,
174                                    const TCollection_AsciiString& dy );
175   virtual void addSegmentLength( const TCollection_AsciiString& length );
176   virtual void addSegmentX( const TCollection_AsciiString& x,
177                             int CurrentIndex );
178   virtual void addSegmentY( const TCollection_AsciiString& y,
179                             int CurrentIndex );
180   virtual void addSegmentAngleLength( const TCollection_AsciiString& angle,
181                                       const TCollection_AsciiString& length,
182                                       int& CurrentIndex );
183   virtual void addSegmentAngleX( const TCollection_AsciiString& angle,
184                                  const TCollection_AsciiString& x,
185                                  int& CurrentIndex );
186   virtual void addSegmentAngleY( const TCollection_AsciiString& angle,
187                                  const TCollection_AsciiString& y,
188                                  int& CurrentIndex );
189   virtual void addSegmentDirectionLength( const TCollection_AsciiString& dx,
190                                           const TCollection_AsciiString& dy,
191                                           const TCollection_AsciiString& length,
192                                           int& CurrentIndex );
193   virtual void addSegmentDirectionX( const TCollection_AsciiString& dx,
194                                      const TCollection_AsciiString& dy,
195                                      const TCollection_AsciiString& x,
196                                      int& CurrentIndex );
197   virtual void addSegmentDirectionY( const TCollection_AsciiString& dx,
198                                      const TCollection_AsciiString& dy,
199                                      const TCollection_AsciiString& y,
200                                      int& CurrentIndex );
201   virtual void addArcAbsolute( const TCollection_AsciiString& x,
202                                const TCollection_AsciiString& y );
203   virtual void addArcRelative( const TCollection_AsciiString& dx,
204                                const TCollection_AsciiString& dy );
205   virtual void addArcRadiusAbsolute( const TCollection_AsciiString& x,
206                                      const TCollection_AsciiString& y,
207                                      const TCollection_AsciiString& radius,
208                                      const TCollection_AsciiString& flag );
209   virtual void addArcRadiusRelative( const TCollection_AsciiString& dx,
210                                      const TCollection_AsciiString& dy,
211                                      const TCollection_AsciiString& radius,
212                                      const TCollection_AsciiString& flag );
213   virtual void addArcCenterAbsolute( const TCollection_AsciiString& x,
214                                      const TCollection_AsciiString& y,
215                                      const TCollection_AsciiString& xc,
216                                      const TCollection_AsciiString& yc,
217                                      const TCollection_AsciiString& flag1,
218                                      const TCollection_AsciiString& flag2 );
219   virtual void addArcCenterRelative( const TCollection_AsciiString& dx,
220                                      const TCollection_AsciiString& dy,
221                                      const TCollection_AsciiString& xc,
222                                      const TCollection_AsciiString& yc,
223                                      const TCollection_AsciiString& flag1,
224                                      const TCollection_AsciiString& flag2 );
225   virtual void addArcRadiusLength( const TCollection_AsciiString& radius,
226                                    const TCollection_AsciiString& length );
227   virtual void addArcAngleRadiusLength( const TCollection_AsciiString& angle,
228                                         const TCollection_AsciiString& radius,
229                                         const TCollection_AsciiString& length ,
230                                         int& CurrentIndex );
231   virtual void addArcDirectionRadiusLength( const TCollection_AsciiString& dx,
232                                             const TCollection_AsciiString& dy,
233                                             const TCollection_AsciiString& radius,
234                                             const TCollection_AsciiString& length ,
235                                             int& CurrentIndex );
236   virtual void closeWire();
237   virtual void closeWireAndBuildFace();
238
239   virtual void nextCommand( int& CurrentIndex );
240   virtual void makeResult();
241
242   TopoDS_Shape getShape();
243
244 private:
245   void setMove( int& CurrentIndex );
246
247 private:
248   Standard_Real myX0, myY0, myX, myY, myDx, myDy;
249   Standard_Boolean myFirst, myStayFirst, myFace, myClose;
250   Standard_Real myLength, myRadius, myAngle;
251
252   enum {line, circle, point, none} myMove;
253
254   TopLoc_Location TheLocation; // ?????????
255   gp_Pln myPlane;
256   TopoDS_Vertex myVertex;
257   BRepBuilderAPI_MakeWire myMakeWire;
258
259   TopoDS_Shape myShape;
260 };
261
262 /*!
263   \class Sketcher_Profile::ShapeFunctor
264   \brief Functor that generates a Python script from sketcher command
265   \internal
266 */
267
268 class Sketcher_Profile::DumpFunctor : public Functor
269 {
270 public:
271   DumpFunctor();
272
273   virtual void init( const TCollection_AsciiString& );
274
275   virtual void initCommand();
276   virtual void addPoint( const TCollection_AsciiString& x,
277                          const TCollection_AsciiString& y );
278   virtual void addAngle( const TCollection_AsciiString& angle );
279   virtual void addSegmentParalX( const TCollection_AsciiString& x );
280   virtual void addSegmentParalXToZero();
281   virtual void addSegmentParalY( const TCollection_AsciiString& y );
282   virtual void addSegmentParalYToZero();
283   virtual void addSegmentAbsolute( const TCollection_AsciiString& x,
284                                    const TCollection_AsciiString& y );
285   virtual void addSegmentRelative( const TCollection_AsciiString& dx,
286                                    const TCollection_AsciiString& dy );
287   virtual void addSegmentLength( const TCollection_AsciiString& length );
288   virtual void addSegmentX( const TCollection_AsciiString& x,
289                             int CurrentIndex );
290   virtual void addSegmentY( const TCollection_AsciiString& y,
291                             int CurrentIndex );
292   virtual void addSegmentAngleLength( const TCollection_AsciiString& angle,
293                                       const TCollection_AsciiString& length,
294                                       int& CurrentIndex );
295   virtual void addSegmentAngleX( const TCollection_AsciiString& angle,
296                                  const TCollection_AsciiString& x,
297                                  int& CurrentIndex );
298   virtual void addSegmentAngleY( const TCollection_AsciiString& angle,
299                                  const TCollection_AsciiString& y,
300                                  int& CurrentIndex );
301   virtual void addSegmentDirectionLength( const TCollection_AsciiString& dx,
302                                           const TCollection_AsciiString& dy,
303                                           const TCollection_AsciiString& length,
304                                           int& CurrentIndex );
305   virtual void addSegmentDirectionX( const TCollection_AsciiString& dx,
306                                      const TCollection_AsciiString& dy,
307                                      const TCollection_AsciiString& x,
308                                      int& CurrentIndex );
309   virtual void addSegmentDirectionY( const TCollection_AsciiString& dx,
310                                      const TCollection_AsciiString& dy,
311                                      const TCollection_AsciiString& y,
312                                      int& CurrentIndex );
313   virtual void addArcAbsolute( const TCollection_AsciiString& x,
314                                const TCollection_AsciiString& y );
315   virtual void addArcRelative( const TCollection_AsciiString& dx,
316                                const TCollection_AsciiString& dy );
317   virtual void addArcRadiusAbsolute( const TCollection_AsciiString& x,
318                                      const TCollection_AsciiString& y,
319                                      const TCollection_AsciiString& radius,
320                                      const TCollection_AsciiString& flag );
321   virtual void addArcRadiusRelative( const TCollection_AsciiString& dx,
322                                      const TCollection_AsciiString& dy,
323                                      const TCollection_AsciiString& radius,
324                                      const TCollection_AsciiString& flag );
325   virtual void addArcCenterAbsolute( const TCollection_AsciiString& x,
326                                      const TCollection_AsciiString& y,
327                                      const TCollection_AsciiString& xc,
328                                      const TCollection_AsciiString& yc,
329                                      const TCollection_AsciiString& flag1,
330                                      const TCollection_AsciiString& flag2 );
331   virtual void addArcCenterRelative( const TCollection_AsciiString& dx,
332                                      const TCollection_AsciiString& dy,
333                                      const TCollection_AsciiString& xc,
334                                      const TCollection_AsciiString& yc,
335                                      const TCollection_AsciiString& flag1,
336                                      const TCollection_AsciiString& flag2 );
337   virtual void addArcRadiusLength( const TCollection_AsciiString& radius,
338                                    const TCollection_AsciiString& length );
339   virtual void addArcAngleRadiusLength( const TCollection_AsciiString& angle,
340                                         const TCollection_AsciiString& radius,
341                                         const TCollection_AsciiString& length ,
342                                         int& CurrentIndex );
343   virtual void addArcDirectionRadiusLength( const TCollection_AsciiString& dx,
344                                             const TCollection_AsciiString& dy,
345                                             const TCollection_AsciiString& radius,
346                                             const TCollection_AsciiString& length ,
347                                             int& CurrentIndex );
348   virtual void closeWire();
349   virtual void closeWireAndBuildFace();
350
351   virtual void nextCommand( int& CurrentIndex );
352   virtual void makeResult();
353
354   TCollection_AsciiString getDescription();
355
356 private:
357   TCollection_AsciiString myDescr;
358   TCollection_AsciiString mySketcherEntry;
359   TCollection_AsciiString myWPEntry;
360   TCollection_AsciiString myTail;
361   Standard_Boolean        myFace;
362 };
363
364 //===========================================================================
365 // Sketcher_Profile::Functor
366 //===========================================================================
367
368 /*!
369   \brief Constructor
370   \internal
371 */
372 Sketcher_Profile::Functor::Functor() : myNumberOfCommand( 0 ), myError( 0 ), myOk( true )
373 {
374 }
375
376 /*!
377   \brief Destructor
378   \internal
379 */
380 Sketcher_Profile::Functor::~Functor()
381 {
382 }
383
384 /*!
385   \brief Initialize functor from the script
386   \param command sketcher command being parsed
387   \internal
388 */
389 void Sketcher_Profile::Functor::init( const TCollection_AsciiString& /*command*/ )
390 {
391 }
392
393 /*!
394   \brief Set total number of sketcher operators
395   \param n total number of sketcher operators
396   \internal
397 */
398 void Sketcher_Profile::Functor::setNumberOfCommand( int n )
399 {
400   myNumberOfCommand = n;
401 }
402
403 /*!
404   \brief Get error (numerical value that describes, e.g. a deviation of point from the specified arc)
405   \return numerical error
406   \internal
407 */
408 double Sketcher_Profile::Functor::error()
409 {
410   return myError;
411 }
412
413 /*!
414   \brief Get result of parsing
415   \return \c true if parsing is successful or \c false otherwise
416   \internal
417 */
418 bool Sketcher_Profile::Functor::isOk()
419 {
420   return myOk;
421 }
422
423 //===========================================================================
424 // Sketcher_Profile::ShapeFunctor
425 //===========================================================================
426
427 /*!
428   \brief Constructor
429   \internal
430 */
431 Sketcher_Profile::ShapeFunctor::ShapeFunctor() : Functor()
432 {
433   myX0 = myY0 = 0;
434   myX  = myY  = 0;
435   myDy = 0;
436   myDx = 1;
437
438   myFirst = Standard_True;
439   myStayFirst = myFace = myClose = Standard_False;
440
441   myLength = myRadius = myAngle = 0;
442
443   myMove = point;
444
445   myPlane = gp_Pln( gp_Ax3( gp::XOY() ) );
446 }
447
448 /*!
449   \brief Prepare functor for processing of new sketcher operator
450   \internal
451 */
452 void Sketcher_Profile::ShapeFunctor::initCommand()
453 {
454   myLength = myRadius = myAngle = 0;
455   myMove = point;
456 }
457
458 /*!
459   \brief Add point with absolute coordinates (\a x, \a y)
460   \param x X coordinate
461   \param y Y coordinate
462   \internal
463 */
464 void Sketcher_Profile::ShapeFunctor::addPoint( const TCollection_AsciiString& x,
465                                                const TCollection_AsciiString& y )
466 {
467   if ( !myFirst ) {
468     MESSAGE("profile : The addPoint instruction must precede all moves");
469     return;
470   }
471   myX0 = myX = x.RealValue();
472   myY0 = myY = y.RealValue();
473   myStayFirst = Standard_True;
474 }
475
476 /*!
477   \brief Add angle
478   \param angle angle
479   \internal
480 */
481 void Sketcher_Profile::ShapeFunctor::addAngle( const TCollection_AsciiString& angle )
482 {
483   myAngle = angle.RealValue() * M_PI / 180.;
484   myDx = Cos( myAngle );
485   myDy = Sin( myAngle );
486 }
487
488 /*!
489   \brief Add new segment of \a x length along X axis
490   \param x length of segment
491   \internal
492 */
493 void Sketcher_Profile::ShapeFunctor::addSegmentParalX( const TCollection_AsciiString& x )
494 {
495   myLength = x.RealValue();
496   myDx = 1;
497   myDy = 0;
498   myMove = line;
499 }
500
501 /*!
502   \brief Add new segment along X axis with X coordinate of end set to 0
503   \internal
504 */
505 void Sketcher_Profile::ShapeFunctor::addSegmentParalXToZero()
506 {
507   myLength -= myX;
508   myDx = 1;
509   myDy = 0;
510   myMove = line;
511 }
512
513 /*!
514   \brief Add new segment of \a y length along Y axis
515   \param y length of segment
516   \internal
517 */
518 void Sketcher_Profile::ShapeFunctor::addSegmentParalY( const TCollection_AsciiString& y )
519 {
520   myLength = y.RealValue();
521   myDx = 0;
522   myDy = 1;
523   myMove = line;
524 }
525
526 /*!
527   \brief Add new segment along Y axis with Y coordinate of end set to 0
528   \internal
529 */
530 void Sketcher_Profile::ShapeFunctor::addSegmentParalYToZero()
531 {
532   myLength -= myY;
533   myDx = 0;
534   myDy = 1;
535   myMove = line;
536 }
537
538 /*!
539   \brief Set current angle
540   \param angle current working angle
541   \internal
542 */
543 void Sketcher_Profile::ShapeFunctor::setAngle( const TCollection_AsciiString& angle )
544 {
545   myAngle = angle.RealValue();
546   Standard_Real alpha = myAngle * M_PI / 180.;
547   Standard_Real c = Cos( alpha );
548   Standard_Real s = Sin( alpha );
549   Standard_Real t = c * myDx - s * myDy;
550   myDy = s * myDx + c * myDy;
551   myDx = t;
552 }
553
554 /*!
555   \brief Set current direction
556   \param dx X component of direction vector
557   \param dy Y component of direction vector
558   \internal
559 */
560 void Sketcher_Profile::ShapeFunctor::setDirection( const TCollection_AsciiString& dx,
561                                                    const TCollection_AsciiString& dy )
562 {
563   Standard_Real vx = dx.RealValue();
564   Standard_Real vy = dy.RealValue();
565   myLength = Sqrt( vx * vx + vy * vy );
566   if ( myLength > Precision::Confusion() ) {
567     myDx = vx / myLength;
568     myDy = vy / myLength;
569   }
570   else
571     myMove = none;
572 }
573
574 /*!
575   \brief Add segment by absolute coordinates
576   \param x X coordinate of segment end
577   \param y Y coordinate of segment end
578   \internal
579 */
580 void Sketcher_Profile::ShapeFunctor::addSegmentAbsolute( const TCollection_AsciiString& x,
581                                                          const TCollection_AsciiString& y )
582 {
583   Standard_Real vx = x.RealValue() - myX;
584   Standard_Real vy = y.RealValue() - myY;
585   myLength = Sqrt( vx * vx + vy * vy );
586   if ( myLength > Precision::Confusion() ) {
587     myMove = line;
588     myDx = vx / myLength;
589     myDy = vy / myLength;
590   }
591   else
592     myMove = none;
593 }
594
595 /*!
596   \brief Add segment by relativ coordinates
597   \param dx dX value specifying segment end
598   \param dy dY value specifying segment end
599   \internal
600 */
601 void Sketcher_Profile::ShapeFunctor::addSegmentRelative( const TCollection_AsciiString& dx,
602                                                          const TCollection_AsciiString& dy )
603 {
604   Standard_Real vx = dx.RealValue();
605   Standard_Real vy = dy.RealValue();
606   myLength = Sqrt( vx * vx + vy * vy );
607   if ( myLength > Precision::Confusion() ) {
608     myMove = line;
609     myDx = vx / myLength;
610     myDy = vy / myLength;
611   }
612   else
613     myMove = none;
614 }
615
616 /*!
617   \brief Add segment with specified length along current direction
618   \param length segment length
619   \internal
620 */
621 void Sketcher_Profile::ShapeFunctor::addSegmentLength( const TCollection_AsciiString& length )
622 {
623   myLength = length.RealValue();
624   if ( Abs( myLength ) > Precision::Confusion() )
625     myMove = line;
626   else
627     myMove = none;
628 }
629
630 /*!
631   \brief Add segment along X axis to reach specified X coordinate
632   \param x X coordinate of segment end
633   \param CurrentIndex index of current operator
634   \internal
635 */
636 void Sketcher_Profile::ShapeFunctor::addSegmentX( const TCollection_AsciiString& x,
637                                                   int CurrentIndex )
638 {
639   (void)CurrentIndex; // unused in release mode
640   myMove = none;
641   myLength = x.RealValue();
642   if ( Abs( myDx ) < Precision::Confusion() ) {
643     MESSAGE("profile : cannot intersect, arg "<<CurrentIndex-1);
644     return;
645   }
646   myLength = ( myLength - myX ) / myDx;
647   if ( Abs( myLength ) > Precision::Confusion() )
648     myMove = line;
649 }
650
651 /*!
652   \brief Add segment along Y axis to reach specified Y coordinate
653   \param y Y coordinate of segment end
654   \param CurrentIndex index of current operator
655   \internal
656 */
657 void Sketcher_Profile::ShapeFunctor::addSegmentY( const TCollection_AsciiString& y,
658                                                   int CurrentIndex )
659 {
660   (void)CurrentIndex; // unused in release mode
661   myMove = none;
662   myLength = y.RealValue();
663   if ( Abs( myDy ) < Precision::Confusion() ) {
664     MESSAGE("profile : cannot intersect, arg "<<CurrentIndex-1);
665     return;
666   }
667   myLength = ( myLength - myY ) / myDy;
668   if ( Abs( myLength ) > Precision::Confusion() )
669     myMove = line;
670 }
671
672 /*!
673   \brief Add segment by specified angle and length
674   \param angle angle that specifies segment direction
675   \param length segment length
676   \param CurrentIndex index of current operator
677   \internal
678 */
679 void Sketcher_Profile::ShapeFunctor::addSegmentAngleLength( const TCollection_AsciiString& angle,
680                                                             const TCollection_AsciiString& length,
681                                                             int& CurrentIndex )
682 {
683   setAngle( angle );
684   setMove( CurrentIndex );
685   addSegmentLength( length );
686 }
687
688 /*!
689   \brief Add segment that crosses Y axis by specified angle and X coordinate
690   \param angle angle that specifies segment direction
691   \param x X coordinate of segment end
692   \param CurrentIndex index of current operator
693   \internal
694 */
695 void Sketcher_Profile::ShapeFunctor::addSegmentAngleX( const TCollection_AsciiString& angle,
696                                                        const TCollection_AsciiString& x,
697                                                        int& CurrentIndex )
698 {
699   setAngle( angle );
700   setMove( CurrentIndex );
701   addSegmentX( x, CurrentIndex );
702 }
703
704 /*!
705   \brief Add segment that crosses X axis by specified angle and Y coordinate
706   \param angle angle that specifies segment direction
707   \param y Y coordinate of segment end
708   \param CurrentIndex index of current operator
709   \internal
710 */
711 void Sketcher_Profile::ShapeFunctor::addSegmentAngleY( const TCollection_AsciiString& angle,
712                                                        const TCollection_AsciiString& y,
713                                                        int& CurrentIndex )
714 {
715   setAngle( angle );
716   setMove( CurrentIndex );
717   addSegmentY( y, CurrentIndex );
718 }
719
720 /*!
721   \brief Add segment by specified direction and length
722   \param dx X component of direction vector
723   \param dx Y component of direction vector
724   \param length segment length
725   \param CurrentIndex index of current operator
726   \internal
727 */
728 void Sketcher_Profile::ShapeFunctor::addSegmentDirectionLength( const TCollection_AsciiString& dx,
729                                                                 const TCollection_AsciiString& dy,
730                                                                 const TCollection_AsciiString& length,
731                                                                 int& CurrentIndex )
732 {
733   setDirection( dx, dy );
734   setMove( CurrentIndex );
735   addSegmentLength( length );
736 }
737
738 /*!
739   \brief Add segment by specified direction and X coordinate
740   \param dx X component of direction vector
741   \param dx Y component of direction vector
742   \param x X coordinate of segment end
743   \param CurrentIndex index of current operator
744   \internal
745 */
746 void Sketcher_Profile::ShapeFunctor::addSegmentDirectionX( const TCollection_AsciiString& dx,
747                                                            const TCollection_AsciiString& dy,
748                                                            const TCollection_AsciiString& x,
749                                                            int& CurrentIndex )
750 {
751   setDirection( dx, dy );
752   setMove( CurrentIndex );
753   addSegmentX( x, CurrentIndex );
754 }
755
756 /*!
757   \brief Add segment by specified direction and Y coordinate
758   \param dx X component of direction vector
759   \param dx Y component of direction vector
760   \param y Y coordinate of segment end
761   \param CurrentIndex index of current operator
762   \internal
763 */
764 void Sketcher_Profile::ShapeFunctor::addSegmentDirectionY( const TCollection_AsciiString& dx,
765                                                            const TCollection_AsciiString& dy,
766                                                            const TCollection_AsciiString& y,
767                                                            int& CurrentIndex )
768 {
769   setDirection( dx, dy );
770   setMove( CurrentIndex );
771   addSegmentY( y, CurrentIndex );
772 }
773
774 /*!
775   \brief Add arc along current direction vector by specified absolute coordinates
776   \param x X coordinate of arc end
777   \param x Y coordinate of arc end
778   \internal
779 */
780 void Sketcher_Profile::ShapeFunctor::addArcAbsolute( const TCollection_AsciiString& x,
781                                                      const TCollection_AsciiString& y )
782 {
783   Standard_Real vx = x.RealValue() - myX;
784   Standard_Real vy = y.RealValue() - myY;
785   Standard_Real det = myDx * vy - myDy * vx;
786   Standard_Real c = Sqrt( ( myDx * myDx + myDy * myDy ) * ( vx * vx + vy * vy ) );
787   if ( Abs( det ) > Precision::Confusion() && Abs( c ) > Precision::Confusion() ) {
788     // Cosine of alpha = arc of angle / 2 , alpha in [0,Pi]
789     c = ( myDx * vx + myDy * vy ) / c;
790     // radius = distance between start and end point / 2 * sin(alpha)
791     // radius is > 0 or < 0
792     myRadius = ( vx * vx + vy * vy )* Sqrt( myDx * myDx + myDy * myDy ) / ( 2.0 * det );
793     if ( Abs( myRadius ) > Precision::Confusion() ) {
794       myAngle = 2.0 * acos( c ); // angle in [0,2Pi]
795       myMove = circle;
796     }
797     else
798       myMove = none;
799   }
800   else
801     myMove = none;
802 }
803
804 /*!
805   \brief Add arc along current direction vector by specified relative coordinates
806   \param dx dX value specifying arc end
807   \param dy dY value specifying arc end
808   \internal
809 */
810 void Sketcher_Profile::ShapeFunctor::addArcRelative( const TCollection_AsciiString& dx,
811                                                      const TCollection_AsciiString& dy )
812 {
813   Standard_Real vx = dx.RealValue();
814   Standard_Real vy = dy.RealValue();
815   Standard_Real det = myDx * vy - myDy * vx;
816   Standard_Real c = Sqrt( ( myDx * myDx + myDy * myDy ) * ( vx * vx + vy * vy ) );
817   if ( Abs( det ) > Precision::Confusion() && Abs( c ) > Precision::Confusion() ) {
818     // Cosine of alpha = arc of angle / 2 , alpha in [0,Pi]
819     c = ( myDx * vx + myDy * vy ) / c;
820     // radius = distance between start and end point / 2 * sin(alpha)
821     // radius is > 0 or < 0
822     myRadius = ( vx * vx + vy * vy )* Sqrt( myDx * myDx + myDy * myDy ) / ( 2.0 * det );
823     if ( Abs( myRadius ) > Precision::Confusion() ) {
824       myAngle = 2.0 * acos(c); // angle in [0,2Pi]
825       myMove = circle;
826     }
827     else
828       myMove = none;
829   }
830   else
831     myMove = none;
832 }
833
834 /*!
835   \brief Add arc with given radius by specified absolute coordinates
836   \param x X coordinate of arc end
837   \param x Y coordinate of arc end
838   \param radius arc radius
839   \param flag reverse direction flag
840   \internal
841 */
842 void Sketcher_Profile::ShapeFunctor::addArcRadiusAbsolute( const TCollection_AsciiString& x,
843                                                            const TCollection_AsciiString& y,
844                                                            const TCollection_AsciiString& radius,
845                                                            const TCollection_AsciiString& flag )
846 {
847   Standard_Real vx = x.RealValue() - myX;
848   Standard_Real vy = y.RealValue() - myY;
849   myRadius  = radius.RealValue();
850   int reversed = flag.IntegerValue();
851   Standard_Real length = Sqrt( vx * vx + vy * vy );
852   if ( Abs( myRadius ) > Precision::Confusion() &&
853        ( 4.0 - ( vx * vx + vy * vy ) / ( myRadius * myRadius ) >= 0.0 ) && ( length > Precision::Confusion() ) ) {
854     // Cosine of alpha = arc angle / 2 , alpha in [0,Pi/2]
855     Standard_Real c = 0.5 * Sqrt( 4.0 - ( vx * vx + vy * vy ) / ( myRadius * myRadius ) );
856     myAngle = 2.0 * acos( c ); // angle in [0,Pi]
857     if ( reversed == 2 )
858       myAngle = myAngle - 2 * M_PI;
859     myDx =  0.5 * ( vy * 1.0 / myRadius
860                     + vx * Sqrt( 4.0 / ( vx * vx + vy * vy ) - 1.0 / ( myRadius * myRadius ) ) );
861     myDy = -0.5 * ( vx * 1.0 / myRadius
862                     - vy * Sqrt( 4.0 / ( vx * vx + vy * vy ) - 1.0 / ( myRadius * myRadius ) ) );
863     myMove = circle;
864   }
865   else {
866     myMove = none;
867   }
868 }
869
870 /*!
871   \brief Add arc with given radius by specified relative coordinates
872   \param dx dX value specifying arc end
873   \param dy dY value specifying arc end
874   \param radius arc radius
875   \param flag reverse direction flag
876   \internal
877 */
878 void Sketcher_Profile::ShapeFunctor::addArcRadiusRelative( const TCollection_AsciiString& dx,
879                                                            const TCollection_AsciiString& dy,
880                                                            const TCollection_AsciiString& radius,
881                                                            const TCollection_AsciiString& flag )
882 {
883   Standard_Real vx = dx.RealValue();
884   Standard_Real vy = dy.RealValue();
885   myRadius  = radius.RealValue();
886   int reversed = flag.IntegerValue();
887   Standard_Real length = Sqrt( vx * vx + vy * vy );
888   if ( Abs( myRadius ) > Precision::Confusion() &&
889        ( 4.0 - ( vx * vx + vy * vy ) / ( myRadius * myRadius ) >= 0.0 ) && ( length > Precision::Confusion() ) ) {
890     // Cosine of alpha = arc angle / 2 , alpha in [0,Pi/2]
891     Standard_Real c = 0.5 * Sqrt( 4.0 - ( vx * vx + vy * vy ) / ( myRadius * myRadius ) );
892     myAngle = 2.0 * acos( c ); // angle in [0,Pi]
893     if ( reversed == 2 )
894       myAngle = myAngle - 2 * M_PI;
895     myDx =  0.5 * ( vy * 1.0 / myRadius
896                     + vx * Sqrt( 4.0  / ( vx * vx + vy * vy ) - 1.0 / ( myRadius * myRadius ) ) );
897     myDy = -0.5 * ( vx * 1.0 / myRadius
898                     - vy * Sqrt( 4.0  / ( vx * vx + vy * vy ) - 1.0 / ( myRadius * myRadius ) ) );
899     myMove = circle;
900   }
901   else {
902     myMove = none;
903   }
904 }
905
906 /*!
907   \brief Add arc with given center by specified absolute coordinates
908   \param x X coordinate of arc end
909   \param x Y coordinate of arc end
910   \param xc X coordinate of arc center
911   \param yc Y coordinate of arc center
912   \param flag1 reverse direction flag
913   \param flag2 tolerance
914   \internal
915 */
916 void Sketcher_Profile::ShapeFunctor::addArcCenterAbsolute( const TCollection_AsciiString& x,
917                                                            const TCollection_AsciiString& y,
918                                                            const TCollection_AsciiString& xc,
919                                                            const TCollection_AsciiString& yc,
920                                                            const TCollection_AsciiString& flag1,
921                                                            const TCollection_AsciiString& flag2 )
922 {
923   Standard_Real vx = x.RealValue() - myX;
924   Standard_Real vy = y.RealValue() - myY;
925   Standard_Real vxc  = xc.RealValue() - myX;
926   Standard_Real vyc  = yc.RealValue() - myY;
927   int reversed = flag1.IntegerValue();
928   int control_Tolerance = flag2.IntegerValue();
929
930   myRadius = Sqrt( vxc * vxc + vyc * vyc );
931   Standard_Real det = vx * vyc - vy * vxc;
932   Standard_Real length = Sqrt( vx * vx + vy * vy );
933   Standard_Real length2 = Sqrt( ( vx - vxc ) * ( vx - vxc ) + ( vy - vyc ) * ( vy - vyc ) );
934   Standard_Real length3 = Sqrt( vxc * vxc + vyc * vyc );
935   Standard_Real error = Abs( length2 - myRadius );
936   myError = error;
937   if ( error > Precision::Confusion() ) {
938     MESSAGE("Warning : The specified end point is not on the Arc, distance = "<<error);
939   }
940   if ( error > Precision::Confusion() && control_Tolerance == 1 ) // Don't create the arc if the end point
941     myMove = none;                                                // is too far from it
942   else if ( ( length  > Precision::Confusion() ) &&
943             ( length2 > Precision::Confusion() ) &&
944             ( length3 > Precision::Confusion() ) ) {
945     Standard_Real c = ( myRadius * myRadius - ( vx * vxc + vy * vyc ) )
946       / ( myRadius * Sqrt( ( vx - vxc ) * ( vx - vxc ) + ( vy - vyc ) * ( vy - vyc ) ) ) ;  // Cosine of arc angle
947     myAngle = acos(c);                                                                      // angle in [0,Pi]
948     if ( reversed == 2 )
949       myAngle = myAngle - 2 * M_PI;
950     if ( det < 0 )
951       myAngle = -myAngle;
952     myDx =  vyc / myRadius;
953     myDy = -vxc / myRadius;
954     myMove = circle;
955   }
956   else {
957     myMove = none;
958   }
959 }
960
961 /*!
962   \brief Add arc with given center by specified relative coordinates
963   \param dx dX value specifying arc end
964   \param dy dY value specifying arc end
965   \param xc X coordinate of arc center
966   \param yc Y coordinate of arc center
967   \param flag1 reverse direction flag
968   \param flag2 tolerance
969   \internal
970 */
971 void Sketcher_Profile::ShapeFunctor::addArcCenterRelative( const TCollection_AsciiString& dx,
972                                                            const TCollection_AsciiString& dy,
973                                                            const TCollection_AsciiString& xc,
974                                                            const TCollection_AsciiString& yc,
975                                                            const TCollection_AsciiString& flag1,
976                                                            const TCollection_AsciiString& flag2 )
977 {
978   Standard_Real vx = dx.RealValue();
979   Standard_Real vy = dy.RealValue();
980   Standard_Real vxc  = xc.RealValue();
981   Standard_Real vyc  = yc.RealValue();
982   int reversed = flag1.IntegerValue();
983   int control_Tolerance = flag2.IntegerValue();
984   myRadius = Sqrt( vxc * vxc + vyc * vyc );
985   Standard_Real det = vx * vyc - vy * vxc;
986   Standard_Real length = Sqrt( vx * vx + vy * vy );
987   Standard_Real length2 = Sqrt( ( vx - vxc ) * ( vx - vxc ) + ( vy - vyc ) * ( vy - vyc ) );
988   Standard_Real length3 = Sqrt( vxc * vxc + vyc * vyc );
989   Standard_Real error = Abs( length2 - myRadius );
990   myError = error;
991   if ( error > Precision::Confusion() ) {
992     MESSAGE("Warning : The specified end point is not on the Arc, distance = "<<error);
993   }
994   if ( error > Precision::Confusion() && control_Tolerance == 1 ) // Don't create the arc if the end point
995     myMove = none;                                                // is too far from it
996   else if ( ( length  > Precision::Confusion() ) &&
997             ( length2 > Precision::Confusion() ) &&
998             ( length3 > Precision::Confusion() ) ) {
999     Standard_Real c = ( myRadius * myRadius - ( vx * vxc + vy * vyc ) )
1000       / ( myRadius * Sqrt( ( vx - vxc ) * ( vx - vxc ) + ( vy - vyc ) * ( vy - vyc ) ) ) ;  // Cosine of arc angle
1001     myAngle = acos( c );                                                                    // angle in [0,Pi]
1002     if ( reversed == 2 )
1003       myAngle = myAngle - 2 * M_PI;
1004     if ( det < 0 )
1005       myAngle = -myAngle;
1006     myDx =  vyc / myRadius;
1007     myDy = -vxc / myRadius;
1008     myMove = circle;
1009   }
1010   else {
1011     myMove = none;
1012   }
1013 }
1014
1015 /*!
1016   \brief Add arc with given radius by specified length
1017   \param radius arc radius
1018   \param length arc length
1019   \internal
1020 */
1021 void Sketcher_Profile::ShapeFunctor::addArcRadiusLength( const TCollection_AsciiString& radius,
1022                                                          const TCollection_AsciiString& length )
1023 {
1024   myRadius = radius.RealValue();
1025   if ( Abs( myRadius ) > Precision::Confusion() ) {
1026     myAngle = length.RealValue() * M_PI / 180.;
1027     myMove = circle;
1028   }
1029   else
1030     myMove = none;
1031 }
1032
1033 /*!
1034   \brief Add arc with given radius by specified angle and length
1035   \param angle angle between arc start tangent and current direction
1036   \param radius arc radius
1037   \param length arc length
1038   \param CurrentIndex index of current operator
1039   \internal
1040 */
1041 void Sketcher_Profile::ShapeFunctor::addArcAngleRadiusLength( const TCollection_AsciiString& angle,
1042                                                               const TCollection_AsciiString& radius,
1043                                                               const TCollection_AsciiString& length ,
1044                                                               int& CurrentIndex )
1045 {
1046   setAngle( angle );
1047   setMove( CurrentIndex );
1048   addArcRadiusLength( radius, length );
1049 }
1050
1051 /*!
1052   \brief Add arc with given radius by specified direction and length
1053   \param dx X component of direction vector
1054   \param dx Y component of direction vector
1055   \param radius arc radius
1056   \param length arc length
1057   \param CurrentIndex index of current operator
1058   \internal
1059 */
1060 void Sketcher_Profile::ShapeFunctor::addArcDirectionRadiusLength( const TCollection_AsciiString& dx,
1061                                                                   const TCollection_AsciiString& dy,
1062                                                                   const TCollection_AsciiString& radius,
1063                                                                   const TCollection_AsciiString& length ,
1064                                                                   int& CurrentIndex )
1065 {
1066   setDirection( dx, dy );
1067   setMove( CurrentIndex );
1068   addArcRadiusLength( radius, length );
1069 }
1070
1071 /*!
1072   \brief Close wire
1073   \internal
1074 */
1075 void Sketcher_Profile::ShapeFunctor::closeWire()
1076 {
1077   myClose = Standard_True;
1078 }
1079
1080 /*!
1081   \brief Close wire and build face
1082   \internal
1083 */
1084 void Sketcher_Profile::ShapeFunctor::closeWireAndBuildFace()
1085 {
1086   myClose = Standard_True;
1087   myFace = Standard_True;
1088 }
1089
1090 /*!
1091   \brief Set internal parameters according to the current operator type
1092   \param CurrentIndex index of current operator
1093   \internal
1094 */
1095 void Sketcher_Profile::ShapeFunctor::setMove( int& CurrentIndex )
1096 {
1097   switch ( myMove )
1098   {
1099   case line :
1100     {
1101       if ( myLength < 0 ) {
1102         myLength = -myLength;
1103         myDx = -myDx;
1104         myDy = -myDy;
1105       }
1106       Handle(Geom2d_Line) l = new Geom2d_Line( gp_Pnt2d( myX, myY ),gp_Dir2d( myDx, myDy ) );
1107       BRepBuilderAPI_MakeEdge ME( GeomAPI::To3d( l, myPlane ), 0, myLength );
1108       if ( !ME.IsDone() )
1109         return;
1110       myMakeWire.Add( ME );
1111       myX += myLength * myDx;
1112       myY += myLength * myDy;
1113       break;
1114     }
1115   case circle :
1116     {
1117       Standard_Boolean sense = Standard_True;
1118       if ( myRadius < 0 ) {
1119         myRadius = -myRadius;
1120         sense = !sense;
1121         myDx = -myDx;
1122         myDy = -myDy;
1123       }
1124       gp_Ax2d ax( gp_Pnt2d( myX - myRadius * myDy, myY + myRadius * myDx ), gp_Dir2d( myDy, -myDx ) );
1125       if ( myAngle < 0 ) {
1126         myAngle = -myAngle;
1127         sense = !sense;
1128       }
1129       Handle(Geom2d_Circle) c = new Geom2d_Circle( ax, myRadius, sense );
1130       BRepBuilderAPI_MakeEdge ME( GeomAPI::To3d( c, myPlane ), 0, myAngle );
1131       if ( !ME.IsDone() )
1132         return;
1133       myMakeWire.Add( ME );
1134       gp_Pnt2d p;
1135       gp_Vec2d v;
1136       c->D1( myAngle, p, v );
1137       myX = p.X();
1138       myY = p.Y();
1139       myDx = v.X() / myRadius;
1140       myDy = v.Y() / myRadius;
1141       break;
1142     }
1143   case point:
1144     {
1145       myVertex = BRepBuilderAPI_MakeVertex( gp_Pnt( myX, myY, 0.0 ) );
1146       break;
1147     }
1148   case none:
1149     {
1150       CurrentIndex = myNumberOfCommand - 1;
1151       break;
1152     }
1153   }
1154 }
1155
1156 /*!
1157   \brief Complete parsing of current operator
1158   \param CurrentIndex index of current operator
1159   \internal
1160 */
1161 void Sketcher_Profile::ShapeFunctor::nextCommand( int& CurrentIndex )
1162 {
1163   setMove( CurrentIndex );
1164   CurrentIndex ++;
1165   // update first
1166   myFirst = myStayFirst;
1167   myStayFirst = Standard_False;
1168
1169   // next segment....
1170   if ( ( CurrentIndex == myNumberOfCommand ) && myClose ) {
1171     // the closing segment
1172     myDx = myX0 - myX;
1173     myDy = myY0 - myY;
1174     myLength = Sqrt( myDx * myDx + myDy * myDy );
1175     myMove = line;
1176     if ( myLength > Precision::Confusion() ) {
1177       myDx = myDx / myLength;
1178       myDy = myDy / myLength;
1179       setMove( CurrentIndex );
1180     }
1181   }
1182 }
1183
1184 /*!
1185   \brief Finish parsing and create result
1186   \internal
1187 */
1188 void Sketcher_Profile::ShapeFunctor::makeResult()
1189 {
1190   // get the result, face or wire
1191   if ( myMove == none ) {
1192     myOk = false;
1193     return;
1194   }
1195   else if ( myMove == point ) {
1196     myShape = myVertex;
1197   }
1198   else if ( myFace ) {
1199     if ( !myMakeWire.IsDone() ) {
1200       myOk = false;
1201       return;
1202     }
1203     BRepBuilderAPI_MakeFace MF ( myPlane, myMakeWire.Wire() );
1204     if ( !MF.IsDone() ) {
1205       myOk = false;
1206       return;
1207     }
1208     myShape = MF;
1209   }
1210   else {
1211     if ( !myMakeWire.IsDone() ) {
1212       myOk = false;
1213       return;
1214     }
1215     myShape = myMakeWire.Shape();
1216   }
1217
1218   if ( !TheLocation.IsIdentity() )
1219     myShape.Move( TheLocation );
1220 }
1221
1222 /*!
1223   \brief Get resulting shape
1224   \return shape resulting from parsing of sketcher command
1225   \internal
1226 */
1227 TopoDS_Shape Sketcher_Profile::ShapeFunctor::getShape()
1228 {
1229   return myShape;
1230 }
1231
1232 //===========================================================================
1233 // Sketcher_Profile::DumpFunctor
1234 //===========================================================================
1235
1236 /*!
1237   \brief Constructor
1238   \internal
1239 */
1240 Sketcher_Profile::DumpFunctor::DumpFunctor()
1241 {
1242   myFace = Standard_False;
1243 }
1244
1245 /*!
1246   \brief Initialize functor from the script
1247   \param command sketcher command being parsed
1248   \internal
1249 */
1250 void Sketcher_Profile::DumpFunctor::init( const TCollection_AsciiString& command )
1251 {
1252   // parse only first line of the script
1253   TCollection_AsciiString aSubStr = command.Token( "\n\t" );
1254   if ( aSubStr.Length() < command.Length() )
1255     myTail = command.SubString( aSubStr.Length()+1, command.Length() );
1256   // get sketch entry
1257   mySketcherEntry = aSubStr.Token( " =" );
1258   // Using this Working Plane for Sketcher
1259   myWPEntry = myWPEntry + "[" + aSubStr.Token( "[]", 2 ) + "]";
1260   // Using this Working Plane for SketcherOnPlane
1261   if ( aSubStr.Search( "MakeSketcherOnPlane" ) != -1 ) {
1262     myWPEntry = aSubStr.Token( ",)", 2 );
1263     myWPEntry.RemoveAll( ' ' );
1264   }
1265   myDescr += "sk = geompy.Sketcher2D()";
1266 }
1267
1268 /*!
1269   \brief Prepare functor for processing of new sketcher operator
1270   \internal
1271 */
1272 void Sketcher_Profile::DumpFunctor::initCommand()
1273 {
1274   myDescr += "\n\t";
1275 }
1276
1277 /*!
1278   \brief Add point with absolute coordinates (\a x, \a y)
1279   \param x X coordinate
1280   \param y Y coordinate
1281   \internal
1282 */
1283 void Sketcher_Profile::DumpFunctor::addPoint( const TCollection_AsciiString& x,
1284                                               const TCollection_AsciiString& y )
1285 {
1286   myDescr += "sk.addPoint(";
1287   myDescr += x + ", " + y + ")";
1288 }
1289
1290 /*!
1291   \brief Add angle
1292   \param angle angle
1293   \internal
1294 */
1295 void Sketcher_Profile::DumpFunctor::addAngle( const TCollection_AsciiString& angle )
1296 {
1297   myDescr += "sk.addAngle(";
1298   myDescr += angle + ")";
1299 }
1300
1301 /*!
1302   \brief Add new segment of \a x length along X axis
1303   \param x length of segment
1304   \internal
1305 */
1306 void Sketcher_Profile::DumpFunctor::addSegmentParalX( const TCollection_AsciiString& x )
1307 {
1308   myDescr += "sk.addSegmentParalX(";
1309   myDescr += x + ")";
1310 }
1311
1312 /*!
1313   \brief Add new segment along X axis with X coordinate of end set to 0
1314   \internal
1315 */
1316 void Sketcher_Profile::DumpFunctor::addSegmentParalXToZero()
1317 {
1318   myDescr += "sk.addSegmentParalXToZero()";
1319 }
1320
1321 /*!
1322   \brief Add new segment of \a y length along Y axis
1323   \param y length of segment
1324   \internal
1325 */
1326 void Sketcher_Profile::DumpFunctor::addSegmentParalY( const TCollection_AsciiString& y )
1327 {
1328   myDescr += "sk.addSegmentParalY(";
1329   myDescr += y + ")";
1330 }
1331
1332 /*!
1333   \brief Add new segment along Y axis with Y coordinate of end set to 0
1334   \internal
1335 */
1336 void Sketcher_Profile::DumpFunctor::addSegmentParalYToZero()
1337 {
1338   myDescr += "sk.addSegmentParalYToZero()";
1339 }
1340
1341 /*!
1342   \brief Add segment by absolute coordinates
1343   \param x X coordinate of segment end
1344   \param y Y coordinate of segment end
1345   \internal
1346 */
1347 void Sketcher_Profile::DumpFunctor::addSegmentAbsolute( const TCollection_AsciiString& x,
1348                                                         const TCollection_AsciiString& y )
1349 {
1350   myDescr += "sk.addSegmentAbsolute(";
1351   myDescr += x + ", " + y + ")";
1352 }
1353
1354 /*!
1355   \brief Add segment by relativ coordinates
1356   \param dx dX value specifying segment end
1357   \param dy dY value specifying segment end
1358   \internal
1359 */
1360 void Sketcher_Profile::DumpFunctor::addSegmentRelative( const TCollection_AsciiString& dx,
1361                                                         const TCollection_AsciiString& dy )
1362 {
1363   myDescr += "sk.addSegmentRelative(";
1364   myDescr += dx + ", " + dy + ")";
1365 }
1366
1367 /*!
1368   \brief Add segment with specified length along current direction
1369   \param length segment length
1370   \internal
1371 */
1372 void Sketcher_Profile::DumpFunctor::addSegmentLength( const TCollection_AsciiString& length )
1373 {
1374   myDescr += "sk.addSegmentLength(";
1375   myDescr += length + ")";
1376 }
1377
1378 /*!
1379   \brief Add segment along X axis to reach specified X coordinate
1380   \param x X coordinate of segment end
1381   \param CurrentIndex index of current operator
1382   \internal
1383 */
1384 void Sketcher_Profile::DumpFunctor::addSegmentX( const TCollection_AsciiString& x,
1385                                                  int /*CurrentIndex*/ )
1386 {
1387   myDescr += "sk.addSegmentX(";
1388   myDescr += x + ")";
1389 }
1390
1391 /*!
1392   \brief Add segment along Y axis to reach specified Y coordinate
1393   \param y Y coordinate of segment end
1394   \param CurrentIndex index of current operator
1395   \internal
1396 */
1397 void Sketcher_Profile::DumpFunctor::addSegmentY( const TCollection_AsciiString& y,
1398                                                  int /*CurrentIndex*/  )
1399 {
1400   myDescr += "sk.addSegmentY(";
1401   myDescr += y + ")";
1402 }
1403
1404 /*!
1405   \brief Add segment by specified angle and length
1406   \param angle angle that specifies segment direction
1407   \param length segment length
1408   \param CurrentIndex index of current operator
1409   \internal
1410 */
1411 void Sketcher_Profile::DumpFunctor::addSegmentAngleLength( const TCollection_AsciiString& angle,
1412                                                            const TCollection_AsciiString& length,
1413                                                            int& /*CurrentIndex*/ )
1414 {
1415   double aAngle = angle.RealValue();
1416   if ( aAngle == 90 ) {
1417     myDescr += "sk.addSegmentPerpLength(";
1418     myDescr += length + ")";
1419   }
1420   else {
1421     myDescr += "sk.addSegmentAngleLength(";
1422     myDescr += angle + ", " + length + ")";
1423   }
1424 }
1425
1426 /*!
1427   \brief Add segment that crosses Y axis by specified angle and X coordinate
1428   \param angle angle that specifies segment direction
1429   \param x X coordinate of segment end
1430   \param CurrentIndex index of current operator
1431   \internal
1432 */
1433 void Sketcher_Profile::DumpFunctor::addSegmentAngleX( const TCollection_AsciiString& angle,
1434                                                       const TCollection_AsciiString& x,
1435                                                       int& /*CurrentIndex*/ )
1436 {
1437   double aAngle = angle.RealValue();
1438   if ( aAngle == 90 ) {
1439     myDescr += "sk.addSegmentPerpX(";
1440     myDescr += x + ")";
1441   }
1442   else {
1443     myDescr += "sk.addSegmentAngleX(";
1444     myDescr += angle + ", " + x + ")";
1445   }
1446 }
1447
1448 /*!
1449   \brief Add segment that crosses X axis by specified angle and Y coordinate
1450   \param angle angle that specifies segment direction
1451   \param y Y coordinate of segment end
1452   \param CurrentIndex index of current operator
1453   \internal
1454 */
1455 void Sketcher_Profile::DumpFunctor::addSegmentAngleY( const TCollection_AsciiString& angle,
1456                                                       const TCollection_AsciiString& y,
1457                                                       int& /*CurrentIndex*/ )
1458 {
1459   double aAngle = angle.RealValue();
1460   if ( aAngle == 90 ) {
1461     myDescr += "sk.addSegmentPerpY(";
1462     myDescr += y + ")";
1463   }
1464   else {
1465     myDescr += "sk.addSegmentAngleY(";
1466     myDescr += angle + ", " + y + ")";
1467   }
1468 }
1469
1470 /*!
1471   \brief Add segment by specified direction and length
1472   \param dx X component of direction vector
1473   \param dx Y component of direction vector
1474   \param length segment length
1475   \param CurrentIndex index of current operator
1476   \internal
1477 */
1478 void Sketcher_Profile::DumpFunctor::addSegmentDirectionLength( const TCollection_AsciiString& dx,
1479                                                                const TCollection_AsciiString& dy,
1480                                                                const TCollection_AsciiString& length,
1481                                                                int& /*CurrentIndex*/ )
1482 {
1483   myDescr += "sk.addSegmentDirectionLength(";
1484   myDescr += dx + ", " + dy + ", " + length + ")";
1485 }
1486
1487 /*!
1488   \brief Add segment by specified direction and X coordinate
1489   \param dx X component of direction vector
1490   \param dx Y component of direction vector
1491   \param x X coordinate of segment end
1492   \param CurrentIndex index of current operator
1493   \internal
1494 */
1495 void Sketcher_Profile::DumpFunctor::addSegmentDirectionX( const TCollection_AsciiString& dx,
1496                                                           const TCollection_AsciiString& dy,
1497                                                           const TCollection_AsciiString& x,
1498                                                           int& /*CurrentIndex*/ )
1499 {
1500   myDescr += "sk.addSegmentDirectionX(";
1501   myDescr += dx + ", " + dy + ", " + x + ")";
1502 }
1503
1504 /*!
1505   \brief Add segment by specified direction and Y coordinate
1506   \param dx X component of direction vector
1507   \param dx Y component of direction vector
1508   \param y Y coordinate of segment end
1509   \param CurrentIndex index of current operator
1510   \internal
1511 */
1512 void Sketcher_Profile::DumpFunctor::addSegmentDirectionY( const TCollection_AsciiString& dx,
1513                                                           const TCollection_AsciiString& dy,
1514                                                           const TCollection_AsciiString& y,
1515                                                           int& /*CurrentIndex*/ )
1516 {
1517   myDescr += "sk.addSegmentDirectionY(";
1518   myDescr += dx + ", " + dy + ", " + y + ")";
1519 }
1520
1521 /*!
1522   \brief Add arc along current direction vector by specified absolute coordinates
1523   \param x X coordinate of arc end
1524   \param x Y coordinate of arc end
1525   \internal
1526 */
1527 void Sketcher_Profile::DumpFunctor::addArcAbsolute( const TCollection_AsciiString& x,
1528                                                     const TCollection_AsciiString& y )
1529 {
1530   myDescr += "sk.addArcAbsolute(";
1531   myDescr += x + ", " + y + ")";
1532 }
1533
1534 /*!
1535   \brief Add arc along current direction vector by specified relative coordinates
1536   \param dx dX value specifying arc end
1537   \param dy dY value specifying arc end
1538   \internal
1539 */
1540 void Sketcher_Profile::DumpFunctor::addArcRelative( const TCollection_AsciiString& dx,
1541                                                     const TCollection_AsciiString& dy )
1542 {
1543   myDescr += "sk.addArcRelative(";
1544   myDescr += dx + ", " + dy + ")";
1545 }
1546
1547 /*!
1548   \brief Add arc with given radius by specified absolute coordinates
1549   \param x X coordinate of arc end
1550   \param x Y coordinate of arc end
1551   \param radius arc radius
1552   \param flag reverse direction flag
1553   \internal
1554 */
1555 void Sketcher_Profile::DumpFunctor::addArcRadiusAbsolute( const TCollection_AsciiString& x,
1556                                                           const TCollection_AsciiString& y,
1557                                                           const TCollection_AsciiString& radius,
1558                                                           const TCollection_AsciiString& flag )
1559 {
1560   myDescr += "sk.addArcRadiusAbsolute(";
1561   myDescr += x + ", " + y + ", " + radius + ", " + flag + ")";
1562 }
1563
1564 /*!
1565   \brief Add arc with given radius by specified relative coordinates
1566   \param dx dX value specifying arc end
1567   \param dy dY value specifying arc end
1568   \param radius arc radius
1569   \param flag reverse direction flag
1570   \internal
1571 */
1572 void Sketcher_Profile::DumpFunctor::addArcRadiusRelative( const TCollection_AsciiString& dx,
1573                                                           const TCollection_AsciiString& dy,
1574                                                           const TCollection_AsciiString& radius,
1575                                                           const TCollection_AsciiString& flag )
1576 {
1577   myDescr += "sk.addArcRadiusRelative(";
1578   myDescr += dx + ", " + dy + ", " + radius + ", " + flag + ")";
1579 }
1580
1581 /*!
1582   \brief Add arc with given center by specified absolute coordinates
1583   \param x X coordinate of arc end
1584   \param x Y coordinate of arc end
1585   \param xc X coordinate of arc center
1586   \param yc Y coordinate of arc center
1587   \param flag1 reverse direction flag
1588   \param flag2 tolerance
1589   \internal
1590 */
1591 void Sketcher_Profile::DumpFunctor::addArcCenterAbsolute( const TCollection_AsciiString& x,
1592                                                           const TCollection_AsciiString& y,
1593                                                           const TCollection_AsciiString& xc,
1594                                                           const TCollection_AsciiString& yc,
1595                                                           const TCollection_AsciiString& flag1,
1596                                                           const TCollection_AsciiString& flag2 )
1597 {
1598   myDescr += "sk.addArcCenterAbsolute(";
1599   myDescr += xc + ", " + yc + ", " + x + ", " + y + ", " + flag1 + ", " + flag2 + ")";
1600 }
1601
1602 /*!
1603   \brief Add arc with given center by specified relative coordinates
1604   \param dx dX value specifying arc end
1605   \param dy dY value specifying arc end
1606   \param xc X coordinate of arc center
1607   \param yc Y coordinate of arc center
1608   \param flag1 reverse direction flag
1609   \param flag2 tolerance
1610   \internal
1611 */
1612 void Sketcher_Profile::DumpFunctor::addArcCenterRelative( const TCollection_AsciiString& dx,
1613                                                           const TCollection_AsciiString& dy,
1614                                                           const TCollection_AsciiString& xc,
1615                                                           const TCollection_AsciiString& yc,
1616                                                           const TCollection_AsciiString& flag1,
1617                                                           const TCollection_AsciiString& flag2 )
1618 {
1619   myDescr += "sk.addArcCenterRelative(";
1620   myDescr += xc + ", " + yc + ", " + dx + ", " + dy + ", " + flag1 + ", " + flag2 + ")";
1621 }
1622
1623 /*!
1624   \brief Add arc with given radius by specified length
1625   \param radius arc radius
1626   \param length arc length
1627   \internal
1628 */
1629 void Sketcher_Profile::DumpFunctor::addArcRadiusLength( const TCollection_AsciiString& radius,
1630                                                         const TCollection_AsciiString& length )
1631 {
1632   myDescr += "sk.addArcRadiusLength(";
1633   myDescr += radius + ", " + length + ")";
1634 }
1635
1636 /*!
1637   \brief Add arc with given radius by specified angle and length
1638   \param angle angle between arc start tangent and current direction
1639   \param radius arc radius
1640   \param length arc length
1641   \param CurrentIndex index of current operator
1642   \internal
1643 */
1644 void Sketcher_Profile::DumpFunctor::addArcAngleRadiusLength( const TCollection_AsciiString& angle,
1645                                                              const TCollection_AsciiString& radius,
1646                                                              const TCollection_AsciiString& length ,
1647                                                              int& /*CurrentIndex*/ )
1648 {
1649   double aAngle = angle.RealValue();
1650   if ( aAngle == 90 ) {
1651     myDescr += "sk.addArcPerpRadiusLength(";
1652     myDescr += radius + ", " + length + ")";
1653   }
1654   else {
1655     myDescr += "sk.addArcAngleRadiusLength(";
1656     myDescr += angle + ", " + radius + ", " + length + ")";
1657   }
1658 }
1659
1660 /*!
1661   \brief Add arc with given radius by specified direction and length
1662   \param dx X component of direction vector
1663   \param dx Y component of direction vector
1664   \param radius arc radius
1665   \param length arc length
1666   \param CurrentIndex index of current operator
1667   \internal
1668 */
1669 void Sketcher_Profile::DumpFunctor::addArcDirectionRadiusLength( const TCollection_AsciiString& dx,
1670                                                                  const TCollection_AsciiString& dy,
1671                                                                  const TCollection_AsciiString& radius,
1672                                                                  const TCollection_AsciiString& length ,
1673                                                                  int& /*CurrentIndex*/ )
1674 {
1675   myDescr += "sk.addArcDirectionRadiusLength(";
1676   myDescr += dx + ", " + dy + ", " + radius + ", " + length + ")";
1677 }
1678
1679 /*!
1680   \brief Close wire
1681   \internal
1682 */
1683 void Sketcher_Profile::DumpFunctor::closeWire()
1684 {
1685   myDescr += "sk.close()";
1686 }
1687
1688 /*!
1689   \brief Close wire and build face
1690   \internal
1691 */
1692 void Sketcher_Profile::DumpFunctor::closeWireAndBuildFace()
1693 {
1694   myDescr += "sk.close()";
1695   myFace = Standard_True;
1696 }
1697
1698 /*!
1699   \brief Complete parsing of current operator
1700   \param CurrentIndex index of current operator
1701   \internal
1702 */
1703 void Sketcher_Profile::DumpFunctor::nextCommand( int& CurrentIndex )
1704 {
1705   CurrentIndex++;
1706 }
1707
1708 /*!
1709   \brief Finish parsing and create result
1710   \internal
1711 */
1712 void Sketcher_Profile::DumpFunctor::makeResult()
1713 {
1714   if ( mySketcherEntry == "" ) {
1715     myOk = false;
1716     return;
1717   }
1718   myDescr += "\n\t";
1719   if ( myFace )
1720     myDescr += mySketcherEntry + " = sk.face(" + myWPEntry + ")";
1721   else
1722     myDescr += mySketcherEntry + " = sk.wire(" + myWPEntry + ")";
1723   myDescr += myTail;
1724 }
1725
1726 /*!
1727   \brief Get python script
1728   \return string representing Python dump resulting from parsing of sketcher command
1729   \internal
1730 */
1731 TCollection_AsciiString Sketcher_Profile::DumpFunctor::getDescription()
1732 {
1733   return myDescr;
1734 }
1735
1736 //=======================================================================
1737 // Sketcher_Profile
1738 //=======================================================================
1739
1740
1741 /*!
1742   \brief Default constructor
1743 */
1744 Sketcher_Profile::Sketcher_Profile()
1745 {
1746 }
1747
1748 /*!
1749   \brief Constructor
1750   \param command sketcher script to parse
1751 */
1752 Sketcher_Profile::Sketcher_Profile( const char* command )
1753 {
1754   SetCommand( command );
1755 }
1756
1757 /*!
1758   \brief Set sketcher script to parse
1759   \param command sketcher script to parse
1760 */
1761 void Sketcher_Profile::SetCommand( const char* command )
1762 {
1763   myCommand = command;
1764 }
1765
1766 /*!
1767   \brief Parse sketcher command and get resulting shape
1768   \param isDone if specified (non-zero), result of parsing is returned via this parameter
1769   \param error if specified (non-zero), numerical error is returned via this parameter
1770   \return shape resulting from parsing of sketcher command
1771 */
1772 TopoDS_Shape Sketcher_Profile::GetShape( bool* isDone, double* error )
1773 {
1774   ShapeFunctor functor;
1775   parse( myCommand, &functor );
1776   TopoDS_Shape s = functor.getShape();
1777
1778   if ( isDone ) *isDone = functor.isOk();
1779   if ( error )  *error  = functor.error();
1780
1781   return s;
1782 }
1783
1784 /*!
1785   \brief Parse sketcher command and get resulting Python script
1786   \param isDone if specified (non-zero), result of parsing is returned via this parameter
1787   \return string representing Python dump resulting from parsing of sketcher command
1788 */
1789 TCollection_AsciiString Sketcher_Profile::GetDump( bool* isDone )
1790 {
1791   DumpFunctor functor;
1792   parse( myCommand, &functor );
1793   TCollection_AsciiString d = functor.getDescription();
1794
1795   if ( isDone ) *isDone = functor.isOk();
1796
1797   return d;
1798 }
1799
1800 /*!
1801   \brief Parse sketcher script using specified functor
1802   \param cmd sketcher script to parse
1803   \internal
1804 */
1805 void Sketcher_Profile::parse( const TCollection_AsciiString& /*cmd*/, Functor* functor )
1806 {
1807   int CurrentIndex = 1;
1808   int NumberOfArg = 0;
1809   int NumberOfCommand = 0;
1810
1811   functor->init( myCommand );
1812   TCollection_AsciiString command = extractCommand( myCommand );
1813
1814   TCollection_AsciiString aToken = command.Token( ":", 1 );
1815   TColStd_Array1OfAsciiString aTab( 0, command.Length() - 1 );
1816   if ( command.Length() ) {
1817     while ( aToken.Length() != 0 ) {
1818       TCollection_AsciiString aNewToken = command.Token( ":", NumberOfCommand + 1 );
1819       if ( aNewToken.Length() > 0 )
1820         aTab( NumberOfCommand ) = aNewToken;
1821       aToken = command.Token( ":", ++NumberOfCommand );
1822     }
1823     --NumberOfCommand;
1824   }
1825
1826   functor->setNumberOfCommand( NumberOfCommand );
1827   if ( aTab.Length() && aTab( 0 ).Length() ) {
1828     while ( CurrentIndex < NumberOfCommand ) {
1829       functor->initCommand();
1830       TColStd_Array1OfAsciiString a( 0, aTab( 0 ).Length() );
1831       findNextCommand( aTab, a, CurrentIndex, NumberOfArg );
1832       if ( a( 0 ) == "F" ) {
1833         if ( NumberOfArg != 3 ) badArgs();
1834         functor->addPoint( a.Value( 1 ), a.Value( 2 ) );
1835       }
1836       else if ( a( 0 ) == "X" ) {
1837         if ( NumberOfArg != 2 ) badArgs();
1838         functor->addSegmentParalX( a.Value( 1 ) );
1839       }
1840       else if ( a( 0 ) == "XX" ) {
1841         if ( NumberOfArg != 2 ) badArgs();
1842         functor->addSegmentParalXToZero();
1843       }
1844       else if ( a( 0 ) == "Y" ) {
1845         if ( NumberOfArg != 2 ) badArgs();
1846         functor->addSegmentParalY( a.Value( 1 ) );
1847       }
1848       else if ( a( 0 ) == "YY" ) {
1849         if ( NumberOfArg != 2 ) badArgs();
1850         functor->addSegmentParalYToZero();
1851       }
1852       else if ( a( 0 ) == "RR" ) {
1853         if ( NumberOfArg != 2 ) badArgs();
1854         functor->addAngle( a.Value( 1 ) );
1855       }
1856       else if ( a( 0 ) == "TT" ) {
1857         if ( NumberOfArg != 3 ) badArgs();
1858         functor->addSegmentAbsolute( a.Value( 1 ), a.Value( 2 ) );
1859       }
1860       else if ( a( 0 ) == "T" ) {
1861         if ( NumberOfArg != 3 ) badArgs();
1862         functor->addSegmentRelative( a.Value( 1 ), a.Value( 2 ) );
1863       }
1864       else if ( a( 0 ) == "L" ) {
1865         if ( NumberOfArg != 2 ) badArgs();
1866         functor->addSegmentLength( a.Value( 1 ) );
1867       }
1868       else if ( a( 0 ) == "IX" ) {
1869         if ( NumberOfArg != 2 ) badArgs();
1870         functor->addSegmentX( a.Value( 1 ), CurrentIndex );
1871       }
1872       else if ( a( 0 ) == "IY" ) {
1873         if ( NumberOfArg != 2 ) badArgs();
1874         functor->addSegmentY( a.Value( 1 ), CurrentIndex );
1875       }
1876       else if ( a( 0 ) == "R" ) {
1877         if ( NumberOfArg != 2) badArgs();
1878         CurrentIndex++;
1879         TColStd_Array1OfAsciiString aNew( 0, aTab( 0 ).Length() );
1880         findNextCommand( aTab, aNew, CurrentIndex, NumberOfArg );
1881         if ( aNew( 0 ) == "L" ) {
1882           if ( NumberOfArg != 2 ) badArgs();
1883           functor->addSegmentAngleLength( a.Value( 1 ), aNew.Value( 1 ), CurrentIndex );
1884         }
1885         else if ( aNew( 0 ) == "IX" ) {
1886           if ( NumberOfArg != 2 ) badArgs();
1887           functor->addSegmentAngleX( a.Value( 1 ), aNew.Value( 1 ), CurrentIndex );
1888         }
1889         else if ( aNew( 0 ) == "IY" ) {
1890           if ( NumberOfArg != 2 ) badArgs();
1891           functor->addSegmentAngleY( a.Value( 1 ), aNew.Value( 1 ), CurrentIndex );
1892         }
1893         else if ( aNew( 0 ) == "C" ) {
1894           if ( NumberOfArg != 3 ) badArgs();
1895           functor->addArcAngleRadiusLength( a.Value( 1 ), aNew.Value( 1 ), aNew.Value( 2 ), CurrentIndex );
1896         }
1897       }
1898       else if ( a( 0 ) == "D" ) {
1899         if ( NumberOfArg != 3 ) badArgs();
1900         CurrentIndex++;
1901         TColStd_Array1OfAsciiString aNew ( 0, aTab( 0 ).Length() );
1902         findNextCommand( aTab, aNew, CurrentIndex, NumberOfArg );
1903         if ( aNew( 0 ) == "L" ) {
1904           if ( NumberOfArg != 2 ) badArgs();
1905           functor->addSegmentDirectionLength( a.Value( 1 ), a.Value( 2 ), aNew.Value( 1 ), CurrentIndex );
1906         }
1907         else if ( aNew( 0 ) == "IX" ) {
1908           if ( NumberOfArg != 2 ) badArgs();
1909           functor->addSegmentDirectionX( a.Value( 1 ), a.Value( 2 ), aNew.Value( 1 ), CurrentIndex );
1910         }
1911         else if ( aNew( 0 ) == "IY" ) {
1912           if ( NumberOfArg != 2 ) badArgs();
1913           functor->addSegmentDirectionY( a.Value( 1 ), a.Value( 2 ), aNew.Value( 1 ), CurrentIndex );
1914         }
1915         else if ( aNew( 0 ) == "C" ) {
1916           if ( NumberOfArg != 3 ) badArgs();
1917           functor->addArcDirectionRadiusLength( a.Value( 1 ), a.Value( 2 ), aNew.Value( 1 ), aNew.Value( 2 ), CurrentIndex );
1918         }
1919       }
1920       else if ( a( 0 ) == "AA" ) {
1921         if ( NumberOfArg != 3 ) badArgs();
1922         functor->addArcAbsolute( a.Value( 1 ), a.Value( 2 ) );
1923       }
1924       else if ( a( 0 ) == "A" ) {
1925         if ( NumberOfArg != 3 ) badArgs();
1926         functor->addArcRelative( a.Value( 1 ), a.Value( 2 ) );
1927       }
1928       else if ( a( 0 ) == "UU" ) {
1929         if ( NumberOfArg != 5 ) badArgs();
1930         functor->addArcRadiusAbsolute( a.Value( 1 ), a.Value( 2 ), a.Value( 3 ), a.Value( 4 ) );
1931       }
1932       else if ( a( 0 ) == "U" ) {
1933         if ( NumberOfArg != 5 ) badArgs();
1934         functor->addArcRadiusRelative( a.Value( 1 ), a.Value( 2 ), a.Value( 3 ), a.Value( 4 ) );
1935       }
1936       else if ( a( 0 ) == "EE" ) {
1937         if ( NumberOfArg != 7 ) badArgs();
1938         functor->addArcCenterAbsolute( a.Value( 1 ), a.Value( 2 ), a.Value( 3 ), a.Value( 4 ), a.Value( 5 ), a.Value( 6 ) );
1939       }
1940       else if ( a( 0 ) == "E" ) {
1941         if ( NumberOfArg != 7 ) badArgs();
1942         functor->addArcCenterRelative( a.Value( 1 ), a.Value( 2 ), a.Value( 3 ), a.Value( 4 ), a.Value( 5 ), a.Value( 6 ) );
1943       }
1944       else if ( a( 0 ) == "C" ) {
1945         if ( NumberOfArg != 3 ) badArgs();
1946         functor->addArcRadiusLength( a.Value( 1 ), a.Value( 2 ) );
1947       }
1948       else if ( a( 0 ) == "WW" ) {
1949         functor->closeWire();
1950         CurrentIndex = NumberOfCommand - 1;
1951       }
1952       else if ( a( 0 ) == "WF" ) {
1953         functor->closeWireAndBuildFace();
1954         CurrentIndex = NumberOfCommand - 1;
1955       }
1956       else {
1957         MESSAGE("profile : unknown code " << a(CurrentIndex));
1958         return;
1959       }
1960       functor->nextCommand( CurrentIndex );
1961     }
1962   }
1963
1964   functor->makeResult();
1965 }
1966
1967 /*!
1968   \brief Extract sketcher command from script
1969   \param cmd sketcher script to parse
1970   \return sketcher command
1971   \internal
1972 */
1973 TCollection_AsciiString Sketcher_Profile::extractCommand( const TCollection_AsciiString& cmd )
1974 {
1975   // parse only first line of the script
1976   TCollection_AsciiString aSubStr = cmd.Token( "\n\t", 1 );
1977   return aSubStr.Token( "\"", aSubStr.Search( "=" ) != -1 ? 2 : 1 );
1978 }
1979
1980 /*!
1981   \brief Print an error message if the number of arguments of sketcher operator is wrong
1982   \internal
1983 */
1984 void Sketcher_Profile::badArgs()
1985 {
1986   MESSAGE("profile : bad number of arguments");
1987 }
1988
1989 /*!
1990   \brief Find the next sketcher operator in the input string
1991   \param aTab all sketcher command data
1992   \param a sketcher operator with parameters is returned via this parameter
1993   \param CurrentIndex current operator index
1994   \param NumberOfArg number of operator arguments is returned via this parameter
1995   \internal
1996 */
1997 void Sketcher_Profile::findNextCommand( const TColStd_Array1OfAsciiString& aTab,
1998                                         TColStd_Array1OfAsciiString& a, int CurrentIndex,
1999                                         int& NumberOfArg)
2000 {
2001   int n1 = 0;
2002   TCollection_AsciiString aToken = aTab(CurrentIndex).Token(" ", 1);
2003   while (aToken.Length() != 0) {
2004     if (aTab(CurrentIndex).Token(" ", n1 + 1).Length() > 0)
2005       a(n1) = aTab(CurrentIndex).Token(" ", n1 + 1);
2006     aToken = aTab(CurrentIndex).Token(" ", ++n1);
2007   }
2008   n1 = n1 - 1;
2009   NumberOfArg = n1;
2010 }
2011