mirror of
https://git.salome-platform.org/gitpub/modules/smesh.git
synced 2024-12-27 09:50:34 +05:00
1872 lines
58 KiB
C++
1872 lines
58 KiB
C++
// Copyright (C) 2007-2019 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, or (at your option) any later version.
|
|
//
|
|
// 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_MeshEditPreview.h"
|
|
#include "SMESHGUI_VTKUtils.h"
|
|
#include <SMESH_TypeFilter.hxx>
|
|
#include <SMESH_MeshAlgos.hxx>
|
|
#include <SMESH_LogicalFilter.hxx>
|
|
#include <SMDS_Mesh.hxx>
|
|
#include <SMDS_MeshNode.hxx>
|
|
|
|
#include <LightApp_SelectionMgr.h>
|
|
#include <SUIT_OverrideCursor.h>
|
|
#include <SUIT_ResourceMgr.h>
|
|
#include <SVTK_ViewWindow.h>
|
|
#include <SALOME_ListIO.hxx>
|
|
|
|
#include <QButtonGroup>
|
|
#include <QGridLayout>
|
|
#include <QGroupBox>
|
|
#include <QHBoxLayout>
|
|
#include <QKeyEvent>
|
|
#include <QLabel>
|
|
#include <QLineEdit>
|
|
#include <QPushButton>
|
|
#include <QRadioButton>
|
|
#include <QTabWidget>
|
|
#include <QVBoxLayout>
|
|
|
|
#include <vtkPoints.h>
|
|
#include <vtkUnstructuredGrid.h>
|
|
#include <vtkIdList.h>
|
|
#include <vtkCellArray.h>
|
|
#include <vtkUnsignedCharArray.h>
|
|
#include <vtkDataSetMapper.h>
|
|
#include <VTKViewer_CellLocationsArray.h>
|
|
#include <vtkProperty.h>
|
|
|
|
#include <ElCLib.hxx>
|
|
|
|
#include <SALOMEconfig.h>
|
|
#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 ), myPreview( 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<SUIT_SelectionFilter*> filters;
|
|
filters.append( new SMESH_TypeFilter( SMESH::MESHorSUBMESH ) );
|
|
filters.append( new SMESH_TypeFilter( SMESH::GROUP ) );
|
|
myFilter = new SMESH_LogicalFilter( filters, SMESH_LogicalFilter::LO_OR );
|
|
|
|
mySecondTgt->setEnabled( mySecond->checkedId() != OriginTgt );
|
|
clear();
|
|
|
|
//setTarget( FirstTgt );
|
|
selectionChanged();
|
|
}
|
|
|
|
/*!
|
|
\brief Destructor
|
|
*/
|
|
SMESHGUI_MinDistance::~SMESHGUI_MinDistance()
|
|
{
|
|
erasePreview();
|
|
if ( myPreview )
|
|
myPreview->Delete();
|
|
}
|
|
|
|
/*!
|
|
\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 Erase preview actor
|
|
*/
|
|
void SMESHGUI_MinDistance::erasePreview()
|
|
{
|
|
SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow();
|
|
if ( aViewWindow && myPreview ) {
|
|
aViewWindow->RemoveActor( myPreview );
|
|
aViewWindow->Repaint();
|
|
}
|
|
}
|
|
|
|
/*!
|
|
\brief Display preview actor
|
|
*/
|
|
void SMESHGUI_MinDistance::displayPreview()
|
|
{
|
|
SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow();
|
|
if ( aViewWindow && myPreview ) {
|
|
aViewWindow->AddActor( myPreview );
|
|
aViewWindow->Repaint();
|
|
}
|
|
}
|
|
|
|
/*!
|
|
\brief Create preview actor
|
|
\param x1 X coordinate of first point
|
|
\param y1 X coordinate of first point
|
|
\param z1 Y coordinate of first point
|
|
\param x2 Y coordinate of second point
|
|
\param y2 Z coordinate of second point
|
|
\param z2 Z coordinate of second point
|
|
*/
|
|
void SMESHGUI_MinDistance::createPreview( double x1, double y1, double z1, double x2, double y2, double z2 )
|
|
{
|
|
if ( myPreview )
|
|
myPreview->Delete();
|
|
|
|
vtkUnstructuredGrid* aGrid = vtkUnstructuredGrid::New();
|
|
// create points
|
|
vtkPoints* aPoints = vtkPoints::New();
|
|
aPoints->SetNumberOfPoints( 2 );
|
|
aPoints->SetPoint( 0, x1, y1, z1 );
|
|
aPoints->SetPoint( 1, x2, y2, z2 );
|
|
aGrid->SetPoints( aPoints );
|
|
aPoints->Delete();
|
|
// create cells
|
|
vtkIdList* anIdList = vtkIdList::New();
|
|
anIdList->SetNumberOfIds( 2 );
|
|
vtkCellArray* aCells = vtkCellArray::New();
|
|
aCells->Allocate( 2, 0);
|
|
vtkUnsignedCharArray* aCellTypesArray = vtkUnsignedCharArray::New();
|
|
aCellTypesArray->SetNumberOfComponents( 1 );
|
|
aCellTypesArray->Allocate( 1 );
|
|
anIdList->SetId( 0, 0 ); anIdList->SetId( 1, 1 );
|
|
aCells->InsertNextCell( anIdList );
|
|
aCellTypesArray->InsertNextValue( VTK_LINE );
|
|
anIdList->Delete();
|
|
VTKViewer_CellLocationsArray* aCellLocationsArray = VTKViewer_CellLocationsArray::New();
|
|
aCellLocationsArray->SetNumberOfComponents( 1 );
|
|
aCellLocationsArray->SetNumberOfTuples( 1 );
|
|
aCells->InitTraversal();
|
|
for( vtkIdType idType = 0, *pts, npts; aCells->GetNextCell( npts, pts ); idType++ )
|
|
aCellLocationsArray->SetValue( idType, aCells->GetTraversalLocation( npts ) );
|
|
aGrid->SetCells( aCellTypesArray, aCellLocationsArray, aCells );
|
|
aCellLocationsArray->Delete();
|
|
aCellTypesArray->Delete();
|
|
aCells->Delete();
|
|
// create actor
|
|
vtkDataSetMapper* aMapper = vtkDataSetMapper::New();
|
|
aMapper->SetInputData( aGrid );
|
|
aGrid->Delete();
|
|
myPreview = SALOME_Actor::New();
|
|
myPreview->PickableOff();
|
|
myPreview->SetMapper( aMapper );
|
|
myPreview->SetResolveCoincidentTopology(true);
|
|
aMapper->Delete();
|
|
vtkProperty* aProp = vtkProperty::New();
|
|
aProp->SetRepresentationToWireframe();
|
|
aProp->SetColor( 250, 0, 250 );
|
|
aProp->SetPointSize( 5 );
|
|
aProp->SetLineWidth( 3 );
|
|
myPreview->SetProperty( aProp );
|
|
aProp->Delete();
|
|
}
|
|
|
|
/*!
|
|
\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<SMESH::SMESH_IDSource>( 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();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
clear();
|
|
}
|
|
|
|
/*!
|
|
\brief Called when first target mode is changed by the user
|
|
*/
|
|
void SMESHGUI_MinDistance::firstChanged()
|
|
{
|
|
myFirstSrc = SMESH::SMESH_IDSource::_nil();
|
|
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()
|
|
{
|
|
mySecondSrc = SMESH::SMESH_IDSource::_nil();
|
|
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 );
|
|
if ( sender() == myFirstTgt )
|
|
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 );
|
|
if ( sender() == mySecondTgt )
|
|
clear();
|
|
QString text = mySecondTgt->text();
|
|
if ( !mySecondActor )
|
|
{
|
|
selectionChanged();
|
|
mySecondTgt->setText( text );
|
|
}
|
|
SVTK_Selector* selector = SMESH::GetViewWindow()->GetSelector();
|
|
if ( mySecondActor && selector ) {
|
|
Handle(SALOME_InteractiveObject) IO = mySecondActor->getIO();
|
|
if ( mySecond->checkedId() == NodeTgt || mySecond->checkedId() == ElementTgt ) {
|
|
if ( !text.isEmpty() ) {
|
|
TColStd_MapOfInteger ID;
|
|
ID.Add( 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::IDSource_wrap s1;
|
|
SMESH::IDSource_wrap 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;
|
|
s1->Register();
|
|
}
|
|
}
|
|
|
|
// 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;
|
|
s2->Register();
|
|
}
|
|
}
|
|
|
|
if ( !CORBA::is_nil( s1 ) && ( !CORBA::is_nil( s2 ) || isOrigin ) ) {
|
|
// compute min distance
|
|
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->UnRegister();
|
|
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 ) ) );
|
|
// update preview actor
|
|
erasePreview();
|
|
double x1, y1, z1, x2, y2, z2;
|
|
SMESH::double_array_var coord = s1->GetMesh()->GetNodeXYZ( result.node1 );
|
|
x1 = coord[0]; y1 = coord[1]; z1 = coord[2];
|
|
if ( isOrigin ) {
|
|
x2 = y2 = z2 = 0.;
|
|
}
|
|
else if ( mySecond->checkedId() == NodeTgt ) {
|
|
coord = s2->GetMesh()->GetNodeXYZ( result.node2 );
|
|
x2 = coord[0]; y2 = coord[1]; z2 = coord[2];
|
|
}
|
|
else
|
|
{
|
|
x2 = result.maxX; y2 = result.maxY; z2 = result.maxZ;
|
|
}
|
|
createPreview( x1, y1, z1, x2, y2, z2 );
|
|
displayPreview();
|
|
}
|
|
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();
|
|
erasePreview();
|
|
}
|
|
|
|
/*!
|
|
\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 ), myPreview( 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<SUIT_SelectionFilter*> filters;
|
|
filters.append( new SMESH_TypeFilter( SMESH::MESHorSUBMESH ) );
|
|
filters.append( new SMESH_TypeFilter( SMESH::GROUP ) );
|
|
myFilter = new SMESH_LogicalFilter( filters, SMESH_LogicalFilter::LO_OR );
|
|
|
|
clear();
|
|
}
|
|
|
|
/*!
|
|
\brief Destructor
|
|
*/
|
|
SMESHGUI_BoundingBox::~SMESHGUI_BoundingBox()
|
|
{
|
|
erasePreview();
|
|
if ( myPreview )
|
|
myPreview->Delete();
|
|
}
|
|
|
|
/*!
|
|
\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();
|
|
|
|
if ( mySource->text().isEmpty() )
|
|
selectionChanged();
|
|
}
|
|
|
|
/*!
|
|
\brief Deactivate widget
|
|
*/
|
|
void SMESHGUI_BoundingBox::deactivate()
|
|
{
|
|
disconnect( SMESHGUI::selectionMgr(), 0, this, 0 );
|
|
}
|
|
|
|
/*!
|
|
\brief Erase preview actor
|
|
*/
|
|
void SMESHGUI_BoundingBox::erasePreview()
|
|
{
|
|
SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow();
|
|
if ( aViewWindow && myPreview ) {
|
|
aViewWindow->RemoveActor( myPreview );
|
|
aViewWindow->Repaint();
|
|
}
|
|
}
|
|
|
|
/*!
|
|
\brief Display preview actor
|
|
*/
|
|
void SMESHGUI_BoundingBox::displayPreview()
|
|
{
|
|
SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow();
|
|
if ( aViewWindow && myPreview ) {
|
|
aViewWindow->AddActor( myPreview );
|
|
aViewWindow->Repaint();
|
|
}
|
|
}
|
|
|
|
/*!
|
|
\brief Create preview actor
|
|
\param minX min X coordinate of bounding box
|
|
\param maxX max X coordinate of bounding box
|
|
\param minY min Y coordinate of bounding box
|
|
\param maxY max Y coordinate of bounding box
|
|
\param minZ min Z coordinate of bounding box
|
|
\param maxZ max Z coordinate of bounding box
|
|
*/
|
|
void SMESHGUI_BoundingBox::createPreview( double minX, double maxX, double minY, double maxY, double minZ, double maxZ )
|
|
{
|
|
if ( myPreview )
|
|
myPreview->Delete();
|
|
|
|
vtkUnstructuredGrid* aGrid = vtkUnstructuredGrid::New();
|
|
// create points
|
|
vtkPoints* aPoints = vtkPoints::New();
|
|
aPoints->SetNumberOfPoints( 8 );
|
|
aPoints->SetPoint( 0, minX, minY, minZ );
|
|
aPoints->SetPoint( 1, maxX, minY, minZ );
|
|
aPoints->SetPoint( 2, minX, maxY, minZ );
|
|
aPoints->SetPoint( 3, maxX, maxY, minZ );
|
|
aPoints->SetPoint( 4, minX, minY, maxZ );
|
|
aPoints->SetPoint( 5, maxX, minY, maxZ );
|
|
aPoints->SetPoint( 6, minX, maxY, maxZ );
|
|
aPoints->SetPoint( 7, maxX, maxY, maxZ );
|
|
aGrid->SetPoints( aPoints );
|
|
aPoints->Delete();
|
|
// create cells
|
|
// connectivity: 0-1 0-4 0-2 1-5 1-3 2-6 2-3 3-7 4-6 4-5 5-7 6-7
|
|
vtkIdList* anIdList = vtkIdList::New();
|
|
anIdList->SetNumberOfIds( 2 );
|
|
vtkCellArray* aCells = vtkCellArray::New();
|
|
aCells->Allocate( 2*12, 0);
|
|
vtkUnsignedCharArray* aCellTypesArray = vtkUnsignedCharArray::New();
|
|
aCellTypesArray->SetNumberOfComponents( 1 );
|
|
aCellTypesArray->Allocate( 12 );
|
|
anIdList->SetId( 0, 0 ); anIdList->SetId( 1, 1 );
|
|
aCells->InsertNextCell( anIdList );
|
|
aCellTypesArray->InsertNextValue( VTK_LINE );
|
|
anIdList->SetId( 0, 0 ); anIdList->SetId( 1, 4 );
|
|
aCells->InsertNextCell( anIdList );
|
|
aCellTypesArray->InsertNextValue( VTK_LINE );
|
|
anIdList->SetId( 0, 0 ); anIdList->SetId( 1, 2 );
|
|
aCells->InsertNextCell( anIdList );
|
|
aCellTypesArray->InsertNextValue( VTK_LINE );
|
|
anIdList->SetId( 0, 1 ); anIdList->SetId( 1, 5 );
|
|
aCells->InsertNextCell( anIdList );
|
|
aCellTypesArray->InsertNextValue( VTK_LINE );
|
|
anIdList->SetId( 0, 1 ); anIdList->SetId( 1, 3 );
|
|
aCells->InsertNextCell( anIdList );
|
|
aCellTypesArray->InsertNextValue( VTK_LINE );
|
|
anIdList->SetId( 0, 2 ); anIdList->SetId( 1, 6 );
|
|
aCells->InsertNextCell( anIdList );
|
|
aCellTypesArray->InsertNextValue( VTK_LINE );
|
|
anIdList->SetId( 0, 2 ); anIdList->SetId( 1, 3 );
|
|
aCells->InsertNextCell( anIdList );
|
|
aCellTypesArray->InsertNextValue( VTK_LINE );
|
|
anIdList->SetId( 0, 3 ); anIdList->SetId( 1, 7 );
|
|
aCells->InsertNextCell( anIdList );
|
|
aCellTypesArray->InsertNextValue( VTK_LINE );
|
|
anIdList->SetId( 0, 4 ); anIdList->SetId( 1, 6 );
|
|
aCells->InsertNextCell( anIdList );
|
|
aCellTypesArray->InsertNextValue( VTK_LINE );
|
|
anIdList->SetId( 0, 4 ); anIdList->SetId( 1, 5 );
|
|
aCells->InsertNextCell( anIdList );
|
|
aCellTypesArray->InsertNextValue( VTK_LINE );
|
|
anIdList->SetId( 0, 5 ); anIdList->SetId( 1, 7 );
|
|
aCells->InsertNextCell( anIdList );
|
|
aCellTypesArray->InsertNextValue( VTK_LINE );
|
|
anIdList->SetId( 0, 6 ); anIdList->SetId( 1, 7 );
|
|
aCells->InsertNextCell( anIdList );
|
|
aCellTypesArray->InsertNextValue( VTK_LINE );
|
|
anIdList->Delete();
|
|
VTKViewer_CellLocationsArray* aCellLocationsArray = VTKViewer_CellLocationsArray::New();
|
|
aCellLocationsArray->SetNumberOfComponents( 1 );
|
|
aCellLocationsArray->SetNumberOfTuples( 12 );
|
|
aCells->InitTraversal();
|
|
for( vtkIdType idType = 0, *pts, npts; aCells->GetNextCell( npts, pts ); idType++ )
|
|
aCellLocationsArray->SetValue( idType, aCells->GetTraversalLocation( npts ) );
|
|
aGrid->SetCells( aCellTypesArray, aCellLocationsArray, aCells );
|
|
aCellLocationsArray->Delete();
|
|
aCellTypesArray->Delete();
|
|
aCells->Delete();
|
|
// create actor
|
|
vtkDataSetMapper* aMapper = vtkDataSetMapper::New();
|
|
aMapper->SetInputData( aGrid );
|
|
aGrid->Delete();
|
|
myPreview = SALOME_Actor::New();
|
|
myPreview->PickableOff();
|
|
myPreview->SetMapper( aMapper );
|
|
aMapper->Delete();
|
|
vtkProperty* aProp = vtkProperty::New();
|
|
aProp->SetRepresentationToWireframe();
|
|
aProp->SetColor( 250, 0, 250 );
|
|
aProp->SetPointSize( 5 );
|
|
aProp->SetLineWidth( 3 );
|
|
myPreview->SetProperty( aProp );
|
|
aProp->Delete();
|
|
}
|
|
|
|
/*!
|
|
\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<SMESH::SMESH_IDSource>( 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<SMESH::SMESH_IDSource>( IO );
|
|
if ( !CORBA::is_nil( obj ) ) {
|
|
mySrc.append( obj );
|
|
}
|
|
}
|
|
QString aName;
|
|
SMESH::GetNameOfSelectedIObjects( SMESHGUI::selectionMgr(), aName );
|
|
mySource->setText( aName );
|
|
}
|
|
else {
|
|
mySource->clear();
|
|
}
|
|
}
|
|
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()
|
|
{
|
|
if ( sender() == mySource )
|
|
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 = myIDs.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;
|
|
SMESH::ListOfIDSources_var srcList = new SMESH::ListOfIDSources();
|
|
if ( mySourceMode->checkedId() == NodesSrc || mySourceMode->checkedId() == ElementsSrc ) {
|
|
if ( mySrc.count() > 0 && !CORBA::is_nil( mySrc[0] ) ) {
|
|
SMESH::SMESH_Mesh_var m = mySrc[0]->GetMesh();
|
|
QStringList ids = myIDs.split( " ", QString::SkipEmptyParts );
|
|
if ( !CORBA::is_nil( m ) && ids.count() > 0 ) {
|
|
SMESH::long_array_var ids_in = new SMESH::long_array();
|
|
ids_in->length( ids.count() );
|
|
for( int i = 0; i < ids.count(); i++ )
|
|
ids_in[i] = ids[i].trimmed().toLong();
|
|
SMESH::SMESH_MeshEditor_var me = m->GetMeshEditor();
|
|
SMESH::SMESH_IDSource_var s = me->MakeIDSource( ids_in.in(), mySourceMode->checkedId() == NodesSrc ? SMESH::NODE : SMESH::FACE );
|
|
srcList->length( 1 );
|
|
srcList[0] = s;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
srcList->length( mySrc.count() );
|
|
for( int i = 0; i < mySrc.count(); i++ ) {
|
|
srcList[i] = mySrc[i];
|
|
mySrc[i]->Register();
|
|
}
|
|
}
|
|
if ( srcList->length() > 0 ) {
|
|
// compute bounding box
|
|
int precision = SMESHGUI::resourceMgr()->integerValue( "SMESH", "length_precision", 6 );
|
|
SMESH::Measurements_var measure = SMESHGUI::GetSMESHGen()->CreateMeasurements();
|
|
SMESH::Measure result = measure->BoundingBox( srcList.in() );
|
|
SALOME::UnRegister( srcList );
|
|
measure->UnRegister();
|
|
myXmin->setText( QString::number( result.minX, precision > 0 ? 'f' : 'g', qAbs( precision ) ) );
|
|
myXmax->setText( QString::number( result.maxX, precision > 0 ? 'f' : 'g', qAbs( precision ) ) );
|
|
myDX->setText( QString::number( result.maxX-result.minX, precision > 0 ? 'f' : 'g', qAbs( precision ) ) );
|
|
myYmin->setText( QString::number( result.minY, precision > 0 ? 'f' : 'g', qAbs( precision ) ) );
|
|
myYmax->setText( QString::number( result.maxY, precision > 0 ? 'f' : 'g', qAbs( precision ) ) );
|
|
myDY->setText( QString::number( result.maxY-result.minY, precision > 0 ? 'f' : 'g', qAbs( precision ) ) );
|
|
myZmin->setText( QString::number( result.minZ, precision > 0 ? 'f' : 'g', qAbs( precision ) ) );
|
|
myZmax->setText( QString::number( result.maxZ, precision > 0 ? 'f' : 'g', qAbs( precision ) ) );
|
|
myDZ->setText( QString::number( result.maxZ-result.minZ, precision > 0 ? 'f' : 'g', qAbs( precision ) ) );
|
|
// update preview actor
|
|
erasePreview();
|
|
createPreview( result.minX, result.maxX, result.minY, result.maxY, result.minZ, result.maxZ );
|
|
displayPreview();
|
|
}
|
|
else {
|
|
clear();
|
|
}
|
|
}
|
|
|
|
/*!
|
|
\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();
|
|
erasePreview();
|
|
}
|
|
|
|
/*!
|
|
\class SMESHGUI_BasicProperties
|
|
\brief basic properties measurement widget.
|
|
|
|
Widget to calculate length, area or volume for the selected object(s).
|
|
*/
|
|
|
|
/*!
|
|
\brief Constructor.
|
|
\param parent parent widget
|
|
*/
|
|
SMESHGUI_BasicProperties::SMESHGUI_BasicProperties( QWidget* parent )
|
|
: QWidget( parent )
|
|
{
|
|
// Property (length, area or volume)
|
|
QGroupBox* aPropertyGrp = new QGroupBox( tr( "PROPERTY" ), this );
|
|
|
|
QRadioButton* aLength = new QRadioButton( tr( "LENGTH" ), aPropertyGrp );
|
|
QRadioButton* anArea = new QRadioButton( tr( "AREA" ), aPropertyGrp );
|
|
QRadioButton* aVolume = new QRadioButton( tr( "VOLUME" ), aPropertyGrp );
|
|
|
|
myMode = new QButtonGroup( this );
|
|
myMode->addButton( aLength, Length );
|
|
myMode->addButton( anArea, Area );
|
|
myMode->addButton( aVolume, Volume );
|
|
|
|
QHBoxLayout* aPropertyLayout = new QHBoxLayout;
|
|
aPropertyLayout->addWidget( aLength );
|
|
aPropertyLayout->addWidget( anArea );
|
|
aPropertyLayout->addWidget( aVolume );
|
|
|
|
aPropertyGrp->setLayout( aPropertyLayout );
|
|
|
|
// Source object
|
|
QGroupBox* aSourceGrp = new QGroupBox( tr( "SOURCE_MESH_SUBMESH_GROUP" ), this );
|
|
|
|
mySource = new QLineEdit( aSourceGrp );
|
|
mySource->setReadOnly( true );
|
|
|
|
QHBoxLayout* aSourceLayout = new QHBoxLayout;
|
|
aSourceLayout->addWidget( mySource );
|
|
|
|
aSourceGrp->setLayout( aSourceLayout );
|
|
|
|
// Compute button
|
|
QPushButton* aCompute = new QPushButton( tr( "COMPUTE" ), this );
|
|
|
|
// Result of computation (length, area or volume)
|
|
myResultGrp = new QGroupBox( this );
|
|
|
|
myResult = new QLineEdit;
|
|
myResult->setReadOnly( true );
|
|
|
|
QHBoxLayout* aResultLayout = new QHBoxLayout;
|
|
aResultLayout->addWidget( myResult );
|
|
|
|
myResultGrp->setLayout( aResultLayout );
|
|
|
|
// Layout
|
|
QGridLayout* aMainLayout = new QGridLayout( this );
|
|
aMainLayout->setMargin( MARGIN );
|
|
aMainLayout->setSpacing( SPACING );
|
|
|
|
aMainLayout->addWidget( aPropertyGrp, 0, 0, 1, 2 );
|
|
aMainLayout->addWidget( aSourceGrp, 1, 0, 1, 2 );
|
|
aMainLayout->addWidget( aCompute, 2, 0 );
|
|
aMainLayout->addWidget( myResultGrp, 3, 0, 1, 2 );
|
|
aMainLayout->setColumnStretch( 1, 5 );
|
|
aMainLayout->setRowStretch( 4, 5 );
|
|
|
|
// Initial state
|
|
setMode( Length );
|
|
|
|
// Connections
|
|
connect( myMode, SIGNAL( buttonClicked( int ) ), this, SLOT( modeChanged( int ) ) );
|
|
connect( aCompute, SIGNAL( clicked() ), this, SLOT( compute() ) );
|
|
|
|
// Selection filter
|
|
QList<SUIT_SelectionFilter*> filters;
|
|
filters.append( new SMESH_TypeFilter( SMESH::MESHorSUBMESH ) );
|
|
filters.append( new SMESH_TypeFilter( SMESH::GROUP ) );
|
|
myFilter = new SMESH_LogicalFilter( filters, SMESH_LogicalFilter::LO_OR );
|
|
}
|
|
|
|
/*!
|
|
\brief Destructor
|
|
*/
|
|
SMESHGUI_BasicProperties::~SMESHGUI_BasicProperties()
|
|
{
|
|
}
|
|
|
|
/*!
|
|
\brief Sets the measurement mode.
|
|
\param theMode the mode to set (length, area or volume meausurement)
|
|
*/
|
|
void SMESHGUI_BasicProperties::setMode( const Mode theMode )
|
|
{
|
|
QRadioButton* aButton = qobject_cast<QRadioButton*>( myMode->button( theMode ) );
|
|
if ( aButton ) {
|
|
aButton->setChecked( true );
|
|
modeChanged( theMode );
|
|
}
|
|
}
|
|
|
|
/*!
|
|
\brief Setup the selection mode.
|
|
*/
|
|
void SMESHGUI_BasicProperties::updateSelection()
|
|
{
|
|
LightApp_SelectionMgr* selMgr = SMESHGUI::selectionMgr();
|
|
|
|
disconnect( selMgr, 0, this, 0 );
|
|
selMgr->clearFilters();
|
|
|
|
SMESH::SetPointRepresentation( false );
|
|
if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow() ) {
|
|
aViewWindow->SetSelectionMode( ActorSelection );
|
|
}
|
|
selMgr->installFilter( myFilter );
|
|
|
|
connect( selMgr, SIGNAL( currentSelectionChanged() ), this, SLOT( selectionChanged() ) );
|
|
|
|
if ( mySource->text().isEmpty() )
|
|
selectionChanged();
|
|
}
|
|
|
|
/*!
|
|
\brief Deactivate widget
|
|
*/
|
|
void SMESHGUI_BasicProperties::deactivate()
|
|
{
|
|
disconnect( SMESHGUI::selectionMgr(), 0, this, 0 );
|
|
}
|
|
|
|
/*!
|
|
\brief Called when selection is changed
|
|
*/
|
|
void SMESHGUI_BasicProperties::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<SMESH::SMESH_IDSource>( IO );
|
|
if ( !CORBA::is_nil( obj ) ) {
|
|
mySrc = obj;
|
|
|
|
QString aName;
|
|
SMESH::GetNameOfSelectedIObjects( SMESHGUI::selectionMgr(), aName );
|
|
mySource->setText( aName );
|
|
}
|
|
}
|
|
|
|
clear();
|
|
}
|
|
|
|
/*!
|
|
\brief Called when the measurement mode selection is changed.
|
|
\param theMode the selected mode
|
|
*/
|
|
void SMESHGUI_BasicProperties::modeChanged( int theMode )
|
|
{
|
|
clear();
|
|
|
|
if ( theMode == Length ) {
|
|
myResultGrp->setTitle( tr("LENGTH") );
|
|
} else if ( theMode == Area ) {
|
|
myResultGrp->setTitle( tr("AREA") );
|
|
} else if ( theMode == Volume ) {
|
|
myResultGrp->setTitle( tr("VOLUME") );
|
|
}
|
|
}
|
|
|
|
/*!
|
|
\brief Calculate length, area or volume for the selected object(s)
|
|
*/
|
|
void SMESHGUI_BasicProperties::compute()
|
|
{
|
|
SUIT_OverrideCursor wc;
|
|
|
|
SMESH::SMESH_IDSource_var source;
|
|
|
|
if ( !CORBA::is_nil( mySrc ) ) {
|
|
// compute
|
|
int precision = SMESHGUI::resourceMgr()->integerValue( "SMESH", "length_precision", 6 );
|
|
SMESH::Measurements_var measure = SMESHGUI::GetSMESHGen()->CreateMeasurements();
|
|
|
|
double result = 0;
|
|
|
|
if ( myMode->checkedId() == Length ) {
|
|
result = measure->Length( mySrc.in() );
|
|
} else if ( myMode->checkedId() == Area ) {
|
|
result = measure->Area( mySrc.in() );
|
|
} else if ( myMode->checkedId() == Volume ) {
|
|
result = measure->Volume( mySrc.in() );
|
|
}
|
|
|
|
measure->UnRegister();
|
|
|
|
myResult->setText( QString::number( result, precision > 0 ? 'f' : 'g', qAbs( precision ) ) );
|
|
} else {
|
|
clear();
|
|
}
|
|
}
|
|
|
|
/*!
|
|
\brief Reset the widget to the initial state (nullify the result field)
|
|
*/
|
|
void SMESHGUI_BasicProperties::clear()
|
|
{
|
|
myResult->clear();
|
|
}
|
|
|
|
/*!
|
|
\class SMESHGUI_Angle
|
|
\brief Angle measurement widget.
|
|
|
|
Widget to calculate angle between 3 nodes.
|
|
*/
|
|
|
|
/*!
|
|
\brief Constructor.
|
|
\param parent parent widget
|
|
*/
|
|
SMESHGUI_Angle::SMESHGUI_Angle( QWidget* parent )
|
|
: QWidget( parent )
|
|
{
|
|
// 3 nodes
|
|
|
|
QGroupBox* aNodesGrp = new QGroupBox( tr( "NODES_GROUP" ), this );
|
|
myNodes = new QLineEdit( aNodesGrp );
|
|
myNodes->setValidator( new SMESHGUI_IdValidator( this, 3 ));
|
|
QHBoxLayout* aNodesLayout = new QHBoxLayout( aNodesGrp );
|
|
aNodesLayout->addWidget( myNodes );
|
|
|
|
// Compute button
|
|
QPushButton* aCompute = new QPushButton( tr( "COMPUTE" ), this );
|
|
|
|
// Angle
|
|
|
|
QGroupBox* aResultGrp = new QGroupBox( tr( "RESULT" ), this );
|
|
|
|
myResult = new QLineEdit;
|
|
myResult->setReadOnly( true );
|
|
|
|
QHBoxLayout* aResultLayout = new QHBoxLayout( aResultGrp );
|
|
aResultLayout->addWidget( myResult );
|
|
|
|
// Layout
|
|
|
|
QGridLayout* aMainLayout = new QGridLayout( this );
|
|
aMainLayout->setMargin( MARGIN );
|
|
aMainLayout->setSpacing( SPACING );
|
|
|
|
aMainLayout->addWidget( aNodesGrp, 0, 0, 1, 2 );
|
|
aMainLayout->addWidget( aCompute, 1, 0 );
|
|
aMainLayout->addWidget( aResultGrp, 2, 0, 1, 2 );
|
|
aMainLayout->setColumnStretch( 1, 5 );
|
|
aMainLayout->setRowStretch( 3, 5 );
|
|
|
|
// Connections
|
|
connect( aCompute, SIGNAL( clicked() ), this, SLOT( compute() ));
|
|
|
|
// preview
|
|
myPreview = 0;
|
|
if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow() )
|
|
{
|
|
myPreview = new SMESHGUI_MeshEditPreview( aViewWindow );
|
|
if ( myPreview && myPreview->GetActor() )
|
|
myPreview->GetActor()->GetProperty()->SetLineWidth( 5 );
|
|
}
|
|
myActor = 0;
|
|
}
|
|
|
|
SMESHGUI_Angle::~SMESHGUI_Angle()
|
|
{
|
|
if ( myPreview )
|
|
delete myPreview;
|
|
}
|
|
|
|
/*!
|
|
\brief Setup selection mode
|
|
*/
|
|
void SMESHGUI_Angle::updateSelection()
|
|
{
|
|
LightApp_SelectionMgr* selMgr = SMESHGUI::selectionMgr();
|
|
|
|
disconnect( selMgr, 0, this, 0 );
|
|
selMgr->clearFilters();
|
|
|
|
SMESH::SetPointRepresentation( true );
|
|
if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow() )
|
|
aViewWindow->SetSelectionMode( NodeSelection );
|
|
|
|
connect( selMgr, SIGNAL( currentSelectionChanged() ), this, SLOT( selectionChanged() ));
|
|
connect( myNodes, SIGNAL( textEdited( QString ) ), this, SLOT( nodesEdited() ));
|
|
|
|
if ( myPoints.empty() )
|
|
selectionChanged();
|
|
}
|
|
|
|
/*!
|
|
\brief Called when selection is changed
|
|
*/
|
|
void SMESHGUI_Angle::selectionChanged()
|
|
{
|
|
clear();
|
|
QString nodesString;
|
|
|
|
TColStd_IndexedMapOfInteger idsMap;
|
|
SALOME_ListIO selected;
|
|
SMESHGUI::selectionMgr()->selectedObjects( selected );
|
|
selected.Reverse(); // to keep order of selection
|
|
|
|
SALOME_ListIteratorOfListIO ioIterator( selected );
|
|
for ( ; ioIterator.More(); ioIterator.Next() )
|
|
{
|
|
Handle(SALOME_InteractiveObject) IO = ioIterator.Value();
|
|
|
|
idsMap.Clear();
|
|
if ( SVTK_Selector* selector = SMESH::GetViewWindow()->GetSelector() )
|
|
selector->GetIndex( IO, idsMap );
|
|
|
|
if ( SMESH_Actor* actor = SMESH::FindActorByEntry( IO->getEntry() ))
|
|
{
|
|
myActor = actor;
|
|
for ( int i = 1; i <= idsMap.Extent() && myPoints.size() < 3; ++i )
|
|
if ( addPointByActor( idsMap(i) ))
|
|
nodesString += QString(" %1").arg( idsMap(i) );
|
|
idsMap.Clear();
|
|
}
|
|
SMESH::SMESH_IDSource_var obj = SMESH::IObjectToInterface<SMESH::SMESH_IDSource>( IO );
|
|
if ( !CORBA::is_nil( obj ) )
|
|
{
|
|
myIDSrc = obj;
|
|
for ( int i = 1; i <= idsMap.Extent() && myPoints.size() < 3; ++i )
|
|
if ( addPointByIDSource( idsMap(i) ))
|
|
nodesString += QString(" %1").arg( idsMap(i) );
|
|
}
|
|
}
|
|
|
|
myNodes->setText( nodesString );
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : clear
|
|
//purpose : Erase preview and result
|
|
//=======================================================================
|
|
|
|
void SMESHGUI_Angle::clear()
|
|
{
|
|
myPoints.clear();
|
|
myResult->clear();
|
|
if ( myPreview && myPreview->GetActor())
|
|
{
|
|
myPreview->GetActor()->SetVisibility( false );
|
|
if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow() )
|
|
aViewWindow->Repaint();
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : addPointByActor
|
|
//purpose : append to myPoints XYZ got from myActor
|
|
//=======================================================================
|
|
|
|
bool SMESHGUI_Angle::addPointByActor( int id )
|
|
{
|
|
size_t nbP = myPoints.size();
|
|
|
|
if ( myActor )
|
|
{
|
|
TVisualObjPtr obj = myActor->GetObject();
|
|
if ( SMDS_Mesh* mesh = obj->GetMesh() )
|
|
if ( const SMDS_MeshNode* node = mesh->FindNode( id ))
|
|
{
|
|
SMESH::PointStruct p = { node->X(), node->Y(), node->Z() };
|
|
myPoints.push_back( p );
|
|
}
|
|
}
|
|
return nbP < myPoints.size();
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : addPointByIDSource
|
|
//purpose : append to myPoints XYZ got from myIDSrc
|
|
//=======================================================================
|
|
|
|
bool SMESHGUI_Angle::addPointByIDSource( int id )
|
|
{
|
|
size_t nbP = myPoints.size();
|
|
|
|
if ( !myIDSrc->_is_nil() )
|
|
{
|
|
SMESH::SMESH_Mesh_var mesh = myIDSrc->GetMesh();
|
|
if ( !mesh->_is_nil() )
|
|
{
|
|
SMESH::double_array_var xyz = mesh->GetNodeXYZ( id );
|
|
if ( xyz->length() == 3 )
|
|
{
|
|
SMESH::PointStruct p = { xyz[0], xyz[1], xyz[2] };
|
|
myPoints.push_back( p );
|
|
}
|
|
}
|
|
}
|
|
return nbP < myPoints.size();
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : nodesEdited
|
|
//purpose : SLOT called when the user types node IDs
|
|
//=======================================================================
|
|
|
|
void SMESHGUI_Angle::nodesEdited()
|
|
{
|
|
clear();
|
|
|
|
TColStd_MapOfInteger ID;
|
|
QStringList ids = myNodes->text().split( " ", QString::SkipEmptyParts );
|
|
foreach ( QString idStr, ids )
|
|
{
|
|
int id = idStr.trimmed().toLong();
|
|
if (( !ID.Contains( id )) &&
|
|
( addPointByActor( id ) || addPointByIDSource( id )))
|
|
ID.Add( id );
|
|
}
|
|
|
|
SVTK_Selector* selector = SMESH::GetViewWindow()->GetSelector();
|
|
if ( myActor && selector )
|
|
{
|
|
Handle(SALOME_InteractiveObject) IO = myActor->getIO();
|
|
selector->AddOrRemoveIndex( IO, ID, false );
|
|
if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow() )
|
|
aViewWindow->highlight( IO, true, true );
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : compute
|
|
//purpose : SLOT. Compute angle and show preview
|
|
//=======================================================================
|
|
|
|
void SMESHGUI_Angle::compute()
|
|
{
|
|
if ( myPoints.size() != 3 )
|
|
return;
|
|
|
|
// --------------
|
|
// compute angle
|
|
// --------------
|
|
|
|
SMESH::Measurements_var measure = SMESHGUI::GetSMESHGen()->CreateMeasurements();
|
|
double radians = measure->Angle( myPoints[0], myPoints[1], myPoints[2] );
|
|
measure->UnRegister();
|
|
if ( radians < 0 )
|
|
return;
|
|
|
|
int precision = SMESHGUI::resourceMgr()->integerValue( "SMESH", "length_precision", 6 );
|
|
myResult->setText( QString::number( radians * 180 / M_PI,
|
|
precision > 0 ? 'f' : 'g', qAbs( precision )));
|
|
|
|
// -------------
|
|
// show preview
|
|
// -------------
|
|
|
|
if ( !myPreview || !myPreview->GetActor() )
|
|
return;
|
|
|
|
SMESH::MeshPreviewStruct preveiwData;
|
|
|
|
const double anglePerSeg = 5 * M_PI/180; // angle per an arc segment
|
|
const double arcRadiusFactor = 0.5; // arc position, from p1
|
|
|
|
gp_Pnt p0 ( myPoints[0].x, myPoints[0].y, myPoints[0].z );
|
|
gp_Pnt p1 ( myPoints[1].x, myPoints[1].y, myPoints[1].z );
|
|
gp_Pnt p2 ( myPoints[2].x, myPoints[2].y, myPoints[2].z );
|
|
gp_Vec vec10( p1, p0 ), vec12( p1, p2 ), norm( vec10 ^ vec12 );
|
|
|
|
if ( norm.Magnitude() <= gp::Resolution() ) // 180 degrees
|
|
norm = getNormal( vec10 );
|
|
|
|
double len10 = vec10.Magnitude();
|
|
double len12 = vec12.Magnitude();
|
|
double lenMax = Max( len10, len12 );
|
|
double arcRadius = arcRadiusFactor * lenMax;
|
|
|
|
p0 = p1.Translated( lenMax * vec10.Normalized() );
|
|
p2 = p1.Translated( lenMax * vec12.Normalized() );
|
|
|
|
gp_Circ arc( gp_Ax2( p1, norm, vec10 ), arcRadius );
|
|
|
|
int nbRadialSegmensts = ceil( radians / anglePerSeg ) + 1;
|
|
int nbNodes = 3 + ( nbRadialSegmensts + 1 );
|
|
|
|
// coordinates
|
|
preveiwData.nodesXYZ.length( nbNodes );
|
|
int iP = 0;
|
|
for ( ; iP < nbRadialSegmensts + 1; ++iP )
|
|
{
|
|
double u = double( iP ) / nbRadialSegmensts * radians;
|
|
gp_Pnt p = ElCLib::Value( u, arc );
|
|
preveiwData.nodesXYZ[ iP ].x = p.X();
|
|
preveiwData.nodesXYZ[ iP ].y = p.Y();
|
|
preveiwData.nodesXYZ[ iP ].z = p.Z();
|
|
}
|
|
int iP0 = iP;
|
|
preveiwData.nodesXYZ[ iP ].x = p0.X();
|
|
preveiwData.nodesXYZ[ iP ].y = p0.Y();
|
|
preveiwData.nodesXYZ[ iP ].z = p0.Z();
|
|
int iP1 = ++iP;
|
|
preveiwData.nodesXYZ[ iP ].x = p1.X();
|
|
preveiwData.nodesXYZ[ iP ].y = p1.Y();
|
|
preveiwData.nodesXYZ[ iP ].z = p1.Z();
|
|
int iP2 = ++iP;
|
|
preveiwData.nodesXYZ[ iP ].x = p2.X();
|
|
preveiwData.nodesXYZ[ iP ].y = p2.Y();
|
|
preveiwData.nodesXYZ[ iP ].z = p2.Z();
|
|
|
|
// connectivity
|
|
preveiwData.elementConnectivities.length( 2 * ( 2 + nbRadialSegmensts ));
|
|
for ( int iSeg = 0; iSeg < nbRadialSegmensts; ++iSeg )
|
|
{
|
|
preveiwData.elementConnectivities[ iSeg * 2 + 0 ] = iSeg;
|
|
preveiwData.elementConnectivities[ iSeg * 2 + 1 ] = iSeg + 1;
|
|
}
|
|
int iSeg = nbRadialSegmensts;
|
|
preveiwData.elementConnectivities[ iSeg * 2 + 0 ] = iP0;
|
|
preveiwData.elementConnectivities[ iSeg * 2 + 1 ] = iP1;
|
|
++iSeg;
|
|
preveiwData.elementConnectivities[ iSeg * 2 + 0 ] = iP1;
|
|
preveiwData.elementConnectivities[ iSeg * 2 + 1 ] = iP2;
|
|
|
|
// types
|
|
preveiwData.elementTypes.length( 2 + nbRadialSegmensts );
|
|
SMESH::ElementSubType type = { SMESH::EDGE, /*isPoly=*/false, /*nbNodesInElement=*/2 };
|
|
for ( CORBA::ULong i = 0; i < preveiwData.elementTypes.length(); ++i )
|
|
preveiwData.elementTypes[ i ] = type;
|
|
|
|
myPreview->SetData( preveiwData );
|
|
}
|
|
|
|
//================================================================================
|
|
/*!
|
|
* \brief Return normal to a plane of drawing in the case of 180 degrees angle
|
|
*/
|
|
//================================================================================
|
|
|
|
gp_Vec SMESHGUI_Angle::getNormal(const gp_Vec& vec10 )
|
|
{
|
|
gp_XYZ norm;
|
|
|
|
// try to get normal by a face at the 2nd node
|
|
if ( myActor && myActor->GetObject()->GetMesh() )
|
|
{
|
|
QStringList ids = myNodes->text().split( " ", QString::SkipEmptyParts );
|
|
SMDS_Mesh* mesh = myActor->GetObject()->GetMesh();
|
|
if ( const SMDS_MeshNode* n = mesh->FindNode( ids[1].trimmed().toLong() ))
|
|
{
|
|
SMDS_ElemIteratorPtr faceIt = n->GetInverseElementIterator( SMDSAbs_Face );
|
|
while ( faceIt->more() )
|
|
if ( SMESH_MeshAlgos::FaceNormal( faceIt->next(), norm ))
|
|
return norm;
|
|
}
|
|
}
|
|
int iMinCoord = 1;
|
|
if ( vec10.Coord( iMinCoord ) > vec10.Y() ) iMinCoord = 2;
|
|
if ( vec10.Coord( iMinCoord ) > vec10.Z() ) iMinCoord = 3;
|
|
|
|
gp_Vec vec = vec10;
|
|
vec.SetCoord( iMinCoord, vec10.Coord( iMinCoord ) + 1. );
|
|
|
|
return vec ^ vec10;
|
|
}
|
|
|
|
/*!
|
|
\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 );
|
|
|
|
SUIT_ResourceMgr* resMgr = SMESHGUI::resourceMgr();
|
|
|
|
myTabWidget = new QTabWidget( this );
|
|
|
|
// min distance
|
|
|
|
myMinDist = new SMESHGUI_MinDistance( myTabWidget );
|
|
int aMinDistInd = myTabWidget->addTab( myMinDist, resMgr->loadPixmap( "SMESH", tr( "ICON_MEASURE_MIN_DIST" ) ), tr( "MIN_DIST" ) );
|
|
|
|
// bounding box
|
|
|
|
myBndBox = new SMESHGUI_BoundingBox( myTabWidget );
|
|
int aBndBoxInd = myTabWidget->addTab( myBndBox, resMgr->loadPixmap( "SMESH", tr( "ICON_MEASURE_BND_BOX" ) ), tr( "BND_BOX" ) );
|
|
|
|
// basic properties
|
|
|
|
myBasicProps = new SMESHGUI_BasicProperties( myTabWidget );
|
|
int aBasicPropInd = myTabWidget->addTab( myBasicProps, resMgr->loadPixmap( "SMESH", tr( "ICON_MEASURE_BASIC_PROPS" ) ), tr( "BASIC_PROPERTIES" ) );
|
|
|
|
myAngle = new SMESHGUI_Angle( myTabWidget );
|
|
int aAngleInd = myTabWidget->addTab( myAngle, resMgr->loadPixmap( "SMESH", tr( "ICON_MEASURE_ANGLE" ) ), tr( "ANGLE" ) );
|
|
|
|
// 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 );
|
|
|
|
int anInd = -1;
|
|
if ( page == MinDistance ) {
|
|
anInd = aMinDistInd;
|
|
} else if ( page == BoundingBox ) {
|
|
anInd = aBndBoxInd;
|
|
} else if ( page == Angle ) {
|
|
anInd = aAngleInd;
|
|
} else if ( page == Length || page == Area || page == Volume ) {
|
|
myBasicProps->setMode( (SMESHGUI_BasicProperties::Mode)(page - Length) );
|
|
anInd = aBasicPropInd;
|
|
}
|
|
|
|
if ( anInd >= 0 ) {
|
|
myTabWidget->setCurrentIndex( anInd );
|
|
}
|
|
|
|
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();
|
|
else if ( myTabWidget->currentWidget() == myAngle )
|
|
myAngle->updateSelection();
|
|
else {
|
|
myBndBox->erasePreview();
|
|
myBasicProps->updateSelection();
|
|
}
|
|
}
|
|
|
|
/*!
|
|
\brief Show help page
|
|
*/
|
|
void SMESHGUI_MeasureDlg::help()
|
|
{
|
|
QString aHelpFile;
|
|
if ( myTabWidget->currentIndex() == MinDistance ) {
|
|
aHelpFile = "measurements.html#min-distance-anchor";
|
|
} else if ( myTabWidget->currentIndex() == BoundingBox ) {
|
|
aHelpFile = "measurements.html#bounding-box-anchor";
|
|
} else if ( myTabWidget->currentWidget() == myAngle ) {
|
|
aHelpFile = "measurements.html#angle-anchor";
|
|
} else {
|
|
aHelpFile = "measurements.html#basic-properties-anchor";
|
|
}
|
|
|
|
SMESH::ShowHelpFile( aHelpFile );
|
|
}
|
|
|
|
/*!
|
|
\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()
|
|
{
|
|
myBasicProps->deactivate();
|
|
myMinDist->deactivate();
|
|
myBndBox->deactivate();
|
|
myTabWidget->setEnabled( false );
|
|
disconnect( SMESHGUI::selectionMgr(), SIGNAL( currentSelectionChanged() ), this, SLOT( updateInfo() ) );
|
|
}
|