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