diff --git a/src/SMESHGUI/Makefile.am b/src/SMESHGUI/Makefile.am index 43ed76c57..7e7448f59 100644 --- a/src/SMESHGUI/Makefile.am +++ b/src/SMESHGUI/Makefile.am @@ -48,6 +48,7 @@ salomeinclude_HEADERS = \ SMESHGUI_RemoveNodesDlg.h \ SMESHGUI_RemoveElementsDlg.h \ SMESHGUI_MeshInfo.h \ + SMESHGUI_Measurements.h \ SMESHGUI_Preferences_ColorDlg.h \ SMESHGUI_Preferences_ScalarBarDlg.h \ SMESHGUI_AddMeshElementDlg.h \ @@ -110,6 +111,7 @@ dist_libSMESH_la_SOURCES = \ SMESHGUI_RemoveNodesDlg.cxx \ SMESHGUI_RemoveElementsDlg.cxx \ SMESHGUI_MeshInfo.cxx \ + SMESHGUI_Measurements.cxx \ SMESHGUI_Preferences_ColorDlg.cxx \ SMESHGUI_Preferences_ScalarBarDlg.cxx \ SMESHGUI_AddMeshElementDlg.cxx \ @@ -180,6 +182,7 @@ MOC_FILES = \ SMESHGUI_RemoveNodesDlg_moc.cxx \ SMESHGUI_RemoveElementsDlg_moc.cxx \ SMESHGUI_MeshInfo_moc.cxx \ + SMESHGUI_Measurements_moc.cxx \ SMESHGUI_Preferences_ColorDlg_moc.cxx \ SMESHGUI_Preferences_ScalarBarDlg_moc.cxx \ SMESHGUI_AddMeshElementDlg_moc.cxx \ diff --git a/src/SMESHGUI/SMESHGUI.cxx b/src/SMESHGUI/SMESHGUI.cxx index bcc33b748..9a83e9be2 100644 --- a/src/SMESHGUI/SMESHGUI.cxx +++ b/src/SMESHGUI/SMESHGUI.cxx @@ -49,6 +49,7 @@ #include "SMESHGUI_Make2DFrom3DOp.h" #include "SMESHGUI_MakeNodeAtPointDlg.h" //#include "SMESHGUI_MeshInfosDlg.h" +#include "SMESHGUI_Measurements.h" #include "SMESHGUI_MeshInfo.h" #include "SMESHGUI_MeshOp.h" #include "SMESHGUI_MeshOrderOp.h" @@ -2985,6 +2986,15 @@ bool SMESHGUI::OnGUIEvent( int theCommandID ) } break; } + case 501: + case 502: + { + int page = theCommandID == 501 ? SMESHGUI_MeasureDlg::MinDistance : SMESHGUI_MeasureDlg::BoundingBox; + EmitSignalDeactivateDialog(); + SMESHGUI_MeasureDlg* dlg = new SMESHGUI_MeasureDlg( SMESHGUI::desktop(), page ); + dlg->show(); + break; + } } anApp->updateActions(); //SRN: To update a Save button in the toolbar @@ -3238,6 +3248,9 @@ void SMESHGUI::initialize( CAM_Application* app ) createSMESHAction( 1137, "DISABLE_AUTO_COLOR" ); createSMESHAction( 2000, "CTRL" ); + createSMESHAction( 501, "MEASURE_MIN_DIST" ); + createSMESHAction( 502, "MEASURE_BND_BOX" ); + createSMESHAction( 300, "ERASE" ); createSMESHAction( 301, "DISPLAY" ); createSMESHAction( 302, "DISPLAY_ONLY" ); @@ -3251,13 +3264,14 @@ void SMESHGUI::initialize( CAM_Application* app ) createSMESHAction( 4040, "QUADRATIC_HEXAHEDRON", "ICON_DLG_QUADRATIC_HEXAHEDRON" ); // ----- create menu -------------- - int fileId = createMenu( tr( "MEN_FILE" ), -1, 1 ), - editId = createMenu( tr( "MEN_EDIT" ), -1, 3 ), - toolsId = createMenu( tr( "MEN_TOOLS" ), -1, 5, 50 ), - meshId = createMenu( tr( "MEN_MESH" ), -1, 70, 10 ), - ctrlId = createMenu( tr( "MEN_CTRL" ), -1, 60, 10 ), - modifyId = createMenu( tr( "MEN_MODIFY" ), -1, 40, 10 ), - viewId = createMenu( tr( "MEN_VIEW" ), -1, 2 ); + int fileId = createMenu( tr( "MEN_FILE" ), -1, 1 ), + editId = createMenu( tr( "MEN_EDIT" ), -1, 3 ), + toolsId = createMenu( tr( "MEN_TOOLS" ), -1, 5, 50 ), + meshId = createMenu( tr( "MEN_MESH" ), -1, 70, 10 ), + ctrlId = createMenu( tr( "MEN_CTRL" ), -1, 60, 10 ), + modifyId = createMenu( tr( "MEN_MODIFY" ), -1, 40, 10 ), + measureId = createMenu( tr( "MEN_MEASURE" ), -1, 50, 10 ), + viewId = createMenu( tr( "MEN_VIEW" ), -1, 2 ); createMenu( separator(), fileId ); @@ -3387,6 +3401,8 @@ void SMESHGUI::initialize( CAM_Application* app ) createMenu( 417, modifyId, -1 ); createMenu( 418, modifyId, -1 ); + createMenu( 501, measureId, -1 ); + createMenu( 502, measureId, -1 ); createMenu( 214, viewId, -1 ); // ----- create toolbars -------------- diff --git a/src/SMESHGUI/SMESHGUI_Measurements.cxx b/src/SMESHGUI/SMESHGUI_Measurements.cxx new file mode 100644 index 000000000..5aef4bf35 --- /dev/null +++ b/src/SMESHGUI/SMESHGUI_Measurements.cxx @@ -0,0 +1,938 @@ +// Copyright (C) 2007-2010 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// +// File : SMESHGUI_Measurements.cxx +// Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com) + +#include "SMESHGUI_Measurements.h" + +#include "SMESH_Actor.h" +#include "SMESHGUI.h" +#include "SMESHGUI_IdValidator.h" +#include "SMESHGUI_Utils.h" +#include "SMESHGUI_VTKUtils.h" +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include CORBA_SERVER_HEADER(SMESH_MeshEditor) +#include CORBA_SERVER_HEADER(SMESH_Measurements) + +const int SPACING = 6; // layout spacing +const int MARGIN = 9; // layout margin +const int MAX_NB_FOR_EDITOR = 40; // max nb of items in the ID list editor field + +// Uncomment as soon as elements are supported by Min Distance operation +//#define MINDIST_ENABLE_ELEMENT + +// Uncomment as soon as objects are supported by Min Distance operation +//#define MINDIST_ENABLE_OBJECT + +/*! + \class SMESHGUI_MinDistance + \brief Minimum distance measurement widget. + + Widget to calculate minimum distance between two objects. +*/ + +/*! + \brief Constructor. + \param parent parent widget +*/ +SMESHGUI_MinDistance::SMESHGUI_MinDistance( QWidget* parent ) +: QWidget( parent ), myCurrentTgt( FirstTgt ), myFirstActor( 0 ), mySecondActor( 0 ) +{ + QGroupBox* aFirstTgtGrp = new QGroupBox( tr( "FIRST_TARGET" ), this ); + QRadioButton* aFNode = new QRadioButton( tr( "NODE" ), aFirstTgtGrp ); + QRadioButton* aFElem = new QRadioButton( tr( "ELEMENT" ), aFirstTgtGrp ); + QRadioButton* aFObject = new QRadioButton( tr( "OBJECT" ), aFirstTgtGrp ); + myFirstTgt = new QLineEdit( aFirstTgtGrp ); + + QGridLayout* fl = new QGridLayout( aFirstTgtGrp ); + fl->setMargin( MARGIN ); + fl->setSpacing( SPACING ); + fl->addWidget( aFNode, 0, 0 ); + fl->addWidget( aFElem, 0, 1 ); + fl->addWidget( aFObject, 0, 2 ); + fl->addWidget( myFirstTgt, 1, 0, 1, 3 ); + + myFirst = new QButtonGroup( this ); + myFirst->addButton( aFNode, NodeTgt ); + myFirst->addButton( aFElem, ElementTgt ); + myFirst->addButton( aFObject, ObjectTgt ); + + QGroupBox* aSecondTgtGrp = new QGroupBox( tr( "SECOND_TARGET" ), this ); + QRadioButton* aSOrigin = new QRadioButton( tr( "ORIGIN" ), aSecondTgtGrp ); + QRadioButton* aSNode = new QRadioButton( tr( "NODE" ), aSecondTgtGrp ); + QRadioButton* aSElem = new QRadioButton( tr( "ELEMENT" ), aSecondTgtGrp ); + QRadioButton* aSObject = new QRadioButton( tr( "OBJECT" ), aSecondTgtGrp ); + mySecondTgt = new QLineEdit( aSecondTgtGrp ); + + QGridLayout* sl = new QGridLayout( aSecondTgtGrp ); + sl->setMargin( MARGIN ); + sl->setSpacing( SPACING ); + sl->addWidget( aSOrigin, 0, 0 ); + sl->addWidget( aSNode, 0, 1 ); + sl->addWidget( aSElem, 0, 2 ); + sl->addWidget( aSObject, 0, 3 ); + sl->addWidget( mySecondTgt, 1, 0, 1, 4 ); + + mySecond = new QButtonGroup( this ); + mySecond->addButton( aSOrigin, OriginTgt ); + mySecond->addButton( aSNode, NodeTgt ); + mySecond->addButton( aSElem, ElementTgt ); + mySecond->addButton( aSObject, ObjectTgt ); + + QPushButton* aCompute = new QPushButton( tr( "COMPUTE" ), this ); + + QGroupBox* aResults = new QGroupBox( tr( "RESULT" ), this ); + QLabel* aDxLab = new QLabel( "dX", aResults ); + myDX = new QLineEdit( aResults ); + QLabel* aDyLab = new QLabel( "dY", aResults ); + myDY = new QLineEdit( aResults ); + QLabel* aDzLab = new QLabel( "dZ", aResults ); + myDZ = new QLineEdit( aResults ); + QLabel* aDistLab = new QLabel( tr( "DISTANCE" ), aResults ); + myDistance = new QLineEdit( aResults ); + + QGridLayout* rl = new QGridLayout( aResults ); + rl->setMargin( MARGIN ); + rl->setSpacing( SPACING ); + rl->addWidget( aDxLab, 0, 0 ); + rl->addWidget( myDX, 0, 1 ); + rl->addWidget( aDyLab, 1, 0 ); + rl->addWidget( myDY, 1, 1 ); + rl->addWidget( aDzLab, 2, 0 ); + rl->addWidget( myDZ, 2, 1 ); + rl->addWidget( aDistLab, 0, 2 ); + rl->addWidget( myDistance, 0, 3 ); + + QGridLayout* l = new QGridLayout( this ); + l->setMargin( MARGIN ); + l->setSpacing( SPACING ); + + l->addWidget( aFirstTgtGrp, 0, 0, 1, 2 ); + l->addWidget( aSecondTgtGrp, 1, 0, 1, 2 ); + l->addWidget( aCompute, 2, 0 ); + l->addWidget( aResults, 3, 0, 1, 2 ); + l->setColumnStretch( 1, 5 ); + l->setRowStretch( 4, 5 ); + + aFNode->setChecked( true ); + aSOrigin->setChecked( true ); +#ifndef MINDIST_ENABLE_ELEMENT + aFElem->setEnabled( false ); // NOT AVAILABLE YET + aSElem->setEnabled( false ); // NOT AVAILABLE YET +#endif +#ifndef MINDIST_ENABLE_OBJECT + aFObject->setEnabled( false ); // NOT AVAILABLE YET + aSObject->setEnabled( false ); // NOT AVAILABLE YET +#endif + myDX->setReadOnly( true ); + myDY->setReadOnly( true ); + myDZ->setReadOnly( true ); + myDistance->setReadOnly( true ); + + myValidator = new SMESHGUI_IdValidator( this, 1 ); + + myFirstTgt->installEventFilter( this ); + mySecondTgt->installEventFilter( this ); + + connect( myFirst, SIGNAL( buttonClicked( int ) ), this, SLOT( firstChanged() ) ); + connect( mySecond, SIGNAL( buttonClicked( int ) ), this, SLOT( secondChanged() ) ); + connect( aCompute, SIGNAL( clicked() ), this, SLOT( compute() ) ); + connect( myFirstTgt, SIGNAL( textEdited( QString ) ), this, SLOT( firstEdited() ) ); + connect( mySecondTgt, SIGNAL( textEdited( QString ) ), this, SLOT( secondEdited() ) ); + + QList filters; + filters.append( new SMESH_TypeFilter( MESHorSUBMESH ) ); + filters.append( new SMESH_TypeFilter( GROUP ) ); + myFilter = new SMESH_LogicalFilter( filters, SMESH_LogicalFilter::LO_OR ); + + clear(); + + //setTarget( FirstTgt ); +} + +/*! + \brief Destructor +*/ +SMESHGUI_MinDistance::~SMESHGUI_MinDistance() +{ +} + +/*! + \brief Event filter + \param o object + \param o event + \return \c true if event is filtered or \c false otherwise +*/ +bool SMESHGUI_MinDistance::eventFilter( QObject* o, QEvent* e ) +{ + if ( e->type() == QEvent::FocusIn ) { + if ( o == myFirstTgt ) + setTarget( FirstTgt ); + else if ( o == mySecondTgt ) + setTarget( SecondTgt ); + } + return QWidget::eventFilter( o, e ); +} + +/*! + \brief Setup selection mode depending on the current widget state +*/ +void SMESHGUI_MinDistance::updateSelection() +{ + LightApp_SelectionMgr* selMgr = SMESHGUI::selectionMgr(); + + disconnect( selMgr, 0, this, 0 ); + selMgr->clearFilters(); + + bool nodeMode = ( myCurrentTgt == FirstTgt && myFirst->checkedId() == NodeTgt ) || + ( myCurrentTgt == SecondTgt && mySecond->checkedId() == NodeTgt ); + bool elemMode = ( myCurrentTgt == FirstTgt && myFirst->checkedId() == ElementTgt ) || + ( myCurrentTgt == SecondTgt && mySecond->checkedId() == ElementTgt ); + bool objMode = ( myCurrentTgt == FirstTgt && myFirst->checkedId() == ObjectTgt ) || + ( myCurrentTgt == SecondTgt && mySecond->checkedId() == ObjectTgt ) || + ( myCurrentTgt == NoTgt ); + + if ( nodeMode ) { + SMESH::SetPointRepresentation( true ); + if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow() ) + aViewWindow->SetSelectionMode( NodeSelection ); + } + else if ( elemMode ) { + SMESH::SetPointRepresentation( false ); + if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow() ) + aViewWindow->SetSelectionMode( CellSelection ); + } + else if ( objMode ) { + SMESH::SetPointRepresentation( false ); + if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow() ) + aViewWindow->SetSelectionMode( ActorSelection ); + selMgr->installFilter( myFilter ); + } + + connect( selMgr, SIGNAL( currentSelectionChanged() ), this, SLOT( selectionChanged() ) ); + + if ( myCurrentTgt == FirstTgt ) + firstEdited(); + else if ( myCurrentTgt == SecondTgt ) + secondEdited(); + + //selectionChanged(); +} + +/*! + \brief Deactivate widget +*/ +void SMESHGUI_MinDistance::deactivate() +{ + disconnect( SMESHGUI::selectionMgr(), 0, this, 0 ); +} + +/*! + \brief Set current target for selection + \param target new target ID +*/ +void SMESHGUI_MinDistance::setTarget( int target ) +{ + if ( myCurrentTgt != target ) { + myCurrentTgt = target; + updateSelection(); + } +} + +/*! + \brief Called when selection is changed +*/ +void SMESHGUI_MinDistance::selectionChanged() +{ + SUIT_OverrideCursor wc; + + SALOME_ListIO selected; + SMESHGUI::selectionMgr()->selectedObjects( selected ); + + if ( selected.Extent() == 1 ) { + Handle(SALOME_InteractiveObject) IO = selected.First(); + SMESH::SMESH_IDSource_var obj = SMESH::IObjectToInterface( IO ); + if ( !CORBA::is_nil( obj ) ) { + if ( myCurrentTgt == FirstTgt ) { + myFirstSrc = obj; + myFirstActor = SMESH::FindActorByEntry( IO->getEntry() ); + if ( myFirst->checkedId() == ObjectTgt ) { + QString aName; + SMESH::GetNameOfSelectedIObjects( SMESHGUI::selectionMgr(), aName ); + myFirstTgt->setText( aName ); + } + else { + SVTK_Selector* selector = SMESH::GetViewWindow()->GetSelector(); + QString ID; + int nb = 0; + if ( myFirstActor && selector ) { + nb = myFirst->checkedId() == NodeTgt ? + SMESH::GetNameOfSelectedElements( selector, IO, ID ) : + SMESH::GetNameOfSelectedNodes( selector, IO, ID ); + } + if ( nb == 1 ) + myFirstTgt->setText( ID.trimmed() ); + else + myFirstTgt->clear(); + } + } + else if ( myCurrentTgt == SecondTgt ) { + mySecondSrc = obj; + mySecondActor = SMESH::FindActorByEntry( IO->getEntry() ); + if ( mySecond->checkedId() == ObjectTgt ) { + QString aName; + SMESH::GetNameOfSelectedIObjects( SMESHGUI::selectionMgr(), aName ); + mySecondTgt->setText( aName ); + } + else { + SVTK_Selector* selector = SMESH::GetViewWindow()->GetSelector(); + QString ID; + int nb = 0; + if ( mySecondActor && selector ) { + nb = mySecond->checkedId() == NodeTgt ? + SMESH::GetNameOfSelectedElements( selector, IO, ID ) : + SMESH::GetNameOfSelectedNodes( selector, IO, ID ); + } + if ( nb == 1 ) + mySecondTgt->setText( ID.trimmed() ); + else + mySecondTgt->clear(); + } + } + } + } +} + +/*! + \brief Called when first target mode is changed by the user +*/ +void SMESHGUI_MinDistance::firstChanged() +{ + myFirstTgt->clear(); + myFirstTgt->setReadOnly( myFirst->checkedId() == ObjectTgt ); + myFirstTgt->setValidator( myFirst->checkedId() == ObjectTgt ? 0 : myValidator ); + setTarget( FirstTgt ); + updateSelection(); + clear(); +} + +/*! + \brief Called when second target mode is changed by the user +*/ +void SMESHGUI_MinDistance::secondChanged() +{ + mySecondTgt->setEnabled( mySecond->checkedId() != OriginTgt ); + mySecondTgt->setReadOnly( mySecond->checkedId() == ObjectTgt ); + mySecondTgt->setValidator( mySecond->checkedId() == ObjectTgt ? 0 : myValidator ); + mySecondTgt->clear(); + setTarget( mySecond->checkedId() != OriginTgt ? SecondTgt : NoTgt ); + updateSelection(); + clear(); +} + +/*! + \brief Called when first target is edited by the user +*/ +void SMESHGUI_MinDistance::firstEdited() +{ + setTarget( FirstTgt ); + clear(); + SVTK_Selector* selector = SMESH::GetViewWindow()->GetSelector(); + if ( myFirstActor && selector ) { + Handle(SALOME_InteractiveObject) IO = myFirstActor->getIO(); + if ( myFirst->checkedId() == NodeTgt || myFirst->checkedId() == ElementTgt ) { + TColStd_MapOfInteger ID; + ID.Add( myFirstTgt->text().toLong() ); + selector->AddOrRemoveIndex( IO, ID, false ); + } + if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow() ) + aViewWindow->highlight( IO, true, true ); + } +} + +/*! + \brief Called when second target is edited by the user +*/ +void SMESHGUI_MinDistance::secondEdited() +{ + setTarget( SecondTgt ); + clear(); + SVTK_Selector* selector = SMESH::GetViewWindow()->GetSelector(); + if ( mySecondActor && selector ) { + Handle(SALOME_InteractiveObject) IO = mySecondActor->getIO(); + if ( mySecond->checkedId() == NodeTgt || mySecond->checkedId() == ElementTgt ) { + TColStd_MapOfInteger ID; + ID.Add( mySecondTgt->text().toLong() ); + selector->AddOrRemoveIndex( IO, ID, false ); + } + if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow() ) + aViewWindow->highlight( IO, true, true ); + } +} + +/*! + \brief Compute the minimum distance between targets +*/ +void SMESHGUI_MinDistance::compute() +{ + SUIT_OverrideCursor wc; + SMESH::SMESH_IDSource_var s1; + SMESH::SMESH_IDSource_var s2; + bool isOrigin = mySecond->checkedId() == OriginTgt; + + // process first target + if ( !CORBA::is_nil( myFirstSrc ) ) { + if ( myFirst->checkedId() == NodeTgt || myFirst->checkedId() == ElementTgt ) { + SMESH::SMESH_Mesh_var m = myFirstSrc->GetMesh(); + long id = myFirstTgt->text().toLong(); + if ( !CORBA::is_nil( m ) && id ) { + SMESH::long_array_var ids = new SMESH::long_array(); + ids->length( 1 ); + ids[0] = id; + SMESH::SMESH_MeshEditor_var me = m->GetMeshEditor(); + s1 = me->MakeIDSource( ids.in(), myFirst->checkedId() == NodeTgt ? SMESH::NODE : SMESH::FACE ); + } + } + else { + s1 = myFirstSrc; + } + } + + // process second target + if ( !CORBA::is_nil( mySecondSrc ) ) { + if ( mySecond->checkedId() == NodeTgt || mySecond->checkedId() == ElementTgt ) { + SMESH::SMESH_Mesh_var m = mySecondSrc->GetMesh(); + long id = mySecondTgt->text().toLong(); + if ( !CORBA::is_nil( m ) && id ) { + SMESH::long_array_var ids = new SMESH::long_array(); + ids->length( 1 ); + ids[0] = id; + SMESH::SMESH_MeshEditor_var me = m->GetMeshEditor(); + s2 = me->MakeIDSource( ids.in(), mySecond->checkedId() == NodeTgt ? SMESH::NODE : SMESH::FACE ); + } + } + else { + s2 = mySecondSrc; + } + } + + if ( !CORBA::is_nil( s1 ) && ( !CORBA::is_nil( s2 ) || isOrigin ) ) { + int precision = SMESHGUI::resourceMgr()->integerValue( "SMESH", "length_precision", 6 ); + SMESH::Measurements_var measure = SMESHGUI::GetSMESHGen()->CreateMeasurements(); + SMESH::Measure result = measure->MinDistance( s1.in(), s2.in() ); + measure->Destroy(); + myDX->setText( QString::number( result.minX, precision > 0 ? 'f' : 'g', qAbs( precision ) ) ); + myDY->setText( QString::number( result.minY, precision > 0 ? 'f' : 'g', qAbs( precision ) ) ); + myDZ->setText( QString::number( result.minZ, precision > 0 ? 'f' : 'g', qAbs( precision ) ) ); + myDistance->setText( QString::number( result.value, precision > 0 ? 'f' : 'g', qAbs( precision ) ) ); + } + else { + clear(); + } +} + +/*! + \brief Reset the widget to the initial state (nullify result fields) +*/ +void SMESHGUI_MinDistance::clear() +{ + myDX->clear(); + myDY->clear(); + myDZ->clear(); + myDistance->clear(); +} + +/*! + \class SMESHGUI_BoundingBox + \brief Bounding box measurement widget. + + Widget to calculate bounding box of the selected object(s). +*/ + +/*! + \brief Constructor. + \param parent parent widget +*/ +SMESHGUI_BoundingBox::SMESHGUI_BoundingBox( QWidget* parent ) +: QWidget( parent ), myActor( 0 ) +{ + QGroupBox* aSourceGrp = new QGroupBox( tr( "SOURCE" ), this ); + QRadioButton* aObjects = new QRadioButton( tr( "OBJECTS" ), aSourceGrp ); + QRadioButton* aNodes = new QRadioButton( tr( "NODES" ), aSourceGrp ); + QRadioButton* aElements = new QRadioButton( tr( "ELEMENTS" ), aSourceGrp ); + mySource = new QLineEdit( aSourceGrp ); + + QGridLayout* fl = new QGridLayout( aSourceGrp ); + fl->setMargin( MARGIN ); + fl->setSpacing( SPACING ); + fl->addWidget( aObjects, 0, 0 ); + fl->addWidget( aNodes, 0, 1 ); + fl->addWidget( aElements, 0, 2 ); + fl->addWidget( mySource, 1, 0, 1, 3 ); + + mySourceMode = new QButtonGroup( this ); + mySourceMode->addButton( aObjects, ObjectsSrc ); + mySourceMode->addButton( aNodes, NodesSrc ); + mySourceMode->addButton( aElements, ElementsSrc ); + + QPushButton* aCompute = new QPushButton( tr( "COMPUTE" ), this ); + + QGroupBox* aResults = new QGroupBox( tr( "RESULT" ), this ); + QLabel* aXminLab = new QLabel( "Xmin", aResults ); + myXmin = new QLineEdit( aResults ); + QLabel* aXmaxLab = new QLabel( "Xmax", aResults ); + myXmax = new QLineEdit( aResults ); + QLabel* aDxLab = new QLabel( "dX", aResults ); + myDX = new QLineEdit( aResults ); + QLabel* aYminLab = new QLabel( "Ymin", aResults ); + myYmin = new QLineEdit( aResults ); + QLabel* aYmaxLab = new QLabel( "Ymax", aResults ); + myYmax = new QLineEdit( aResults ); + QLabel* aDyLab = new QLabel( "dY", aResults ); + myDY = new QLineEdit( aResults ); + QLabel* aZminLab = new QLabel( "Zmin", aResults ); + myZmin = new QLineEdit( aResults ); + QLabel* aZmaxLab = new QLabel( "Zmax", aResults ); + myZmax = new QLineEdit( aResults ); + QLabel* aDzLab = new QLabel( "dZ", aResults ); + myDZ = new QLineEdit( aResults ); + + QGridLayout* rl = new QGridLayout( aResults ); + rl->setMargin( MARGIN ); + rl->setSpacing( SPACING ); + rl->addWidget( aXminLab, 0, 0 ); + rl->addWidget( myXmin, 0, 1 ); + rl->addWidget( aXmaxLab, 0, 2 ); + rl->addWidget( myXmax, 0, 3 ); + rl->addWidget( aDxLab, 0, 4 ); + rl->addWidget( myDX, 0, 5 ); + rl->addWidget( aYminLab, 1, 0 ); + rl->addWidget( myYmin, 1, 1 ); + rl->addWidget( aYmaxLab, 1, 2 ); + rl->addWidget( myYmax, 1, 3 ); + rl->addWidget( aDyLab, 1, 4 ); + rl->addWidget( myDY, 1, 5 ); + rl->addWidget( aZminLab, 2, 0 ); + rl->addWidget( myZmin, 2, 1 ); + rl->addWidget( aZmaxLab, 2, 2 ); + rl->addWidget( myZmax, 2, 3 ); + rl->addWidget( aDzLab, 2, 4 ); + rl->addWidget( myDZ, 2, 5 ); + + QGridLayout* l = new QGridLayout( this ); + l->setMargin( MARGIN ); + l->setSpacing( SPACING ); + + l->addWidget( aSourceGrp, 0, 0, 1, 2 ); + l->addWidget( aCompute, 1, 0 ); + l->addWidget( aResults, 2, 0, 1, 2 ); + l->setColumnStretch( 1, 5 ); + l->setRowStretch( 3, 5 ); + + aObjects->setChecked( true ); + myXmin->setReadOnly( true ); + myXmax->setReadOnly( true ); + myDX->setReadOnly( true ); + myYmin->setReadOnly( true ); + myYmax->setReadOnly( true ); + myDY->setReadOnly( true ); + myZmin->setReadOnly( true ); + myZmax->setReadOnly( true ); + myDZ->setReadOnly( true ); + + myValidator = new SMESHGUI_IdValidator( this ); + + connect( mySourceMode, SIGNAL( buttonClicked( int ) ), this, SLOT( sourceChanged() ) ); + connect( aCompute, SIGNAL( clicked() ), this, SLOT( compute() ) ); + connect( mySource, SIGNAL( textEdited( QString ) ), this, SLOT( sourceEdited() ) ); + + QList filters; + filters.append( new SMESH_TypeFilter( MESHorSUBMESH ) ); + filters.append( new SMESH_TypeFilter( GROUP ) ); + myFilter = new SMESH_LogicalFilter( filters, SMESH_LogicalFilter::LO_OR ); + + clear(); +} + +/*! + \brief Destructor +*/ +SMESHGUI_BoundingBox::~SMESHGUI_BoundingBox() +{ +} + +/*! + \brief Setup selection mode depending on the current widget state +*/ +void SMESHGUI_BoundingBox::updateSelection() +{ + LightApp_SelectionMgr* selMgr = SMESHGUI::selectionMgr(); + + disconnect( selMgr, 0, this, 0 ); + selMgr->clearFilters(); + + bool nodeMode = mySourceMode->checkedId() == NodesSrc; + bool elemMode = mySourceMode->checkedId() == ElementsSrc; + bool objMode = mySourceMode->checkedId() == ObjectsSrc; + + if ( nodeMode ) { + SMESH::SetPointRepresentation( true ); + if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow() ) + aViewWindow->SetSelectionMode( NodeSelection ); + } + else if ( elemMode ) { + SMESH::SetPointRepresentation( false ); + if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow() ) + aViewWindow->SetSelectionMode( CellSelection ); + } + else if ( objMode ) { + SMESH::SetPointRepresentation( false ); + if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow() ) + aViewWindow->SetSelectionMode( ActorSelection ); + selMgr->installFilter( myFilter ); + } + + connect( selMgr, SIGNAL( currentSelectionChanged() ), this, SLOT( selectionChanged() ) ); + + sourceEdited(); + + //selectionChanged(); +} + +/*! + \brief Deactivate widget +*/ +void SMESHGUI_BoundingBox::deactivate() +{ + disconnect( SMESHGUI::selectionMgr(), 0, this, 0 ); +} + +/*! + \brief Called when selection is changed +*/ +void SMESHGUI_BoundingBox::selectionChanged() +{ + SUIT_OverrideCursor wc; + + SALOME_ListIO selected; + SMESHGUI::selectionMgr()->selectedObjects( selected ); + + if ( selected.Extent() == 1 ) { + Handle(SALOME_InteractiveObject) IO = selected.First(); + SMESH::SMESH_IDSource_var obj = SMESH::IObjectToInterface( IO ); + if ( !CORBA::is_nil( obj ) ) { + mySrc.clear(); + mySrc.append( obj ); + myActor = SMESH::FindActorByEntry( IO->getEntry() ); + if ( mySourceMode->checkedId() == ObjectsSrc ) { + QString aName; + SMESH::GetNameOfSelectedIObjects( SMESHGUI::selectionMgr(), aName ); + mySource->setText( aName ); + } + else { + SVTK_Selector* selector = SMESH::GetViewWindow()->GetSelector(); + QString ID; + int nb = 0; + if ( myActor && selector ) { + nb = mySourceMode->checkedId() == NodesSrc ? + SMESH::GetNameOfSelectedElements( selector, IO, ID ) : + SMESH::GetNameOfSelectedNodes( selector, IO, ID ); + } + if ( nb > 0 ) { + myIDs = ID.trimmed(); + if ( nb < MAX_NB_FOR_EDITOR ) { + mySource->setReadOnly( false ); + if ( mySource->validator() != myValidator ) + mySource->setValidator( myValidator ); + mySource->setText( ID.trimmed() ); + } + else { + mySource->setReadOnly( true ); + mySource->setValidator( 0 ); + mySource->setText( tr( "SELECTED_NB_OBJ" ).arg( nb ) + .arg( mySourceMode->checkedId() == NodesSrc ? tr( "NB_NODES" ) : tr( "NB_ELEMENTS") ) ); + } + } + else { + myIDs = ""; + mySource->clear(); + mySource->setReadOnly( false ); + mySource->setValidator( myValidator ); + } + } + } + } + else if ( selected.Extent() > 1 ) { + myIDs = ""; + SALOME_ListIteratorOfListIO It( selected ); + mySrc.clear(); + myActor = 0; + if ( mySourceMode->checkedId() == ObjectsSrc ) { + for( ; It.More(); It.Next()){ + Handle(SALOME_InteractiveObject) IO = It.Value(); + SMESH::SMESH_IDSource_var obj = SMESH::IObjectToInterface( IO ); + if ( !CORBA::is_nil( obj ) ) { + mySrc.append( obj ); + } + } + QString aName; + SMESH::GetNameOfSelectedIObjects( SMESHGUI::selectionMgr(), aName ); + mySource->setText( aName ); + } + else { + mySource->clear(); + } + } +} + +/*! + \brief Called when source mode is changed by the user +*/ +void SMESHGUI_BoundingBox::sourceChanged() +{ + myIDs = ""; + mySource->clear(); + mySource->setReadOnly( mySourceMode->checkedId() == ObjectsSrc ); + mySource->setValidator( mySourceMode->checkedId() == ObjectsSrc ? 0 : myValidator ); + updateSelection(); + clear(); +} + +/*! + \brief Called when source mode is edited by the user +*/ +void SMESHGUI_BoundingBox::sourceEdited() +{ + clear(); + SVTK_Selector* selector = SMESH::GetViewWindow()->GetSelector(); + if ( myActor && selector ) { + Handle(SALOME_InteractiveObject) IO = myActor->getIO(); + if ( mySourceMode->checkedId() == NodesSrc || mySourceMode->checkedId() == ElementsSrc ) { + TColStd_MapOfInteger ID; + if ( !mySource->isReadOnly() ) + myIDs = mySource->text(); + QStringList ids = mySource->text().split( " ", QString::SkipEmptyParts ); + foreach ( QString id, ids ) + ID.Add( id.trimmed().toLong() ); + selector->AddOrRemoveIndex( IO, ID, false ); + } + if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow() ) + aViewWindow->highlight( IO, true, true ); + } +} + +/*! + \brief Calculate bounding box of the selected object(s) +*/ +void SMESHGUI_BoundingBox::compute() +{ + SUIT_OverrideCursor wc; + if ( mySourceMode->checkedId() == NodesSrc ) { + } + else { + } +} + +/*! + \brief Reset the widget to the initial state (nullify result fields) +*/ +void SMESHGUI_BoundingBox::clear() +{ + myXmin->clear(); + myXmax->clear(); + myDX->clear(); + myYmin->clear(); + myYmax->clear(); + myDY->clear(); + myZmin->clear(); + myZmax->clear(); + myDZ->clear(); +} + +/*! + \class SMESHGUI_MeshInfoDlg + \brief Centralized dialog box for the measurements +*/ + +/*! + \brief Constructor + \param parent parent widget + \param page specifies the dialog page to be shown at the start-up +*/ +SMESHGUI_MeasureDlg::SMESHGUI_MeasureDlg( QWidget* parent, int page ) +: QDialog( parent ) +{ + setModal( false ); + setAttribute( Qt::WA_DeleteOnClose, true ); + setWindowTitle( tr( "MEASUREMENTS" ) ); + setSizeGripEnabled( true ); + + myTabWidget = new QTabWidget( this ); + + // min distance + + myMinDist = new SMESHGUI_MinDistance( myTabWidget ); + myTabWidget->addTab( myMinDist, tr( "MIN_DIST" ) ); + + // bounding box + + myBndBox = new SMESHGUI_BoundingBox( myTabWidget ); + myTabWidget->addTab( myBndBox, tr( "BND_BOX" ) ); + + // buttons + QPushButton* okBtn = new QPushButton( tr( "SMESH_BUT_OK" ), this ); + okBtn->setAutoDefault( true ); + okBtn->setDefault( true ); + okBtn->setFocus(); + QPushButton* helpBtn = new QPushButton( tr( "SMESH_BUT_HELP" ), this ); + helpBtn->setAutoDefault( true ); + + QHBoxLayout* btnLayout = new QHBoxLayout; + btnLayout->setSpacing( SPACING ); + btnLayout->setMargin( 0 ); + btnLayout->addWidget( okBtn ); + btnLayout->addStretch( 10 ); + btnLayout->addWidget( helpBtn ); + + QVBoxLayout* l = new QVBoxLayout ( this ); + l->setMargin( MARGIN ); + l->setSpacing( SPACING ); + l->addWidget( myTabWidget ); + l->addStretch(); + l->addLayout( btnLayout ); + + myTabWidget->setCurrentIndex( qMax( (int)MinDistance, qMin( (int)BoundingBox, page ) ) ); + + connect( okBtn, SIGNAL( clicked() ), this, SLOT( reject() ) ); + connect( helpBtn, SIGNAL( clicked() ), this, SLOT( help() ) ); + connect( myTabWidget, SIGNAL( currentChanged( int ) ), this, SLOT( updateSelection() ) ); + connect( SMESHGUI::GetSMESHGUI(), SIGNAL( SignalDeactivateActiveDialog() ), this, SLOT( deactivate() ) ); + connect( SMESHGUI::GetSMESHGUI(), SIGNAL( SignalCloseAllDialogs() ), this, SLOT( reject() ) ); + + updateSelection(); +} + +/*! + \brief Destructor +*/ +SMESHGUI_MeasureDlg::~SMESHGUI_MeasureDlg() +{ +} + +/*! + \brief Perform clean-up actions on the dialog box closing. +*/ +void SMESHGUI_MeasureDlg::reject() +{ + LightApp_SelectionMgr* selMgr = SMESHGUI::selectionMgr(); + selMgr->clearFilters(); + SMESH::SetPointRepresentation( false ); + if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow() ) + aViewWindow->SetSelectionMode( ActorSelection ); + QDialog::reject(); +} + +/*! + \brief Process keyboard event + \param e key press event +*/ +void SMESHGUI_MeasureDlg::keyPressEvent( QKeyEvent* e ) +{ + QDialog::keyPressEvent( e ); + if ( !e->isAccepted() && e->key() == Qt::Key_F1 ) { + e->accept(); + help(); + } +} + +/*! + \brief Reactivate dialog box, when mouse pointer goes into it. +*/ +void SMESHGUI_MeasureDlg::enterEvent( QEvent* ) +{ + activate(); +} + +/*! + \brief Setup selection mode depending on the current dialog box state. +*/ +void SMESHGUI_MeasureDlg::updateSelection() +{ + if ( myTabWidget->currentIndex() == MinDistance ) + myMinDist->updateSelection(); + else if ( myTabWidget->currentIndex() == BoundingBox ) + myBndBox->updateSelection(); + +} + +/*! + \brief Show help page +*/ +void SMESHGUI_MeasureDlg::help() +{ + SMESH::ShowHelpFile( myTabWidget->currentIndex() == MinDistance ? + "measurements_page.html#min_distance_anchor" : + "measurements_page.html#bounding_box_anchor" ); +} + +/*! + \brief Activate dialog box +*/ +void SMESHGUI_MeasureDlg::activate() +{ + SMESHGUI::GetSMESHGUI()->EmitSignalDeactivateDialog(); + SMESHGUI::GetSMESHGUI()->SetActiveDialogBox( this ); + myTabWidget->setEnabled( true ); + updateSelection(); +} + +/*! + \brief Deactivate dialog box +*/ +void SMESHGUI_MeasureDlg::deactivate() +{ + myMinDist->deactivate(); + myBndBox->deactivate(); + myTabWidget->setEnabled( false ); + disconnect( SMESHGUI::selectionMgr(), SIGNAL( currentSelectionChanged() ), this, SLOT( updateInfo() ) ); +} diff --git a/src/SMESHGUI/SMESHGUI_Measurements.h b/src/SMESHGUI/SMESHGUI_Measurements.h new file mode 100644 index 000000000..ae3d31270 --- /dev/null +++ b/src/SMESHGUI/SMESHGUI_Measurements.h @@ -0,0 +1,161 @@ +// Copyright (C) 2007-2010 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// +// File : SMESHGUI_Measurements.h +// Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com) + +#ifndef SMESHGUI_MEASUREMENTS_H +#define SMESHGUI_MEASUREMENTS_H + +#include "SMESH_SMESHGUI.hxx" + +#include + +class QButtonGroup; +class QLineEdit; +class QTabWidget; +class SUIT_SelectionFilter; +class SMESH_Actor; +class SMESHGUI_IdValidator; + +#include +#include CORBA_SERVER_HEADER(SMESH_Mesh) + +class SMESHGUI_EXPORT SMESHGUI_MinDistance : public QWidget +{ + Q_OBJECT; + + enum { NoTgt, FirstTgt, SecondTgt }; + enum { OriginTgt, NodeTgt, ElementTgt, ObjectTgt }; + +public: + SMESHGUI_MinDistance( QWidget* = 0 ); + ~SMESHGUI_MinDistance(); + + bool eventFilter( QObject*, QEvent* ); + void updateSelection(); + void deactivate(); + +private: + void setTarget( int ); + +private slots: + void selectionChanged(); + void firstChanged(); + void secondChanged(); + void firstEdited(); + void secondEdited(); + void compute(); + void clear(); + +private: + QButtonGroup* myFirst; + QButtonGroup* mySecond; + QLineEdit* myFirstTgt; + QLineEdit* mySecondTgt; + QLineEdit* myDX; + QLineEdit* myDY; + QLineEdit* myDZ; + QLineEdit* myDistance; + int myCurrentTgt; + SMESH::SMESH_IDSource_var myFirstSrc; + SMESH::SMESH_IDSource_var mySecondSrc; + SMESH_Actor* myFirstActor; + SMESH_Actor* mySecondActor; + SMESHGUI_IdValidator* myValidator; + SUIT_SelectionFilter* myFilter; +}; + +class SMESHGUI_EXPORT SMESHGUI_BoundingBox : public QWidget +{ + Q_OBJECT; + + enum { ObjectsSrc, NodesSrc, ElementsSrc }; + +public: + SMESHGUI_BoundingBox( QWidget* = 0 ); + ~SMESHGUI_BoundingBox(); + + void updateSelection(); + void deactivate(); + +private slots: + void selectionChanged(); + void sourceChanged(); + void sourceEdited(); + void compute(); + void clear(); + +private: + typedef QList SourceList; + QButtonGroup* mySourceMode; + QLineEdit* mySource; + QLineEdit* myXmin; + QLineEdit* myXmax; + QLineEdit* myDX; + QLineEdit* myYmin; + QLineEdit* myYmax; + QLineEdit* myDY; + QLineEdit* myZmin; + QLineEdit* myZmax; + QLineEdit* myDZ; + SourceList mySrc; + SMESH_Actor* myActor; + SMESHGUI_IdValidator* myValidator; + QString myIDs; + SUIT_SelectionFilter* myFilter; +}; + +class SMESHGUI_EXPORT SMESHGUI_MeasureDlg : public QDialog +{ + Q_OBJECT; + + enum { NodeMode, ElemMode }; + +public: + //! Measurement type + enum { + MinDistance, //!< minimum distance + BoundingBox //!< bounding box + }; + + SMESHGUI_MeasureDlg( QWidget* = 0, int = MinDistance ); + ~SMESHGUI_MeasureDlg(); + + void reject(); + +protected: + void keyPressEvent( QKeyEvent* ); + void enterEvent( QEvent* ); + +private slots: + void help(); + void updateSelection(); + void activate(); + void deactivate(); + +private: + QTabWidget* myTabWidget; + SMESHGUI_MinDistance* myMinDist; + SMESHGUI_BoundingBox* myBndBox; +}; + +#endif // SMESHGUI_MEASUREMENTS_H diff --git a/src/SMESHGUI/SMESH_msg_en.ts b/src/SMESHGUI/SMESH_msg_en.ts index 6f5139439..c5183a84e 100644 --- a/src/SMESHGUI/SMESH_msg_en.ts +++ b/src/SMESHGUI/SMESH_msg_en.ts @@ -487,6 +487,34 @@ MEN_MODIFY Modification + + MEN_MEASURE + Measurements + + + MEN_MEASURE_MIN_DIST + Minimum Distance + + + STB_MEASURE_MIN_DIST + Calculate minimum distance between two objects + + + TOP_MEASURE_MIN_DIST + Minimum distance + + + MEN_MEASURE_BND_BOX + Bounding Box + + + STB_MEASURE_BND_BOX + Calculate bounding box for the selected object(s) + + + TOP_MEASURE_BND_BOX + Bounding box + MEN_MOVE Move Node @@ -5645,4 +5673,97 @@ It is impossible to read point coordinates from file Value + + SMESHGUI_MinDistance + + FIRST_TARGET + First target + + + SECOND_TARGET + Second target + + + NODE + Node + + + ELEMENT + Element + + + OBJECT + Object + + + ORIGIN + Origin + + + COMPUTE + Compute + + + RESULT + Distance between targets + + + DISTANCE + Distance + + + + SMESHGUI_MeasureDlg + + MEASUREMENTS + Measurements + + + MIN_DIST + Minimum Distance + + + BND_BOX + Bounding Box + + + + SMESHGUI_BoundingBox + + SOURCE + Source + + + OBJECTS + Objects + + + NODES + Nodes + + + ELEMENTS + Elements + + + COMPUTE + Compute + + + RESULT + Bounding Box + + + SELECTED_NB_OBJ + %1 %2 selected + + + NB_NODES + nodes + + + NB_ELEMENTS + elements + + diff --git a/src/SMESH_I/SMESH_Measurements_i.cxx b/src/SMESH_I/SMESH_Measurements_i.cxx index fa52f66e6..87946a1da 100644 --- a/src/SMESH_I/SMESH_Measurements_i.cxx +++ b/src/SMESH_I/SMESH_Measurements_i.cxx @@ -95,18 +95,27 @@ Measurements_i::~Measurements_i() //TPythonDump()<X(); dd -= theNode2->X(); dd *= dd; dist += dd; - dd = theNode1->Y(); dd -= theNode2->Y(); dd *= dd; dist += dd; - dd = theNode1->Z(); dd -= theNode2->Z(); dd *= dd; dist += dd; + + if (!theNode1) + return false; + + dd = theNode1->X(); if (theNode2) dd -= theNode2->X(); theMeasure.minX = dd; dd *= dd; dist += dd; + dd = theNode1->Y(); if (theNode2) dd -= theNode2->Y(); theMeasure.minY = dd; dd *= dd; dist += dd; + dd = theNode1->Z(); if (theNode2) dd -= theNode2->Z(); theMeasure.minZ = dd; dd *= dd; dist += dd; + if (dist < 0) - return 0; - return sqrt(dist); + return false; + + theMeasure.value = sqrt(dist); + theMeasure.node1 = theNode1->GetID(); + theMeasure.node2 = theNode2 ? theNode2->GetID() : 0; + + return true; } static SMESHDS_Mesh* getMesh(SMESH::SMESH_IDSource_ptr theSource) @@ -136,38 +145,39 @@ SMESH::Measure Measurements_i::MinDistance SMESH::Measure aMeasure; initMeasure(aMeasure); - if (CORBA::is_nil( theSource1 ) || CORBA::is_nil( theSource2 )) + if (CORBA::is_nil( theSource1 )) return aMeasure; + + // if second source is null, min distance from theSource1 to the origin is calculated + bool isOrigin = CORBA::is_nil( theSource2 ); // calculate minimal distance between two mesh entities SMESH::array_of_ElementType_var types1 = theSource1->GetTypes(); - SMESH::array_of_ElementType_var types2 = theSource2->GetTypes(); + SMESH::array_of_ElementType_var types2; + if ( !isOrigin ) types2 = theSource2->GetTypes(); + // here we assume that type of all IDs defined by first type in array - const bool isNode1 = isNodeType(types1); - const bool isNode2 = isNodeType(types2); + bool isNode1 = isNodeType(types1); + bool isNode2 = isOrigin || isNodeType(types2); SMESH::long_array_var aElementsId1 = theSource1->GetIDs(); - SMESH::long_array_var aElementsId2 = theSource2->GetIDs(); + SMESH::long_array_var aElementsId2; + if ( !isOrigin ) aElementsId2 = theSource2->GetIDs(); // compute distance between two entities - /** NOTE: currently only node-node case implemented - * all other cases could be implemented later - * this IF should be replaced by comples swtich + /* NOTE: currently only node-to-node case is implemented + * all other cases will be implemented later + * below IF should be replaced by complete switch * on mesh entities types */ if (isNode1 && isNode2) { // node - node const SMESHDS_Mesh* aMesh1 = getMesh( theSource1 ); - const SMESHDS_Mesh* aMesh2 = getMesh( theSource2 ); + const SMESHDS_Mesh* aMesh2 = isOrigin ? 0 : getMesh( theSource2 ); const SMDS_MeshNode* theNode1 = aMesh1 ? aMesh1->FindNode( aElementsId1[0] ) : 0; const SMDS_MeshNode* theNode2 = aMesh2 ? aMesh2->FindNode( aElementsId2[0] ) : 0; - aMeasure.value = getNodeNodeDistance( theNode1, theNode2 ); - if (theNode1 && theNode2) - { - aMeasure.node1 = theNode1->GetID(); - aMeasure.node2 = theNode2->GetID(); - } + getNodeNodeDistance( aMeasure, theNode1, theNode2 ); } else { @@ -216,7 +226,7 @@ static void enlargeBoundingBox(const SMESH::SMESH_IDSource_ptr theObject, enlargeBoundingBox( aMesh->FindNode( aElementsId[i] ), theMeasure); else { - const SMDS_MeshElement * elem = aMesh->FindElement( aElementsId[i] ); + const SMDS_MeshElement* elem = aMesh->FindElement( aElementsId[i] ); if (!elem) continue; SMDS_ElemIteratorPtr aNodeIter = elem->nodesIterator();