1 // Copyright (C) 2007-2021 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 // File : SMESHGUI_MakeNodeAtPointDlg.cxx
24 // Author : Edward AGAPOV, Open CASCADE S.A.S.
27 #include "SMESHGUI_MakeNodeAtPointDlg.h"
30 #include "SMESHGUI_IdValidator.h"
31 #include "SMESHGUI_MeshUtils.h"
32 #include "SMESHGUI_VTKUtils.h"
33 #include "SMESHGUI_SpinBox.h"
34 #include "SMESHGUI_MeshEditPreview.h"
36 #include <SMDS_Mesh.hxx>
37 #include <SMESH_Actor.h>
38 #include <SMESH_ActorUtils.h>
39 #include <SMESH_NumberFilter.hxx>
40 #include <SMESH_LogicalFilter.hxx>
42 // SALOME GEOM includes
45 // SALOME GUI includes
46 #include <LightApp_SelectionMgr.h>
47 #include <SALOME_ListIO.hxx>
48 #include <SUIT_Desktop.h>
49 #include <SVTK_ViewModel.h>
50 #include <SVTK_ViewWindow.h>
51 #include <SVTK_Renderer.h>
52 #include <SVTK_RenderWindowInteractor.h>
53 #include <SVTK_Event.h>
54 #include <SalomeApp_Tools.h>
55 #include <SalomeApp_TypeFilter.h>
56 #include <SUIT_ResourceMgr.h>
57 #include <SUIT_OverrideCursor.h>
58 #include <SUIT_MessageBox.h>
61 #include <TColStd_MapOfInteger.hxx>
62 #include <TopoDS_Vertex.hxx>
63 #include <BRep_Tool.hxx>
67 #include <QApplication>
69 #include <QGridLayout>
70 #include <QHBoxLayout>
71 #include <QVBoxLayout>
73 #include <QPushButton>
75 #include <QRadioButton>
77 #include <QButtonGroup>
80 #include <vtkObject.h>
81 #include <vtkProperty.h>
82 #include <vtkGenericRenderWindowInteractor.h>
83 #include <vtkInteractorObserver.h>
86 #include <SALOMEconfig.h>
87 #include CORBA_SERVER_HEADER(SMESH_Mesh)
88 #include CORBA_SERVER_HEADER(SMESH_MeshEditor)
95 enum { MANUAL_MODE = 0, SEARCH_MODE, INTERACTIVE_MODE };
98 //#define SELECTION_PRECISION 4
100 //=======================================================================
102 * \brief Dialog to publish a sub-shape of the mesh main shape
103 * by selecting mesh elements
105 //=======================================================================
107 SMESHGUI_MakeNodeAtPointDlg::SMESHGUI_MakeNodeAtPointDlg()
108 : SMESHGUI_Dialog( 0, false, true )
110 setWindowTitle(tr("CAPTION"));
112 QVBoxLayout* aDlgLay = new QVBoxLayout (mainFrame());
113 aDlgLay->setMargin(0);
114 aDlgLay->setSpacing(SPACING);
115 myMainFrame = createMainFrame(mainFrame());
117 aDlgLay->addWidget(myMainFrame);
119 aDlgLay->setStretchFactor(myMainFrame, 1);
122 //=======================================================================
123 // function : createMainFrame()
124 // purpose : Create frame containing dialog's input fields
125 //=======================================================================
127 QWidget* SMESHGUI_MakeNodeAtPointDlg::createMainFrame (QWidget* theParent)
129 QWidget* aFrame = new QWidget(theParent);
131 SUIT_ResourceMgr* rm = SMESH::GetResourceMgr( SMESHGUI::GetSMESHGUI() );
132 QPixmap iconMoveNode (rm->loadPixmap("SMESH", tr("ICON_DLG_MOVE_NODE")));
133 QPixmap iconMoveWithoutNode (rm->loadPixmap("SMESH", tr("ICON_DLG_MOVE_WITHOUT_NODE")));
134 QPixmap iconMoveInteractive (rm->loadPixmap("SMESH", tr("ICON_DLG_MOVE_NODE_INTERACTIVE")));
135 QPixmap iconSelect (rm->loadPixmap("SMESH", tr("ICON_SELECT")));
138 QGroupBox* aPixGrp = new QGroupBox(tr("MOVE_NODE"), this);
139 aPixGrp->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) );
140 myButtonGroup = new QButtonGroup(this);
141 QHBoxLayout* aPixGrpLayout = new QHBoxLayout(aPixGrp);
142 aPixGrpLayout->setMargin(MARGIN);
143 aPixGrpLayout->setSpacing(SPACING);
145 myRButNodeToMove = new QRadioButton(aPixGrp);
146 myRButMoveWithoutNode = new QRadioButton(aPixGrp);
147 myRButMoveInteractive = new QRadioButton(aPixGrp);
148 myRButNodeToMove->setIcon(iconMoveNode);
149 myRButMoveWithoutNode->setIcon(iconMoveWithoutNode);
150 myRButMoveInteractive->setIcon(iconMoveInteractive);
151 myRButNodeToMove->setChecked(true);
153 aPixGrpLayout->addWidget(myRButNodeToMove);
154 aPixGrpLayout->addWidget(myRButMoveWithoutNode);
155 aPixGrpLayout->addWidget(myRButMoveInteractive);
156 myButtonGroup->addButton(myRButNodeToMove, 0);
157 myButtonGroup->addButton(myRButMoveWithoutNode, 1);
158 myButtonGroup->addButton(myRButMoveInteractive, 2);
162 myNodeToMoveGrp = new QGroupBox(tr("NODE_2MOVE"), aFrame);
163 myNodeToMoveGrp->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) );
164 QLabel* idLabel = new QLabel(tr("NODE_2MOVE_ID"), myNodeToMoveGrp);
165 myIdBtn = new QPushButton(myNodeToMoveGrp);
166 myIdBtn->setIcon(iconSelect);
167 myIdBtn->setCheckable(true);
168 myId = new QLineEdit(myNodeToMoveGrp);
169 myId->setValidator(new SMESHGUI_IdValidator(this, 1));
171 myUpdateBtn = new QPushButton(tr("UPDATE_DESTINATION"), myNodeToMoveGrp);
172 myUpdateBtn->setAutoDefault(true);
174 QWidget* aCoordWidget = new QWidget(myNodeToMoveGrp);
176 QLabel* aCurrentXLabel = new QLabel(tr("SMESH_X"), aCoordWidget);
177 myCurrentX = new SMESHGUI_SpinBox(aCoordWidget);
178 myCurrentX->setButtonSymbols(QAbstractSpinBox::NoButtons);
179 myCurrentX->setReadOnly(true);
181 QLabel* aCurrentYLabel = new QLabel(tr("SMESH_Y"), aCoordWidget);
182 myCurrentY = new SMESHGUI_SpinBox(aCoordWidget);
183 myCurrentY->setButtonSymbols(QAbstractSpinBox::NoButtons);
184 myCurrentY->setReadOnly(true);
186 QLabel* aCurrentZLabel = new QLabel(tr("SMESH_Z"), aCoordWidget);
187 myCurrentZ = new SMESHGUI_SpinBox(aCoordWidget);
188 myCurrentZ->setButtonSymbols(QAbstractSpinBox::NoButtons);
189 myCurrentZ->setReadOnly(true);
191 myCurrentX->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, "length_precision");
192 myCurrentY->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, "length_precision");
193 myCurrentZ->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, "length_precision");
195 QGridLayout* aCoordLayout = new QGridLayout(aCoordWidget);
196 aCoordLayout->setMargin(0);
197 aCoordLayout->setSpacing(SPACING);
198 aCoordLayout->addWidget(aCurrentXLabel, 0, 0);
199 aCoordLayout->addWidget(myCurrentX, 0, 1);
200 aCoordLayout->addWidget(aCurrentYLabel, 0, 2);
201 aCoordLayout->addWidget(myCurrentY, 0, 3);
202 aCoordLayout->addWidget(aCurrentZLabel, 0, 4);
203 aCoordLayout->addWidget(myCurrentZ, 0, 5);
204 aCoordLayout->setColumnStretch(1, 1);
205 aCoordLayout->setColumnStretch(3, 1);
206 aCoordLayout->setColumnStretch(5, 1);
208 QGridLayout* myNodeToMoveGrpLayout = new QGridLayout(myNodeToMoveGrp);
209 myNodeToMoveGrpLayout->setSpacing(SPACING);
210 myNodeToMoveGrpLayout->setMargin(MARGIN);
212 myNodeToMoveGrpLayout->addWidget( idLabel, 0, 0 );
213 myNodeToMoveGrpLayout->addWidget( myIdBtn, 0, 1 );
214 myNodeToMoveGrpLayout->addWidget( myId, 0, 2 );
215 myNodeToMoveGrpLayout->addWidget( myUpdateBtn, 0, 3 );
216 myNodeToMoveGrpLayout->addWidget( aCoordWidget, 1, 0, 1, 4 );
220 myDestinationGrp = new QGroupBox(tr("DESTINATION"), aFrame);
221 myDestinationGrp->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) );
223 myDestBtn = new QPushButton(myDestinationGrp);
224 myDestBtn->setIcon(iconSelect);
225 myDestBtn->setCheckable(true);
227 QLabel* aDestinationXLabel = new QLabel(tr("SMESH_X"), myDestinationGrp);
228 myDestinationX = new SMESHGUI_SpinBox(myDestinationGrp);
230 QLabel* aDestinationYLabel = new QLabel(tr("SMESH_Y"), myDestinationGrp);
231 myDestinationY = new SMESHGUI_SpinBox(myDestinationGrp);
233 QLabel* aDestinationZLabel = new QLabel(tr("SMESH_Z"), myDestinationGrp);
234 myDestinationZ = new SMESHGUI_SpinBox(myDestinationGrp);
236 myDestDXLabel = new QLabel(tr("SMESH_DX"), myDestinationGrp);
237 myDestDX = new SMESHGUI_SpinBox(myDestinationGrp);
238 myDestDX->setReadOnly(true);
240 myDestDYLabel = new QLabel(tr("SMESH_DY"), myDestinationGrp);
241 myDestDY = new SMESHGUI_SpinBox(myDestinationGrp);
242 myDestDY->setReadOnly(true);
244 myDestDZLabel = new QLabel(tr("SMESH_DZ"), myDestinationGrp);
245 myDestDZ = new SMESHGUI_SpinBox(myDestinationGrp);
246 myDestDZ->setReadOnly(true);
248 myDestinationX->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, "length_precision");
249 myDestinationY->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, "length_precision");
250 myDestinationZ->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, "length_precision");
251 myDestDX->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, "length_precision");
252 myDestDY->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, "length_precision");
253 myDestDZ->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, "length_precision");
255 QGridLayout* aDestLayout = new QGridLayout(myDestinationGrp);
256 aDestLayout->setMargin(MARGIN);
257 aDestLayout->setSpacing(SPACING);
258 aDestLayout->addWidget(myDestBtn, 0, 0);
259 aDestLayout->addWidget(aDestinationXLabel, 0, 1);
260 aDestLayout->addWidget(myDestinationX, 0, 2);
261 aDestLayout->addWidget(aDestinationYLabel, 0, 3);
262 aDestLayout->addWidget(myDestinationY, 0, 4);
263 aDestLayout->addWidget(aDestinationZLabel, 0, 5);
264 aDestLayout->addWidget(myDestinationZ, 0, 6);
265 aDestLayout->addWidget(myDestDXLabel, 1, 1);
266 aDestLayout->addWidget(myDestDX, 1, 2);
267 aDestLayout->addWidget(myDestDYLabel, 1, 3);
268 aDestLayout->addWidget(myDestDY, 1, 4);
269 aDestLayout->addWidget(myDestDZLabel, 1, 5);
270 aDestLayout->addWidget(myDestDZ, 1, 6);
271 aDestLayout->setColumnStretch(2, 1);
272 aDestLayout->setColumnStretch(4, 1);
273 aDestLayout->setColumnStretch(6, 1);
277 myPreviewChkBox = new QCheckBox( tr("PREVIEW"), aFrame);
279 QVBoxLayout* aLay = new QVBoxLayout(aFrame);
280 aLay->addWidget(aPixGrp);
281 aLay->addWidget(myNodeToMoveGrp);
282 aLay->addWidget(myDestinationGrp);
283 aLay->addWidget(myPreviewChkBox);
285 connect(myDestBtn, SIGNAL (toggled(bool)), this, SLOT(ButtonToggled(bool)));
286 connect(myIdBtn, SIGNAL (toggled(bool)), this, SLOT(ButtonToggled(bool)));
287 connect(myButtonGroup, SIGNAL (buttonClicked(int)), SLOT(ConstructorsClicked(int)));
289 myIdBtn->setChecked(true);
294 //================================================================================
296 * \brief SLOT called when any button is toggled
297 * \param bool - on or off
299 //================================================================================
301 void SMESHGUI_MakeNodeAtPointDlg::ButtonToggled (bool on)
303 const QObject* aSender = sender();
305 if ( aSender == myDestBtn ) // button to set coord by node selection
307 if ( myIdBtn->isEnabled() )
308 myIdBtn->setChecked( !on );
310 else if ( aSender == myIdBtn ) // button to select a node to move
312 myDestBtn->setChecked( !on );
316 //================================================================================
318 * \brief SLOT called when clicked radio button
319 * \param int - number of the button
321 //================================================================================
323 void SMESHGUI_MakeNodeAtPointDlg::ConstructorsClicked (int constructorId)
325 switch (constructorId) {
327 case INTERACTIVE_MODE:
329 myUpdateBtn->setVisible( constructorId == MANUAL_MODE );
330 myDestinationGrp->setTitle( tr( constructorId == MANUAL_MODE ? "DESTINATION" : "DESTINATION_BY_MOUSE"));
331 myDestDXLabel->show();
332 myDestDYLabel->show();
333 myDestDZLabel->show();
337 myCurrentX->SetValue(0);
338 myCurrentY->SetValue(0);
339 myCurrentZ->SetValue(0);
340 if (!myNodeToMoveGrp->isVisible()) myNodeToMoveGrp->show();
341 myIdBtn->setChecked( true );
347 myCurrentX->SetValue(0);
348 myCurrentY->SetValue(0);
349 myCurrentZ->SetValue(0);
350 myDestDXLabel->hide();
351 myDestDYLabel->hide();
352 myDestDZLabel->hide();
356 if (myNodeToMoveGrp->isVisible()) myNodeToMoveGrp->hide();
357 myDestBtn->setChecked( true );
361 QApplication::instance()->processEvents();
365 resize(minimumSizeHint());
368 //================================================================================
372 //================================================================================
374 SMESHGUI_MakeNodeAtPointOp::SMESHGUI_MakeNodeAtPointOp(int defaultConstructor) :
375 SMESHGUI_InteractiveOp()
377 myDefaultConstructor = defaultConstructor;
380 myDlg = new SMESHGUI_MakeNodeAtPointDlg;
382 myHelpFileName = "mesh_through_point.html";
385 myUpdateDestination = false;
386 myDestCoordChanged = true;
388 // connect signals and slots
389 connect(myDlg->myDestinationX, SIGNAL (valueChanged(double)), this, SLOT(redisplayPreview()));
390 connect(myDlg->myDestinationY, SIGNAL (valueChanged(double)), this, SLOT(redisplayPreview()));
391 connect(myDlg->myDestinationZ, SIGNAL (valueChanged(double)), this, SLOT(redisplayPreview()));
392 connect(myDlg->myDestDX, SIGNAL (valueChanged(double)), this, SLOT(onDestCoordChanged()));
393 connect(myDlg->myDestDY, SIGNAL (valueChanged(double)), this, SLOT(onDestCoordChanged()));
394 connect(myDlg->myDestDZ, SIGNAL (valueChanged(double)), this, SLOT(onDestCoordChanged()));
395 connect(myDlg->myId, SIGNAL (textChanged(const QString&)),SLOT(redisplayPreview()));
396 connect(myDlg->myPreviewChkBox, SIGNAL (toggled(bool)), SLOT(redisplayPreview()));
397 connect(myDlg->myButtonGroup, SIGNAL (buttonClicked(int)), SLOT(constructorChanged()));
399 // IPAL22913: TC6.5.0: selected in "Move node" dialog box node is not highlighted
400 // note: this slot seems to be lost together with removed obsolete SMESHGUI_MoveNodesDlg class
401 connect(myDlg->myId,SIGNAL (textChanged(const QString&)),SLOT(onTextChange(const QString&)));
402 connect(myDlg->myUpdateBtn, SIGNAL (clicked()), this, SLOT(onUpdateDestination()));
405 //================================================================================
407 * \brief SLOT. Update preview upon [Update destination] clicked
409 //================================================================================
411 void SMESHGUI_MakeNodeAtPointOp::onUpdateDestination()
413 myUpdateDestination = true;
415 myUpdateDestination = false;
418 //================================================================================
420 * \brief SLOT. Update preview upon Destination coordinates change
422 //================================================================================
424 void SMESHGUI_MakeNodeAtPointOp::onDestCoordChanged()
426 myDestCoordChanged = false;
428 myDestCoordChanged = true;
432 //=======================================================================
433 // function : startOperation()
434 // purpose : Init dialog fields, connect signals and slots, show dialog
435 //=======================================================================
437 void SMESHGUI_MakeNodeAtPointOp::startOperation()
442 // init simulation with a current View
443 if ( mySimulation ) delete mySimulation;
444 mySMESHGUI = getSMESHGUI();
445 mySimulation = new SMESHGUI_MeshEditPreview(SMESH::GetViewWindow(mySMESHGUI));
447 connect(mySMESHGUI, SIGNAL (SignalActivatedViewManager()), this, SLOT(onOpenView()));
448 connect(mySMESHGUI, SIGNAL (SignalCloseView()), this, SLOT(onCloseView()));
449 vtkProperty* aProp = vtkProperty::New();
450 aProp->SetRepresentationToWireframe();
451 aProp->SetColor(250, 0, 250);
452 aProp->SetPointSize(5);
453 aProp->SetLineWidth( SMESH::GetFloat("SMESH:element_width",1) + 1);
454 mySimulation->GetActor()->SetProperty(aProp);
457 // SalomeApp_TypeFilter depends on a current study
458 if ( myFilter ) delete myFilter;
459 QList<SUIT_SelectionFilter*> filters;
460 filters.append( new SalomeApp_TypeFilter((SalomeApp_Study*)study(), "SMESH" ));
461 TColStd_MapOfInteger vertexType;
462 vertexType.Add( TopAbs_VERTEX );
463 filters.append( new SMESH_NumberFilter("GEOM", TopAbs_VERTEX, 1, vertexType ));
464 myFilter = new SMESH_LogicalFilter( filters, SMESH_LogicalFilter::LO_OR );
467 SMESHGUI_SelectionOp::startOperation(); // this method should be called only after filter creation
468 //activateSelection(); // set filters // called inside of previous statement
469 SMESHGUI_InteractiveOp::startOperation();
470 myDlg->myId->setText("");
471 myDlg->myDestinationX->SetValue(0);
472 myDlg->myDestinationY->SetValue(0);
473 myDlg->myDestinationZ->SetValue(0);
474 myDlg->myDestDX->SetValue(0);
475 myDlg->myDestDY->SetValue(0);
476 myDlg->myDestDZ->SetValue(0);
477 myDlg->myCurrentX->SetValue(0);
478 myDlg->myCurrentY->SetValue(0);
479 myDlg->myCurrentZ->SetValue(0);
480 myDlg->myDestDX->setReadOnly(true);
481 myDlg->myDestDY->setReadOnly(true);
482 myDlg->myDestDZ->setReadOnly(true);
483 myDlg->myRButNodeToMove->setChecked(true);
485 if ( myDefaultConstructor == INTERACTIVE_MODE ) {
487 myDlg->myButtonGroup->button( INTERACTIVE_MODE )->setChecked(true);
489 myDlg->ConstructorsClicked( GetConstructorId() );
493 onSelectionDone(); // init myMeshActor
496 //=================================================================================
497 // function : GetConstructorId()
499 //=================================================================================
501 int SMESHGUI_MakeNodeAtPointOp::GetConstructorId()
503 return myDlg->myButtonGroup->checkedId();
506 //================================================================================
508 * \brief Stops operation
510 //================================================================================
512 void SMESHGUI_MakeNodeAtPointOp::stopOperation()
517 mySimulation->SetVisibility(false);
524 SMESH::SetPointRepresentation( false );
525 SMESH::RepaintCurrentView();
527 disconnect(mySMESHGUI, SIGNAL (SignalActivatedViewManager()), this, SLOT(onOpenView()));
528 disconnect(mySMESHGUI, SIGNAL (SignalCloseView()), this, SLOT(onCloseView()));
529 selectionMgr()->removeFilter( myFilter );
530 SMESHGUI_SelectionOp::stopOperation();
534 //================================================================================
536 * \brief perform it's intention action: move or create a node
538 //================================================================================
540 bool SMESHGUI_MakeNodeAtPointOp::onApply()
542 if( SMESHGUI::isStudyLocked() )
545 if ( !myMeshActor ) {
546 SUIT_MessageBox::warning( dlg(), tr( "SMESH_WRN_WARNING" ),
547 tr("INVALID_MESH") );
553 if ( !isValid( msg ) ) { // node id is invalid
555 SUIT_MessageBox::warning( dlg(), tr( "SMESH_WRN_WARNING" ),
561 QStringList aParameters;
562 aParameters << myDlg->myDestinationX->text();
563 aParameters << myDlg->myDestinationY->text();
564 aParameters << myDlg->myDestinationZ->text();
567 SMESH::SMESH_Mesh_var aMesh = SMESH::GetMeshByIO(myMeshActor->getIO());
568 if (aMesh->_is_nil()) {
569 SUIT_MessageBox::information(SMESHGUI::desktop(), tr("SMESH_ERROR"),
570 tr("SMESHG_NO_MESH") );
573 SMESH::SMESH_MeshEditor_var aMeshEditor = aMesh->GetMeshEditor();
574 if (aMeshEditor->_is_nil())
577 aMesh->SetParameters( aParameters.join(":").toUtf8().constData() );
580 int anId = myDlg->myId->text().toInt( &ok );
581 if( !ok || anId < 1 )
582 anId = FromSmIdType<int>(aMeshEditor->FindNodeClosestTo(myDlg->myDestinationX->GetValue(),
583 myDlg->myDestinationY->GetValue(),
584 myDlg->myDestinationZ->GetValue()));
586 int aResult = aMeshEditor->MoveNode(anId,
587 myDlg->myDestinationX->GetValue(),
588 myDlg->myDestinationY->GetValue(),
589 myDlg->myDestinationZ->GetValue() );
593 myDlg->myCurrentX->SetValue(0);
594 myDlg->myCurrentY->SetValue(0);
595 myDlg->myCurrentZ->SetValue(0);
596 myDlg->myDestDX->SetValue(0);
597 myDlg->myDestDY->SetValue(0);
598 myDlg->myDestDZ->SetValue(0);
601 selectionMgr()->setSelectedObjects(aList,false);
602 aList.Append(myMeshActor->getIO());
603 selectionMgr()->setSelectedObjects(aList,false);
605 SMESHGUI::Modified();
608 catch (const SALOME::SALOME_Exception& S_ex) {
609 SalomeApp_Tools::QtCatchCorbaException(S_ex);
617 //================================================================================
619 * \brief Check selected node id validity
621 //================================================================================
623 bool SMESHGUI_MakeNodeAtPointOp::isValid( QString& msg )
626 if ( myMeshActor && myDlg->myRButNodeToMove->isChecked() )
629 int id = myDlg->myId->text().toInt();
631 if (SMDS_Mesh* aMesh = myMeshActor->GetObject()->GetMesh())
632 ok = aMesh->FindNode( id );
634 msg += tr("INVALID_ID") + "\n";
637 ok = myDlg->myDestinationX->isValid( msg, !myNoPreview ) && ok;
638 ok = myDlg->myDestinationY->isValid( msg, !myNoPreview ) && ok;
639 ok = myDlg->myDestinationZ->isValid( msg, !myNoPreview ) && ok;
644 //================================================================================
646 * \brief SLOT called when selection changed
648 //================================================================================
650 void SMESHGUI_MakeNodeAtPointOp::onSelectionDone()
652 if ( !myDlg->isVisible() || !myDlg->isEnabled() )
658 selectionMgr()->selectedObjects(aList, SVTK_Viewer::Type());
659 if (aList.Extent() != 1)
661 Handle(SALOME_InteractiveObject) anIO = aList.First();
662 SMESH_Actor* aMeshActor = SMESH::FindActorByEntry(anIO->getEntry());
664 if (( myDlg->myIdBtn->isChecked() && myDlg->myIdBtn->isEnabled() ) ||
665 ( !myDlg->myNodeToMoveGrp->isVisible() ))
666 myMeshActor = aMeshActor;
668 if (!aMeshActor) { // coord by geom
669 if ( myDlg->myDestBtn->isChecked() ) {
670 GEOM::GEOM_Object_var geom = SMESH::IObjectToInterface<GEOM::GEOM_Object>(anIO);
671 if ( !geom->_is_nil() ) {
672 TopoDS_Vertex aShape;
673 if ( GEOMBase::GetShape(geom, aShape) &&
674 aShape.ShapeType() == TopAbs_VERTEX ) {
675 gp_Pnt P = BRep_Tool::Pnt(aShape);
676 myDlg->myDestinationX->SetValue(P.X());
677 myDlg->myDestinationY->SetValue(P.Y());
678 myDlg->myDestinationZ->SetValue(P.Z());
688 int nbElems = SMESH::GetNameOfSelectedElements(selector(),anIO, aString);
690 if (SMDS_Mesh* aMesh = aMeshActor->GetObject()->GetMesh()) {
691 if (const SMDS_MeshNode* aNode = aMesh->FindNode(aString.toInt())) {
692 if ( myDlg->myDestBtn->isChecked() ) { // set coord
693 myDlg->myDestinationX->SetValue(aNode->X());
694 myDlg->myDestinationY->SetValue(aNode->Y());
695 myDlg->myDestinationZ->SetValue(aNode->Z());
697 else if ( myDlg->myIdBtn->isChecked() &&
698 myDlg->myIdBtn->isEnabled() ) { // set node to move
699 myDlg->myId->setText(aString);
700 myDlg->myCurrentX->SetValue( aNode->X() );
701 myDlg->myCurrentY->SetValue( aNode->Y() );
702 myDlg->myCurrentZ->SetValue( aNode->Z() );
706 double x = myDlg->myCurrentX->GetValue();
707 double y = myDlg->myCurrentY->GetValue();
708 double z = myDlg->myCurrentZ->GetValue();
709 double dx = myDlg->myDestinationX->GetValue() - x;
710 double dy = myDlg->myDestinationY->GetValue() - y;
711 double dz = myDlg->myDestinationZ->GetValue() - z;
712 myDlg->myDestDX->SetValue(dx);
713 myDlg->myDestDY->SetValue(dy);
714 myDlg->myDestDZ->SetValue(dz);
715 myDlg->myDestDX->setReadOnly(false);
716 myDlg->myDestDY->setReadOnly(false);
717 myDlg->myDestDZ->setReadOnly(false);
728 //================================================================================
730 * \brief update preview
732 //================================================================================
734 void SMESHGUI_MakeNodeAtPointOp::redisplayPreview()
740 if ( !myMeshActor && GetConstructorId() == SEARCH_MODE )
743 SMESH::MeshPreviewStruct_var aMeshPreviewStruct;
745 bool moveShown = false;
748 const bool isPreview = myDlg->myPreviewChkBox->isChecked();
749 const bool isMoveNode = myDlg->myRButMoveWithoutNode->isChecked();
751 if ( isValid( msg ) )
754 SMESH::SMESH_Mesh_var aMesh = SMESH::GetMeshByIO(myMeshActor->getIO());
755 if (!aMesh->_is_nil()) {
756 SMESH::SMESH_MeshEditor_var aPreviewer = aMesh->GetMeshEditPreviewer();
757 if (!aPreviewer->_is_nil())
759 SUIT_OverrideCursor aWaitCursor;
761 int anId = myDlg->myId->text().toInt();
763 SMESH::double_array_var aXYZ = aMesh->GetNodeXYZ( anId );
764 if( &aXYZ.in() && aXYZ->length() >= 3 )
773 if ( myUpdateDestination ) {
774 myDlg->myDestinationX->SetValue(x);
775 myDlg->myDestinationY->SetValue(y);
776 myDlg->myDestinationZ->SetValue(z);
777 myDlg->myDestDX->SetValue(dx);
778 myDlg->myDestDY->SetValue(dy);
779 myDlg->myDestDZ->SetValue(dz);
783 if ( myDestCoordChanged ) {
784 dx = myDlg->myDestinationX->GetValue() - x;
785 dy = myDlg->myDestinationY->GetValue() - y;
786 dz = myDlg->myDestinationZ->GetValue() - z;
787 myDlg->myDestDX->SetValue(dx);
788 myDlg->myDestDY->SetValue(dy);
789 myDlg->myDestDZ->SetValue(dz);
792 dx = myDlg->myDestDX->GetValue() + x;
793 dy = myDlg->myDestDY->GetValue() + y;
794 dz = myDlg->myDestDZ->GetValue() + z;
795 myDlg->myDestinationX->SetValue(dx);
796 myDlg->myDestinationY->SetValue(dy);
797 myDlg->myDestinationZ->SetValue(dz);
800 myDlg->myCurrentX->SetValue(x);
801 myDlg->myCurrentY->SetValue(y);
802 myDlg->myCurrentZ->SetValue(z);
803 myDlg->myDestDX->setReadOnly(false);
804 myDlg->myDestDY->setReadOnly(false);
805 myDlg->myDestDZ->setReadOnly(false);
808 myDlg->myCurrentX->SetValue(0);
809 myDlg->myCurrentY->SetValue(0);
810 myDlg->myCurrentZ->SetValue(0);
811 myDlg->myDestDX->SetValue(0);
812 myDlg->myDestDY->SetValue(0);
813 myDlg->myDestDZ->SetValue(0);
814 myDlg->myDestDX->setReadOnly(true);
815 myDlg->myDestDY->setReadOnly(true);
816 myDlg->myDestDZ->setReadOnly(true);
818 if ( isPreview && isMoveNode && anId == 0 )
819 anId = FromSmIdType<int>(aPreviewer->FindNodeClosestTo(myDlg->myDestinationX->GetValue(),
820 myDlg->myDestinationY->GetValue(),
821 myDlg->myDestinationZ->GetValue()));
822 // find id and/or just compute preview
823 aPreviewer->MoveNode(anId,
824 myDlg->myDestinationX->GetValue(),
825 myDlg->myDestinationY->GetValue(),
826 myDlg->myDestinationZ->GetValue());
828 if ( isPreview ) { // fill preview data
829 aMeshPreviewStruct = aPreviewer->GetPreviewData();
830 moveShown = ( anId > 0 );
842 aMeshPreviewStruct = new SMESH::MeshPreviewStruct();
844 aMeshPreviewStruct->nodesXYZ.length(1);
845 aMeshPreviewStruct->nodesXYZ[0].x = myDlg->myDestinationX->GetValue();
846 aMeshPreviewStruct->nodesXYZ[0].y = myDlg->myDestinationY->GetValue();
847 aMeshPreviewStruct->nodesXYZ[0].z = myDlg->myDestinationZ->GetValue();
849 aMeshPreviewStruct->elementTypes.length(1);
850 aMeshPreviewStruct->elementTypes[0].SMDS_ElementType = SMESH::NODE;
851 aMeshPreviewStruct->elementTypes[0].isPoly = false;
852 aMeshPreviewStruct->elementTypes[0].nbNodesInElement = 1;
854 aMeshPreviewStruct->elementConnectivities.length(1);
855 aMeshPreviewStruct->elementConnectivities[0] = 0;
858 mySimulation = new SMESHGUI_MeshEditPreview(SMESH::GetViewWindow( mySMESHGUI ));
860 if ( & aMeshPreviewStruct.in() )
862 mySimulation->SetData( aMeshPreviewStruct.in() );
866 mySimulation->SetVisibility(false);
872 //=================================================================================
874 * \brief SLOT called when the viewer opened
876 //=================================================================================
878 void SMESHGUI_MakeNodeAtPointOp::onOpenView()
880 if ( mySimulation ) {
881 mySimulation->SetVisibility(false);
882 SMESH::SetPointRepresentation(false);
885 mySimulation = new SMESHGUI_MeshEditPreview(SMESH::GetViewWindow( mySMESHGUI ));
889 //=================================================================================
891 * \brief SLOT called when the creation mode is changed
893 //=================================================================================
895 void SMESHGUI_MakeNodeAtPointOp::constructorChanged() {
897 if (GetConstructorId() == INTERACTIVE_MODE) {
906 //=================================================================================
908 * \brief SLOT called when the viewer closed
910 //=================================================================================
912 void SMESHGUI_MakeNodeAtPointOp::onCloseView()
918 //================================================================================
920 * \brief SLOT called when the node id is manually changed
922 //================================================================================
924 void SMESHGUI_MakeNodeAtPointOp::onTextChange( const QString& theText )
928 if( SMDS_Mesh* aMesh = myMeshActor->GetObject()->GetMesh() )
930 Handle(SALOME_InteractiveObject) anIO = myMeshActor->getIO();
932 aList.Append( anIO );
933 selectionMgr()->setSelectedObjects( aList, false );
935 if( const SMDS_MeshNode* aNode = aMesh->FindNode( theText.toInt() ) )
937 SVTK_TVtkIDsMap aListInd;
938 aListInd.Add( FromSmIdType<int>(aNode->GetID()) );
939 selector()->AddOrRemoveIndex( anIO, aListInd, false );
940 if( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( SMESHGUI::GetSMESHGUI() ) )
941 aViewWindow->highlight( anIO, true, true );
947 //================================================================================
949 * \brief Activate Node selection
951 //================================================================================
953 void SMESHGUI_MakeNodeAtPointOp::activateSelection()
955 selectionMgr()->clearFilters();
956 SMESH::SetPointRepresentation( true );
957 selectionMgr()->installFilter( myFilter );
958 setSelectionMode( NodeSelection );
961 //================================================================================
965 //================================================================================
967 SMESHGUI_MakeNodeAtPointOp::~SMESHGUI_MakeNodeAtPointOp()
969 if ( myDlg ) delete myDlg;
970 if ( mySimulation ) delete mySimulation;
971 if ( myFilter ) delete myFilter;
974 //================================================================================
976 * \brief Gets dialog of this operation
977 * \retval LightApp_Dialog* - pointer to dialog of this operation
979 //================================================================================
981 LightApp_Dialog* SMESHGUI_MakeNodeAtPointOp::dlg() const
987 //================================================================================
989 * \brief Process InteractiveSelectionChanged event
991 //================================================================================
993 void SMESHGUI_MakeNodeAtPointOp::processStyleEvents(unsigned long theEvent, void* theCallData) {
994 if (theEvent == SVTK::InteractiveSelectionChanged) {
995 double* aCoord = (double*)theCallData;
996 myDlg->myDestinationX->SetValue(aCoord[0]);
997 myDlg->myDestinationY->SetValue(aCoord[1]);
998 myDlg->myDestinationZ->SetValue(aCoord[2]);
1003 //================================================================================
1005 * \brief Process LeftButtonPressEvent event
1007 //================================================================================
1008 void SMESHGUI_MakeNodeAtPointOp::processInteractorEvents(unsigned long theEvent, void* theCallData) {
1010 if (theEvent == vtkCommand::LeftButtonPressEvent) {
1011 bool control = myRWInteractor->GetDevice()->GetControlKey();
1012 bool shift = myRWInteractor->GetDevice()->GetControlKey();
1013 if (GetConstructorId() == INTERACTIVE_MODE && myDlg->myDestBtn->isChecked() && !shift && !control) {
1014 if (SVTK_ViewWindow* svtkViewWindow = SMESH::GetViewWindow(SMESHGUI::GetSMESHGUI())) {
1015 svtkViewWindow->activateInteractiveSelection();
1020 if ( myRWInteractor && myRWInteractor->GetDevice() && myInteractorStyle ) {
1021 int xClick, yClick; // Last click position
1022 myRWInteractor->GetDevice()->GetEventPosition(xClick, yClick);
1023 double nodeCoords[3];
1024 vtkInteractorObserver::ComputeWorldToDisplay(myRWInteractor->GetRenderer()->GetDevice(),
1025 myDlg->myDestinationX->GetValue(),
1026 myDlg->myDestinationY->GetValue(),
1027 myDlg->myDestinationZ->GetValue(),
1029 double rad = std::sqrt(std::pow(xClick - nodeCoords[0], 2) + std::pow(yClick - nodeCoords[1], 2));
1030 if (rad < SELECTION_PRECISION) {
1031 if (SVTK_ViewWindow* svtkViewWindow = SMESH::GetViewWindow(mySMESHGUI)) {
1032 svtkViewWindow->activateInteractiveSelection();