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