]> SALOME platform Git repositories - modules/geom.git/blob - src/EntityGUI/EntityGUI_3DSketcherDlg.cxx
Salome HOME
EDF 1337 : Sketcher 3D, add definition of a point by an angle
[modules/geom.git] / src / EntityGUI / EntityGUI_3DSketcherDlg.cxx
1 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18
19 // GEOM GEOMGUI : GUI for Geometry component
20 // File   : EntityGUI_3DSketcherDlg.cxx
21 // Author : DMV, OCN
22
23 #include <cmath>
24 #include <string>
25 #include <boost/lexical_cast.hpp>
26
27 #include "EntityGUI_3DSketcherDlg.h"
28 #include "EntityGUI_Widgets.h"
29 #include <SalomeApp_DoubleSpinBox.h>
30
31 #include <GEOMBase.h>
32 #include <GeometryGUI.h>
33 #include <Precision.hxx>
34
35 #include <DlgRef.h>
36 #include <SUIT_Session.h>
37 #include <SUIT_Desktop.h>
38 #include <SUIT_MessageBox.h>
39 #include <SUIT_ResourceMgr.h>
40 #include <SUIT_ViewWindow.h>
41 #include <SUIT_ViewManager.h>
42 #include <SOCC_Prs.h>
43 #include <SOCC_ViewModel.h>
44 #include <SalomeApp_Application.h>
45 #include <LightApp_Application.h>
46 #include <LightApp_SelectionMgr.h>
47
48 #include <SalomeApp_Tools.h>
49
50 //OCCT includes
51 #include <TopoDS.hxx>
52 #include <TColStd_IndexedMapOfInteger.hxx>
53 #include <BRepBuilderAPI_MakeVertex.hxx>
54 #include <BRepBuilderAPI_MakePolygon.hxx>
55 #include <BRepBuilderAPI_MakeEdge.hxx>
56
57 #include <AIS_Trihedron.hxx>
58 #include <AIS_AngleDimension.hxx>
59 #include <AIS_LengthDimension.hxx>
60 #include <AIS_Drawer.hxx>
61 #include <Geom_Axis2Placement.hxx>
62 #include <Geom_Plane.hxx>
63 #include <SelectMgr_Selection.hxx>
64 #include <gce_MakePln.hxx>
65 #include <Prs3d_AngleAspect.hxx>
66 #include <Prs3d_LineAspect.hxx>
67 #include <Prs3d_LengthAspect.hxx>
68
69 // This include must be *AFTER* SOCC_ViewModel.h because
70 // of the constant ROTATE which is a #define in
71 // GEOMImpl_Types.hxx and an enum in SOCC_ViewModel.h
72 #include <GEOMImpl_Types.hxx>
73
74 // TODO
75 //
76 // + Ecrire la partie absolute / relative pour les coordonnées angulaires       Done
77 // + Ecrire les bons tests pour les coordonnées cylindriques                    Done
78 // + Finir refactoring des outils de display (displayLength)                    Done
79 // + Mettre en place la visualisation (côtes ...) pour les coordonnées cylindriques Done
80 // + Changement du mode de représentation (côtes) pour le cas absolu                Half done
81 // + Dump pour les coordonnées cylindriques et 
82 //   report des modifs sur les autres types de coordonnées        Done
83 // + Correction BUG coordonées cylindriques relatives --> la hauteur est absolue    Done
84 // + Améliorer rendu des cotes pour coordonées cylindriques (tailles relatives
85 //   de la cote rayon et de la cote hauteur)
86 // + Prendre en compte les remarques de Raphaël
87 // + Traductions                                       Done
88
89 enum
90 {
91   OXY,
92   OYZ,
93   OXZ
94 };
95
96 class Locker
97 {
98 public:
99   Locker(bool& l) : myLock(l) { myLock = true;  }
100   ~Locker()                   { myLock = false; }
101 private:
102   bool& myLock;
103 };
104
105 //=================================================================================
106 // class    : EntityGUI_3DSketcherDlg()
107 // purpose  : Constructs a EntityGUI_3DSketcherDlg which is a child of 'parent', with the
108 //            name 'name' and widget flags set to 'f'.
109 //            The dialog will by default be modeless, unless you set 'modal' to
110 //            TRUE to construct a modal dialog.
111 //=================================================================================
112 EntityGUI_3DSketcherDlg::EntityGUI_3DSketcherDlg (GeometryGUI* theGeometryGUI, QWidget* parent,
113                                                   bool modal, Qt::WindowFlags fl,
114                                                   const double lineWidth)
115   : GEOMBase_Skeleton(theGeometryGUI, parent, modal, fl),
116     myMode(-1),
117     myOK(false),
118     myLineWidth(lineWidth),
119     myGeometryGUI(theGeometryGUI),
120     myLengthIORedoList()
121 {
122   QPixmap image0(SUIT_Session::session()->resourceMgr()->loadPixmap("GEOM", tr("ICON_SELECT")));
123   QPixmap image1(SUIT_Session::session()->resourceMgr()->loadPixmap("GEOM", tr("ICON_DLG_UNDO")));
124   QPixmap image2(SUIT_Session::session()->resourceMgr()->loadPixmap("GEOM", tr("ICON_DLG_REDO")));
125   QPixmap image3(SUIT_Session::session()->resourceMgr()->loadPixmap("GEOM", tr("ICO_3DSKETCH")));
126
127   setWindowTitle(tr("GEOM_3DSKETCHER_TITLE"));
128
129   /***************************************************************/
130
131   mainFrame()->GroupConstructors->setTitle(tr("GEOM_3DSKETCHER"));
132   mainFrame()->RadioButton1->setIcon(image3);;
133   mainFrame()->RadioButton2->close();
134   mainFrame()->RadioButton3->close();
135
136   GroupType = new EntityGUI_Type(centralWidget());
137   GroupType->GroupType2->setTitle(tr("GEOM_COORDINATES_TYPE"));
138   GroupType->GroupType1->setTitle(tr("GEOM_MODE"));
139   GroupType->RadioButton1->setText(tr("GEOM_SKETCHER_ABS"));
140   GroupType->RadioButton2->setText(tr("GEOM_SKETCHER_REL"));
141   GroupType->RadioButton3->setText(tr("(X,Y,Z)"));
142   GroupType->RadioButton4->setText(tr("GEOM_ANGLES"));
143  
144   myTypeGroup1 = new QButtonGroup(this);
145   myTypeGroup1->setExclusive(true);
146   myTypeGroup1->addButton(GroupType->RadioButton1, 0);
147   myTypeGroup1->addButton(GroupType->RadioButton2, 1);
148   
149   myTypeGroup2 = new QButtonGroup(this);
150   myTypeGroup2->setExclusive(true);
151   myTypeGroup2->addButton(GroupType->RadioButton3, 0);
152   myTypeGroup2->addButton(GroupType->RadioButton4, 1);
153
154   Group3Spin = new EntityGUI_3Spin(centralWidget());
155   Group3Spin->GroupBox1->setTitle(tr("GEOM_SKETCHER_VALUES"));
156   Group3Spin->buttonApply->setText(tr("GEOM_SKETCHER_APPLY"));
157   Group3Spin->buttonUndo->setIcon(image1);
158   Group3Spin->buttonRedo->setIcon(image2);
159   Group3Spin->TextLabel1->setText(tr("GEOM_SKETCHER_X2"));
160   Group3Spin->TextLabel2->setText(tr("GEOM_SKETCHER_Y2"));
161   Group3Spin->TextLabel3->setText(tr("GEOM_SKETCHER_Z2"));
162
163   GroupAngles = new EntityGUI_Angles(centralWidget());
164   GroupAngles->buttonApply->setText(tr("GEOM_SKETCHER_APPLY"));
165   GroupAngles->buttonUndo->setIcon(image1);
166   GroupAngles->buttonRedo->setIcon(image2);
167   GroupAngles->TextLabel1->setText(tr("GEOM_LENGTH"));
168   GroupAngles->TextLabel2->setText(tr("GEOM_ANGLE")); 
169   GroupAngles->checkBox  ->setText(tr("GEOM_ANGLE_2"));
170   GroupAngles->checkBox_2->setText(tr("GEOM_HEIGHT"));
171
172   GroupControls = new EntityGUI_Controls(centralWidget());
173   GroupControls->GroupBox1->setTitle(tr("GEOM_CONTROLS"));
174   GroupControls->CheckBox1->setText(tr("GEOM_SHOW_LENGTH")); 
175   GroupControls->CheckBox2->setText(tr("GEOM_SHOW_ANGLE"));
176   GroupControls->CheckBox3->setText(tr("GEOM_SHOW_POINTS_COORD"));
177   GroupControls->lineEdit_1->setReadOnly(true);
178   GroupControls->lineEdit_2->setReadOnly(true);
179   GroupControls->lineEdit_3->setReadOnly(true);
180   GroupControls->lineEdit_4->setReadOnly(true);
181   GroupControls->lineEdit_5->setReadOnly(true);
182   GroupControls->lineEdit_6->setReadOnly(true);
183   GroupControls->label_1->setText(tr("X:"));
184   GroupControls->label_2->setText(tr("Y:"));
185   GroupControls->label_3->setText(tr("Z:"));
186   GroupControls->label_4->setText(tr("X:"));
187   GroupControls->label_5->setText(tr("Y:"));
188   GroupControls->label_6->setText(tr("Z:"));
189   GroupControls->label_7->setText(tr("GEOM_START"));
190   GroupControls->label_8->setText(tr("GEOM_END"));
191
192   buttonOk()->setText(tr("GEOM_BUT_END_SKETCH"));
193   buttonApply()->setText(tr("GEOM_BUT_CLOSE_SKETCH"));
194
195   QVBoxLayout* layout = new QVBoxLayout(centralWidget());
196   layout->setMargin(0); layout->setSpacing(6);
197   layout->addWidget(GroupType);
198   layout->addWidget(Group3Spin);
199   layout->addWidget(GroupAngles);
200   layout->addWidget(GroupControls);
201
202   setHelpFileName("create_3dsketcher_page.html");
203
204   resize(100,100);
205   Init();
206 }
207
208 //=================================================================================
209 // function : ~EntityGUI_3DSketcherDlg()
210 // purpose  : Destroys the object and frees any allocated resources
211 //=================================================================================
212 EntityGUI_3DSketcherDlg::~EntityGUI_3DSketcherDlg()
213 {
214   myGeomGUI->SetActiveDialogBox(0);
215 }
216
217 //=================================================================================
218 // function : Init()
219 // purpose  :
220 //=================================================================================
221 void EntityGUI_3DSketcherDlg::Init()
222 {
223   myOK = false;
224   myOrientation = OXY;
225   myPrsType = prsType();
226
227   SUIT_ViewWindow* vw = SUIT_Session::session()->activeApplication()->desktop()->activeWindow();
228   myAnglePrs = dynamic_cast<SOCC_Prs*>(((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->CreatePrs(0));
229   myLengthPrs = dynamic_cast<SOCC_Prs*>(((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->CreatePrs(0));
230
231   localSelection(GEOM::GEOM_Object::_nil(), TopAbs_VERTEX);
232
233   /* Get setting of step value from file configuration */
234   double step = SUIT_Session::session()->resourceMgr()->doubleValue("Geometry", "SettingsGeomStep", 100.0);
235
236   /* min, max, step and decimals for spin boxes */
237   initSpinBox(Group3Spin->SpinBox_DX, COORD_MIN, COORD_MAX, step, "length_precision");
238   initSpinBox(Group3Spin->SpinBox_DY, COORD_MIN, COORD_MAX, step, "length_precision");
239   initSpinBox(Group3Spin->SpinBox_DZ, COORD_MIN, COORD_MAX, step, "length_precision");
240
241   initSpinBox(GroupAngles->SpinBox_DA , -360.0, 360.0, step, "angular_precision");
242   initSpinBox(GroupAngles->SpinBox_DA2,  -90.0,  90.0, step, "angular_precision");
243   initSpinBox(GroupAngles->SpinBox_DL , COORD_MIN, COORD_MAX, step, "length_precision");
244   initSpinBox(GroupAngles->SpinBox_DH , COORD_MIN, COORD_MAX, step, "length_precision");
245
246   Group3Spin->SpinBox_DX->setValue(0.0);
247   Group3Spin->SpinBox_DY->setValue(0.0);
248   Group3Spin->SpinBox_DZ->setValue(0.0);
249
250   GroupAngles->SpinBox_DA->setValue(0.0);
251   GroupAngles->SpinBox_DA2->setValue(0.0);
252   GroupAngles->SpinBox_DL->setValue(0.0);
253   GroupAngles->SpinBox_DH->setValue(0.0);
254
255   GroupAngles->radioButton_1->setChecked(true);
256   GroupAngles->checkBox->setChecked(false);
257   GroupAngles->checkBox_2->setChecked(false);
258   GroupAngles->SpinBox_DA2->setEnabled(false);
259   GroupAngles->SpinBox_DH->setEnabled(false);
260
261   GroupControls->CheckBox1->setChecked(true);
262   GroupControls->CheckBox2->setChecked(true);
263   GroupControls->CheckBox3->setChecked(true);
264   
265   isLengthVisible = true;
266   isAngleVisible = true;
267
268   GroupAngles->hide();
269
270   /* signals and slots connections */
271   connect(buttonOk(),     SIGNAL(clicked()), this, SLOT(ClickOnOk()));
272   connect(buttonApply(),  SIGNAL(clicked()), this, SLOT(ClickOnApply()));
273
274   connect(myGeomGUI->getApp()->selectionMgr(), SIGNAL(currentSelectionChanged()), this, SLOT(SelectionIntoArgument()));
275
276   connect(Group3Spin->buttonApply,   SIGNAL(clicked()), this, SLOT(ClickOnAddPoint()));
277   connect(Group3Spin->buttonUndo,    SIGNAL(clicked()), this, SLOT(ClickOnUndo()));
278   connect(Group3Spin->buttonRedo,    SIGNAL(clicked()), this, SLOT(ClickOnRedo())) ;
279
280   connect(GroupAngles->buttonApply,  SIGNAL(clicked()), this, SLOT(ClickOnAddPoint()));
281   connect(GroupAngles->buttonUndo,   SIGNAL(clicked()), this, SLOT(ClickOnUndo()));
282   connect(GroupAngles->buttonRedo,   SIGNAL(clicked()), this, SLOT(ClickOnRedo())) ;
283
284   connect(myTypeGroup1, SIGNAL(buttonClicked(int)),  this, SLOT(TypeClicked(int)));
285   connect(myTypeGroup2, SIGNAL(buttonClicked(int)),  this, SLOT(TypeClicked(int)));
286
287   connect(Group3Spin->SpinBox_DX,       SIGNAL(valueChanged(double)), this, SLOT(ValueChangedInSpinBox(double)));
288   connect(Group3Spin->SpinBox_DY,       SIGNAL(valueChanged(double)), this, SLOT(ValueChangedInSpinBox(double)));
289   connect(Group3Spin->SpinBox_DZ,       SIGNAL(valueChanged(double)), this, SLOT(ValueChangedInSpinBox(double)));
290
291   connect(GroupAngles->SpinBox_DA,      SIGNAL(valueChanged(double)), this, SLOT(ValueChangedInSpinBox(double)));
292   connect(GroupAngles->SpinBox_DA2,     SIGNAL(valueChanged(double)), this, SLOT(ValueChangedInSpinBox(double)));
293   connect(GroupAngles->SpinBox_DL,      SIGNAL(valueChanged(double)), this, SLOT(ValueChangedInSpinBox(double)));
294   connect(GroupAngles->SpinBox_DH,      SIGNAL(valueChanged(double)), this, SLOT(ValueChangedInSpinBox(double)));
295
296   connect(GroupAngles->radioButton_1,   SIGNAL(clicked (bool)), this, SLOT(ButtonClicked(bool))) ;
297   connect(GroupAngles->radioButton_2,   SIGNAL(clicked (bool)), this, SLOT(ButtonClicked(bool))) ;
298   connect(GroupAngles->radioButton_3,   SIGNAL(clicked (bool)), this, SLOT(ButtonClicked(bool))) ;
299
300   connect(GroupAngles->checkBox,        SIGNAL(clicked (bool)), this, SLOT(BoxChecked (bool))) ;
301   connect(GroupAngles->checkBox_2,      SIGNAL(clicked (bool)), this, SLOT(BoxChecked (bool))) ;
302   connect(GroupControls->CheckBox1,     SIGNAL(clicked (bool)), this, SLOT(BoxChecked (bool))) ;
303   connect(GroupControls->CheckBox2,     SIGNAL(clicked (bool)), this, SLOT(BoxChecked (bool))) ;
304   connect(GroupControls->CheckBox3,     SIGNAL(clicked (bool)), this, SLOT(BoxChecked (bool))) ;
305
306   connect(myGeomGUI, SIGNAL(SignalDefaultStepValueChanged(double)), this, SLOT(SetDoubleSpinBoxStep(double)));
307
308   connect(myGeomGUI, SIGNAL(SignalDeactivateActiveDialog()), this, SLOT(DeactivateActiveDialog()));
309   connect(myGeomGUI, SIGNAL(SignalCloseAllDialogs()),        this, SLOT(ClickOnCancel()));
310
311   initName(tr("GEOM_3DSKETCHER"));
312   
313   GroupControls->CheckBox3->click();
314
315   UpdateButtonsState();
316   
317   myMode      = 0;
318   myCoordType = 0;
319   
320   GEOMBase_Helper::displayPreview(true, false, true, true, myLineWidth);
321 }
322
323 //=================================================================================
324 // function : TypeClicked()
325 // purpose  : Radio button management
326 //=================================================================================
327 void EntityGUI_3DSketcherDlg::TypeClicked (int id)
328 {
329   QButtonGroup* send = (QButtonGroup*) sender();
330   
331   int coordType = myCoordType;
332   int mode      = myMode;
333   
334   if (send == myTypeGroup1)
335   {
336     if(id == myMode) return;
337     mode = id;   
338   }
339   else if (send == myTypeGroup2)
340   {
341     if (id == myCoordType) return;
342     coordType = id;  
343   }
344   
345   GroupAngles->hide();
346   Group3Spin->show();
347
348   bool blocked = Group3Spin->SpinBox_DX->signalsBlocked();
349   Group3Spin->SpinBox_DX->blockSignals(true);
350   Group3Spin->SpinBox_DY->blockSignals(true);
351   Group3Spin->SpinBox_DZ->blockSignals(true);
352
353   // Get setting of step value from file configuration
354   XYZ xyz = getLastPoint();
355   bool okx, oky, okz;
356   Group3Spin->SpinBox_DX->text().toDouble(&okx);
357   Group3Spin->SpinBox_DY->text().toDouble(&oky);
358   Group3Spin->SpinBox_DZ->text().toDouble(&okz);
359
360   if (coordType == 0)  // Cartesian coordinates
361   {
362     if (mode == 0) {   // XYZ
363       Group3Spin->TextLabel1->setText(tr("GEOM_SKETCHER_X2"));
364       Group3Spin->TextLabel2->setText(tr("GEOM_SKETCHER_Y2"));
365       Group3Spin->TextLabel3->setText(tr("GEOM_SKETCHER_Z2"));
366       if (myCoordType == 0 && myMode == 1)
367       {
368         if (okx) Group3Spin->SpinBox_DX->setValue(xyz.x + Group3Spin->SpinBox_DX->value());
369         if (oky) Group3Spin->SpinBox_DY->setValue(xyz.y + Group3Spin->SpinBox_DY->value());
370         if (okz) Group3Spin->SpinBox_DZ->setValue(xyz.z + Group3Spin->SpinBox_DZ->value());
371       }
372       Group3Spin->buttonApply->setFocus();
373     }
374     else if (mode == 1) { // DXDYDZ
375       Group3Spin->TextLabel1->setText(tr("GEOM_SKETCHER_DX2"));
376       Group3Spin->TextLabel2->setText(tr("GEOM_SKETCHER_DY2"));
377       Group3Spin->TextLabel3->setText(tr("GEOM_SKETCHER_DZ2"));
378       if (myCoordType == 0 && myMode == 0)
379       {
380         if (okx) Group3Spin->SpinBox_DX->setValue(Group3Spin->SpinBox_DX->value() - xyz.x);
381         if (oky) Group3Spin->SpinBox_DY->setValue(Group3Spin->SpinBox_DY->value() - xyz.y);
382         if (okz) Group3Spin->SpinBox_DZ->setValue(Group3Spin->SpinBox_DZ->value() - xyz.z);
383       }
384       Group3Spin->buttonApply->setFocus();
385     }
386   }
387   else if (coordType == 1) // Angles and Length
388   {
389     Group3Spin->hide();
390     GroupAngles->show();
391     GroupAngles->buttonApply->setFocus();
392   }
393
394   Group3Spin->SpinBox_DX->blockSignals(blocked);
395   Group3Spin->SpinBox_DY->blockSignals(blocked);
396   Group3Spin->SpinBox_DZ->blockSignals(blocked);
397
398   myMode = mode;
399   myCoordType = coordType;
400
401   updateGeometry();
402   resize(minimumSizeHint());
403
404   GEOMBase_Helper::displayPreview(true, false, true, true, myLineWidth);
405 }
406
407 //=================================================================================
408 // function : ClickOnAddPoint()
409 // purpose  : called when the point coordinates is Applyed
410 //=================================================================================
411 void EntityGUI_3DSketcherDlg::ClickOnAddPoint()
412
413   QString msg;
414   if (!isValid(msg)) {
415     showError(msg);
416     return;
417   }
418   
419   myPrsType   = prsType();
420   
421   if(myMode == 1)
422     displayDimensions( /*store = */true);
423
424   myPointsList.append(getCurrentPoint());
425   myRedoList.clear();
426   myLengthIORedoList.Clear();
427   myAngleIORedoList.Clear();
428
429   if (myCoordType == 0 && myMode == 1)     // RELATIVE CARTESIAN COORDINATES
430   {
431     Group3Spin->SpinBox_DX->setValue(0.0);
432     Group3Spin->SpinBox_DY->setValue(0.0);
433     Group3Spin->SpinBox_DZ->setValue(0.0);
434   }
435   else if (myCoordType == 1 && myMode == 1) // RELATIVE ANGULAR COORDINATES
436   {
437     GroupAngles->SpinBox_DA->setValue(0.0);
438     GroupAngles->SpinBox_DL->setValue(0.0);
439     GroupAngles->SpinBox_DA2->setValue(0.0);
440   }
441   
442   UpdatePointCoordinates();
443     
444   UpdateButtonsState();
445   GEOMBase_Helper::displayPreview(true, false, true, true, myLineWidth);
446 }
447
448 //=================================================================================
449 // function : UpdateButtonsState()
450 // purpose  :
451 //=================================================================================
452 void EntityGUI_3DSketcherDlg::UpdateButtonsState()
453 {
454   if (myPointsList.count() == 0) 
455   {
456     GroupType->RadioButton1->click();
457     GroupType->RadioButton3->click();
458   }
459   GroupType->RadioButton2->setEnabled(myPointsList.count() > 0);
460   GroupType->RadioButton3->setEnabled(myPointsList.count() > 0);
461   GroupType->RadioButton4->setEnabled(myPointsList.count() > 0);
462   Group3Spin->buttonUndo->setEnabled(myPointsList.count() > 0);
463   Group3Spin->buttonRedo->setEnabled(myRedoList.count() > 0);
464   GroupAngles->buttonUndo->setEnabled(myPointsList.count() > 0);
465   GroupAngles->buttonRedo->setEnabled(myRedoList.count() > 0);
466 }
467
468 //=================================================================================
469 // function : UpdatePointCoordinates()
470 // purpose  :Update point coordinates in the control groupbox
471 //=================================================================================
472 void EntityGUI_3DSketcherDlg::UpdatePointCoordinates()
473 {
474   SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
475   int aPrecision = resMgr->integerValue("Geometry", "length_precision", 6);
476   
477   if (myPointsList.count() == 0)
478   {
479     GroupControls->lineEdit_1->setText("");
480     GroupControls->lineEdit_2->setText("");
481     GroupControls->lineEdit_3->setText("");
482     
483     GroupControls->lineEdit_4->setText("");
484     GroupControls->lineEdit_5->setText("");
485     GroupControls->lineEdit_6->setText("");
486   }
487   else if (myPointsList.count() == 1)
488   {
489     GroupControls->lineEdit_1->setText(DlgRef::PrintDoubleValue(getLastPoint().x, aPrecision));
490     GroupControls->lineEdit_2->setText(DlgRef::PrintDoubleValue(getLastPoint().y, aPrecision));
491     GroupControls->lineEdit_3->setText(DlgRef::PrintDoubleValue(getLastPoint().z, aPrecision));
492     
493     GroupControls->lineEdit_4->setText("");
494     GroupControls->lineEdit_5->setText("");
495     GroupControls->lineEdit_6->setText("");
496   }
497   else
498   {
499     GroupControls->lineEdit_4->setText(DlgRef::PrintDoubleValue(getLastPoint().x, aPrecision));
500     GroupControls->lineEdit_5->setText(DlgRef::PrintDoubleValue(getLastPoint().y, aPrecision));
501     GroupControls->lineEdit_6->setText(DlgRef::PrintDoubleValue(getLastPoint().z, aPrecision));
502   }
503   
504 }
505
506 //=================================================================================
507 // function : ClickOnUndo()
508 // purpose  :
509 //=================================================================================
510 void EntityGUI_3DSketcherDlg::ClickOnUndo()
511 {
512   if (myPointsList.count() > 0) {
513     
514     myRedoList.append(myPointsList.last());
515
516     // Erase dimensions presentations
517     SUIT_ViewWindow* vw = SUIT_Session::session()->activeApplication()->desktop()->activeWindow();
518     ((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->Erase(myLengthPrs, true);
519     ((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->Erase(myAnglePrs, true);
520     
521     removeLastIOFromPrs();
522
523     // Display modified presentation
524     if (isLengthVisible)
525       ((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->Display(myLengthPrs);
526     if (isAngleVisible)
527       ((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->Display(myAnglePrs);
528     
529     // Remove last point from list
530     myPointsList.removeLast();
531     GEOMBase_Helper::displayPreview(true, false, true, true, myLineWidth);
532     UpdateButtonsState();
533     
534     // Update of point coordinates in the control groupbox
535     UpdatePointCoordinates();
536
537     updateViewer();
538   }
539 }
540
541 //=================================================================================
542 // function : ClickOnRedo()
543 // purpose  :
544 //=================================================================================
545 void EntityGUI_3DSketcherDlg::ClickOnRedo()
546 {
547   if (myRedoList.count() > 0) {
548     
549     myPointsList.append(myRedoList.last());
550
551     // Erase dimensions presentations
552     SUIT_ViewWindow* vw = SUIT_Session::session()->activeApplication()->desktop()->activeWindow();
553     ((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->Erase(myLengthPrs, true);
554     ((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->Erase(myAnglePrs, true);
555     
556     restoreLastIOToPrs();
557
558     // Display modified presentation
559     if (isLengthVisible)
560       ((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->Display(myLengthPrs);
561     if (isAngleVisible)
562       ((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->Display(myAnglePrs);
563     
564     // Remove last point from redo list
565     myRedoList.removeLast();
566     GEOMBase_Helper::displayPreview(true, false, true, true, myLineWidth);
567     UpdateButtonsState();
568     
569     // Update of point coordinates in the control groupbox
570     UpdatePointCoordinates();
571
572     updateViewer();
573   }
574 }
575
576 //=================================================================================
577 // function : removeLastIO()
578 // purpose  :
579 //=================================================================================
580 void EntityGUI_3DSketcherDlg::removeLastIOFromPrs ()
581 {
582   AIS_ListOfInteractive anIOList;
583   XYZ Last = getLastPoint();
584   
585   for (int l = 0; l<Last.L; l++)
586   {
587     myLengthPrs->GetObjects(anIOList);
588     myLengthIORedoList.Prepend(anIOList.First());  // Store last prepended Length IO in redo list
589     myLengthPrs->RemoveFirst();                    // Remove it from myLengthPrs
590   }
591   for (int a = 0; a<Last.A; a++)
592   {
593     myAnglePrs->GetObjects(anIOList);
594     myAngleIORedoList.Prepend(anIOList.First());  // Store last prepended Angle IO in redo list
595     myAnglePrs->RemoveFirst();                    // Remove it from myAnglePrs
596   }
597 }
598
599 //=================================================================================
600 // function : restoreLastIO()
601 // purpose  :
602 //=================================================================================
603 void EntityGUI_3DSketcherDlg::restoreLastIOToPrs ()
604 {
605   XYZ LastDeleted = myRedoList.last();
606   
607   for (int l = 0; l<LastDeleted.L; l++)
608   {
609     myLengthPrs->PrependObject(myLengthIORedoList.First()); // Restore last removed IO
610     myLengthIORedoList.RemoveFirst();                       // Remove it from redo list
611   } 
612   for (int a = 0; a<LastDeleted.A; a++)
613   {
614     myAnglePrs->PrependObject(myAngleIORedoList.First());  // Restore last removed IO
615     myAngleIORedoList.RemoveFirst();                       // Remove it from redo list
616   }
617 }
618
619 //=================================================================================
620 // function : SelectionIntoArgument()
621 // purpose  : Called when selection as changed
622 //=================================================================================
623 void EntityGUI_3DSketcherDlg::SelectionIntoArgument()
624 {
625   LightApp_SelectionMgr* aSelMgr = myGeomGUI->getApp()->selectionMgr();
626   SALOME_ListIO aSelList;
627   aSelMgr->selectedObjects(aSelList);
628
629   int nbSel = aSelList.Extent();
630   if (nbSel == 1) {
631     GEOM::GEOM_Object_var aSelectedObject = GEOMBase::ConvertIOinGEOMObject(aSelList.First());
632     if (!CORBA::is_nil(aSelectedObject)) {
633       TopoDS_Shape aShape;
634       if (GEOMBase::GetShape(aSelectedObject, aShape, TopAbs_SHAPE)) {
635         // Explore the shape if its a local selection
636         TColStd_IndexedMapOfInteger aMap;
637         aSelMgr->GetIndexes(aSelList.First(), aMap);
638         if (aMap.Extent() == 1) {
639           int anIndex = aMap(1);
640           GEOM::GEOM_IShapesOperations_var aShapesOp = getGeomEngine()->GetIShapesOperations(getStudyId());
641           aSelectedObject = aShapesOp->GetSubShape(aSelectedObject, anIndex);
642         }
643       }
644       bool isOk = true;
645       if (aShape.ShapeType() != TopAbs_VERTEX)
646         isOk = GEOMBase::GetShape(aSelectedObject, aShape, TopAbs_VERTEX);
647       if (isOk) {
648         gp_Pnt aPnt;
649         if (GEOMBase::VertexToPoint(aShape, aPnt)) {
650           // set coordinates to the Spin Boxes
651           double aX, aY, aZ;
652           aX = aPnt.X();
653           aY = aPnt.Y();
654           aZ = aPnt.Z();
655           bool blocked = Group3Spin->SpinBox_DX->signalsBlocked();
656           Group3Spin->SpinBox_DX->blockSignals(true);
657           Group3Spin->SpinBox_DY->blockSignals(true);
658           Group3Spin->SpinBox_DZ->blockSignals(true);
659           if (GroupType->RadioButton1->isChecked()) {
660             Group3Spin->SpinBox_DX->setValue(aX);
661             Group3Spin->SpinBox_DY->setValue(aY);
662             Group3Spin->SpinBox_DZ->setValue(aZ);
663           }
664           else if (GroupType->RadioButton2->isChecked()) {
665             XYZ xyz = getLastPoint();
666             Group3Spin->SpinBox_DX->setValue(aX - xyz.x);
667             Group3Spin->SpinBox_DY->setValue(aY - xyz.y);
668             Group3Spin->SpinBox_DZ->setValue(aZ - xyz.z);
669           }
670           Group3Spin->SpinBox_DX->blockSignals(blocked);
671           Group3Spin->SpinBox_DY->blockSignals(blocked);
672           Group3Spin->SpinBox_DZ->blockSignals(blocked);
673         }
674       }
675     }
676   }
677   GEOMBase_Helper::displayPreview(true, false, true, true, myLineWidth);
678 }
679
680 //=================================================================================
681 // function : DeactivateActiveDialog()
682 // purpose  :
683 //=================================================================================
684 void EntityGUI_3DSketcherDlg::DeactivateActiveDialog()
685 {
686   setEnabled(false);
687   globalSelection();
688   disconnect(myGeomGUI->getApp()->selectionMgr(), 0, this, 0);
689   myGeomGUI->SetActiveDialogBox(0);
690 }
691
692 //=================================================================================
693 // function : ActivateThisDialog()
694 // purpose  :
695 //=================================================================================
696 void EntityGUI_3DSketcherDlg::ActivateThisDialog()
697 {
698   myGeomGUI->EmitSignalDeactivateDialog();
699   setEnabled(true);
700   myGeomGUI->SetActiveDialogBox(this);
701
702   connect(myGeomGUI->getApp()->selectionMgr(),
703           SIGNAL(currentSelectionChanged()), this, SLOT(SelectionIntoArgument()));
704
705   localSelection(GEOM::GEOM_Object::_nil(), TopAbs_VERTEX);
706   GEOMBase_Helper::displayPreview(true, false, true, true, myLineWidth);
707 }
708
709 //=================================================================================
710 // function : ValueChangedInSpinBox()
711 // purpose  :
712 //=================================================================================
713 void EntityGUI_3DSketcherDlg::ValueChangedInSpinBox (double newValue)
714 {
715   GEOMBase_Helper::displayPreview(true, false, true, true, myLineWidth);
716 }
717
718 //=================================================================================
719 // function : BoxChecked()
720 // purpose  : ChecBoxes management
721 //=================================================================================
722 void EntityGUI_3DSketcherDlg::BoxChecked (bool checked)
723 {
724   QCheckBox* send = (QCheckBox*) sender();
725   SUIT_ViewWindow* vw = SUIT_Session::session()->activeApplication()->desktop()->activeWindow();
726
727   if (send == GroupAngles->checkBox)
728   {
729     GroupAngles->SpinBox_DA2->setEnabled(checked);
730     if(checked)
731     {
732       GroupAngles->SpinBox_DH->setEnabled(false);
733       GroupAngles->checkBox_2->setChecked(false);
734     }
735   }
736   else if (send == GroupAngles->checkBox_2)
737   {
738     GroupAngles->SpinBox_DH->setEnabled(checked);
739     if(checked)
740     {
741       GroupAngles->SpinBox_DA2->setEnabled(false);
742       GroupAngles->checkBox->setChecked(false);
743     }
744   }
745
746   else if (send == GroupControls->CheckBox1)
747   {
748     ((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->Erase(myLengthPrs, true);
749     if (checked){
750       ((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->Display(myLengthPrs);
751       isLengthVisible=true;
752     }
753     else
754       isLengthVisible=false;
755   }
756   else if (send == GroupControls->CheckBox2)
757   {
758     ((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->Erase(myAnglePrs, true);
759     if (checked)
760     {
761       ((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->Display(myAnglePrs);
762       isAngleVisible=true;
763     }
764     else
765       isAngleVisible=false;
766   }
767   else if (send == GroupControls->CheckBox3)
768   {
769     GroupControls->lineEdit_1->setVisible(checked);
770     GroupControls->lineEdit_2->setVisible(checked);
771     GroupControls->lineEdit_3->setVisible(checked);
772     GroupControls->lineEdit_4->setVisible(checked);
773     GroupControls->lineEdit_5->setVisible(checked);
774     GroupControls->lineEdit_6->setVisible(checked);
775     
776     GroupControls->label_1->setVisible(checked);
777     GroupControls->label_2->setVisible(checked);
778     GroupControls->label_3->setVisible(checked);
779     GroupControls->label_4->setVisible(checked);
780     GroupControls->label_5->setVisible(checked);
781     GroupControls->label_6->setVisible(checked);
782     GroupControls->label_7->setVisible(checked);
783     GroupControls->label_8->setVisible(checked);
784     
785     GroupControls->updateGeometry();
786     GroupControls->resize(minimumSizeHint());
787   } 
788
789   updateGeometry();
790   resize(minimumSizeHint());
791   
792   GEOMBase_Helper::displayPreview(true, false, true, true, myLineWidth);
793 }
794
795 //=================================================================================
796 // function : ButtonClicked()
797 // purpose  :
798 //=================================================================================
799 void EntityGUI_3DSketcherDlg::ButtonClicked (bool checked)
800 {
801   if (GroupAngles->radioButton_1->isChecked())
802     myOrientation = OXY;
803   else if (GroupAngles->radioButton_2->isChecked())
804     myOrientation = OYZ;
805   else
806     myOrientation = OXZ;
807
808   GEOMBase_Helper::displayPreview(true, false, true, true, myLineWidth);
809 }
810
811 //=================================================================================
812 // function : enterEvent()
813 // purpose  :
814 //=================================================================================
815 void EntityGUI_3DSketcherDlg::enterEvent (QEvent*)
816 {
817   if (!mainFrame()->GroupConstructors->isEnabled())
818     ActivateThisDialog();
819 }
820
821 //=================================================================================
822 // function : createOperation
823 // purpose  :
824 //=================================================================================
825 GEOM::GEOM_IOperations_ptr EntityGUI_3DSketcherDlg::createOperation()
826 {
827   return getGeomEngine()->GetICurvesOperations(getStudyId());
828 }
829
830 //=================================================================================
831 // function : isValid
832 // purpose  :
833 //=================================================================================
834 bool EntityGUI_3DSketcherDlg::isValid (QString& msg)
835 {
836   bool ok = true;
837   ok = Group3Spin->SpinBox_DX->isValid(msg, !IsPreview()) && ok;
838   ok = Group3Spin->SpinBox_DY->isValid(msg, !IsPreview()) && ok;
839   ok = Group3Spin->SpinBox_DZ->isValid(msg, !IsPreview()) && ok;
840   return ok;
841 }
842
843 //=================================================================================
844 // function : execute
845 // purpose  :
846 //=================================================================================
847 bool EntityGUI_3DSketcherDlg::execute (ObjectList& objects)
848 {
849   //GEOM::ListOfDouble_var aCoordsArray = new GEOM::ListOfDouble;
850   //if (!myOK || myPointsList.size() == 0)
851   //  aCoordsArray->length((myPointsList.size()+1)*3);
852   //else
853   //  aCoordsArray->length(myPointsList.size()*3);
854
855   QStringList aCommands;
856   aCommands << "3DSketcher";
857   QStringList aParameters;
858
859   //int i = 0;
860   QList<XYZ>::const_iterator it;
861   for (it = myPointsList.begin(); it != myPointsList.end(); ++it) {
862     //aCoordsArray[i++] = (*it).x;
863     //aCoordsArray[i++] = (*it).y;
864     //aCoordsArray[i++] = (*it).z;
865     aCommands << (*it).command;
866     aParameters << (*it).params;
867   }
868
869   if (!myOK || myPointsList.size() == 0) {
870     XYZ xyz = getCurrentPoint();
871     //aCoordsArray[i++] = xyz.x;
872     //aCoordsArray[i++] = xyz.y;
873     //aCoordsArray[i++] = xyz.z;
874     aCommands << xyz.command;
875     aParameters << xyz.params;
876   }
877
878 //   MESSAGE("aCommands.last() = "<< aCommands.last().toStdString());
879   GEOM::GEOM_ICurvesOperations_var anOper = GEOM::GEOM_ICurvesOperations::_narrow(getOperation());
880   //GEOM::GEOM_Object_var anObj = anOper->Make3DSketcher(aCoordsArray);
881   GEOM::GEOM_Object_var anObj = anOper->Make3DSketcherCommand(aCommands.join(":").toLatin1().constData());
882
883   if (!anObj->_is_nil()) {
884     if (!IsPreview()) anObj->SetParameters(aParameters.join(":").toLatin1().constData());
885     objects.push_back(anObj._retn());
886   }
887
888   return true;
889 }
890
891 //=================================================================================
892 // function : SetDoubleSpinBoxStep()
893 // purpose  : Double spin box management
894 //=================================================================================
895 void EntityGUI_3DSketcherDlg::SetDoubleSpinBoxStep (double step)
896 {
897   Group3Spin->SpinBox_DX->setSingleStep(step);
898   Group3Spin->SpinBox_DY->setSingleStep(step);
899   Group3Spin->SpinBox_DZ->setSingleStep(step);
900   GroupAngles->SpinBox_DA ->setSingleStep(step);
901   GroupAngles->SpinBox_DA2->setSingleStep(step);
902   GroupAngles->SpinBox_DL->setSingleStep(step);
903   GroupAngles->SpinBox_DH->setSingleStep(step);
904 }
905
906 //=================================================================================
907 // function : ClickOnOk()
908 // purpose  :
909 //=================================================================================
910 void EntityGUI_3DSketcherDlg::ClickOnOk()
911 {
912   Locker lock(myOK);
913
914   if (!onAccept())
915     return;
916
917   ClickOnCancel();
918 }
919
920 //=================================================================================
921 // function : ClickOnApply()
922 // purpose  :
923 //=================================================================================
924 bool EntityGUI_3DSketcherDlg::ClickOnApply()
925 {
926   QString msg;
927   if (!isValid(msg)) {
928     showError(msg);
929     return false;
930   }
931
932   if (myPointsList.count() > 0)
933     myPointsList.append(myPointsList[0]);
934
935   Locker lock(myOK);
936
937   if (!onAccept())
938     return false;
939
940   ClickOnCancel();
941   return true;
942 }
943
944 //=================================================================================
945 // function : getLastPoint()
946 // purpose  : return last points from list
947 //=================================================================================
948 EntityGUI_3DSketcherDlg::XYZ EntityGUI_3DSketcherDlg::getLastPoint() const
949 {
950   return myPointsList.count() > 0 ? myPointsList.last() : XYZ();
951 }
952
953 //=================================================================================
954 // function : getPenultimatePoint()
955 // purpose  : return penultimate point from list
956 //=================================================================================
957 EntityGUI_3DSketcherDlg::XYZ EntityGUI_3DSketcherDlg::getPenultimatePoint() const
958 {
959   double size = myPointsList.count();
960   return size > 1 ? myPointsList.at(size - 2) : XYZ();
961 }
962
963 //=================================================================================
964 // function : getCurrentPoint()
965 // purpose  : returns current point
966 //=================================================================================
967 EntityGUI_3DSketcherDlg::XYZ EntityGUI_3DSketcherDlg::getCurrentPoint() const
968 {
969   XYZ xyz;
970
971   SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
972   int aPrecision = resMgr->integerValue("Geometry", "length_precision", 7);
973   
974   bool spherical   = GroupAngles->checkBox->isChecked();
975   bool cylindrical = GroupAngles->checkBox_2->isChecked();
976
977   if (myCoordType == 1) 
978   {
979     if (GroupAngles->radioButton_1->isChecked())
980       xyz.command = "OXY";
981     else if (GroupAngles->radioButton_2->isChecked())
982       xyz.command = "OYZ";
983     else
984       xyz.command = "OXZ";
985     
986     if (cylindrical)       // Cylindrical coordinates (radius, angle, height)
987       xyz.command += "C";
988     else
989       xyz.command += "S";  // Spherical coordinates (radius, angle1, angle2) --> polar if angle2 = 0
990     
991     if (myMode == 0)       // Absolute coordinates
992       xyz.command += "A ";
993     else if (myMode == 1)  // Relative coordinates
994       xyz.command += "R ";
995       
996
997     double anAngle  = GroupAngles->SpinBox_DA->value();
998     double aLength  = GroupAngles->SpinBox_DL->value();
999
1000     double anAngle2 = 0.0;
1001     QString da2 = "0";
1002     if (spherical) {       // Spherical coordinates (radius, angle1, angle2)
1003       anAngle2 = GroupAngles->SpinBox_DA2->value();
1004       da2 = GroupAngles->SpinBox_DA2->text();
1005     }
1006     
1007     double aHeight = 0.0;
1008     QString dh = "0";
1009     if (cylindrical) {
1010       aHeight = GroupAngles->SpinBox_DH->value();
1011       dh = GroupAngles->SpinBox_DH->text();
1012     }
1013
1014     xyz.command +=
1015       QString::number(anAngle, 'g', aPrecision) + " ";
1016     xyz.params =
1017       GroupAngles->SpinBox_DA->text() + ":"; 
1018     
1019     if(cylindrical)
1020     {
1021       xyz.command +=
1022         QString::number(aHeight, 'g', aPrecision) + " ";
1023       xyz.params +=
1024         dh + ":";
1025     }
1026     else                  // Spherical or polar coordinates
1027     {
1028       xyz.command +=
1029         QString::number(anAngle2, 'g', aPrecision) + " ";
1030       xyz.params +=
1031         dh + ":";
1032     }
1033     
1034     xyz.command +=
1035       QString::number(aLength, 'g', aPrecision);
1036     xyz.params +=
1037       GroupAngles->SpinBox_DL->text();
1038
1039       
1040     // Calculate point coordinates for preview
1041     anAngle  = anAngle * M_PI/180.0;
1042     anAngle2 = anAngle2 * M_PI/180.0;
1043     double aProjectedLength = aLength * cos(anAngle2);
1044     
1045     XYZ xyzP = getLastPoint();
1046     if (myMode == 0)
1047       xyzP.x=xyzP.y=xyzP.z=0.0; 
1048     if (GroupAngles->radioButton_1->isChecked()) // OXY
1049     {
1050       xyz.x = xyzP.x + aProjectedLength * cos(anAngle);
1051       xyz.y = xyzP.y + aProjectedLength * sin(anAngle);
1052       if (cylindrical)
1053         xyz.z = xyzP.z + aHeight;
1054       else
1055         xyz.z = xyzP.z + aLength * sin(anAngle2);
1056     }
1057     else if (GroupAngles->radioButton_2->isChecked()) // OYZ
1058     {
1059       xyz.y = xyzP.y + aProjectedLength * cos(anAngle);
1060       xyz.z = xyzP.z + aProjectedLength * sin(anAngle);
1061       if (cylindrical)
1062         xyz.x = xyzP.x + aHeight;
1063       else
1064         xyz.x = xyzP.x + aLength * sin(anAngle2);
1065     }
1066     else // OXZ
1067     {
1068       xyz.z = xyzP.z + aProjectedLength * sin(anAngle);
1069       xyz.x = xyzP.x + aProjectedLength * cos(anAngle);
1070       if (cylindrical)
1071         xyz.y = xyzP.y + aHeight;
1072       else
1073         xyz.y = xyzP.y + aLength * sin(anAngle2);
1074     }
1075   }
1076   else if(myCoordType == 0) {
1077     if (myMode == 0) { // XYZ
1078       xyz.x = Group3Spin->SpinBox_DX->value();
1079       xyz.y = Group3Spin->SpinBox_DY->value();
1080       xyz.z = Group3Spin->SpinBox_DZ->value();
1081       xyz.command = "TT ";
1082     }
1083     else { // DXDYDZ
1084       xyz = getLastPoint();
1085       xyz.x += Group3Spin->SpinBox_DX->value();
1086       xyz.y += Group3Spin->SpinBox_DY->value();
1087       xyz.z += Group3Spin->SpinBox_DZ->value();
1088       xyz.command = "T ";
1089     }
1090
1091     double aX  = Group3Spin->SpinBox_DX->value();
1092     double aY  = Group3Spin->SpinBox_DY->value();
1093     double aZ  = Group3Spin->SpinBox_DZ->value();
1094
1095     xyz.command +=
1096       QString::number(aX, 'g', aPrecision) + " " +
1097       QString::number(aY, 'g', aPrecision) + " " +
1098       QString::number(aZ, 'g', aPrecision);
1099     xyz.params =
1100       Group3Spin->SpinBox_DX->text() + ":" +
1101       Group3Spin->SpinBox_DY->text() + ":" +
1102       Group3Spin->SpinBox_DZ->text();
1103   }
1104   // Update point presentation type
1105   xyz.A = myPrsType.A;  // Number of angle diomensions
1106   xyz.L = myPrsType.L;  // Number of length dimensions
1107   
1108   return xyz;
1109 }
1110
1111
1112 //=================================================================================
1113 // function : getPresentationPlane()
1114 // purpose  : returns the suitable plane for right
1115 //            relative positioning of dimension presentations
1116 //=================================================================================
1117 gp_Dir EntityGUI_3DSketcherDlg::getPresentationPlane() const
1118
1119   bool withAngle = (myCoordType == 1);
1120   bool twoAngles = GroupAngles->checkBox->isChecked();
1121   
1122   XYZ Last    = getLastPoint();
1123   XYZ Current = getCurrentPoint();
1124   XYZ Penultimate = getPenultimatePoint();
1125   
1126   gp_Pnt P1 = gp_Pnt(Last.x,Last.y,Last.z);
1127   if (myMode == 0) // Absolute coordinates
1128     P1 = gp::Origin();
1129   
1130   gp_Pnt P2 = gp_Pnt(Current.x,Current.y,Current.z);
1131   gp_Pnt P3 = gp_Pnt(Penultimate.x,Penultimate.y,Penultimate.z);
1132   
1133   gp_Vec Vec1(P1,P2);
1134   gp_Vec Vec2(P1,P3);
1135   gp_Vec Vec3 = Vec1;
1136   
1137   gp_Dir aNormal;                  // Normal defining the plane of the presentation 
1138   
1139   if (withAngle)                   // If one angle
1140   {
1141     switch(myOrientation)
1142     {
1143       case OXY:
1144       {
1145         if (Vec1.CrossMagnitude(gp::DZ()) > Precision::Confusion())
1146           aNormal = gp::DZ().Crossed(gp_Dir(Vec1)); // --> the plane is orthogonal to the angle presentation   
1147         else                                        //     plane and contains the current edge
1148           aNormal = gp::DY();
1149
1150         if (twoAngles)            // If two angles 
1151         { 
1152           gp_XYZ Vec1_XY(Vec1.X(),Vec1.Y(),0.0);// --> define Vec3 as the projection of the current 
1153           Vec3 = gp_Vec(Vec1_XY);               //     edge on the plane chosen for the first angle
1154         }
1155         break;
1156       }
1157       case OYZ:
1158       {
1159         if (Vec1.CrossMagnitude(gp::DX()) > Precision::Confusion())
1160           aNormal = gp::DX().Crossed(gp_Dir(Vec1));
1161         else
1162           aNormal = gp::DZ();
1163           
1164         if (twoAngles)
1165         {
1166           gp_XYZ Vec1_YZ(0.0,Vec1.Y(),Vec1.Z());
1167           Vec3 = gp_Vec(Vec1_YZ);
1168         }
1169         break;
1170       }
1171       case OXZ:
1172       {
1173         if (Vec1.CrossMagnitude(gp::DY()) > Precision::Confusion())
1174           aNormal = gp::DY().Crossed(gp_Dir(Vec1));
1175         else
1176           aNormal = gp::DZ();
1177         
1178         if (twoAngles)
1179         {
1180           gp_XYZ Vec1_XZ(Vec1.X(),0.0,Vec1.Z());
1181           Vec3 = gp_Vec(Vec1_XZ);
1182         }
1183         break;
1184       }
1185     }
1186  
1187     if(twoAngles                  // If two angles 
1188       && Abs(Vec1.CrossMagnitude(Vec3)) > Precision::Confusion())                                  
1189     { 
1190       aNormal = gp_Dir(Vec1.Crossed(Vec3));//       --> set the normal as the cross product of
1191     }                                      //           the current edge with its projection           
1192   }                                        //           it ensures that the dimension changes
1193                                            //           side when the angle becomes negative
1194   else
1195   {
1196     // Check colinearity
1197     if (Abs(Vec1.CrossMagnitude(Vec2)) < Precision::Confusion())
1198     {
1199       Vec2 = gp_Vec(gp::DX());
1200       if (Abs(Vec1.CrossMagnitude(Vec2)) < Precision::Confusion())
1201       {
1202         Vec2 = gp_Vec(gp::DY());
1203       }
1204     }
1205     aNormal = gp_Dir(Vec1.Crossed(Vec2)); // If no angles --> the plane is the one formed by
1206   }                                       //                  the last edge and the current one
1207   return aNormal;
1208 }
1209
1210 //================================================================
1211 // Function : displayPreview
1212 // Purpose  : Method for displaying preview of resulting shape
1213 //            Redefined from GEOMBase_Helper.
1214 //================================================================
1215 void EntityGUI_3DSketcherDlg::displayPreview (GEOM::GEOM_Object_ptr object,
1216                                               const bool            append,
1217                                               const bool            activate,
1218                                               const bool            update,
1219                                               const double          lineWidth,
1220                                               const int             displayMode,
1221                                               const int             color)
1222 {
1223   SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
1224
1225   QColor aColor = resMgr->colorValue("Geometry","line_color",QColor(255,0,0));
1226   Quantity_NameOfColor line_color = SalomeApp_Tools::color(aColor).Name();
1227
1228   // set width of displayed shape
1229   int lw = lineWidth;
1230   if (lw == -1) {
1231     lw = resMgr->integerValue("Geometry", "preview_edge_width", -1);
1232   }
1233   getDisplayer()->SetWidth(lw);
1234
1235   // Disable activation of selection
1236   getDisplayer()->SetToActivate(activate);
1237
1238   // Make a reference to GEOM_Object
1239   CORBA::String_var objStr = myGeometryGUI->getApp()->orb()->object_to_string(object);
1240   getDisplayer()->SetName(objStr.in());
1241
1242   // Create wire from applied object
1243   TopoDS_Shape anApplyedWire, aLastSegment;
1244   if (!createShapes(object, anApplyedWire, aLastSegment))
1245     return;
1246
1247   // Set color for preview shape
1248   getDisplayer()->SetColor(line_color);
1249
1250   // Build prs
1251   SALOME_Prs* aPrs = getDisplayer()->BuildPrs(anApplyedWire);
1252   if (aPrs != 0 && !aPrs->IsNull())
1253     GEOMBase_Helper::displayPreview(aPrs, append, update);
1254
1255   getDisplayer()->SetColor(Quantity_NOC_VIOLET);
1256   aPrs = getDisplayer()->BuildPrs(aLastSegment);
1257
1258   if (aPrs != 0 && !aPrs->IsNull())
1259     GEOMBase_Helper::displayPreview(aPrs, append, update);
1260
1261   getDisplayer()->SetColor(line_color);
1262
1263   // Display local trihedron if the mode is relative
1264   if (myMode == 1)
1265     displayTrihedron(2);
1266
1267   // Display preview of suitable dimension presentations
1268   displayDimensions(false);
1269
1270   getDisplayer()->UnsetName();
1271
1272   // Enable activation of displayed objects
1273   getDisplayer()->SetToActivate(true);
1274 }
1275
1276 //================================================================
1277 // Function : displayTrihedron()
1278 // Purpose  : Method for displaying trihedron
1279 //================================================================
1280 void EntityGUI_3DSketcherDlg::displayTrihedron (int selMode)
1281 {
1282   // Add trihedron to preview
1283   SUIT_ViewWindow* vw = SUIT_Session::session()->activeApplication()->desktop()->activeWindow();
1284
1285   gp_Pnt P(getLastPoint().x,getLastPoint().y,getLastPoint().z);
1286   Handle(Geom_Axis2Placement) anAxis = new Geom_Axis2Placement(P,gp::DZ(),gp::DX());
1287   Handle(AIS_Trihedron) anIO = new AIS_Trihedron(anAxis);
1288   anIO->SetSelectionMode(selMode);
1289
1290   SOCC_Prs* aSPrs = dynamic_cast<SOCC_Prs*>
1291     (((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->CreatePrs(0));
1292
1293   if (aSPrs) {
1294     aSPrs->PrependObject(anIO);
1295     GEOMBase_Helper::displayPreview(aSPrs, true, true);
1296   }
1297 }
1298
1299 //================================================================
1300 // Function : displayDimensions( bool store )
1301 // Purpose  : Method for displaying dimensions if store = true
1302 //            the presentation is stored in a list
1303 //================================================================
1304 void EntityGUI_3DSketcherDlg::displayDimensions (bool store)
1305 {
1306   myPrsType   = prsType();
1307   XYZ Last    = getLastPoint();
1308   if (myMode == 0)                   // Absolute coordinates 
1309     Last.x=Last.y=Last.z=0.0;
1310   
1311   XYZ Current = getCurrentPoint();
1312
1313   gp_Pnt Last_Pnt(Last.x,Last.y,Last.z);
1314   gp_Pnt Current_Pnt(Current.x,Current.y,Current.z);
1315   gp_Pnt P1, P2;
1316   gp_Dir aNormal = getPresentationPlane();
1317   
1318   if (myCoordType == 0)
1319   {
1320     displayLength(Last_Pnt, Current_Pnt, aNormal, store);
1321 //     myPrsType = TYPE_LENGTH;
1322   }
1323   if (myCoordType == 1)             // ANGLES
1324   {
1325     bool spherical   = GroupAngles->checkBox->isChecked(); 
1326     bool cylindrical = GroupAngles->checkBox_2->isChecked();
1327     
1328     double anAngle1 = GroupAngles->SpinBox_DA->value();
1329     double aLength  = GroupAngles->SpinBox_DL->value();
1330     
1331     switch(myOrientation)
1332     {
1333       case OXY:
1334       {
1335         P1 = gp_Pnt(Last.x + aLength,Last.y,Last.z);    // X direction
1336         P2 = gp_Pnt(Last.x + aLength * cos(anAngle1 * M_PI / 180.),
1337                     Last.y + aLength * sin(anAngle1 * M_PI / 180.),
1338                     Last.z);
1339         break;
1340       }
1341       case OYZ:
1342       {
1343         P1 = gp_Pnt(Last.x, Last.y + aLength,Last.z);     // Y direction
1344         P2 = gp_Pnt(Last.x,
1345                     Last.y + aLength * cos(anAngle1 * M_PI / 180.),
1346                     Last.z + aLength * sin(anAngle1 * M_PI / 180.));
1347         break;
1348       }
1349       case OXZ:
1350       {
1351         P1 = gp_Pnt(Last.x + aLength,Last.y,Last.z);     // X direction
1352         P2 = gp_Pnt(Last.x + aLength * cos(anAngle1 * M_PI / 180.) ,
1353                     Last.y,
1354                     Last.z + aLength * sin(anAngle1 * M_PI / 180.));
1355         break;
1356       }
1357     }
1358     
1359     if(!cylindrical)
1360       displayLength(Last_Pnt, Current_Pnt, aNormal, store);
1361     displayAngle(anAngle1, Last_Pnt, P1, P2, store);
1362     
1363     if(spherical)
1364     {
1365       double anAngle2 = GroupAngles->SpinBox_DA2->value();
1366       displayAngle(anAngle2, Last_Pnt, P2, Current_Pnt, store);
1367     }
1368     if(cylindrical)
1369     {
1370       displayLength(Last_Pnt, P2, aNormal, store);               // Radius
1371       displayLength(P2, Current_Pnt, aNormal.Reversed(), store); // Height
1372     }
1373   }
1374 }
1375
1376 //================================================================
1377 // Function : displayAngle()
1378 // Purpose  : Method for displaying angle dimensions
1379 //================================================================
1380 void EntityGUI_3DSketcherDlg::displayAngle (double theAngle,
1381                                             gp_Pnt P0, 
1382                                             gp_Pnt P1, 
1383                                             gp_Pnt P2,
1384                                             bool store)
1385 {
1386   SUIT_ViewWindow* vw = SUIT_Session::session()->activeApplication()->desktop()->activeWindow();
1387   
1388   // Creation of the AIS object
1389   Handle(AIS_AngleDimension) anAngleIO = createAISAngleDimension(theAngle, 
1390                                                                  P0, 
1391                                                                  P1, 
1392                                                                  P2);
1393   if (anAngleIO == NULL)
1394     return;
1395   
1396   if (store)
1397   {
1398     // Erase dimensions presentations
1399     ((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->Erase(myAnglePrs, true);
1400     myAnglePrs->PrependObject(anAngleIO);
1401     
1402     // Display modified presentation
1403     if (isAngleVisible)
1404       ((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->Display(myAnglePrs);
1405     
1406     // Update dimension presentation angle count for later undo / redo
1407     myPrsType.A += 1;
1408   }
1409   else if ( isAngleVisible)
1410   {
1411     SOCC_Prs* aSPrs = dynamic_cast<SOCC_Prs*>
1412         (((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->CreatePrs(0));
1413         
1414     if (aSPrs)
1415     {
1416       aSPrs->AddObject(anAngleIO);
1417       GEOMBase_Helper::displayPreview(aSPrs, true, true); 
1418     }
1419   }
1420 }
1421
1422
1423 //================================================================
1424 // Function : displayLength()
1425 // Purpose  : Method for displaying length dimensions for a segment
1426 //            creation step
1427 //================================================================
1428 void EntityGUI_3DSketcherDlg::displayLength (gp_Pnt P1,
1429                                              gp_Pnt P2,
1430                                              gp_Dir theNormal,
1431                                              bool store)
1432 {
1433   SUIT_ViewWindow* vw = SUIT_Session::session()->activeApplication()->desktop()->activeWindow();
1434   
1435   double aLength = P1.Distance(P2);
1436   
1437   if (aLength < Precision::Confusion())
1438     return;
1439     
1440   Handle(AIS_LengthDimension) anIO = createAISLengthDimension(aLength, P1, P2, theNormal);
1441
1442   if (store)
1443   {
1444     // Erase length dimensions presentation
1445     ((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->Erase(myLengthPrs, true);
1446     myLengthPrs->PrependObject(anIO);
1447
1448     // Display modified presentation
1449     if (isLengthVisible)
1450       ((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->Display(myLengthPrs);
1451     
1452     // Update dimension presentation length count for later undo / redo
1453     myPrsType.L += 1;
1454   }
1455   else if (isLengthVisible)
1456   {
1457     SOCC_Prs* aSPrs = dynamic_cast<SOCC_Prs*>
1458       (((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->CreatePrs(0));
1459     if (aSPrs)
1460     {
1461       aSPrs->PrependObject(anIO);
1462       GEOMBase_Helper::displayPreview(aSPrs, true, true);
1463     }
1464   }
1465 }
1466
1467 //================================================================
1468 // Function : createAISLengthDimension()
1469 // Purpose  : Method for creation of a length dimension object
1470 //            Returns an Handle on the AIS_LengthDimension obect
1471 //================================================================
1472 Handle(AIS_LengthDimension) EntityGUI_3DSketcherDlg::createAISLengthDimension(double theLength, 
1473                                                                               gp_Pnt P1, 
1474                                                                               gp_Pnt P2, 
1475                                                                               gp_Dir theNormal)
1476 {
1477   // Convert length to string
1478   std::string aLength_str = doubleToString(theLength);
1479   
1480   // Plane construction
1481   gce_MakePln gce_MP(P1, theNormal);
1482   Handle(Geom_Plane) aPlane = new Geom_Plane(gce_MP.Value());
1483   
1484   TopoDS_Vertex aVert1 = BRepBuilderAPI_MakeVertex(P1);
1485   TopoDS_Vertex aVert2 = BRepBuilderAPI_MakeVertex(P2);
1486
1487   Handle(AIS_LengthDimension) anIO =
1488     new AIS_LengthDimension(aVert1,
1489                             aVert2,
1490                             aPlane,
1491                             theLength,
1492                             TCollection_ExtendedString(aLength_str.c_str()));
1493   anIO->SetArrowSize(theLength/20);
1494
1495   SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
1496   int w = resMgr->integerValue("Geometry", "measures_line_width", 1);
1497   Handle(Prs3d_LengthAspect) asp = new Prs3d_LengthAspect();
1498   asp->LineAspect()->SetWidth(w);
1499   anIO->Attributes()->SetLengthAspect(asp);
1500   
1501   return anIO;
1502 }
1503
1504 //================================================================
1505 // Function : createAISAngleDimension()
1506 // Purpose  : Method for creation of an angle dimension object
1507 //            Returns an Handle on the AIS_AngleDimension obect
1508 //================================================================
1509 Handle(AIS_AngleDimension) EntityGUI_3DSketcherDlg::createAISAngleDimension(double theAngle, 
1510                                                                             gp_Pnt P0, 
1511                                                                             gp_Pnt P1, 
1512                                                                             gp_Pnt P2)
1513 {
1514   // Length of the built segment
1515   double aLength = P0.Distance(P1);
1516   
1517   // Check input data
1518   if (Abs(theAngle - 90.0) < Precision::Angular() ||
1519       aLength < Precision::Confusion())
1520     return NULL;
1521   
1522   // Convert angles to string
1523   std::string Angle_str = doubleToString(theAngle);
1524   
1525   // Construction of the plane
1526   gce_MakePln gce_MP2(P0, P1, P2);
1527   Handle(Geom_Plane) aPlane = new Geom_Plane(gce_MP2.Value());
1528   
1529   TopoDS_Vertex V0 = BRepBuilderAPI_MakeVertex(P0);
1530   TopoDS_Vertex V1 = BRepBuilderAPI_MakeVertex(P1);
1531   TopoDS_Vertex V2 = BRepBuilderAPI_MakeVertex(P2);
1532   
1533   TopoDS_Edge anEdge1 = BRepBuilderAPI_MakeEdge(V0, V1);
1534   TopoDS_Edge anEdge2 = BRepBuilderAPI_MakeEdge(V0, V2);
1535
1536   Handle(AIS_AngleDimension) anIO =
1537     new AIS_AngleDimension(anEdge1, anEdge2, aPlane, theAngle * M_PI / 180.,
1538                            TCollection_ExtendedString(Angle_str.c_str()));
1539     
1540   anIO->SetArrowSize((theAngle * M_PI / 180) * (aLength/20));
1541   
1542   SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
1543   int w = resMgr->integerValue("Geometry", "measures_line_width", 1);
1544   Handle(Prs3d_AngleAspect) asp = new Prs3d_AngleAspect();
1545   asp->LineAspect()->SetWidth(w);
1546   anIO->Attributes()->SetAngleAspect(asp);
1547   
1548   return anIO;
1549 }
1550
1551 //================================================================
1552 // Function : createShapes
1553 // Purpose  : Create applyed wire, and last segment from entry object
1554 //================================================================
1555 bool EntityGUI_3DSketcherDlg::createShapes (GEOM::GEOM_Object_ptr /*theObject*/,
1556                                             TopoDS_Shape&         theApplyedWire,
1557                                             TopoDS_Shape&         theLastSegment)
1558 {
1559   QList<gp_Pnt> points;
1560   foreach (XYZ xyz, myPointsList) {
1561     gp_Pnt p(xyz.x, xyz.y, xyz.z);
1562     if (points.isEmpty() || points.last().Distance(p) > gp::Resolution())
1563       points << p;
1564   }
1565
1566   if (points.count() == 1) {
1567     // only one point is created
1568     BRepBuilderAPI_MakeVertex mkVertex (points.last());
1569     theApplyedWire = mkVertex.Shape();
1570   }
1571   else if (points.count() > 1) {
1572     // wire is created
1573     BRepBuilderAPI_MakePolygon mkWire;
1574     foreach(gp_Pnt p, points)
1575       mkWire.Add(p);
1576     theApplyedWire = mkWire.Shape();
1577   }
1578
1579   XYZ curxyz = getCurrentPoint();
1580   gp_Pnt curpnt(curxyz.x, curxyz.y, curxyz.z);
1581
1582   if (points.isEmpty() || points.last().Distance(curpnt) <= gp::Resolution()) {
1583     BRepBuilderAPI_MakeVertex mkVertex (curpnt);
1584     theLastSegment = mkVertex.Shape();
1585   }
1586   else {
1587     BRepBuilderAPI_MakeEdge mkEdge(points.last(), curpnt);
1588     theLastSegment = mkEdge.Shape();
1589   }
1590
1591   /* VSR: old algorithm does not work properly, see bug 0020899
1592   TopoDS_Shape aShape;
1593   if (!GEOMBase::GetShape(theObject, aShape))
1594     return false;
1595
1596   if (aShape.ShapeType() != TopAbs_WIRE && aShape.ShapeType() != TopAbs_VERTEX)
1597     return false;
1598
1599   theApplyedWire = aShape;
1600   if (myOK)
1601      return true;
1602
1603   BRepBuilderAPI_MakeWire aBuilder;
1604   TopExp_Explorer edgeExp(aShape, TopAbs_EDGE);
1605   while (1) {
1606     TopoDS_Shape anEdge = edgeExp.Current();
1607     edgeExp.Next();
1608     if (edgeExp.More()) // i.e. non-last edge
1609       aBuilder.Add(TopoDS::Edge(anEdge));
1610     else {
1611       theLastSegment = anEdge;
1612       break;
1613     }
1614   }
1615
1616   if (aBuilder.IsDone()) {
1617     theApplyedWire = aBuilder.Shape();
1618   }
1619   else if (!theLastSegment.IsNull()) {
1620     TopExp_Explorer vertexExp(theLastSegment, TopAbs_VERTEX);
1621     theApplyedWire = vertexExp.Current();
1622     }
1623   */
1624
1625   return true;
1626 }
1627
1628 //================================================================
1629 // Function : doubleToString
1630 // Purpose  : converts double to string
1631 //================================================================
1632 std::string EntityGUI_3DSketcherDlg::doubleToString (double num)
1633 {
1634   // truncate num
1635   int digNum = 5;
1636   char format = 'g'; // truncated to a number of significant digits
1637
1638   return QString::number(num, format, digNum).toStdString();
1639 }