Salome HOME
Typo-fix by Kunda
[modules/geom.git] / src / SKETCHER / Sketcher_Profile.cxx
1 // Copyright (C) 2007-2016  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   myMove = none;
640   myLength = x.RealValue();
641   if ( Abs( myDx ) < Precision::Confusion() ) {
642     MESSAGE("profile : cannot intersect, arg "<<CurrentIndex-1);
643     return;
644   }
645   myLength = ( myLength - myX ) / myDx;
646   if ( Abs( myLength ) > Precision::Confusion() )
647     myMove = line;
648 }
649
650 /*!
651   \brief Add segment along Y axis to reach specified Y coordinate
652   \param y Y coordinate of segment end
653   \param CurrentIndex index of current operator
654   \internal
655 */
656 void Sketcher_Profile::ShapeFunctor::addSegmentY( const TCollection_AsciiString& y,
657                                                   int CurrentIndex )
658 {
659   myMove = none;
660   myLength = y.RealValue();
661   if ( Abs( myDy ) < Precision::Confusion() ) {
662     MESSAGE("profile : cannot intersect, arg "<<CurrentIndex-1);
663     return;
664   }
665   myLength = ( myLength - myY ) / myDy;
666   if ( Abs( myLength ) > Precision::Confusion() )
667     myMove = line;
668 }
669
670 /*!
671   \brief Add segment by specified angle and length
672   \param angle angle that specifies segment direction
673   \param length segment length
674   \param CurrentIndex index of current operator
675   \internal
676 */
677 void Sketcher_Profile::ShapeFunctor::addSegmentAngleLength( const TCollection_AsciiString& angle,
678                                                             const TCollection_AsciiString& length,
679                                                             int& CurrentIndex )
680 {
681   setAngle( angle );
682   setMove( CurrentIndex );
683   addSegmentLength( length );
684 }
685
686 /*!
687   \brief Add segment that crosses Y axis by specified angle and X coordinate
688   \param angle angle that specifies segment direction
689   \param x X coordinate of segment end
690   \param CurrentIndex index of current operator
691   \internal
692 */
693 void Sketcher_Profile::ShapeFunctor::addSegmentAngleX( const TCollection_AsciiString& angle,
694                                                        const TCollection_AsciiString& x,
695                                                        int& CurrentIndex )
696 {
697   setAngle( angle );
698   setMove( CurrentIndex );
699   addSegmentX( x, CurrentIndex );
700 }
701
702 /*!
703   \brief Add segment that crosses X axis by specified angle and Y coordinate
704   \param angle angle that specifies segment direction
705   \param y Y coordinate of segment end
706   \param CurrentIndex index of current operator
707   \internal
708 */
709 void Sketcher_Profile::ShapeFunctor::addSegmentAngleY( const TCollection_AsciiString& angle,
710                                                        const TCollection_AsciiString& y,
711                                                        int& CurrentIndex )
712 {
713   setAngle( angle );
714   setMove( CurrentIndex );
715   addSegmentY( y, CurrentIndex );
716 }
717
718 /*!
719   \brief Add segment by specified direction and length
720   \param dx X component of direction vector
721   \param dx Y component of direction vector
722   \param length segment length
723   \param CurrentIndex index of current operator
724   \internal
725 */
726 void Sketcher_Profile::ShapeFunctor::addSegmentDirectionLength( const TCollection_AsciiString& dx,
727                                                                 const TCollection_AsciiString& dy,
728                                                                 const TCollection_AsciiString& length,
729                                                                 int& CurrentIndex )
730 {
731   setDirection( dx, dy );
732   setMove( CurrentIndex );
733   addSegmentLength( length );
734 }
735
736 /*!
737   \brief Add segment by specified direction and X coordinate
738   \param dx X component of direction vector
739   \param dx Y component of direction vector
740   \param x X coordinate of segment end
741   \param CurrentIndex index of current operator
742   \internal
743 */
744 void Sketcher_Profile::ShapeFunctor::addSegmentDirectionX( const TCollection_AsciiString& dx,
745                                                            const TCollection_AsciiString& dy,
746                                                            const TCollection_AsciiString& x,
747                                                            int& CurrentIndex )
748 {
749   setDirection( dx, dy );
750   setMove( CurrentIndex );
751   addSegmentX( x, CurrentIndex );
752 }
753
754 /*!
755   \brief Add segment by specified direction and Y coordinate
756   \param dx X component of direction vector
757   \param dx Y component of direction vector
758   \param y Y coordinate of segment end
759   \param CurrentIndex index of current operator
760   \internal
761 */
762 void Sketcher_Profile::ShapeFunctor::addSegmentDirectionY( const TCollection_AsciiString& dx,
763                                                            const TCollection_AsciiString& dy,
764                                                            const TCollection_AsciiString& y,
765                                                            int& CurrentIndex )
766 {
767   setDirection( dx, dy );
768   setMove( CurrentIndex );
769   addSegmentY( y, CurrentIndex );
770 }
771
772 /*!
773   \brief Add arc along current direction vector by specified absolute coordinates
774   \param x X coordinate of arc end
775   \param x Y coordinate of arc end
776   \internal
777 */
778 void Sketcher_Profile::ShapeFunctor::addArcAbsolute( const TCollection_AsciiString& x,
779                                                      const TCollection_AsciiString& y )
780 {
781   Standard_Real vx = x.RealValue() - myX;
782   Standard_Real vy = y.RealValue() - myY;
783   Standard_Real det = myDx * vy - myDy * vx;
784   Standard_Real c = Sqrt( ( myDx * myDx + myDy * myDy ) * ( vx * vx + vy * vy ) );
785   if ( Abs( det ) > Precision::Confusion() && Abs( c ) > Precision::Confusion() ) {
786     // Cosine of alpha = arc of angle / 2 , alpha in [0,Pi]
787     c = ( myDx * vx + myDy * vy ) / c;
788     // radius = distance between start and end point / 2 * sin(alpha)
789     // radius is > 0 or < 0
790     myRadius = ( vx * vx + vy * vy )* Sqrt( myDx * myDx + myDy * myDy ) / ( 2.0 * det );
791     if ( Abs( myRadius ) > Precision::Confusion() ) {
792       myAngle = 2.0 * acos( c ); // angle in [0,2Pi]
793       myMove = circle;
794     }
795     else
796       myMove = none;
797   }
798   else
799     myMove = none;
800 }
801
802 /*!
803   \brief Add arc along current direction vector by specified relative coordinates
804   \param dx dX value specifying arc end
805   \param dy dY value specifying arc end
806   \internal
807 */
808 void Sketcher_Profile::ShapeFunctor::addArcRelative( const TCollection_AsciiString& dx,
809                                                      const TCollection_AsciiString& dy )
810 {
811   Standard_Real vx = dx.RealValue();
812   Standard_Real vy = dy.RealValue();
813   Standard_Real det = myDx * vy - myDy * vx;
814   Standard_Real c = Sqrt( ( myDx * myDx + myDy * myDy ) * ( vx * vx + vy * vy ) );
815   if ( Abs( det ) > Precision::Confusion() && Abs( c ) > Precision::Confusion() ) {
816     // Cosine of alpha = arc of angle / 2 , alpha in [0,Pi]
817     c = ( myDx * vx + myDy * vy ) / c;
818     // radius = distance between start and end point / 2 * sin(alpha)
819     // radius is > 0 or < 0
820     myRadius = ( vx * vx + vy * vy )* Sqrt( myDx * myDx + myDy * myDy ) / ( 2.0 * det );
821     if ( Abs( myRadius ) > Precision::Confusion() ) {
822       myAngle = 2.0 * acos(c); // angle in [0,2Pi]
823       myMove = circle;
824     }
825     else
826       myMove = none;
827   }
828   else
829     myMove = none;
830 }
831
832 /*!
833   \brief Add arc with given radius by specified absolute coordinates
834   \param x X coordinate of arc end
835   \param x Y coordinate of arc end
836   \param radius arc radius
837   \param flag reverse direction flag
838   \internal
839 */
840 void Sketcher_Profile::ShapeFunctor::addArcRadiusAbsolute( const TCollection_AsciiString& x,
841                                                            const TCollection_AsciiString& y,
842                                                            const TCollection_AsciiString& radius,
843                                                            const TCollection_AsciiString& flag )
844 {
845   Standard_Real vx = x.RealValue() - myX;
846   Standard_Real vy = y.RealValue() - myY;
847   myRadius  = radius.RealValue();
848   int reversed = flag.IntegerValue();
849   Standard_Real length = Sqrt( vx * vx + vy * vy );
850   if ( Abs( myRadius ) > Precision::Confusion() &&
851        ( 4.0 - ( vx * vx + vy * vy ) / ( myRadius * myRadius ) >= 0.0 ) && ( length > Precision::Confusion() ) ) {
852     // Cosine of alpha = arc angle / 2 , alpha in [0,Pi/2]
853     Standard_Real c = 0.5 * Sqrt( 4.0 - ( vx * vx + vy * vy ) / ( myRadius * myRadius ) );
854     myAngle = 2.0 * acos( c ); // angle in [0,Pi]
855     if ( reversed == 2 )
856       myAngle = myAngle - 2 * M_PI;
857     myDx =  0.5 * ( vy * 1.0 / myRadius
858                     + vx * Sqrt( 4.0 / ( vx * vx + vy * vy ) - 1.0 / ( myRadius * myRadius ) ) );
859     myDy = -0.5 * ( vx * 1.0 / myRadius
860                     - vy * Sqrt( 4.0 / ( vx * vx + vy * vy ) - 1.0 / ( myRadius * myRadius ) ) );
861     myMove = circle;
862   }
863   else {
864     myMove = none;
865   }
866 }
867
868 /*!
869   \brief Add arc with given radius by specified relative coordinates
870   \param dx dX value specifying arc end
871   \param dy dY value specifying arc end
872   \param radius arc radius
873   \param flag reverse direction flag
874   \internal
875 */
876 void Sketcher_Profile::ShapeFunctor::addArcRadiusRelative( const TCollection_AsciiString& dx,
877                                                            const TCollection_AsciiString& dy,
878                                                            const TCollection_AsciiString& radius,
879                                                            const TCollection_AsciiString& flag )
880 {
881   Standard_Real vx = dx.RealValue();
882   Standard_Real vy = dy.RealValue();
883   myRadius  = radius.RealValue();
884   int reversed = flag.IntegerValue();
885   Standard_Real length = Sqrt( vx * vx + vy * vy );
886   if ( Abs( myRadius ) > Precision::Confusion() &&
887        ( 4.0 - ( vx * vx + vy * vy ) / ( myRadius * myRadius ) >= 0.0 ) && ( length > Precision::Confusion() ) ) {
888     // Cosine of alpha = arc angle / 2 , alpha in [0,Pi/2]
889     Standard_Real c = 0.5 * Sqrt( 4.0 - ( vx * vx + vy * vy ) / ( myRadius * myRadius ) );
890     myAngle = 2.0 * acos( c ); // angle in [0,Pi]
891     if ( reversed == 2 )
892       myAngle = myAngle - 2 * M_PI;
893     myDx =  0.5 * ( vy * 1.0 / myRadius
894                     + vx * Sqrt( 4.0  / ( vx * vx + vy * vy ) - 1.0 / ( myRadius * myRadius ) ) );
895     myDy = -0.5 * ( vx * 1.0 / myRadius
896                     - vy * Sqrt( 4.0  / ( vx * vx + vy * vy ) - 1.0 / ( myRadius * myRadius ) ) );
897     myMove = circle;
898   }
899   else {
900     myMove = none;
901   }
902 }
903
904 /*!
905   \brief Add arc with given center by specified absolute coordinates
906   \param x X coordinate of arc end
907   \param x Y coordinate of arc end
908   \param xc X coordinate of arc center
909   \param yc Y coordinate of arc center
910   \param flag1 reverse direction flag
911   \param flag2 tolerance
912   \internal
913 */
914 void Sketcher_Profile::ShapeFunctor::addArcCenterAbsolute( const TCollection_AsciiString& x,
915                                                            const TCollection_AsciiString& y,
916                                                            const TCollection_AsciiString& xc,
917                                                            const TCollection_AsciiString& yc,
918                                                            const TCollection_AsciiString& flag1,
919                                                            const TCollection_AsciiString& flag2 )
920 {
921   Standard_Real vx = x.RealValue() - myX;
922   Standard_Real vy = y.RealValue() - myY;
923   Standard_Real vxc  = xc.RealValue() - myX;
924   Standard_Real vyc  = yc.RealValue() - myY;
925   int reversed = flag1.IntegerValue();
926   int control_Tolerance = flag2.IntegerValue();
927
928   myRadius = Sqrt( vxc * vxc + vyc * vyc );
929   Standard_Real det = vx * vyc - vy * vxc;
930   Standard_Real length = Sqrt( vx * vx + vy * vy );
931   Standard_Real length2 = Sqrt( ( vx - vxc ) * ( vx - vxc ) + ( vy - vyc ) * ( vy - vyc ) );
932   Standard_Real length3 = Sqrt( vxc * vxc + vyc * vyc );
933   Standard_Real error = Abs( length2 - myRadius );
934   myError = error;
935   if ( error > Precision::Confusion() ) {
936     MESSAGE("Warning : The specified end point is not on the Arc, distance = "<<error);
937   }
938   if ( error > Precision::Confusion() && control_Tolerance == 1 ) // Don't create the arc if the end point
939     myMove = none;                                                // is too far from it
940   else if ( ( length  > Precision::Confusion() ) &&
941             ( length2 > Precision::Confusion() ) &&
942             ( length3 > Precision::Confusion() ) ) {
943     Standard_Real c = ( myRadius * myRadius - ( vx * vxc + vy * vyc ) )
944       / ( myRadius * Sqrt( ( vx - vxc ) * ( vx - vxc ) + ( vy - vyc ) * ( vy - vyc ) ) ) ;  // Cosine of arc angle
945     myAngle = acos(c);                                                                      // angle in [0,Pi]
946     if ( reversed == 2 )
947       myAngle = myAngle - 2 * M_PI;
948     if ( det < 0 )
949       myAngle = -myAngle;
950     myDx =  vyc / myRadius;
951     myDy = -vxc / myRadius;
952     myMove = circle;
953   }
954   else {
955     myMove = none;
956   }
957 }
958
959 /*!
960   \brief Add arc with given center by specified relative coordinates
961   \param dx dX value specifying arc end
962   \param dy dY value specifying arc end
963   \param xc X coordinate of arc center
964   \param yc Y coordinate of arc center
965   \param flag1 reverse direction flag
966   \param flag2 tolerance
967   \internal
968 */
969 void Sketcher_Profile::ShapeFunctor::addArcCenterRelative( const TCollection_AsciiString& dx,
970                                                            const TCollection_AsciiString& dy,
971                                                            const TCollection_AsciiString& xc,
972                                                            const TCollection_AsciiString& yc,
973                                                            const TCollection_AsciiString& flag1,
974                                                            const TCollection_AsciiString& flag2 )
975 {
976   Standard_Real vx = dx.RealValue();
977   Standard_Real vy = dy.RealValue();
978   Standard_Real vxc  = xc.RealValue();
979   Standard_Real vyc  = yc.RealValue();
980   int reversed = flag1.IntegerValue();
981   int control_Tolerance = flag2.IntegerValue();
982   myRadius = Sqrt( vxc * vxc + vyc * vyc );
983   Standard_Real det = vx * vyc - vy * vxc;
984   Standard_Real length = Sqrt( vx * vx + vy * vy );
985   Standard_Real length2 = Sqrt( ( vx - vxc ) * ( vx - vxc ) + ( vy - vyc ) * ( vy - vyc ) );
986   Standard_Real length3 = Sqrt( vxc * vxc + vyc * vyc );
987   Standard_Real error = Abs( length2 - myRadius );
988   myError = error;
989   if ( error > Precision::Confusion() ) {
990     MESSAGE("Warning : The specified end point is not on the Arc, distance = "<<error);
991   }
992   if ( error > Precision::Confusion() && control_Tolerance == 1 ) // Don't create the arc if the end point
993     myMove = none;                                                // is too far from it
994   else if ( ( length  > Precision::Confusion() ) &&
995             ( length2 > Precision::Confusion() ) &&
996             ( length3 > Precision::Confusion() ) ) {
997     Standard_Real c = ( myRadius * myRadius - ( vx * vxc + vy * vyc ) )
998       / ( myRadius * Sqrt( ( vx - vxc ) * ( vx - vxc ) + ( vy - vyc ) * ( vy - vyc ) ) ) ;  // Cosine of arc angle
999     myAngle = acos( c );                                                                    // angle in [0,Pi]
1000     if ( reversed == 2 )
1001       myAngle = myAngle - 2 * M_PI;
1002     if ( det < 0 )
1003       myAngle = -myAngle;
1004     myDx =  vyc / myRadius;
1005     myDy = -vxc / myRadius;
1006     myMove = circle;
1007   }
1008   else {
1009     myMove = none;
1010   }
1011 }
1012
1013 /*!
1014   \brief Add arc with given radius by specified length
1015   \param radius arc radius
1016   \param length arc length
1017   \internal
1018 */
1019 void Sketcher_Profile::ShapeFunctor::addArcRadiusLength( const TCollection_AsciiString& radius,
1020                                                          const TCollection_AsciiString& length )
1021 {
1022   myRadius = radius.RealValue();
1023   if ( Abs( myRadius ) > Precision::Confusion() ) {
1024     myAngle = length.RealValue() * M_PI / 180.;
1025     myMove = circle;
1026   }
1027   else
1028     myMove = none;
1029 }
1030
1031 /*!
1032   \brief Add arc with given radius by specified angle and length
1033   \param angle angle between arc start tangent and current direction
1034   \param radius arc radius
1035   \param length arc length
1036   \param CurrentIndex index of current operator
1037   \internal
1038 */
1039 void Sketcher_Profile::ShapeFunctor::addArcAngleRadiusLength( const TCollection_AsciiString& angle,
1040                                                               const TCollection_AsciiString& radius,
1041                                                               const TCollection_AsciiString& length ,
1042                                                               int& CurrentIndex )
1043 {
1044   setAngle( angle );
1045   setMove( CurrentIndex );
1046   addArcRadiusLength( radius, length );
1047 }
1048
1049 /*!
1050   \brief Add arc with given radius by specified direction and length
1051   \param dx X component of direction vector
1052   \param dx Y component of direction vector
1053   \param radius arc radius
1054   \param length arc length
1055   \param CurrentIndex index of current operator
1056   \internal
1057 */
1058 void Sketcher_Profile::ShapeFunctor::addArcDirectionRadiusLength( const TCollection_AsciiString& dx,
1059                                                                   const TCollection_AsciiString& dy,
1060                                                                   const TCollection_AsciiString& radius,
1061                                                                   const TCollection_AsciiString& length ,
1062                                                                   int& CurrentIndex )
1063 {
1064   setDirection( dx, dy );
1065   setMove( CurrentIndex );
1066   addArcRadiusLength( radius, length );
1067 }
1068
1069 /*!
1070   \brief Close wire
1071   \internal
1072 */
1073 void Sketcher_Profile::ShapeFunctor::closeWire()
1074 {
1075   myClose = Standard_True;
1076 }
1077
1078 /*!
1079   \brief Close wire and build face
1080   \internal
1081 */
1082 void Sketcher_Profile::ShapeFunctor::closeWireAndBuildFace()
1083 {
1084   myClose = Standard_True;
1085   myFace = Standard_True;
1086 }
1087
1088 /*!
1089   \brief Set internal parameters according to the current operator type
1090   \param CurrentIndex index of current operator
1091   \internal
1092 */
1093 void Sketcher_Profile::ShapeFunctor::setMove( int& CurrentIndex )
1094 {
1095   switch ( myMove )
1096   {
1097   case line :
1098     {
1099       if ( myLength < 0 ) {
1100         myLength = -myLength;
1101         myDx = -myDx;
1102         myDy = -myDy;
1103       }
1104       Handle(Geom2d_Line) l = new Geom2d_Line( gp_Pnt2d( myX, myY ),gp_Dir2d( myDx, myDy ) );
1105       BRepBuilderAPI_MakeEdge ME( GeomAPI::To3d( l, myPlane ), 0, myLength );
1106       if ( !ME.IsDone() )
1107         return;
1108       myMakeWire.Add( ME );
1109       myX += myLength * myDx;
1110       myY += myLength * myDy;
1111       break;
1112     }
1113   case circle :
1114     {
1115       Standard_Boolean sense = Standard_True;
1116       if ( myRadius < 0 ) {
1117         myRadius = -myRadius;
1118         sense = !sense;
1119         myDx = -myDx;
1120         myDy = -myDy;
1121       }
1122       gp_Ax2d ax( gp_Pnt2d( myX - myRadius * myDy, myY + myRadius * myDx ), gp_Dir2d( myDy, -myDx ) );
1123       if ( myAngle < 0 ) {
1124         myAngle = -myAngle;
1125         sense = !sense;
1126       }
1127       Handle(Geom2d_Circle) c = new Geom2d_Circle( ax, myRadius, sense );
1128       BRepBuilderAPI_MakeEdge ME( GeomAPI::To3d( c, myPlane ), 0, myAngle );
1129       if ( !ME.IsDone() )
1130         return;
1131       myMakeWire.Add( ME );
1132       gp_Pnt2d p;
1133       gp_Vec2d v;
1134       c->D1( myAngle, p, v );
1135       myX = p.X();
1136       myY = p.Y();
1137       myDx = v.X() / myRadius;
1138       myDy = v.Y() / myRadius;
1139       break;
1140     }
1141   case point:
1142     {
1143       myVertex = BRepBuilderAPI_MakeVertex( gp_Pnt( myX, myY, 0.0 ) );
1144       break;
1145     }
1146   case none:
1147     {
1148       CurrentIndex = myNumberOfCommand - 1;
1149       break;
1150     }
1151   }
1152 }
1153
1154 /*!
1155   \brief Complete parsing of current operator
1156   \param CurrentIndex index of current operator
1157   \internal
1158 */
1159 void Sketcher_Profile::ShapeFunctor::nextCommand( int& CurrentIndex )
1160 {
1161   setMove( CurrentIndex );
1162   CurrentIndex ++;
1163   // update first
1164   myFirst = myStayFirst;
1165   myStayFirst = Standard_False;
1166
1167   // next segment....
1168   if ( ( CurrentIndex == myNumberOfCommand ) && myClose ) {
1169     // the closing segment
1170     myDx = myX0 - myX;
1171     myDy = myY0 - myY;
1172     myLength = Sqrt( myDx * myDx + myDy * myDy );
1173     myMove = line;
1174     if ( myLength > Precision::Confusion() ) {
1175       myDx = myDx / myLength;
1176       myDy = myDy / myLength;
1177       setMove( CurrentIndex );
1178     }
1179   }
1180 }
1181
1182 /*!
1183   \brief Finish parsing and create result
1184   \internal
1185 */
1186 void Sketcher_Profile::ShapeFunctor::makeResult()
1187 {
1188   // get the result, face or wire
1189   if ( myMove == none ) {
1190     myOk = false;
1191     return;
1192   }
1193   else if ( myMove == point ) {
1194     myShape = myVertex;
1195   }
1196   else if ( myFace ) {
1197     if ( !myMakeWire.IsDone() ) {
1198       myOk = false;
1199       return;
1200     }
1201     BRepBuilderAPI_MakeFace MF ( myPlane, myMakeWire.Wire() );
1202     if ( !MF.IsDone() ) {
1203       myOk = false;
1204       return;
1205     }
1206     myShape = MF;
1207   }
1208   else {
1209     if ( !myMakeWire.IsDone() ) {
1210       myOk = false;
1211       return;
1212     }
1213     myShape = myMakeWire.Shape();
1214   }
1215
1216   if ( !TheLocation.IsIdentity() )
1217     myShape.Move( TheLocation );
1218 }
1219
1220 /*!
1221   \brief Get resulting shape
1222   \return shape resulting from parsing of sketcher command
1223   \internal
1224 */
1225 TopoDS_Shape Sketcher_Profile::ShapeFunctor::getShape()
1226 {
1227   return myShape;
1228 }
1229
1230 //===========================================================================
1231 // Sketcher_Profile::DumpFunctor
1232 //===========================================================================
1233
1234 /*!
1235   \brief Constructor
1236   \internal
1237 */
1238 Sketcher_Profile::DumpFunctor::DumpFunctor()
1239 {
1240   myFace = Standard_False;
1241 }
1242
1243 /*!
1244   \brief Initialize functor from the script
1245   \param command sketcher command being parsed
1246   \internal
1247 */
1248 void Sketcher_Profile::DumpFunctor::init( const TCollection_AsciiString& command )
1249 {
1250   // parse only first line of the script
1251   TCollection_AsciiString aSubStr = command.Token( "\n\t" );
1252   if ( aSubStr.Length() < command.Length() )
1253     myTail = command.SubString( aSubStr.Length()+1, command.Length() );
1254   // get sketch entry
1255   mySketcherEntry = aSubStr.Token( " =" );
1256   // Using this Working Plane for Sketcher
1257   myWPEntry = myWPEntry + "[" + aSubStr.Token( "[]", 2 ) + "]";
1258   // Using this Working Plane for SketcherOnPlane
1259   if ( aSubStr.Search( "MakeSketcherOnPlane" ) != -1 ) {
1260     myWPEntry = aSubStr.Token( ",)", 2 );
1261     myWPEntry.RemoveAll( ' ' );
1262   }
1263   myDescr += "sk = geompy.Sketcher2D()";
1264 }
1265
1266 /*!
1267   \brief Prepare functor for processing of new sketcher operator
1268   \internal
1269 */
1270 void Sketcher_Profile::DumpFunctor::initCommand()
1271 {
1272   myDescr += "\n\t";
1273 }
1274
1275 /*!
1276   \brief Add point with absolute coordinates (\a x, \a y)
1277   \param x X coordinate
1278   \param y Y coordinate
1279   \internal
1280 */
1281 void Sketcher_Profile::DumpFunctor::addPoint( const TCollection_AsciiString& x,
1282                                               const TCollection_AsciiString& y )
1283 {
1284   myDescr += "sk.addPoint(";
1285   myDescr += x + ", " + y + ")";
1286 }
1287
1288 /*!
1289   \brief Add angle
1290   \param angle angle
1291   \internal
1292 */
1293 void Sketcher_Profile::DumpFunctor::addAngle( const TCollection_AsciiString& angle )
1294 {
1295   myDescr += "sk.addAngle(";
1296   myDescr += angle + ")";
1297 }
1298
1299 /*!
1300   \brief Add new segment of \a x length along X axis
1301   \param x length of segment
1302   \internal
1303 */
1304 void Sketcher_Profile::DumpFunctor::addSegmentParalX( const TCollection_AsciiString& x )
1305 {
1306   myDescr += "sk.addSegmentParalX(";
1307   myDescr += x + ")";
1308 }
1309
1310 /*!
1311   \brief Add new segment along X axis with X coordinate of end set to 0
1312   \internal
1313 */
1314 void Sketcher_Profile::DumpFunctor::addSegmentParalXToZero()
1315 {
1316   myDescr += "sk.addSegmentParalXToZero()";
1317 }
1318
1319 /*!
1320   \brief Add new segment of \a y length along Y axis
1321   \param y length of segment
1322   \internal
1323 */
1324 void Sketcher_Profile::DumpFunctor::addSegmentParalY( const TCollection_AsciiString& y )
1325 {
1326   myDescr += "sk.addSegmentParalY(";
1327   myDescr += y + ")";
1328 }
1329
1330 /*!
1331   \brief Add new segment along Y axis with Y coordinate of end set to 0
1332   \internal
1333 */
1334 void Sketcher_Profile::DumpFunctor::addSegmentParalYToZero()
1335 {
1336   myDescr += "sk.addSegmentParalYToZero()";
1337 }
1338
1339 /*!
1340   \brief Add segment by absolute coordinates
1341   \param x X coordinate of segment end
1342   \param y Y coordinate of segment end
1343   \internal
1344 */
1345 void Sketcher_Profile::DumpFunctor::addSegmentAbsolute( const TCollection_AsciiString& x,
1346                                                         const TCollection_AsciiString& y )
1347 {
1348   myDescr += "sk.addSegmentAbsolute(";
1349   myDescr += x + ", " + y + ")";
1350 }
1351
1352 /*!
1353   \brief Add segment by relativ coordinates
1354   \param dx dX value specifying segment end
1355   \param dy dY value specifying segment end
1356   \internal
1357 */
1358 void Sketcher_Profile::DumpFunctor::addSegmentRelative( const TCollection_AsciiString& dx,
1359                                                         const TCollection_AsciiString& dy )
1360 {
1361   myDescr += "sk.addSegmentRelative(";
1362   myDescr += dx + ", " + dy + ")";
1363 }
1364
1365 /*!
1366   \brief Add segment with specified length along current direction
1367   \param length segment length
1368   \internal
1369 */
1370 void Sketcher_Profile::DumpFunctor::addSegmentLength( const TCollection_AsciiString& length )
1371 {
1372   myDescr += "sk.addSegmentLength(";
1373   myDescr += length + ")";
1374 }
1375
1376 /*!
1377   \brief Add segment along X axis to reach specified X coordinate
1378   \param x X coordinate of segment end
1379   \param CurrentIndex index of current operator
1380   \internal
1381 */
1382 void Sketcher_Profile::DumpFunctor::addSegmentX( const TCollection_AsciiString& x,
1383                                                  int CurrentIndex )
1384 {
1385   myDescr += "sk.addSegmentX(";
1386   myDescr += x + ")";
1387 }
1388
1389 /*!
1390   \brief Add segment along Y axis to reach specified Y coordinate
1391   \param y Y coordinate of segment end
1392   \param CurrentIndex index of current operator
1393   \internal
1394 */
1395 void Sketcher_Profile::DumpFunctor::addSegmentY( const TCollection_AsciiString& y,
1396                                                  int CurrentIndex  )
1397 {
1398   myDescr += "sk.addSegmentY(";
1399   myDescr += y + ")";
1400 }
1401
1402 /*!
1403   \brief Add segment by specified angle and length
1404   \param angle angle that specifies segment direction
1405   \param length segment length
1406   \param CurrentIndex index of current operator
1407   \internal
1408 */
1409 void Sketcher_Profile::DumpFunctor::addSegmentAngleLength( const TCollection_AsciiString& angle,
1410                                                            const TCollection_AsciiString& length,
1411                                                            int& CurrentIndex )
1412 {
1413   double aAngle = angle.RealValue();
1414   if ( aAngle == 90 ) {
1415     myDescr += "sk.addSegmentPerpLength(";
1416     myDescr += length + ")";
1417   }
1418   else {
1419     myDescr += "sk.addSegmentAngleLength(";
1420     myDescr += angle + ", " + length + ")";
1421   }
1422 }
1423
1424 /*!
1425   \brief Add segment that crosses Y axis by specified angle and X coordinate
1426   \param angle angle that specifies segment direction
1427   \param x X coordinate of segment end
1428   \param CurrentIndex index of current operator
1429   \internal
1430 */
1431 void Sketcher_Profile::DumpFunctor::addSegmentAngleX( const TCollection_AsciiString& angle,
1432                                                       const TCollection_AsciiString& x,
1433                                                       int& CurrentIndex )
1434 {
1435   double aAngle = angle.RealValue();
1436   if ( aAngle == 90 ) {
1437     myDescr += "sk.addSegmentPerpX(";
1438     myDescr += x + ")";
1439   }
1440   else {
1441     myDescr += "sk.addSegmentAngleX(";
1442     myDescr += angle + ", " + x + ")";
1443   }
1444 }
1445
1446 /*!
1447   \brief Add segment that crosses X axis by specified angle and Y coordinate
1448   \param angle angle that specifies segment direction
1449   \param y Y coordinate of segment end
1450   \param CurrentIndex index of current operator
1451   \internal
1452 */
1453 void Sketcher_Profile::DumpFunctor::addSegmentAngleY( const TCollection_AsciiString& angle,
1454                                                       const TCollection_AsciiString& y,
1455                                                       int& CurrentIndex )
1456 {
1457   double aAngle = angle.RealValue();
1458   if ( aAngle == 90 ) {
1459     myDescr += "sk.addSegmentPerpY(";
1460     myDescr += y + ")";
1461   }
1462   else {
1463     myDescr += "sk.addSegmentAngleY(";
1464     myDescr += angle + ", " + y + ")";
1465   }
1466 }
1467
1468 /*!
1469   \brief Add segment by specified direction and length
1470   \param dx X component of direction vector
1471   \param dx Y component of direction vector
1472   \param length segment length
1473   \param CurrentIndex index of current operator
1474   \internal
1475 */
1476 void Sketcher_Profile::DumpFunctor::addSegmentDirectionLength( const TCollection_AsciiString& dx,
1477                                                                const TCollection_AsciiString& dy,
1478                                                                const TCollection_AsciiString& length,
1479                                                                int& CurrentIndex )
1480 {
1481   myDescr += "sk.addSegmentDirectionLength(";
1482   myDescr += dx + ", " + dy + ", " + length + ")";
1483 }
1484
1485 /*!
1486   \brief Add segment by specified direction and X coordinate
1487   \param dx X component of direction vector
1488   \param dx Y component of direction vector
1489   \param x X coordinate of segment end
1490   \param CurrentIndex index of current operator
1491   \internal
1492 */
1493 void Sketcher_Profile::DumpFunctor::addSegmentDirectionX( const TCollection_AsciiString& dx,
1494                                                           const TCollection_AsciiString& dy,
1495                                                           const TCollection_AsciiString& x,
1496                                                           int& CurrentIndex )
1497 {
1498   myDescr += "sk.addSegmentDirectionX(";
1499   myDescr += dx + ", " + dy + ", " + x + ")";
1500 }
1501
1502 /*!
1503   \brief Add segment by specified direction and Y coordinate
1504   \param dx X component of direction vector
1505   \param dx Y component of direction vector
1506   \param y Y coordinate of segment end
1507   \param CurrentIndex index of current operator
1508   \internal
1509 */
1510 void Sketcher_Profile::DumpFunctor::addSegmentDirectionY( const TCollection_AsciiString& dx,
1511                                                           const TCollection_AsciiString& dy,
1512                                                           const TCollection_AsciiString& y,
1513                                                           int& CurrentIndex )
1514 {
1515   myDescr += "sk.addSegmentDirectionY(";
1516   myDescr += dx + ", " + dy + ", " + y + ")";
1517 }
1518
1519 /*!
1520   \brief Add arc along current direction vector by specified absolute coordinates
1521   \param x X coordinate of arc end
1522   \param x Y coordinate of arc end
1523   \internal
1524 */
1525 void Sketcher_Profile::DumpFunctor::addArcAbsolute( const TCollection_AsciiString& x,
1526                                                     const TCollection_AsciiString& y )
1527 {
1528   myDescr += "sk.addArcAbsolute(";
1529   myDescr += x + ", " + y + ")";
1530 }
1531
1532 /*!
1533   \brief Add arc along current direction vector by specified relative coordinates
1534   \param dx dX value specifying arc end
1535   \param dy dY value specifying arc end
1536   \internal
1537 */
1538 void Sketcher_Profile::DumpFunctor::addArcRelative( const TCollection_AsciiString& dx,
1539                                                     const TCollection_AsciiString& dy )
1540 {
1541   myDescr += "sk.addArcRelative(";
1542   myDescr += dx + ", " + dy + ")";
1543 }
1544
1545 /*!
1546   \brief Add arc with given radius by specified absolute coordinates
1547   \param x X coordinate of arc end
1548   \param x Y coordinate of arc end
1549   \param radius arc radius
1550   \param flag reverse direction flag
1551   \internal
1552 */
1553 void Sketcher_Profile::DumpFunctor::addArcRadiusAbsolute( const TCollection_AsciiString& x,
1554                                                           const TCollection_AsciiString& y,
1555                                                           const TCollection_AsciiString& radius,
1556                                                           const TCollection_AsciiString& flag )
1557 {
1558   myDescr += "sk.addArcRadiusAbsolute(";
1559   myDescr += x + ", " + y + ", " + radius + ", " + flag + ")";
1560 }
1561
1562 /*!
1563   \brief Add arc with given radius by specified relative coordinates
1564   \param dx dX value specifying arc end
1565   \param dy dY value specifying arc end
1566   \param radius arc radius
1567   \param flag reverse direction flag
1568   \internal
1569 */
1570 void Sketcher_Profile::DumpFunctor::addArcRadiusRelative( const TCollection_AsciiString& dx,
1571                                                           const TCollection_AsciiString& dy,
1572                                                           const TCollection_AsciiString& radius,
1573                                                           const TCollection_AsciiString& flag )
1574 {
1575   myDescr += "sk.addArcRadiusRelative(";
1576   myDescr += dx + ", " + dy + ", " + radius + ", " + flag + ")";
1577 }
1578
1579 /*!
1580   \brief Add arc with given center by specified absolute coordinates
1581   \param x X coordinate of arc end
1582   \param x Y coordinate of arc end
1583   \param xc X coordinate of arc center
1584   \param yc Y coordinate of arc center
1585   \param flag1 reverse direction flag
1586   \param flag2 tolerance
1587   \internal
1588 */
1589 void Sketcher_Profile::DumpFunctor::addArcCenterAbsolute( const TCollection_AsciiString& x,
1590                                                           const TCollection_AsciiString& y,
1591                                                           const TCollection_AsciiString& xc,
1592                                                           const TCollection_AsciiString& yc,
1593                                                           const TCollection_AsciiString& flag1,
1594                                                           const TCollection_AsciiString& flag2 )
1595 {
1596   myDescr += "sk.addArcCenterAbsolute(";
1597   myDescr += xc + ", " + yc + ", " + x + ", " + y + ", " + flag1 + ", " + flag2 + ")";
1598 }
1599
1600 /*!
1601   \brief Add arc with given center by specified relative coordinates
1602   \param dx dX value specifying arc end
1603   \param dy dY value specifying arc end
1604   \param xc X coordinate of arc center
1605   \param yc Y coordinate of arc center
1606   \param flag1 reverse direction flag
1607   \param flag2 tolerance
1608   \internal
1609 */
1610 void Sketcher_Profile::DumpFunctor::addArcCenterRelative( const TCollection_AsciiString& dx,
1611                                                           const TCollection_AsciiString& dy,
1612                                                           const TCollection_AsciiString& xc,
1613                                                           const TCollection_AsciiString& yc,
1614                                                           const TCollection_AsciiString& flag1,
1615                                                           const TCollection_AsciiString& flag2 )
1616 {
1617   myDescr += "sk.addArcCenterRelative(";
1618   myDescr += xc + ", " + yc + ", " + dx + ", " + dy + ", " + flag1 + ", " + flag2 + ")";
1619 }
1620
1621 /*!
1622   \brief Add arc with given radius by specified length
1623   \param radius arc radius
1624   \param length arc length
1625   \internal
1626 */
1627 void Sketcher_Profile::DumpFunctor::addArcRadiusLength( const TCollection_AsciiString& radius,
1628                                                         const TCollection_AsciiString& length )
1629 {
1630   myDescr += "sk.addArcRadiusLength(";
1631   myDescr += radius + ", " + length + ")";
1632 }
1633
1634 /*!
1635   \brief Add arc with given radius by specified angle and length
1636   \param angle angle between arc start tangent and current direction
1637   \param radius arc radius
1638   \param length arc length
1639   \param CurrentIndex index of current operator
1640   \internal
1641 */
1642 void Sketcher_Profile::DumpFunctor::addArcAngleRadiusLength( const TCollection_AsciiString& angle,
1643                                                              const TCollection_AsciiString& radius,
1644                                                              const TCollection_AsciiString& length ,
1645                                                              int& CurrentIndex )
1646 {
1647   double aAngle = angle.RealValue();
1648   if ( aAngle == 90 ) {
1649     myDescr += "sk.addArcPerpRadiusLength(";
1650     myDescr += radius + ", " + length + ")";
1651   }
1652   else {
1653     myDescr += "sk.addArcAngleRadiusLength(";
1654     myDescr += angle + ", " + radius + ", " + length + ")";
1655   }
1656 }
1657
1658 /*!
1659   \brief Add arc with given radius by specified direction and length
1660   \param dx X component of direction vector
1661   \param dx Y component of direction vector
1662   \param radius arc radius
1663   \param length arc length
1664   \param CurrentIndex index of current operator
1665   \internal
1666 */
1667 void Sketcher_Profile::DumpFunctor::addArcDirectionRadiusLength( const TCollection_AsciiString& dx,
1668                                                                  const TCollection_AsciiString& dy,
1669                                                                  const TCollection_AsciiString& radius,
1670                                                                  const TCollection_AsciiString& length ,
1671                                                                  int& CurrentIndex )
1672 {
1673   myDescr += "sk.addArcDirectionRadiusLength(";
1674   myDescr += dx + ", " + dy + ", " + radius + ", " + length + ")";
1675 }
1676
1677 /*!
1678   \brief Close wire
1679   \internal
1680 */
1681 void Sketcher_Profile::DumpFunctor::closeWire()
1682 {
1683   myDescr += "sk.close()";
1684 }
1685
1686 /*!
1687   \brief Close wire and build face
1688   \internal
1689 */
1690 void Sketcher_Profile::DumpFunctor::closeWireAndBuildFace()
1691 {
1692   myDescr += "sk.close()";
1693   myFace = Standard_True;
1694 }
1695
1696 /*!
1697   \brief Complete parsing of current operator
1698   \param CurrentIndex index of current operator
1699   \internal
1700 */
1701 void Sketcher_Profile::DumpFunctor::nextCommand( int& CurrentIndex )
1702 {
1703   CurrentIndex++;
1704 }
1705
1706 /*!
1707   \brief Finish parsing and create result
1708   \internal
1709 */
1710 void Sketcher_Profile::DumpFunctor::makeResult()
1711 {
1712   if ( mySketcherEntry == "" ) {
1713     myOk = false;
1714     return;
1715   }
1716   myDescr += "\n\t";
1717   if ( myFace )
1718     myDescr += mySketcherEntry + " = sk.face(" + myWPEntry + ")";
1719   else
1720     myDescr += mySketcherEntry + " = sk.wire(" + myWPEntry + ")";
1721   myDescr += myTail;
1722 }
1723
1724 /*!
1725   \brief Get python script
1726   \return string representing Python dump resulting from parsing of sketcher command
1727   \internal
1728 */
1729 TCollection_AsciiString Sketcher_Profile::DumpFunctor::getDescription()
1730 {
1731   return myDescr;
1732 }
1733
1734 //=======================================================================
1735 // Sketcher_Profile
1736 //=======================================================================
1737
1738
1739 /*!
1740   \brief Default constructor
1741 */
1742 Sketcher_Profile::Sketcher_Profile()
1743 {
1744 }
1745
1746 /*!
1747   \brief Constructor
1748   \param command sketcher script to parse
1749 */
1750 Sketcher_Profile::Sketcher_Profile( const char* command )
1751 {
1752   SetCommand( command );
1753 }
1754
1755 /*!
1756   \brief Set sketcher script to parse
1757   \param command sketcher script to parse
1758 */
1759 void Sketcher_Profile::SetCommand( const char* command )
1760 {
1761   myCommand = command;
1762 }
1763
1764 /*!
1765   \brief Parse sketcher command and get resulting shape
1766   \param isDone if specified (non-zero), result of parsing is returned via this parameter
1767   \param error if specified (non-zero), numerical error is returned via this parameter
1768   \return shape resulting from parsing of sketcher command
1769 */
1770 TopoDS_Shape Sketcher_Profile::GetShape( bool* isDone, double* error )
1771 {
1772   ShapeFunctor functor;
1773   parse( myCommand, &functor );
1774   TopoDS_Shape s = functor.getShape();
1775
1776   if ( isDone ) *isDone = functor.isOk();
1777   if ( error )  *error  = functor.error();
1778
1779   return s;
1780 }
1781
1782 /*!
1783   \brief Parse sketcher command and get resulting Python script
1784   \param isDone if specified (non-zero), result of parsing is returned via this parameter
1785   \return string representing Python dump resulting from parsing of sketcher command
1786 */
1787 TCollection_AsciiString Sketcher_Profile::GetDump( bool* isDone )
1788 {
1789   DumpFunctor functor;
1790   parse( myCommand, &functor );
1791   TCollection_AsciiString d = functor.getDescription();
1792
1793   if ( isDone ) *isDone = functor.isOk();
1794
1795   return d;
1796 }
1797
1798 /*!
1799   \brief Parse sketcher script using specified functor
1800   \param cmd sketcher script to parse
1801   \internal
1802 */
1803 void Sketcher_Profile::parse( const TCollection_AsciiString& cmd, Functor* functor )
1804 {
1805   int CurrentIndex = 1;
1806   int NumberOfArg = 0;
1807   int NumberOfCommand = 0;
1808
1809   functor->init( myCommand );
1810   TCollection_AsciiString command = extractCommand( myCommand );
1811
1812   TCollection_AsciiString aToken = command.Token( ":", 1 );
1813   TColStd_Array1OfAsciiString aTab( 0, command.Length() - 1 );
1814   if ( command.Length() ) {
1815     while ( aToken.Length() != 0 ) {
1816       TCollection_AsciiString aNewToken = command.Token( ":", NumberOfCommand + 1 );
1817       if ( aNewToken.Length() > 0 )
1818         aTab( NumberOfCommand ) = aNewToken;
1819       aToken = command.Token( ":", ++NumberOfCommand );
1820     }
1821     --NumberOfCommand;
1822   }
1823
1824   functor->setNumberOfCommand( NumberOfCommand );
1825   if ( aTab.Length() && aTab( 0 ).Length() ) {
1826     while ( CurrentIndex < NumberOfCommand ) {
1827       functor->initCommand();
1828       TColStd_Array1OfAsciiString a( 0, aTab( 0 ).Length() );
1829       findNextCommand( aTab, a, CurrentIndex, NumberOfArg );
1830       if ( a( 0 ) == "F" ) {
1831         if ( NumberOfArg != 3 ) badArgs();
1832         functor->addPoint( a.Value( 1 ), a.Value( 2 ) );
1833       }
1834       else if ( a( 0 ) == "X" ) {
1835         if ( NumberOfArg != 2 ) badArgs();
1836         functor->addSegmentParalX( a.Value( 1 ) );
1837       }
1838       else if ( a( 0 ) == "XX" ) {
1839         if ( NumberOfArg != 2 ) badArgs();
1840         functor->addSegmentParalXToZero();
1841       }
1842       else if ( a( 0 ) == "Y" ) {
1843         if ( NumberOfArg != 2 ) badArgs();
1844         functor->addSegmentParalY( a.Value( 1 ) );
1845       }
1846       else if ( a( 0 ) == "YY" ) {
1847         if ( NumberOfArg != 2 ) badArgs();
1848         functor->addSegmentParalYToZero();
1849       }
1850       else if ( a( 0 ) == "RR" ) {
1851         if ( NumberOfArg != 2 ) badArgs();
1852         functor->addAngle( a.Value( 1 ) );
1853       }
1854       else if ( a( 0 ) == "TT" ) {
1855         if ( NumberOfArg != 3 ) badArgs();
1856         functor->addSegmentAbsolute( a.Value( 1 ), a.Value( 2 ) );
1857       }
1858       else if ( a( 0 ) == "T" ) {
1859         if ( NumberOfArg != 3 ) badArgs();
1860         functor->addSegmentRelative( a.Value( 1 ), a.Value( 2 ) );
1861       }
1862       else if ( a( 0 ) == "L" ) {
1863         if ( NumberOfArg != 2 ) badArgs();
1864         functor->addSegmentLength( a.Value( 1 ) );
1865       }
1866       else if ( a( 0 ) == "IX" ) {
1867         if ( NumberOfArg != 2 ) badArgs();
1868         functor->addSegmentX( a.Value( 1 ), CurrentIndex );
1869       }
1870       else if ( a( 0 ) == "IY" ) {
1871         if ( NumberOfArg != 2 ) badArgs();
1872         functor->addSegmentY( a.Value( 1 ), CurrentIndex );
1873       }
1874       else if ( a( 0 ) == "R" ) {
1875         if ( NumberOfArg != 2) badArgs();
1876         CurrentIndex++;
1877         TColStd_Array1OfAsciiString aNew( 0, aTab( 0 ).Length() );
1878         findNextCommand( aTab, aNew, CurrentIndex, NumberOfArg );
1879         if ( aNew( 0 ) == "L" ) {
1880           if ( NumberOfArg != 2 ) badArgs();
1881           functor->addSegmentAngleLength( a.Value( 1 ), aNew.Value( 1 ), CurrentIndex );
1882         }
1883         else if ( aNew( 0 ) == "IX" ) {
1884           if ( NumberOfArg != 2 ) badArgs();
1885           functor->addSegmentAngleX( a.Value( 1 ), aNew.Value( 1 ), CurrentIndex );
1886         }
1887         else if ( aNew( 0 ) == "IY" ) {
1888           if ( NumberOfArg != 2 ) badArgs();
1889           functor->addSegmentAngleY( a.Value( 1 ), aNew.Value( 1 ), CurrentIndex );
1890         }
1891         else if ( aNew( 0 ) == "C" ) {
1892           if ( NumberOfArg != 3 ) badArgs();
1893           functor->addArcAngleRadiusLength( a.Value( 1 ), aNew.Value( 1 ), aNew.Value( 2 ), CurrentIndex );
1894         }
1895       }
1896       else if ( a( 0 ) == "D" ) {
1897         if ( NumberOfArg != 3 ) badArgs();
1898         CurrentIndex++;
1899         TColStd_Array1OfAsciiString aNew ( 0, aTab( 0 ).Length() );
1900         findNextCommand( aTab, aNew, CurrentIndex, NumberOfArg );
1901         if ( aNew( 0 ) == "L" ) {
1902           if ( NumberOfArg != 2 ) badArgs();
1903           functor->addSegmentDirectionLength( a.Value( 1 ), a.Value( 2 ), aNew.Value( 1 ), CurrentIndex );
1904         }
1905         else if ( aNew( 0 ) == "IX" ) {
1906           if ( NumberOfArg != 2 ) badArgs();
1907           functor->addSegmentDirectionX( a.Value( 1 ), a.Value( 2 ), aNew.Value( 1 ), CurrentIndex );
1908         }
1909         else if ( aNew( 0 ) == "IY" ) {
1910           if ( NumberOfArg != 2 ) badArgs();
1911           functor->addSegmentDirectionY( a.Value( 1 ), a.Value( 2 ), aNew.Value( 1 ), CurrentIndex );
1912         }
1913         else if ( aNew( 0 ) == "C" ) {
1914           if ( NumberOfArg != 3 ) badArgs();
1915           functor->addArcDirectionRadiusLength( a.Value( 1 ), a.Value( 2 ), aNew.Value( 1 ), aNew.Value( 2 ), CurrentIndex );
1916         }
1917       }
1918       else if ( a( 0 ) == "AA" ) {
1919         if ( NumberOfArg != 3 ) badArgs();
1920         functor->addArcAbsolute( a.Value( 1 ), a.Value( 2 ) );
1921       }
1922       else if ( a( 0 ) == "A" ) {
1923         if ( NumberOfArg != 3 ) badArgs();
1924         functor->addArcRelative( a.Value( 1 ), a.Value( 2 ) );
1925       }
1926       else if ( a( 0 ) == "UU" ) {
1927         if ( NumberOfArg != 5 ) badArgs();
1928         functor->addArcRadiusAbsolute( a.Value( 1 ), a.Value( 2 ), a.Value( 3 ), a.Value( 4 ) );
1929       }
1930       else if ( a( 0 ) == "U" ) {
1931         if ( NumberOfArg != 5 ) badArgs();
1932         functor->addArcRadiusRelative( a.Value( 1 ), a.Value( 2 ), a.Value( 3 ), a.Value( 4 ) );
1933       }
1934       else if ( a( 0 ) == "EE" ) {
1935         if ( NumberOfArg != 7 ) badArgs();
1936         functor->addArcCenterAbsolute( a.Value( 1 ), a.Value( 2 ), a.Value( 3 ), a.Value( 4 ), a.Value( 5 ), a.Value( 6 ) );
1937       }
1938       else if ( a( 0 ) == "E" ) {
1939         if ( NumberOfArg != 7 ) badArgs();
1940         functor->addArcCenterRelative( a.Value( 1 ), a.Value( 2 ), a.Value( 3 ), a.Value( 4 ), a.Value( 5 ), a.Value( 6 ) );
1941       }
1942       else if ( a( 0 ) == "C" ) {
1943         if ( NumberOfArg != 3 ) badArgs();
1944         functor->addArcRadiusLength( a.Value( 1 ), a.Value( 2 ) );
1945       }
1946       else if ( a( 0 ) == "WW" ) {
1947         functor->closeWire();
1948         CurrentIndex = NumberOfCommand - 1;
1949       }
1950       else if ( a( 0 ) == "WF" ) {
1951         functor->closeWireAndBuildFace();
1952         CurrentIndex = NumberOfCommand - 1;
1953       }
1954       else {
1955         MESSAGE("profile : unknown code " << a(CurrentIndex));
1956         return;
1957       }
1958       functor->nextCommand( CurrentIndex );
1959     }
1960   }
1961
1962   functor->makeResult();
1963 }
1964
1965 /*!
1966   \brief Extract sketcher command from script
1967   \param cmd sketcher script to parse
1968   \return sketcher command
1969   \internal
1970 */
1971 TCollection_AsciiString Sketcher_Profile::extractCommand( const TCollection_AsciiString& cmd )
1972 {
1973   // parse only first line of the script
1974   TCollection_AsciiString aSubStr = cmd.Token( "\n\t", 1 );
1975   return aSubStr.Token( "\"", aSubStr.Search( "=" ) != -1 ? 2 : 1 );
1976 }
1977
1978 /*!
1979   \brief Print an error message if the number of arguments of sketcher operator is wrong
1980   \internal
1981 */
1982 void Sketcher_Profile::badArgs()
1983 {
1984   MESSAGE("profile : bad number of arguments");
1985 }
1986
1987 /*!
1988   \brief Find the next sketcher operator in the input string
1989   \param aTab all sketcher command data
1990   \param a sketcher operator with parameters is returned via this parameter
1991   \param CurrentIndex current operator index
1992   \param NumberOfArg number of operator arguments is returned via this parameter
1993   \internal
1994 */
1995 void Sketcher_Profile::findNextCommand( const TColStd_Array1OfAsciiString& aTab,
1996                                         TColStd_Array1OfAsciiString& a, int CurrentIndex,
1997                                         int& NumberOfArg)
1998 {
1999   int n1 = 0;
2000   TCollection_AsciiString aToken = aTab(CurrentIndex).Token(" ", 1);
2001   while (aToken.Length() != 0) {
2002     if (aTab(CurrentIndex).Token(" ", n1 + 1).Length() > 0)
2003       a(n1) = aTab(CurrentIndex).Token(" ", n1 + 1);
2004     aToken = aTab(CurrentIndex).Token(" ", ++n1);
2005   }
2006   n1 = n1 - 1;
2007   NumberOfArg = n1;
2008 }
2009