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