Salome HOME
Synchronizing with GEOM_msg_en.ts
[modules/geom.git] / src / EntityGUI / EntityGUI_3DSketcherDlg.cxx
1 // Copyright (C) 2007-2013  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
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_AngleAspect.hxx>
69 #include <Prs3d_LineAspect.hxx>
70 #include <Prs3d_LengthAspect.hxx>
71 #if OCC_VERSION_LARGE > 0x06050300
72 #include <Prs3d_TextAspect.hxx>
73 #include <Prs3d_Presentation.hxx>
74 #include <Prs3d_Text.hxx>
75 #include <Graphic3d_VerticalTextAlignment.hxx>
76 #include <Graphic3d_HorizontalTextAlignment.hxx>
77 #include <Graphic3d_AspectText3d.hxx>
78 #include <Font_FontAspect.hxx>
79 #endif // OCC_VERSION_LARGE > 0x06050300
80
81 // This include must be *AFTER* SOCC_ViewModel.h because
82 // of the constant ROTATE which is a #define in
83 // GEOMImpl_Types.hxx and an enum in SOCC_ViewModel.h
84 #include <GEOMImpl_Types.hxx>
85
86 // TODO
87 //
88 // Avoid duplication of angle coordinates in cylindrical mode
89 // Check spherical mode in absolute
90
91 enum
92 {
93   OXY,
94   OYZ,
95   OXZ
96 };
97
98 class Locker
99 {
100 public:
101   Locker(bool& l) : myLock(l) { myLock = true;  }
102   ~Locker()                   { myLock = false; }
103 private:
104   bool& myLock;
105 };
106
107 #if OCC_VERSION_LARGE > 0x06050300
108 DEFINE_STANDARD_HANDLE(AIS_Text, AIS_InteractiveObject)
109
110 class AIS_Text:public AIS_InteractiveObject
111 {
112 public:
113   // CASCADE RTTI
114   DEFINE_STANDARD_RTTI(AIS_Text );
115
116   AIS_Text(){};
117
118   AIS_Text
119     (
120       const TCollection_ExtendedString& , const gp_Pnt& ,
121       Quantity_Color color,
122       Standard_Integer aHJust,
123       Standard_Integer aVJust ,
124       Standard_Real Angle ,
125       Standard_Boolean Zoom ,
126       Standard_Real  Height,
127       Font_FontAspect FontAspect,
128       Standard_CString Font
129     );
130
131 private:
132
133   void Compute (  const Handle(PrsMgr_PresentationManager3d)& aPresentationManager,
134                   const Handle(Prs3d_Presentation)& aPresentation,
135                   const Standard_Integer aMode);
136
137   void ComputeSelection (  const Handle(SelectMgr_Selection)& aSelection,
138                            const Standard_Integer aMode){} ;
139
140 protected:
141   TCollection_ExtendedString          aText;
142   gp_Pnt                              aPosition;
143   Standard_Real                       Red;
144   Standard_Real                       Green;
145   Standard_Real                       Blue;
146   Standard_Real                       aAngle;
147   Standard_Real                       aHeight;
148   Standard_Boolean                    aZoomable;
149   Quantity_Color                      aColor;
150   Standard_CString                    aFont;
151   Font_FontAspect                      aFontAspect;
152   Graphic3d_HorizontalTextAlignment   aHJustification;
153   Graphic3d_VerticalTextAlignment     aVJustification;
154 };
155
156 IMPLEMENT_STANDARD_HANDLE(AIS_Text, AIS_InteractiveObject)
157 IMPLEMENT_STANDARD_RTTIEXT(AIS_Text, AIS_InteractiveObject)
158
159 AIS_Text::AIS_Text( const TCollection_ExtendedString& text, const gp_Pnt& position,
160                           Quantity_Color    color       = Quantity_NOC_YELLOW,
161                           Standard_Integer  aHJust      = Graphic3d_HTA_LEFT,
162                           Standard_Integer  aVJust      = Graphic3d_VTA_BOTTOM,
163                           Standard_Real     angle       = 0.0 ,
164                           Standard_Boolean  zoomable    = Standard_False,
165                           Standard_Real     height      = 16.,
166                           Font_FontAspect    fontAspect  = Font_FA_Regular,
167                           Standard_CString  font        = "Courier")
168 {
169   aText           = text;
170   aPosition       = position;
171   aHJustification = Graphic3d_HorizontalTextAlignment(aHJust);
172   aVJustification = Graphic3d_VerticalTextAlignment(aVJust);
173   aAngle          = angle;
174   aZoomable       = zoomable;
175   aHeight         = height;
176   aColor          = color;
177   aFontAspect     = fontAspect;
178   aFont           = font;
179 };
180
181 void AIS_Text::Compute(const Handle(PrsMgr_PresentationManager3d)& aPresentationManager,
182                           const Handle(Prs3d_Presentation)& aPresentation,
183                           const Standard_Integer aMode)
184 {
185
186   aPresentation->Clear();
187
188   Handle_Prs3d_TextAspect asp = myDrawer->TextAspect();
189
190   asp->SetFont(aFont);
191   asp->SetColor(aColor);
192   asp->SetHeight(aHeight); // I am changing the myHeight value
193
194   asp->SetHorizontalJustification(aHJustification);
195   asp->SetVerticalJustification(aVJustification);
196   asp->Aspect()->SetTextZoomable(aZoomable);
197   asp->Aspect()->SetTextAngle(aAngle);
198   asp->Aspect()->SetTextFontAspect(aFontAspect);
199   Prs3d_Text::Draw(aPresentation, asp, aText, aPosition);
200 };
201 #endif // OCC_VERSION_LARGE > 0x06050300
202
203 bool isSame (double d1, double d2)
204
205   return Abs(d1 - d2) <= Precision::Confusion();
206 }
207
208 //=================================================================================
209 // class    : EntityGUI_3DSketcherDlg()
210 // purpose  : Constructs a EntityGUI_3DSketcherDlg which is a child of 'parent', with the
211 //            name 'name' and widget flags set to 'f'.
212 //            The dialog will by default be modeless, unless you set 'modal' to
213 //            TRUE to construct a modal dialog.
214 //=================================================================================
215 EntityGUI_3DSketcherDlg::EntityGUI_3DSketcherDlg (GeometryGUI* theGeometryGUI, QWidget* parent,
216                                                   bool modal, Qt::WindowFlags fl,
217                                                   const double lineWidth)
218   : GEOMBase_Skeleton(theGeometryGUI, parent, modal, fl),
219     myMode(-1),
220     myOK(false),
221     myLineWidth(lineWidth),
222     myGeometryGUI(theGeometryGUI),
223     myLengthIORedoList()
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   if (myPointsList.count() > 0) {
620     
621     myRedoList.append(myPointsList.last());
622
623     // Erase dimensions presentations
624     SUIT_ViewWindow* vw = SUIT_Session::session()->activeApplication()->desktop()->activeWindow();
625     ((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->Erase(myLengthPrs, true);
626     ((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->Erase(myAnglePrs, true);
627     ((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->Erase(myTextPrs, true);
628     
629     removeLastIOFromPrs();
630
631     // Display modified presentation
632     if (isLengthVisible)
633       ((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->Display(myLengthPrs);
634     if (isAngleVisible)
635       ((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->Display(myAnglePrs);
636     ((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->Display(myTextPrs);
637     
638     // Remove last point from list
639     myPointsList.removeLast();
640     GEOMBase_Helper::displayPreview(true, false, true, true, myLineWidth);
641     UpdateButtonsState();
642     
643     // Update of point coordinates in the control groupbox
644     UpdatePointCoordinates();
645
646     updateViewer();
647   }
648 }
649
650 //=================================================================================
651 // function : ClickOnRedo()
652 // purpose  :
653 //=================================================================================
654 void EntityGUI_3DSketcherDlg::ClickOnRedo()
655 {
656   if (myRedoList.count() > 0) {
657     
658     myPointsList.append(myRedoList.last());
659
660     // Erase dimensions presentations
661     SUIT_ViewWindow* vw = SUIT_Session::session()->activeApplication()->desktop()->activeWindow();
662     ((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->Erase(myLengthPrs, true);
663     ((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->Erase(myAnglePrs, true);
664     ((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->Erase(myTextPrs, true);
665     
666     restoreLastIOToPrs();
667
668     // Display modified presentation
669     if (isLengthVisible)
670       ((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->Display(myLengthPrs);
671     if (isAngleVisible)
672       ((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->Display(myAnglePrs);
673     ((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->Display(myTextPrs);
674     
675     // Remove last point from redo list
676     myRedoList.removeLast();
677     GEOMBase_Helper::displayPreview(true, false, true, true, myLineWidth);
678     UpdateButtonsState();
679     
680     // Update of point coordinates in the control groupbox
681     UpdatePointCoordinates();
682
683     updateViewer();
684   }
685 }
686
687 //=================================================================================
688 // function : removeLastIO()
689 // purpose  :
690 //=================================================================================
691 void EntityGUI_3DSketcherDlg::removeLastIOFromPrs ()
692 {
693   AIS_ListOfInteractive anIOList;
694   XYZ Last = getLastPoint();
695   
696   for (int l = 0; l<Last.L; l++)
697   {
698     myLengthPrs->GetObjects(anIOList);
699     myLengthIORedoList.Prepend(anIOList.First());  // Store last prepended Length IO in redo list
700     myLengthPrs->RemoveFirst();                    // Remove it from myLengthPrs
701   }
702   for (int a = 0; a<Last.A; a++)
703   {
704     myAnglePrs->GetObjects(anIOList);
705     myAngleIORedoList.Prepend(anIOList.First());  // Store last prepended Angle IO in redo list
706     myAnglePrs->RemoveFirst();                    // Remove it from myAnglePrs
707   }
708   for (int t = 0; t<Last.T; t++)
709   {
710     myTextPrs->GetObjects(anIOList);
711     myTextIORedoList.Prepend(anIOList.First());  // Store last prepended Text IO in redo list
712     myTextPrs->RemoveFirst();                    // Remove it from myTextPrs
713   }
714 }
715
716 //=================================================================================
717 // function : restoreLastIO()
718 // purpose  :
719 //=================================================================================
720 void EntityGUI_3DSketcherDlg::restoreLastIOToPrs ()
721 {
722   XYZ LastDeleted = myRedoList.last();
723   
724   for (int l = 0; l<LastDeleted.L; l++)
725   {
726     myLengthPrs->PrependObject(myLengthIORedoList.First()); // Restore last removed IO
727     myLengthIORedoList.RemoveFirst();                       // Remove it from redo list
728   } 
729   for (int a = 0; a<LastDeleted.A; a++)
730   {
731     myAnglePrs->PrependObject(myAngleIORedoList.First());  // Restore last removed IO
732     myAngleIORedoList.RemoveFirst();                       // Remove it from redo list
733   }
734   for (int t = 0; t<LastDeleted.T; t++)
735   {
736     myTextPrs->PrependObject(myTextIORedoList.First());  // Restore last removed IO
737     myTextIORedoList.RemoveFirst();                       // Remove it from redo list
738   }
739 }
740
741 //=================================================================================
742 // function : SelectionIntoArgument()
743 // purpose  : Called when selection as changed
744 //=================================================================================
745 void EntityGUI_3DSketcherDlg::SelectionIntoArgument()
746 {
747   LightApp_SelectionMgr* aSelMgr = myGeomGUI->getApp()->selectionMgr();
748   SALOME_ListIO aSelList;
749   aSelMgr->selectedObjects(aSelList);
750
751   int nbSel = aSelList.Extent();
752   if (nbSel == 1) {
753     GEOM::GEOM_Object_var aSelectedObject = GEOMBase::ConvertIOinGEOMObject(aSelList.First());
754     if (!CORBA::is_nil(aSelectedObject)) {
755       TopoDS_Shape aShape;
756       if (GEOMBase::GetShape(aSelectedObject, aShape, TopAbs_SHAPE)) {
757         // Explore the shape if its a local selection
758         TColStd_IndexedMapOfInteger aMap;
759         aSelMgr->GetIndexes(aSelList.First(), aMap);
760         if (aMap.Extent() == 1) {
761           int anIndex = aMap(1);
762           GEOM::GEOM_IShapesOperations_var aShapesOp = getGeomEngine()->GetIShapesOperations(getStudyId());
763           aSelectedObject = aShapesOp->GetSubShape(aSelectedObject, anIndex);
764         }
765       }
766       bool isOk = true;
767       if (aShape.ShapeType() != TopAbs_VERTEX)
768         isOk = GEOMBase::GetShape(aSelectedObject, aShape, TopAbs_VERTEX);
769       if (isOk) {
770         gp_Pnt aPnt;
771         if (GEOMBase::VertexToPoint(aShape, aPnt)) {
772           // set coordinates to the Spin Boxes
773           double aX, aY, aZ;
774           aX = aPnt.X();
775           aY = aPnt.Y();
776           aZ = aPnt.Z();
777           bool blocked = Group3Spin->SpinBox_DX->signalsBlocked();
778           Group3Spin->SpinBox_DX->blockSignals(true);
779           Group3Spin->SpinBox_DY->blockSignals(true);
780           Group3Spin->SpinBox_DZ->blockSignals(true);
781           if (GroupType->RadioButton1->isChecked()) {
782             Group3Spin->SpinBox_DX->setValue(aX);
783             Group3Spin->SpinBox_DY->setValue(aY);
784             Group3Spin->SpinBox_DZ->setValue(aZ);
785           }
786           else if (GroupType->RadioButton2->isChecked()) {
787             XYZ xyz = getLastPoint();
788             Group3Spin->SpinBox_DX->setValue(aX - xyz.x);
789             Group3Spin->SpinBox_DY->setValue(aY - xyz.y);
790             Group3Spin->SpinBox_DZ->setValue(aZ - xyz.z);
791           }
792           Group3Spin->SpinBox_DX->blockSignals(blocked);
793           Group3Spin->SpinBox_DY->blockSignals(blocked);
794           Group3Spin->SpinBox_DZ->blockSignals(blocked);
795         }
796       }
797     }
798   }
799   GEOMBase_Helper::displayPreview(true, false, true, true, myLineWidth);
800 }
801
802 //=================================================================================
803 // function : DeactivateActiveDialog()
804 // purpose  :
805 //=================================================================================
806 void EntityGUI_3DSketcherDlg::DeactivateActiveDialog()
807 {
808   setEnabled(false);
809   globalSelection();
810   disconnect(myGeomGUI->getApp()->selectionMgr(), 0, this, 0);
811   myGeomGUI->SetActiveDialogBox(0);
812 }
813
814 //=================================================================================
815 // function : ActivateThisDialog()
816 // purpose  :
817 //=================================================================================
818 void EntityGUI_3DSketcherDlg::ActivateThisDialog()
819 {
820   myGeomGUI->EmitSignalDeactivateDialog();
821   setEnabled(true);
822   myGeomGUI->SetActiveDialogBox(this);
823
824   connect(myGeomGUI->getApp()->selectionMgr(),
825           SIGNAL(currentSelectionChanged()), this, SLOT(SelectionIntoArgument()));
826
827   localSelection(GEOM::GEOM_Object::_nil(), TopAbs_VERTEX);
828   GEOMBase_Helper::displayPreview(true, false, true, true, myLineWidth);
829 }
830
831 //=================================================================================
832 // function : ValueChangedInSpinBox()
833 // purpose  :
834 //=================================================================================
835 void EntityGUI_3DSketcherDlg::ValueChangedInSpinBox (double newValue)
836 {
837   GEOMBase_Helper::displayPreview(true, false, true, true, myLineWidth);
838 }
839
840 //=================================================================================
841 // function : BoxChecked()
842 // purpose  : ChecBoxes management
843 //=================================================================================
844 void EntityGUI_3DSketcherDlg::BoxChecked (bool checked)
845 {
846   QCheckBox* send = (QCheckBox*) sender();
847   SUIT_ViewWindow* vw = SUIT_Session::session()->activeApplication()->desktop()->activeWindow();
848
849   if (send == GroupAngles->checkBox)
850   {
851     GroupAngles->SpinBox_DA2->setEnabled(checked);
852     if(checked)
853     {
854       GroupAngles->SpinBox_DH->setEnabled(false);
855       GroupAngles->checkBox_2->setChecked(false);
856     }
857   }
858   else if (send == GroupAngles->checkBox_2)
859   {
860     GroupAngles->SpinBox_DH->setEnabled(checked);
861     if(checked)
862     {
863       GroupAngles->SpinBox_DA2->setEnabled(false);
864       GroupAngles->checkBox->setChecked(false);
865     }
866   }
867
868   else if (send == GroupControls->CheckBox1)
869   {
870     ((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->Erase(myLengthPrs, true);
871     if (checked){
872       ((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->Display(myLengthPrs);
873       isLengthVisible=true;
874     }
875     else
876       isLengthVisible=false;
877   }
878   else if (send == GroupControls->CheckBox2)
879   {
880     ((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->Erase(myAnglePrs, true);
881     if (checked)
882     {
883       ((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->Display(myAnglePrs);
884       isAngleVisible=true;
885     }
886     else
887       isAngleVisible=false;
888   }
889   else if (send == GroupControls->CheckBox3)
890   {
891     GroupControls->lineEdit_1->setVisible(checked);
892     GroupControls->lineEdit_2->setVisible(checked);
893     GroupControls->lineEdit_3->setVisible(checked);
894     GroupControls->lineEdit_4->setVisible(checked);
895     GroupControls->lineEdit_5->setVisible(checked);
896     GroupControls->lineEdit_6->setVisible(checked);
897     
898     GroupControls->label_1->setVisible(checked);
899     GroupControls->label_2->setVisible(checked);
900     GroupControls->label_3->setVisible(checked);
901     GroupControls->label_4->setVisible(checked);
902     GroupControls->label_5->setVisible(checked);
903     GroupControls->label_6->setVisible(checked);
904     GroupControls->label_7->setVisible(checked);
905     GroupControls->label_8->setVisible(checked);
906     
907     GroupControls->updateGeometry();
908     GroupControls->resize(minimumSizeHint());
909   } 
910
911   updateGeometry();
912   resize(minimumSizeHint());
913   
914   GEOMBase_Helper::displayPreview(true, false, true, true, myLineWidth);
915 }
916
917 //=================================================================================
918 // function : ButtonClicked()
919 // purpose  :
920 //=================================================================================
921 void EntityGUI_3DSketcherDlg::ButtonClicked (bool checked)
922 {
923   if (GroupAngles->radioButton_1->isChecked())
924     myOrientation = OXY;
925   else if (GroupAngles->radioButton_2->isChecked())
926     myOrientation = OYZ;
927   else
928     myOrientation = OXZ;
929
930   GEOMBase_Helper::displayPreview(true, false, true, true, myLineWidth);
931 }
932
933 //=================================================================================
934 // function : enterEvent()
935 // purpose  :
936 //=================================================================================
937 void EntityGUI_3DSketcherDlg::enterEvent (QEvent*)
938 {
939   if (!mainFrame()->GroupConstructors->isEnabled())
940     ActivateThisDialog();
941 }
942
943 //=================================================================================
944 // function : createOperation
945 // purpose  :
946 //=================================================================================
947 GEOM::GEOM_IOperations_ptr EntityGUI_3DSketcherDlg::createOperation()
948 {
949   return getGeomEngine()->GetICurvesOperations(getStudyId());
950 }
951
952 //=================================================================================
953 // function : isValid
954 // purpose  :
955 //=================================================================================
956 bool EntityGUI_3DSketcherDlg::isValid (QString& msg)
957 {
958   bool ok = true;
959   ok = Group3Spin->SpinBox_DX->isValid(msg, !IsPreview()) && ok;
960   ok = Group3Spin->SpinBox_DY->isValid(msg, !IsPreview()) && ok;
961   ok = Group3Spin->SpinBox_DZ->isValid(msg, !IsPreview()) && ok;
962   return ok;
963 }
964
965 //=================================================================================
966 // function : execute
967 // purpose  :
968 //=================================================================================
969 bool EntityGUI_3DSketcherDlg::execute (ObjectList& objects)
970 {
971   //GEOM::ListOfDouble_var aCoordsArray = new GEOM::ListOfDouble;
972   //if (!myOK || myPointsList.size() == 0)
973   //  aCoordsArray->length((myPointsList.size()+1)*3);
974   //else
975   //  aCoordsArray->length(myPointsList.size()*3);
976
977   QStringList aCommands;
978   aCommands << "3DSketcher";
979   QStringList aParameters;
980
981   //int i = 0;
982   QList<XYZ>::const_iterator it;
983   for (it = myPointsList.begin(); it != myPointsList.end(); ++it) {
984     //aCoordsArray[i++] = (*it).x;
985     //aCoordsArray[i++] = (*it).y;
986     //aCoordsArray[i++] = (*it).z;
987     aCommands << (*it).command;
988     aParameters << (*it).params;
989   }
990
991   if (!myOK || myPointsList.size() == 0) {
992     XYZ xyz = getCurrentPoint();
993     //aCoordsArray[i++] = xyz.x;
994     //aCoordsArray[i++] = xyz.y;
995     //aCoordsArray[i++] = xyz.z;
996     aCommands << xyz.command;
997     aParameters << xyz.params;
998   }
999
1000 //   MESSAGE("aCommands.last() = "<< aCommands.last().toStdString());
1001   GEOM::GEOM_ICurvesOperations_var anOper = GEOM::GEOM_ICurvesOperations::_narrow(getOperation());
1002   //GEOM::GEOM_Object_var anObj = anOper->Make3DSketcher(aCoordsArray);
1003   GEOM::GEOM_Object_var anObj = anOper->Make3DSketcherCommand(aCommands.join(":").toLatin1().constData());
1004
1005   if (!anObj->_is_nil()) {
1006     if (!IsPreview()) anObj->SetParameters(aParameters.join(":").toLatin1().constData());
1007     objects.push_back(anObj._retn());
1008   }
1009
1010   return true;
1011 }
1012
1013 //=================================================================================
1014 // function : SetDoubleSpinBoxStep()
1015 // purpose  : Double spin box management
1016 //=================================================================================
1017 void EntityGUI_3DSketcherDlg::SetDoubleSpinBoxStep (double step)
1018 {
1019   Group3Spin->SpinBox_DX->setSingleStep(step);
1020   Group3Spin->SpinBox_DY->setSingleStep(step);
1021   Group3Spin->SpinBox_DZ->setSingleStep(step);
1022   GroupAngles->SpinBox_DA ->setSingleStep(step);
1023   GroupAngles->SpinBox_DA2->setSingleStep(step);
1024   GroupAngles->SpinBox_DL->setSingleStep(step);
1025   GroupAngles->SpinBox_DH->setSingleStep(step);
1026 }
1027
1028 //=================================================================================
1029 // function : ClickOnOk()
1030 // purpose  :
1031 //=================================================================================
1032 void EntityGUI_3DSketcherDlg::ClickOnOk()
1033 {
1034   Locker lock(myOK);
1035
1036   if (!onAccept())
1037     return;
1038
1039   ClickOnCancel();
1040 }
1041
1042 //=================================================================================
1043 // function : ClickOnApply()
1044 // purpose  :
1045 //=================================================================================
1046 bool EntityGUI_3DSketcherDlg::ClickOnApply()
1047 {
1048   QString msg;
1049   if (!isValid(msg)) {
1050     showError(msg);
1051     return false;
1052   }
1053
1054   if (myPointsList.count() > 0)
1055     myPointsList.append(myPointsList[0]);
1056
1057   Locker lock(myOK);
1058
1059   if (!onAccept())
1060     return false;
1061
1062   ClickOnCancel();
1063   return true;
1064 }
1065
1066 //=================================================================================
1067 // function : getLastPoint()
1068 // purpose  : return last points from list
1069 //=================================================================================
1070 EntityGUI_3DSketcherDlg::XYZ EntityGUI_3DSketcherDlg::getLastPoint() const
1071 {
1072   return myPointsList.count() > 0 ? myPointsList.last() : XYZ();
1073 }
1074
1075 //=================================================================================
1076 // function : getPenultimatePoint()
1077 // purpose  : return penultimate point from list
1078 //=================================================================================
1079 EntityGUI_3DSketcherDlg::XYZ EntityGUI_3DSketcherDlg::getPenultimatePoint() const
1080 {
1081   double size = myPointsList.count();
1082   return size > 1 ? myPointsList.at(size - 2) : XYZ();
1083 }
1084
1085 //=================================================================================
1086 // function : getCurrentPoint()
1087 // purpose  : returns current point
1088 //=================================================================================
1089 EntityGUI_3DSketcherDlg::XYZ EntityGUI_3DSketcherDlg::getCurrentPoint() const
1090 {
1091   XYZ xyz;
1092
1093   SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
1094   int aPrecision = resMgr->integerValue("Geometry", "length_precision", 7);
1095   
1096   bool spherical   = GroupAngles->checkBox->isChecked();
1097   bool cylindrical = GroupAngles->checkBox_2->isChecked();
1098
1099   if (myCoordType == 1) 
1100   {
1101     if (GroupAngles->radioButton_1->isChecked())
1102       xyz.command = "OXY";
1103     else if (GroupAngles->radioButton_2->isChecked())
1104       xyz.command = "OYZ";
1105     else
1106       xyz.command = "OXZ";
1107     
1108     if (cylindrical)       // Cylindrical coordinates (radius, angle, height)
1109       xyz.command += "C";
1110     else
1111       xyz.command += "S";  // Spherical coordinates (radius, angle1, angle2) --> polar if angle2 = 0
1112     
1113     if (myMode == 0)       // Absolute coordinates
1114       xyz.command += "A ";
1115     else if (myMode == 1)  // Relative coordinates
1116       xyz.command += "R ";
1117       
1118
1119     double anAngle  = GroupAngles->SpinBox_DA->value();
1120     double aLength  = GroupAngles->SpinBox_DL->value();
1121
1122     double anAngle2 = 0.0;
1123     QString da2 = "0";
1124     if (spherical) {       // Spherical coordinates (radius, angle1, angle2)
1125       anAngle2 = GroupAngles->SpinBox_DA2->value();
1126       da2 = GroupAngles->SpinBox_DA2->text();
1127     }
1128     
1129     double aHeight = 0.0;
1130     QString dh = "0";
1131     if (cylindrical) {
1132       aHeight = GroupAngles->SpinBox_DH->value();
1133       dh = GroupAngles->SpinBox_DH->text();
1134     }
1135
1136     xyz.command +=
1137       QString::number(anAngle, 'g', aPrecision) + " ";
1138     xyz.params =
1139       GroupAngles->SpinBox_DA->text() + ":"; 
1140     
1141     if(cylindrical)
1142     {
1143       xyz.command +=
1144         QString::number(aHeight, 'g', aPrecision) + " ";
1145       xyz.params +=
1146         dh + ":";
1147     }
1148     else                  // Spherical or polar coordinates
1149     {
1150       xyz.command +=
1151         QString::number(anAngle2, 'g', aPrecision) + " ";
1152       xyz.params +=
1153         dh + ":";
1154     }
1155     
1156     xyz.command +=
1157       QString::number(aLength, 'g', aPrecision);
1158     xyz.params +=
1159       GroupAngles->SpinBox_DL->text();
1160
1161       
1162     // Calculate point coordinates for preview
1163     anAngle  = anAngle * M_PI/180.0;
1164     anAngle2 = anAngle2 * M_PI/180.0;
1165     double aProjectedLength = aLength * cos(anAngle2);
1166     
1167     XYZ xyzP = getLastPoint();
1168     if (myMode == 0)
1169       xyzP.x=xyzP.y=xyzP.z=0.0; 
1170     if (GroupAngles->radioButton_1->isChecked()) // OXY
1171     {
1172       xyz.x = xyzP.x + aProjectedLength * cos(anAngle);
1173       xyz.y = xyzP.y + aProjectedLength * sin(anAngle);
1174       if (cylindrical)
1175         xyz.z = xyzP.z + aHeight;
1176       else
1177         xyz.z = xyzP.z + aLength * sin(anAngle2);
1178     }
1179     else if (GroupAngles->radioButton_2->isChecked()) // OYZ
1180     {
1181       xyz.y = xyzP.y + aProjectedLength * cos(anAngle);
1182       xyz.z = xyzP.z + aProjectedLength * sin(anAngle);
1183       if (cylindrical)
1184         xyz.x = xyzP.x + aHeight;
1185       else
1186         xyz.x = xyzP.x + aLength * sin(anAngle2);
1187     }
1188     else // OXZ
1189     {
1190       xyz.z = xyzP.z + aProjectedLength * sin(anAngle);
1191       xyz.x = xyzP.x + aProjectedLength * cos(anAngle);
1192       if (cylindrical)
1193         xyz.y = xyzP.y + aHeight;
1194       else
1195         xyz.y = xyzP.y + aLength * sin(anAngle2);
1196     }
1197   }
1198   else if(myCoordType == 0) {
1199     if (myMode == 0) { // XYZ
1200       xyz.x = Group3Spin->SpinBox_DX->value();
1201       xyz.y = Group3Spin->SpinBox_DY->value();
1202       xyz.z = Group3Spin->SpinBox_DZ->value();
1203       xyz.command = "TT ";
1204     }
1205     else { // DXDYDZ
1206       xyz = getLastPoint();
1207       xyz.x += Group3Spin->SpinBox_DX->value();
1208       xyz.y += Group3Spin->SpinBox_DY->value();
1209       xyz.z += Group3Spin->SpinBox_DZ->value();
1210       xyz.command = "T ";
1211     }
1212
1213     double aX  = Group3Spin->SpinBox_DX->value();
1214     double aY  = Group3Spin->SpinBox_DY->value();
1215     double aZ  = Group3Spin->SpinBox_DZ->value();
1216
1217     xyz.command +=
1218       QString::number(aX, 'g', aPrecision) + " " +
1219       QString::number(aY, 'g', aPrecision) + " " +
1220       QString::number(aZ, 'g', aPrecision);
1221     xyz.params =
1222       Group3Spin->SpinBox_DX->text() + ":" +
1223       Group3Spin->SpinBox_DY->text() + ":" +
1224       Group3Spin->SpinBox_DZ->text();
1225   }
1226   // Update point presentation type
1227   xyz.A = myPrsType.A;  // Number of angle diomensions
1228   xyz.L = myPrsType.L;  // Number of length dimensions
1229   xyz.T = myPrsType.T;  // Number of text objects
1230   
1231   return xyz;
1232 }
1233
1234
1235 //=================================================================================
1236 // function : getPresentationPlane()
1237 // purpose  : returns the suitable plane for right
1238 //            relative positioning of dimension presentations
1239 //=================================================================================
1240 gp_Dir EntityGUI_3DSketcherDlg::getPresentationPlane() const
1241
1242   bool withAngle = (myCoordType == 1);
1243   bool twoAngles = GroupAngles->checkBox->isChecked();
1244   
1245   XYZ Last    = getLastPoint();
1246   XYZ Current = getCurrentPoint();
1247   XYZ Penultimate = getPenultimatePoint();
1248   
1249   gp_Pnt P1 = gp_Pnt(Last.x,Last.y,Last.z);
1250   if (myMode == 0) // Absolute coordinates
1251     P1 = gp::Origin();
1252   
1253   gp_Pnt P2 = gp_Pnt(Current.x,Current.y,Current.z);
1254   gp_Pnt P3 = gp_Pnt(Penultimate.x,Penultimate.y,Penultimate.z);
1255   
1256   gp_Vec Vec1(P1,P2);
1257   gp_Vec Vec2(P1,P3);
1258   
1259   gp_Dir aNormal;                  // Normal defining the plane of the presentation 
1260   
1261   if (withAngle)                   // If one angle
1262   {
1263     // Transformation from the current coordinate system 
1264     // to the reference coordinate system
1265     gp_Trsf aTransform = toReferenceSystem (P1);
1266     gp_Dir N1 = gp::DZ();
1267     gp_Dir N2 = gp::DY();
1268     N1.Transform(aTransform);
1269     N2.Transform(aTransform);
1270     
1271     if (Vec1.CrossMagnitude(N1) > Precision::Confusion())
1272     {
1273       // The plane is orthogonal to the angle presentation plane 
1274       // and contains the current edge
1275       aNormal = N1.Crossed(gp_Dir(Vec1));
1276     }
1277     else
1278       aNormal = N2;
1279
1280     if (twoAngles)
1281     { 
1282       gp_Vec V = Vec1.Transformed(aTransform.Inverted());
1283       gp_Vec Vec3(V.X(),V.Y(),0.0);
1284       
1285       // Express the coordinates in the refernce coordinate system (OXY)
1286       Vec3.Transform(aTransform);   
1287       if(Abs(Vec1.CrossMagnitude(Vec3)) > Precision::Confusion())                                  
1288       { 
1289         //  set the normal as the cross product of the current edge with its projection
1290         //  it ensures that the dimension changes side when the angle becomes negative
1291         aNormal = gp_Dir(Vec1.Crossed(Vec3));  
1292       } 
1293     }         
1294   }
1295   else
1296   {
1297     // Check colinearity
1298     if (Abs(Vec1.CrossMagnitude(Vec2)) < Precision::Confusion())
1299     {
1300       Vec2 = gp_Vec(gp::DX());
1301       if (Abs(Vec1.CrossMagnitude(Vec2)) < Precision::Confusion())
1302       {
1303         Vec2 = gp_Vec(gp::DY());
1304       }
1305     }
1306     // If no angles, the plane is the one formed by the last edge and the current one
1307     aNormal = gp_Dir(Vec1.Crossed(Vec2)); 
1308   }
1309   return aNormal;
1310 }
1311
1312 //================================================================
1313 // Function : displayPreview
1314 // Purpose  : Method for displaying preview of resulting shape
1315 //            Redefined from GEOMBase_Helper.
1316 //================================================================
1317 void EntityGUI_3DSketcherDlg::displayPreview (GEOM::GEOM_Object_ptr object,
1318                                               const bool            append,
1319                                               const bool            activate,
1320                                               const bool            update,
1321                                               const double          lineWidth,
1322                                               const int             displayMode,
1323                                               const int             color)
1324 {
1325   SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
1326
1327   QColor aColor = resMgr->colorValue("Geometry","line_color",QColor(255,0,0));
1328   Quantity_NameOfColor line_color = SalomeApp_Tools::color(aColor).Name();
1329
1330   // set width of displayed shape
1331   int lw = lineWidth;
1332   if (lw == -1) {
1333     lw = resMgr->integerValue("Geometry", "preview_edge_width", -1);
1334   }
1335   getDisplayer()->SetWidth(lw);
1336
1337   // Disable activation of selection
1338   getDisplayer()->SetToActivate(activate);
1339
1340   // Make a reference to GEOM_Object
1341   CORBA::String_var objStr = myGeometryGUI->getApp()->orb()->object_to_string(object);
1342   getDisplayer()->SetName(objStr.in());
1343
1344   // Create wire from applied object
1345   TopoDS_Shape anApplyedWire, aLastSegment;
1346   if (!createShapes(object, anApplyedWire, aLastSegment))
1347     return;
1348
1349   // Set color for preview shape
1350   getDisplayer()->SetColor(line_color);
1351
1352   // Build prs
1353   SALOME_Prs* aPrs = getDisplayer()->BuildPrs(anApplyedWire);
1354   if (aPrs != 0 && !aPrs->IsNull())
1355     GEOMBase_Helper::displayPreview(aPrs, append, update);
1356
1357   getDisplayer()->SetColor(Quantity_NOC_VIOLET);
1358   aPrs = getDisplayer()->BuildPrs(aLastSegment);
1359
1360   if (aPrs != 0 && !aPrs->IsNull())
1361     GEOMBase_Helper::displayPreview(aPrs, append, update);
1362
1363   getDisplayer()->SetColor(line_color);
1364
1365   // Display local trihedron if the mode is relative
1366   if (myMode == 1)
1367     displayTrihedron(2);
1368
1369   // Display preview of suitable dimension presentations
1370   displayDimensions(false);
1371
1372   getDisplayer()->UnsetName();
1373
1374   // Enable activation of displayed objects
1375   getDisplayer()->SetToActivate(true);
1376 }
1377
1378 //================================================================
1379 // Function : displayTrihedron()
1380 // Purpose  : Method for displaying trihedron
1381 //================================================================
1382 void EntityGUI_3DSketcherDlg::displayTrihedron (int selMode)
1383 {
1384   // Add trihedron to preview
1385   SUIT_ViewWindow* vw = SUIT_Session::session()->activeApplication()->desktop()->activeWindow();
1386
1387   gp_Pnt P(getLastPoint().x,getLastPoint().y,getLastPoint().z);
1388   Handle(Geom_Axis2Placement) anAxis = new Geom_Axis2Placement(P,gp::DZ(),gp::DX());
1389   Handle(AIS_Trihedron) anIO = new AIS_Trihedron(anAxis);
1390   anIO->SetSelectionMode(selMode);
1391
1392   SOCC_Prs* aSPrs = dynamic_cast<SOCC_Prs*>
1393     (((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->CreatePrs(0));
1394
1395   if (aSPrs) {
1396     aSPrs->PrependObject(anIO);
1397     GEOMBase_Helper::displayPreview(aSPrs, true, true);
1398   }
1399 }
1400
1401 //================================================================
1402 // Function : displayDimensions( bool store )
1403 // Purpose  : Method for displaying dimensions. If store = true
1404 //            the presentation is stored in a list
1405 //================================================================
1406 void EntityGUI_3DSketcherDlg::displayDimensions (bool store)
1407 {
1408   myPrsType   = prsType();
1409   XYZ Last    = getLastPoint();
1410   XYZ Current = getCurrentPoint();
1411
1412   gp_Pnt Last_Pnt(Last.x,Last.y,Last.z);
1413   
1414   gp_Pnt P0 = Last_Pnt;
1415   gp_Pnt Origin = gp::Origin();
1416   if (myMode == 0)                 // Absolute coordinates
1417     P0 = Origin;
1418   
1419   gp_Pnt Current_Pnt(Current.x,Current.y,Current.z);
1420   gp_Pnt P1, P2;
1421   
1422   // Check if last end current point are coincident
1423   if (Last_Pnt.IsEqual(Current_Pnt, 1e-7))
1424     return;
1425   
1426   gp_Dir aNormal = getPresentationPlane();
1427   
1428   if (myCoordType == 0)
1429   {
1430     bool oneDimensionalMove =  (isSame(Last_Pnt.X(), Current_Pnt.X()) && 
1431                                 isSame(Last_Pnt.Y(), Current_Pnt.Y()) ) ||
1432                                (isSame(Last_Pnt.Y(), Current_Pnt.Y()) && 
1433                                 isSame(Last_Pnt.Z(), Current_Pnt.Z()) ) ||
1434                                (isSame(Last_Pnt.X(), Current_Pnt.X()) && 
1435                                 isSame(Last_Pnt.Z(), Current_Pnt.Z()) );
1436      
1437     if (myMode == 0)
1438     {
1439       std::string aCoordText = "( " + doubleToString(Current_Pnt.X()) + 
1440                                ", " + doubleToString(Current_Pnt.Y()) +
1441                                ", " + doubleToString(Current_Pnt.Z()) + " )";
1442       displayText(aCoordText, Current_Pnt, store);
1443     }
1444     else 
1445     { 
1446       if (oneDimensionalMove)
1447       {
1448         // For better colocation of dimensions if only one coordinate changes (aNormal is a better choice)
1449         displayLength(P0, Current_Pnt, aNormal, store);
1450       }
1451       else
1452       {
1453         displayLength(gp_Pnt(P0.X(),Current.y,P0.Z()), gp_Pnt(Current.x,Current.y,P0.Z()), gp::DZ().Reversed(), store);
1454         displayLength(gp_Pnt(Current.x,P0.Y(),P0.Z()), gp_Pnt(Current.x,Current.y,P0.Z()), gp::DZ(), store);
1455         displayLength(gp_Pnt(Current.x,Current.y,P0.Z()), Current_Pnt, gp::DX(), store);
1456       }
1457     }
1458   }
1459   else if (myCoordType == 1)             // ANGLES
1460   {
1461     bool spherical   = GroupAngles->checkBox->isChecked(); 
1462     bool cylindrical = GroupAngles->checkBox_2->isChecked();
1463     
1464     double anAngle1 = GroupAngles->SpinBox_DA->value();
1465     double aLength  = GroupAngles->SpinBox_DL->value();
1466     
1467     // Set the coordinates in the current coordinate system
1468     P1.SetCoord( aLength, 0.0, 0.0);    // X direction
1469     P2.SetCoord( aLength * cos(anAngle1 * M_PI / 180. ),
1470                  aLength * sin(anAngle1 * M_PI / 180. ),
1471                  0.0); 
1472     
1473     // Express the coordinates in the refernce coordinate system (OXY)
1474     gp_Trsf aTranform = toReferenceSystem(P0);
1475     P1.Transform(aTranform);    
1476     P2.Transform(aTranform);
1477     P1.Translate(Origin, P0);
1478     P2.Translate(Origin, P0);
1479     
1480     if(myMode !=0  || !store)
1481       displayAngle(anAngle1, P0, P1, P2, store);
1482     else
1483     {
1484       std::string anAngleText = doubleToString(anAngle1) + " deg.";
1485       displayText(anAngleText, Current_Pnt, store);
1486     }
1487     
1488     if(spherical)
1489     {
1490       double anAngle2 = GroupAngles->SpinBox_DA2->value();
1491       displayAngle(anAngle2, P0, P2, Current_Pnt, store);
1492       displayLength(P0, Current_Pnt, aNormal, store);
1493     }
1494     else
1495     {
1496       bool sameRadius = isSame ( radius(Last_Pnt), radius(Current_Pnt) );
1497       bool sameHeight = isSame ( height(Last_Pnt), height(Current_Pnt) );
1498                             
1499       gp_Vec aVec(P2, Current_Pnt);
1500       
1501       if (myMode == 0 && !sameRadius)
1502       {
1503         displayLength(P0.Translated(aVec), P2.Translated(aVec), aNormal, store);  // Radius  
1504       }
1505       else if (myMode == 1)
1506         displayLength(P0, P2, aNormal, store);
1507       
1508       if ( cylindrical && 
1509           (myMode == 1 || !sameHeight) )
1510         displayLength(P2, Current_Pnt, aNormal.Reversed(), store); // Height
1511     }
1512   }
1513 }
1514
1515 //================================================================
1516 // Function : displayAngle()
1517 // Purpose  : Method for displaying angle dimensions
1518 //================================================================
1519 void EntityGUI_3DSketcherDlg::displayAngle (double theAngle,
1520                                             gp_Pnt P0, 
1521                                             gp_Pnt P1, 
1522                                             gp_Pnt P2,
1523                                             bool store)
1524 {
1525   SUIT_ViewWindow* vw = SUIT_Session::session()->activeApplication()->desktop()->activeWindow();
1526   
1527   // Creation of the AIS object
1528   Handle(AIS_AngleDimension) anAngleIO = createAISAngleDimension(theAngle, 
1529                                                                  P0, 
1530                                                                  P1, 
1531                                                                  P2);
1532   if (anAngleIO == NULL)
1533     return;
1534   
1535   if (store)
1536   {
1537     // Erase dimensions presentations
1538     ((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->Erase(myAnglePrs, true);
1539     myAnglePrs->PrependObject(anAngleIO);
1540     
1541     // Display modified presentation
1542     if (isAngleVisible)
1543       ((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->Display(myAnglePrs);
1544     
1545     // Update dimension presentation angle count for later undo / redo
1546     myPrsType.A += 1;
1547   }
1548   else if ( isAngleVisible)
1549   {
1550     SOCC_Prs* aSPrs = dynamic_cast<SOCC_Prs*>
1551         (((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->CreatePrs(0));
1552         
1553     if (aSPrs)
1554     {
1555       aSPrs->AddObject(anAngleIO);
1556       GEOMBase_Helper::displayPreview(aSPrs, true, true); 
1557     }
1558   }
1559 }
1560
1561
1562 //================================================================
1563 // Function : displayLength()
1564 // Purpose  : Method for displaying length dimensions for a segment
1565 //            creation step
1566 //================================================================
1567 void EntityGUI_3DSketcherDlg::displayLength (gp_Pnt P1,
1568                                              gp_Pnt P2,
1569                                              gp_Dir theNormal,
1570                                              bool store)
1571 {
1572   SUIT_ViewWindow* vw = SUIT_Session::session()->activeApplication()->desktop()->activeWindow();
1573   
1574   double aLength = P1.Distance(P2);
1575   
1576   if (aLength < Precision::Confusion())
1577     return;
1578     
1579   Handle(AIS_LengthDimension) anIO = createAISLengthDimension(aLength, P1, P2, theNormal);
1580
1581   if (store)
1582   {
1583     // Erase length dimensions presentation
1584     ((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->Erase(myLengthPrs, true);
1585     myLengthPrs->PrependObject(anIO);
1586
1587     // Display modified presentation
1588     if (isLengthVisible)
1589       ((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->Display(myLengthPrs);
1590     
1591     // Update dimension presentation length count for later undo / redo
1592     myPrsType.L += 1;
1593   }
1594   else if (isLengthVisible)
1595   {
1596     SOCC_Prs* aSPrs = dynamic_cast<SOCC_Prs*>
1597       (((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->CreatePrs(0));
1598     if (aSPrs)
1599     {
1600       aSPrs->PrependObject(anIO);
1601       GEOMBase_Helper::displayPreview(aSPrs, true, true);
1602     }
1603   }
1604 }
1605
1606 //================================================================
1607 // Function : displayText()
1608 // Purpose  : Method for displaying length dimensions for a segment
1609 //            creation step
1610 //================================================================
1611 void EntityGUI_3DSketcherDlg::displayText ( std::string theText,
1612                                             gp_Pnt P,
1613                                             bool store )
1614 {
1615 #if OCC_VERSION_LARGE > 0x06050300
1616   SUIT_ViewWindow* vw = SUIT_Session::session()->activeApplication()->desktop()->activeWindow();
1617     
1618   Handle(AIS_Text) anIO = new AIS_Text(TCollection_ExtendedString(theText.c_str()), P);
1619
1620   if (store)
1621   {
1622     // Erase length dimensions presentation
1623     ((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->Erase(myTextPrs, true);
1624     myTextPrs->PrependObject(anIO);
1625
1626     // Display modified presentation
1627     ((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->Display(myTextPrs);
1628     
1629     // Update dimension presentation text count for later undo / redo
1630     myPrsType.T += 1;
1631   }
1632   else
1633   {
1634     SOCC_Prs* aSPrs = dynamic_cast<SOCC_Prs*>
1635       (((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->CreatePrs(0));
1636     if (aSPrs)
1637     {
1638       aSPrs->PrependObject(anIO);
1639       GEOMBase_Helper::displayPreview(aSPrs, true, true);
1640     }
1641   }
1642 #endif // OCC_VERSION_LARGE > 0x06050300
1643 }
1644
1645 //================================================================
1646 // Function : createAISLengthDimension()
1647 // Purpose  : Method for creation of a length dimension object
1648 //            Returns an Handle on the AIS_LengthDimension obect
1649 //================================================================
1650 Handle(AIS_LengthDimension) EntityGUI_3DSketcherDlg::createAISLengthDimension(double theLength, 
1651                                                                               gp_Pnt P1, 
1652                                                                               gp_Pnt P2, 
1653                                                                               gp_Dir theNormal)
1654 {
1655   // Convert length to string
1656   std::string aLength_str = doubleToString(theLength);
1657   
1658   // Plane construction
1659   gce_MakePln gce_MP(P1, theNormal);
1660   Handle(Geom_Plane) aPlane = new Geom_Plane(gce_MP.Value());
1661   
1662   TopoDS_Vertex aVert1 = BRepBuilderAPI_MakeVertex(P1);
1663   TopoDS_Vertex aVert2 = BRepBuilderAPI_MakeVertex(P2);
1664
1665   Handle(AIS_LengthDimension) anIO =
1666     new AIS_LengthDimension(aVert1,
1667                             aVert2,
1668                             aPlane,
1669                             theLength,
1670                             TCollection_ExtendedString(aLength_str.c_str()));
1671   anIO->SetArrowSize(theLength/20);
1672
1673   SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
1674   int w = resMgr->integerValue("Geometry", "measures_line_width", 1);
1675   Handle(Prs3d_LengthAspect) asp = new Prs3d_LengthAspect();
1676   asp->LineAspect()->SetWidth(w);
1677   anIO->Attributes()->SetLengthAspect(asp);
1678   
1679   return anIO;
1680 }
1681
1682 //================================================================
1683 // Function : createAISAngleDimension()
1684 // Purpose  : Method for creation of an angle dimension object
1685 //            Returns an Handle on the AIS_AngleDimension obect
1686 //================================================================
1687 Handle(AIS_AngleDimension) EntityGUI_3DSketcherDlg::createAISAngleDimension(double theAngle, 
1688                                                                             gp_Pnt P0, 
1689                                                                             gp_Pnt P1, 
1690                                                                             gp_Pnt P2)
1691 {
1692   // Length of the built segment
1693   double aLength = P0.Distance(P1);
1694   
1695   // Check input data
1696   if (Abs(theAngle) < Precision::Angular() ||
1697       aLength < Precision::Confusion())
1698     return NULL;
1699   
1700   // Convert angles to string
1701   std::string Angle_str = doubleToString(theAngle);
1702   
1703   // Construction of the plane
1704   gce_MakePln gce_MP2(P0, P1, P2);
1705   Handle(Geom_Plane) aPlane = new Geom_Plane(gce_MP2.Value());
1706   
1707   TopoDS_Vertex V0 = BRepBuilderAPI_MakeVertex(P0);
1708   TopoDS_Vertex V1 = BRepBuilderAPI_MakeVertex(P1);
1709   TopoDS_Vertex V2 = BRepBuilderAPI_MakeVertex(P2);
1710   
1711   TopoDS_Edge anEdge1 = BRepBuilderAPI_MakeEdge(V0, V1);
1712   TopoDS_Edge anEdge2 = BRepBuilderAPI_MakeEdge(V0, V2);
1713
1714   Handle(AIS_AngleDimension) anIO =
1715     new AIS_AngleDimension(anEdge1, anEdge2, aPlane, theAngle * M_PI / 180.,
1716                            TCollection_ExtendedString(Angle_str.c_str()));
1717     
1718   anIO->SetArrowSize((theAngle * M_PI / 180) * (aLength/20));
1719   
1720   SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
1721   int w = resMgr->integerValue("Geometry", "measures_line_width", 1);
1722   Handle(Prs3d_AngleAspect) asp = new Prs3d_AngleAspect();
1723   asp->LineAspect()->SetWidth(w);
1724   anIO->Attributes()->SetAngleAspect(asp);
1725   
1726   return anIO;
1727 }
1728
1729 //================================================================
1730 // Function : createShapes
1731 // Purpose  : Create applyed wire, and last segment from entry object
1732 //================================================================
1733 bool EntityGUI_3DSketcherDlg::createShapes (GEOM::GEOM_Object_ptr /*theObject*/,
1734                                             TopoDS_Shape&         theApplyedWire,
1735                                             TopoDS_Shape&         theLastSegment)
1736 {
1737   QList<gp_Pnt> points;
1738   foreach (XYZ xyz, myPointsList) {
1739     gp_Pnt p(xyz.x, xyz.y, xyz.z);
1740     if (points.isEmpty() || points.last().Distance(p) > gp::Resolution())
1741       points << p;
1742   }
1743
1744   if (points.count() == 1) {
1745     // only one point is created
1746     BRepBuilderAPI_MakeVertex mkVertex (points.last());
1747     theApplyedWire = mkVertex.Shape();
1748   }
1749   else if (points.count() > 1) {
1750     // wire is created
1751     BRepBuilderAPI_MakePolygon mkWire;
1752     foreach(gp_Pnt p, points)
1753       mkWire.Add(p);
1754     theApplyedWire = mkWire.Shape();
1755   }
1756
1757   XYZ curxyz = getCurrentPoint();
1758   gp_Pnt curpnt(curxyz.x, curxyz.y, curxyz.z);
1759
1760   if (points.isEmpty() || points.last().Distance(curpnt) <= gp::Resolution()) {
1761     BRepBuilderAPI_MakeVertex mkVertex (curpnt);
1762     theLastSegment = mkVertex.Shape();
1763   }
1764   else {
1765     BRepBuilderAPI_MakeEdge mkEdge(points.last(), curpnt);
1766     theLastSegment = mkEdge.Shape();
1767   }
1768
1769   /* VSR: old algorithm does not work properly, see bug 0020899
1770   TopoDS_Shape aShape;
1771   if (!GEOMBase::GetShape(theObject, aShape))
1772     return false;
1773
1774   if (aShape.ShapeType() != TopAbs_WIRE && aShape.ShapeType() != TopAbs_VERTEX)
1775     return false;
1776
1777   theApplyedWire = aShape;
1778   if (myOK)
1779      return true;
1780
1781   BRepBuilderAPI_MakeWire aBuilder;
1782   TopExp_Explorer edgeExp(aShape, TopAbs_EDGE);
1783   while (1) {
1784     TopoDS_Shape anEdge = edgeExp.Current();
1785     edgeExp.Next();
1786     if (edgeExp.More()) // i.e. non-last edge
1787       aBuilder.Add(TopoDS::Edge(anEdge));
1788     else {
1789       theLastSegment = anEdge;
1790       break;
1791     }
1792   }
1793
1794   if (aBuilder.IsDone()) {
1795     theApplyedWire = aBuilder.Shape();
1796   }
1797   else if (!theLastSegment.IsNull()) {
1798     TopExp_Explorer vertexExp(theLastSegment, TopAbs_VERTEX);
1799     theApplyedWire = vertexExp.Current();
1800     }
1801   */
1802
1803   return true;
1804 }
1805
1806 //================================================================
1807 // Function : doubleToString
1808 // Purpose  : converts double to string
1809 //================================================================
1810 std::string EntityGUI_3DSketcherDlg::doubleToString (double num)
1811 {
1812   // truncate num
1813   int digNum = 5;
1814   char format = 'g'; // truncated to a number of significant digits
1815
1816   return QString::number(num, format, digNum).toStdString();
1817 }
1818
1819 //================================================================
1820 // Function : toReferenceSystem ()
1821 // Purpose  :
1822 //================================================================
1823 gp_Trsf EntityGUI_3DSketcherDlg::toReferenceSystem(gp_Pnt origin) const
1824
1825   gp_Trsf T;                        // Identity transformation
1826   gp_Ax3 reference_system;          // OXY
1827   reference_system.SetLocation(origin);
1828   
1829   gp_Ax3 current_system = reference_system;
1830   switch (myOrientation)
1831   {
1832     case OYZ:
1833     {
1834       current_system = gp_Ax3(origin, gp::DX(), gp::DY());
1835       break;
1836     }
1837     case OXZ:
1838     {
1839       current_system = gp_Ax3(origin, gp::DY().Reversed(), gp::DX());
1840       break;
1841     }
1842   }
1843   
1844   T.SetTransformation( current_system, reference_system );
1845   
1846   return T;
1847 }
1848
1849 //================================================================
1850 // Function : toCurrentSystem ()
1851 // Purpose  :
1852 //================================================================
1853 gp_Trsf EntityGUI_3DSketcherDlg::toCurrentSystem(gp_Pnt origin) const
1854 {
1855   return toReferenceSystem(origin).Inverted();
1856 }
1857
1858 //================================================================
1859 // Function : radius (gp_Pnt) const
1860 // Purpose  :
1861 //================================================================
1862 double EntityGUI_3DSketcherDlg::radius (gp_Pnt thePnt) const
1863 {
1864   // Get the point coordinates in the current coordinates system
1865   gp_Trsf aTrsf = toCurrentSystem(gp::Origin());
1866   gp_Pnt aPnt = thePnt.Transformed(aTrsf);
1867   
1868   double radius = sqrt(aPnt.X()*aPnt.X() + aPnt.Y()*aPnt.Y());
1869   return radius;
1870 }
1871
1872 //================================================================
1873 // Function : height (gp_Pnt) const
1874 // Purpose  :
1875 //================================================================
1876 double EntityGUI_3DSketcherDlg::height (gp_Pnt thePnt) const
1877 {
1878   // Get the point coordinates in the current coordinates system
1879   gp_Trsf aTrsf = toCurrentSystem(gp::Origin());
1880   gp_Pnt aPnt = thePnt.Transformed(aTrsf);
1881   
1882   return aPnt.Z();
1883 }