From: eap Date: Mon, 1 Aug 2016 12:42:08 +0000 (+0300) Subject: 23305: [EDF 10301] Extrusion with scaling X-Git-Tag: V8_1_0b1~9 X-Git-Url: http://git.salome-platform.org/gitweb/?p=modules%2Fsmesh.git;a=commitdiff_plain;h=5504d02a2237b17b8459bcd3b1fb2a89468598cd 23305: [EDF 10301] Extrusion with scaling --- diff --git a/doc/salome/gui/SMESH/images/extrusionalongaline1.png b/doc/salome/gui/SMESH/images/extrusionalongaline1.png index 5f0d13039..7de580be1 100644 Binary files a/doc/salome/gui/SMESH/images/extrusionalongaline1.png and b/doc/salome/gui/SMESH/images/extrusionalongaline1.png differ diff --git a/doc/salome/gui/SMESH/input/extrusion.doc b/doc/salome/gui/SMESH/input/extrusion.doc index 6b07af9e1..96da45d43 100644 --- a/doc/salome/gui/SMESH/input/extrusion.doc +++ b/doc/salome/gui/SMESH/input/extrusion.doc @@ -128,6 +128,25 @@ The following dialog will appear:
  • Specify the Number of steps.
  • + +
  • Optionally specify Scale Factors. Each scale factor in + the list is applied to nodes of a corresponding extrusion step + unless Linear Variation of Scale Factors is checked, is + which case the scale factors are spread over all extrusion steps.
  • + +
  • If you activate Generate Groups check-box, the result elements created from selected elements contained in groups will be included into new groups named by pattern "& theScales, + const gp_XYZ* theBasePoint, + const int theFlags, + const double theTolerance): myDir( theStep ), + myBaseP( Precision::Infinite(), 0, 0 ), myFlags( theFlags ), myTolerance( theTolerance ), myElemsToUse( NULL ) @@ -5494,6 +5497,37 @@ SMESH_MeshEditor::ExtrusParam::ExtrusParam( const gp_Vec& theStep, for (int i=1; i<=theNbSteps; i++ ) mySteps->Append( stepSize ); + int nbScales = theScales.size(); + if ( nbScales > 0 ) + { + if ( IsLinearVariation() && nbScales < theNbSteps ) + { + myScales.reserve( theNbSteps ); + std::list::const_iterator scale = theScales.begin(); + double prevScale = 1.0; + for ( int iSc = 1; scale != theScales.end(); ++scale, ++iSc ) + { + int iStep = int( iSc / double( nbScales ) * theNbSteps + 0.5 ); + int stDelta = Max( 1, iStep - myScales.size()); + double scDelta = ( *scale - prevScale ) / stDelta; + for ( int iStep = 0; iStep < stDelta; ++iStep ) + { + myScales.push_back( prevScale + scDelta ); + prevScale = myScales.back(); + } + prevScale = *scale; + } + } + else + { + myScales.assign( theScales.begin(), theScales.end() ); + } + } + if ( theBasePoint ) + { + myBaseP = *theBasePoint; + } + if (( theFlags & EXTRUSION_FLAG_SEW ) && ( theTolerance > 0 )) { @@ -5562,12 +5596,38 @@ SMESH_MeshEditor::ExtrusParam::ExtrusParam( const double theStepSize, //======================================================================= //function : ExtrusParam::SetElementsToUse //purpose : stores elements to use for extrusion by normal, depending on -// state of EXTRUSION_FLAG_USE_INPUT_ELEMS_ONLY flag +// state of EXTRUSION_FLAG_USE_INPUT_ELEMS_ONLY flag; +// define myBaseP for scaling //======================================================================= -void SMESH_MeshEditor::ExtrusParam::SetElementsToUse( const TIDSortedElemSet& elems ) +void SMESH_MeshEditor::ExtrusParam::SetElementsToUse( const TIDSortedElemSet& elems, + const TIDSortedElemSet& nodes ) { myElemsToUse = ToUseInpElemsOnly() ? & elems : 0; + + if ( Precision::IsInfinite( myBaseP.X() )) // myBaseP not defined + { + myBaseP.SetCoord( 0.,0.,0. ); + TIDSortedElemSet newNodes; + + const TIDSortedElemSet* elemSets[] = { &elems, &nodes }; + for ( int is2ndSet = 0; is2ndSet < 2; ++is2ndSet ) + { + const TIDSortedElemSet& elements = *( elemSets[ is2ndSet ]); + TIDSortedElemSet::const_iterator itElem = elements.begin(); + for ( ; itElem != elements.end(); itElem++ ) + { + const SMDS_MeshElement* elem = *itElem; + SMDS_ElemIteratorPtr itN = elem->nodesIterator(); + while ( itN->more() ) { + const SMDS_MeshElement* node = itN->next(); + if ( newNodes.insert( node ).second ) + myBaseP += SMESH_TNodeXYZ( node ); + } + } + } + myBaseP /= newNodes.size(); + } } //======================================================================= @@ -5637,6 +5697,41 @@ makeNodesByDir( SMESHDS_Mesh* mesh, const SMDS_MeshNode * newNode = mesh->AddNode( p.X(), p.Y(), p.Z() ); newNodes.push_back( newNode ); } + + if ( !myScales.empty() ) + { + if ( makeMediumNodes && myMediumScales.empty() ) + { + myMediumScales.resize( myScales.size() ); + double prevFactor = 1.; + for ( size_t i = 0; i < myScales.size(); ++i ) + { + myMediumScales[i] = 0.5 * ( prevFactor + myScales[i] ); + prevFactor = myScales[i]; + } + } + typedef std::vector::iterator ScaleIt; + ScaleIt scales[] = { myScales.begin(), myMediumScales.begin() }; + + size_t iSc = 0, nbScales = myScales.size() + myMediumScales.size(); + + gp_XYZ center = myBaseP; + std::list::iterator nIt = newNodes.begin(); + size_t iN = 0; + for ( beginStepIter( makeMediumNodes ); moreSteps() && ( iN < nbScales ); ++nIt, ++iN ) + { + center += myDir.XYZ() * nextStep(); + + iSc += int( makeMediumNodes ); + ScaleIt& scale = scales[ iSc % 2 ]; + + gp_XYZ xyz = SMESH_TNodeXYZ( *nIt ); + xyz = ( *scale * ( xyz - center )) + center; + mesh->MoveNode( *nIt, xyz.X(), xyz.Y(), xyz.Z() ); + + ++scale; + } + } return nbNodes; } @@ -5811,7 +5906,7 @@ SMESH_MeshEditor::ExtrusionSweep (TIDSortedElemSet theElems[2], const int theFlags, const double theTolerance) { - ExtrusParam aParams( theStep, theNbSteps, theFlags, theTolerance ); + ExtrusParam aParams( theStep, theNbSteps, std::list(), 0, theFlags, theTolerance ); return ExtrusionSweep( theElems, aParams, newElemsMap ); } @@ -5832,16 +5927,12 @@ SMESH_MeshEditor::ExtrusionSweep (TIDSortedElemSet theElemSets[2], // source elements for each generated one SMESH_SequenceOfElemPtr srcElems, srcNodes; - //SMESHDS_Mesh* aMesh = GetMeshDS(); - setElemsFirst( theElemSets ); const int nbSteps = theParams.NbSteps(); - theParams.SetElementsToUse( theElemSets[0] ); + theParams.SetElementsToUse( theElemSets[0], theElemSets[1] ); - TNodeOfNodeListMap mapNewNodes; - //TNodeOfNodeVecMap mapNewNodes; + TNodeOfNodeListMap mapNewNodes; TElemOfVecOfNnlmiMap mapElemNewNodes; - //TElemOfVecOfMapNodesMap mapElemNewNodes; const bool isQuadraticMesh = bool( myMesh->NbEdges(ORDER_QUADRATIC) + myMesh->NbFaces(ORDER_QUADRATIC) + @@ -6656,24 +6747,23 @@ SMESH_MeshEditor::MakeExtrElements(TIDSortedElemSet theElemSets //======================================================================= //function : LinearAngleVariation -//purpose : auxilary for ExtrusionAlongTrack +//purpose : spread values over nbSteps //======================================================================= -void SMESH_MeshEditor::LinearAngleVariation(const int nbSteps, + +void SMESH_MeshEditor::LinearAngleVariation(const int nbSteps, list& Angles) { int nbAngles = Angles.size(); - if( nbSteps > nbAngles ) { + if( nbSteps > nbAngles && nbAngles > 0 ) + { vector theAngles(nbAngles); - list::iterator it = Angles.begin(); - int i = -1; - for(; it!=Angles.end(); it++) { - i++; - theAngles[i] = (*it); - } + theAngles.assign( Angles.begin(), Angles.end() ); + list res; double rAn2St = double( nbAngles ) / double( nbSteps ); double angPrev = 0, angle; - for ( int iSt = 0; iSt < nbSteps; ++iSt ) { + for ( int iSt = 0; iSt < nbSteps; ++iSt ) + { double angCur = rAn2St * ( iSt+1 ); double angCurFloor = floor( angCur ); double angPrevFloor = floor( angPrev ); @@ -6695,10 +6785,7 @@ void SMESH_MeshEditor::LinearAngleVariation(const int nbSteps, res.push_back(angle); angPrev = angCur; } - Angles.clear(); - it = res.begin(); - for(; it!=res.end(); it++) - Angles.push_back( *it ); + Angles.swap( res ); } } diff --git a/src/SMESH/SMESH_MeshEditor.hxx b/src/SMESH/SMESH_MeshEditor.hxx index 4e9d0220d..5dd53807a 100644 --- a/src/SMESH/SMESH_MeshEditor.hxx +++ b/src/SMESH/SMESH_MeshEditor.hxx @@ -293,21 +293,26 @@ public: * else step size is measured along average normal of any element * USE_INPUT_ELEMS_ONLY: to use only input elements to compute extrusion direction * for ExtrusionByNormal() + * SCALE_LINEAR_VARIATION: to make linear variation of scale factors */ enum ExtrusionFlags { EXTRUSION_FLAG_BOUNDARY = 0x01, EXTRUSION_FLAG_SEW = 0x02, EXTRUSION_FLAG_GROUPS = 0x04, EXTRUSION_FLAG_BY_AVG_NORMAL = 0x08, - EXTRUSION_FLAG_USE_INPUT_ELEMS_ONLY = 0x10 + EXTRUSION_FLAG_USE_INPUT_ELEMS_ONLY = 0x10, + EXTRUSION_FLAG_SCALE_LINEAR_VARIATION = 0x20 }; /*! * Generator of nodes for extrusion functionality */ - class SMESH_EXPORT ExtrusParam { + class SMESH_EXPORT ExtrusParam + { gp_Dir myDir; // direction of extrusion Handle(TColStd_HSequenceOfReal) mySteps; // magnitudes for each step + std::vector myScales, myMediumScales;// scale factors + gp_XYZ myBaseP; // scaling center SMESH_SequenceOfNode myNodes; // nodes for using in sewing int myFlags; // see ExtrusionFlags double myTolerance; // tolerance for sewing nodes @@ -319,29 +324,33 @@ public: const bool makeMediumNodes); public: - ExtrusParam( const gp_Vec& theStep, - const int theNbSteps, - const int theFlags = 0, - const double theTolerance = 1e-6); + ExtrusParam( const gp_Vec& theStep, + const int theNbSteps, + const std::list& theScales, + const gp_XYZ* theBaseP, + const int theFlags = 0, + const double theTolerance = 1e-6); ExtrusParam( const gp_Dir& theDir, Handle(TColStd_HSequenceOfReal) theSteps, const int theFlags = 0, const double theTolerance = 1e-6); - ExtrusParam( const double theStep, - const int theNbSteps, - const int theFlags, - const int theDim); // for extrusion by normal + ExtrusParam( const double theStep, + const int theNbSteps, + const int theFlags, + const int theDim); // for extrusion by normal SMESH_SequenceOfNode& ChangeNodes() { return myNodes; } int& Flags() { return myFlags; } bool ToMakeBoundary() const { return myFlags & EXTRUSION_FLAG_BOUNDARY; } bool ToMakeGroups() const { return myFlags & EXTRUSION_FLAG_GROUPS; } bool ToUseInpElemsOnly() const { return myFlags & EXTRUSION_FLAG_USE_INPUT_ELEMS_ONLY; } + bool IsLinearVariation() const { return myFlags & EXTRUSION_FLAG_SCALE_LINEAR_VARIATION; } int NbSteps() const { return mySteps->Length(); } // stores elements to use for extrusion by normal, depending on - // state of EXTRUSION_FLAG_USE_INPUT_ELEMS_ONLY flag - void SetElementsToUse( const TIDSortedElemSet& elems ); + // state of EXTRUSION_FLAG_USE_INPUT_ELEMS_ONLY flag; + // define myBaseP for scaling + void SetElementsToUse( const TIDSortedElemSet& elems, const TIDSortedElemSet& nodes ); // creates nodes and returns number of nodes added in \a newNodes int MakeNodes( SMESHDS_Mesh* mesh, @@ -784,8 +793,8 @@ public: const bool theHasRefPoint, const gp_Pnt& theRefPoint, const bool theMakeGroups); - void LinearAngleVariation(const int NbSteps, - std::list& theAngles); + static void LinearAngleVariation(const int NbSteps, + std::list& theAngles); bool doubleNodes( SMESHDS_Mesh* theMeshDS, const TIDSortedElemSet& theElems, diff --git a/src/SMESHGUI/SMESHGUI_ExtrusionDlg.cxx b/src/SMESHGUI/SMESHGUI_ExtrusionDlg.cxx index af09f482c..6f944e520 100644 --- a/src/SMESHGUI/SMESHGUI_ExtrusionDlg.cxx +++ b/src/SMESHGUI/SMESHGUI_ExtrusionDlg.cxx @@ -28,58 +28,59 @@ #include "SMESHGUI_ExtrusionDlg.h" #include "SMESHGUI.h" -#include "SMESHGUI_Utils.h" -#include "SMESHGUI_VTKUtils.h" -#include "SMESHGUI_MeshUtils.h" -#include "SMESHGUI_SpinBox.h" -#include "SMESHGUI_IdValidator.h" #include "SMESHGUI_FilterDlg.h" +#include "SMESHGUI_IdValidator.h" #include "SMESHGUI_MeshEditPreview.h" - +#include "SMESHGUI_MeshUtils.h" +#include "SMESHGUI_SpinBox.h" +#include "SMESHGUI_Utils.h" +#include "SMESHGUI_VTKUtils.h" +#include +#include #include -#include #include - -#include +#include // SALOME GUI includes -#include +#include +#include #include #include -#include #include - -#include -#include - +#include +#include #include #include - #include // OCCT includes -#include +#include #include +#include +#include #include // Qt includes #include #include +#include +#include #include +#include +#include #include #include +#include #include #include -#include -#include +#include #include -#include -#include // IDL includes #include #include CORBA_SERVER_HEADER(SMESH_Group) #include CORBA_SERVER_HEADER(SMESH_MeshEditor) +#include #define SPACING 6 #define MARGIN 11 @@ -595,7 +596,10 @@ SMESHGUI_ExtrusionDlg::SMESHGUI_ExtrusionDlg (SMESHGUI* theModule) : SMESHGUI_PreviewDlg( theModule ), mySelectionMgr( SMESH::GetSelectionMgr( theModule ) ) { - QPixmap image (SMESH::GetResourceMgr( mySMESHGUI )->loadPixmap("SMESH", tr("ICON_SELECT"))); + SUIT_ResourceMgr* mgr = SMESH::GetResourceMgr( mySMESHGUI ); + QPixmap selectImage ( mgr->loadPixmap("SMESH", tr("ICON_SELECT"))); + QPixmap addImage ( mgr->loadPixmap("SMESH", tr("ICON_APPEND"))); + QPixmap removeImage ( mgr->loadPixmap("SMESH", tr("ICON_REMOVE"))); setModal( false ); setAttribute( Qt::WA_DeleteOnClose, true ); @@ -638,8 +642,8 @@ SMESHGUI_ExtrusionDlg::SMESHGUI_ExtrusionDlg (SMESHGUI* theModule) TextLabelVector = new QLabel(tr("SMESH_VECTOR"), GroupArguments); - SelectVectorButton = new QPushButton(GroupArguments); - SelectVectorButton->setIcon(image); + SelectVectorButton = new QPushButton( GroupArguments ); + SelectVectorButton->setIcon( selectImage ); SelectVectorButton->setCheckable( true ); SelectorWdg->GetButtonGroup()->addButton( SelectVectorButton ); @@ -671,6 +675,66 @@ SMESHGUI_ExtrusionDlg::SMESHGUI_ExtrusionDlg (SMESHGUI* theModule) //Preview check box myPreviewCheckBox = new QCheckBox(tr("PREVIEW"), GroupArguments); + // Base point + + BasePointGrp = new QGroupBox(tr("BASE_POINT"), GroupArguments); + BasePointGrp->setCheckable(true); + BasePointGrp->setChecked(false); + QHBoxLayout* BasePointGrpLayout = new QHBoxLayout(BasePointGrp); + BasePointGrpLayout->setSpacing(SPACING); BasePointGrpLayout->setMargin(MARGIN); + + SelectBasePointButton = new QPushButton(BasePointGrp); + SelectBasePointButton->setIcon(selectImage); + SelectBasePointButton->setCheckable(true); + SelectorWdg->GetButtonGroup()->addButton( SelectBasePointButton ); + + QLabel* XLab = new QLabel(tr("SMESH_X"), BasePointGrp); + BasePoint_XSpin = new SMESHGUI_SpinBox(BasePointGrp); + BasePoint_XSpin->SetValue(0.); + QLabel* YLab = new QLabel(tr("SMESH_Y"), BasePointGrp); + BasePoint_YSpin = new SMESHGUI_SpinBox(BasePointGrp); + BasePoint_YSpin->SetValue(0.); + QLabel* ZLab = new QLabel(tr("SMESH_Z"), BasePointGrp); + BasePoint_ZSpin = new SMESHGUI_SpinBox(BasePointGrp); + BasePoint_ZSpin->SetValue(0.); + + BasePointGrpLayout->addWidget(SelectBasePointButton); + BasePointGrpLayout->addWidget(XLab); + BasePointGrpLayout->addWidget(BasePoint_XSpin, 1); + BasePointGrpLayout->addWidget(YLab); + BasePointGrpLayout->addWidget(BasePoint_YSpin, 1); + BasePointGrpLayout->addWidget(ZLab); + BasePointGrpLayout->addWidget(BasePoint_ZSpin, 1); + + // Scales + + ScalesGrp = new QGroupBox(tr("SMESH_SCALES"), GroupArguments); + QGridLayout* ScalesGrpLayout = new QGridLayout( ScalesGrp ); + ScalesGrpLayout->setSpacing(SPACING); ScalesGrpLayout->setMargin(MARGIN); + + ScalesList = new QListWidget( ScalesGrp ); + ScalesList->setSelectionMode(QListWidget::ExtendedSelection); + + AddScaleButton = new QToolButton( ScalesGrp ); + AddScaleButton->setIcon( addImage ); + + RemoveScaleButton = new QToolButton( ScalesGrp ); + RemoveScaleButton->setIcon( removeImage ); + + ScaleSpin = new SMESHGUI_SpinBox( ScalesGrp ); + ScaleSpin->SetValue(2); + + LinearScalesCheck = new QCheckBox(tr("LINEAR_SCALES"), ScalesGrp ); + + ScalesGrpLayout->addWidget(ScalesList, 0, 0, 4, 1); + ScalesGrpLayout->addWidget(AddScaleButton, 0, 1); + ScalesGrpLayout->addWidget(RemoveScaleButton, 2, 1); + ScalesGrpLayout->addWidget(ScaleSpin, 0, 2); + ScalesGrpLayout->addWidget(LinearScalesCheck, 4, 0); + ScalesGrpLayout->setRowMinimumHeight(1, 10); + ScalesGrpLayout->setRowStretch(3, 10); + + // layouting GroupArgumentsLayout->addWidget(SelectorWdg, 0, 0, 1, 9); GroupArgumentsLayout->addWidget(ExtrMethod_RBut0, 1, 0, 1, 3); GroupArgumentsLayout->addWidget(ExtrMethod_RBut1, 1, 3, 1, 3); @@ -696,8 +760,10 @@ SMESHGUI_ExtrusionDlg::SMESHGUI_ExtrusionDlg (SMESHGUI* theModule) GroupArgumentsLayout->addWidget(SpinBox_NbSteps, 5, 3); GroupArgumentsLayout->addWidget(ByAverageNormalCheck, 6, 0, 1, 4); GroupArgumentsLayout->addWidget(UseInputElemsOnlyCheck, 6, 4, 1, 4); - GroupArgumentsLayout->addWidget(myPreviewCheckBox, 7, 0, 1, 8); - GroupArgumentsLayout->addWidget(MakeGroupsCheck, 8, 0, 1, 8); + GroupArgumentsLayout->addWidget(BasePointGrp, 7, 0, 1, 9); + GroupArgumentsLayout->addWidget(ScalesGrp, 8, 0, 1, 9); + GroupArgumentsLayout->addWidget(myPreviewCheckBox, 9, 0, 1, 8); + GroupArgumentsLayout->addWidget(MakeGroupsCheck, 10,0, 1, 8); GroupArgumentsLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding), 10, 0); /***************************************************************/ @@ -740,6 +806,11 @@ SMESHGUI_ExtrusionDlg::SMESHGUI_ExtrusionDlg (SMESHGUI* theModule) SpinBox_NbSteps->setRange(1, 999999); SpinBox_VDist->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, "length_precision"); + BasePoint_XSpin->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, "length_precision"); + BasePoint_YSpin->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, "length_precision"); + BasePoint_ZSpin->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, "length_precision"); + ScaleSpin->RangeStepAndValidator (COORD_MIN, COORD_MAX, 1.0, "length_precision"); + ExtrMethod_RBut0->setChecked(true); UseInputElemsOnlyCheck->setChecked(true); MakeGroupsCheck->setChecked(true); @@ -771,7 +842,13 @@ SMESHGUI_ExtrusionDlg::SMESHGUI_ExtrusionDlg (SMESHGUI* theModule) connect(SpinBox_Dy, SIGNAL(valueChanged(double)), SLOT(CheckIsEnable())); connect(SpinBox_Dz, SIGNAL(valueChanged(double)), SLOT(CheckIsEnable())); + connect(AddScaleButton, SIGNAL(clicked()), this, SLOT(OnScaleAdded())); + connect(RemoveScaleButton, SIGNAL(clicked()), this, SLOT(OnScaleRemoved())); + connect(SelectVectorButton, SIGNAL(clicked()), this, SLOT(SetEditCurrentArgument())); + connect(SelectBasePointButton,SIGNAL(clicked()), this, SLOT(SetEditCurrentArgument())); + connect(BasePointGrp, SIGNAL(toggled(bool)), this, SLOT(SetEditCurrentArgument())); + connect(BasePointGrp, SIGNAL(toggled(bool)), SelectBasePointButton, SLOT(click())); connect(mySMESHGUI, SIGNAL(SignalDeactivateActiveDialog()), SLOT(DeactivateActiveDialog())); connect(mySelectionMgr, SIGNAL(currentSelectionChanged()), SLOT(toDisplaySimulation())); connect(SelectorWdg, SIGNAL(selectionChanged()), this, SLOT(toDisplaySimulation())); @@ -791,6 +868,13 @@ SMESHGUI_ExtrusionDlg::SMESHGUI_ExtrusionDlg (SMESHGUI* theModule) connect(SpinBox_NbSteps, SIGNAL(valueChanged(int)), this, SLOT(toDisplaySimulation())); connect(ByAverageNormalCheck, SIGNAL(toggled(bool)), this, SLOT(toDisplaySimulation())); connect(UseInputElemsOnlyCheck, SIGNAL(toggled(bool)), this, SLOT(toDisplaySimulation())); + connect(AddScaleButton, SIGNAL(clicked()), this, SLOT(toDisplaySimulation())); + connect(RemoveScaleButton, SIGNAL(clicked()), this, SLOT(toDisplaySimulation())); + connect(LinearScalesCheck, SIGNAL(toggled(bool)), this, SLOT(toDisplaySimulation())); + connect(BasePointGrp, SIGNAL(toggled(bool)), this, SLOT(toDisplaySimulation())); + connect(BasePoint_XSpin, SIGNAL(valueChanged(double)), this, SLOT(toDisplaySimulation())); + connect(BasePoint_YSpin, SIGNAL(valueChanged(double)), this, SLOT(toDisplaySimulation())); + connect(BasePoint_ZSpin, SIGNAL(valueChanged(double)), this, SLOT(toDisplaySimulation())); //To Connect preview check box connectPreviewControl(); @@ -875,6 +959,31 @@ bool SMESHGUI_ExtrusionDlg::isValuesValid() return aModule > 1.0E-38; } +//======================================================================= +//function : getScaleParams +//purpose : return 3 scaling parameters +//======================================================================= + +bool SMESHGUI_ExtrusionDlg::getScaleParams( SMESH::double_array*& scales, + SMESH::double_array*& basePoint ) +{ + scales = new SMESH::double_array; + scales->length( myScalesList.count() ); + for ( int i = 0; i < myScalesList.count(); ++i ) + (*scales)[i] = myScalesList[i]; + + basePoint = new SMESH::double_array; + if ( BasePointGrp->isChecked() ) + { + basePoint->length( 3 ); + (*basePoint)[0] = BasePoint_XSpin->GetValue(); + (*basePoint)[1] = BasePoint_YSpin->GetValue(); + (*basePoint)[2] = BasePoint_ZSpin->GetValue(); + } + + return ( scales->length() > 0 && LinearScalesCheck->isChecked() ); +} + //================================================================================= // function : ClickOnRadio() // purpose : Radio button management @@ -989,7 +1098,7 @@ bool SMESHGUI_ExtrusionDlg::ClickOnApply() { SMESH::DirStruct aVector; getExtrusionVector(aVector); - + QStringList aParameters; if ( ExtrMethod_RBut0->isChecked() ) { @@ -1011,14 +1120,22 @@ bool SMESHGUI_ExtrusionDlg::ClickOnApply() } long aNbSteps = (long)SpinBox_NbSteps->value(); - aParameters << SpinBox_NbSteps->text(); + SMESH::double_array_var scales = new SMESH::double_array; + scales->length( myScalesList.count() ); + for (int i = 0; i < myScalesList.count(); i++) + { + scales[i] = myScalesList[i]; + aParameters << ScalesList->item(i)->text(); + } + bool meshHadNewTypeBefore = true; int maxSelType = 0; const bool makeGroups = ( MakeGroupsCheck->isEnabled() && MakeGroupsCheck->isChecked() ); - try { + try + { SUIT_OverrideCursor aWaitCursor; SMESH::SMESH_Mesh_var mesh = SelectorWdg->GetMesh(); @@ -1054,8 +1171,12 @@ bool SMESHGUI_ExtrusionDlg::ClickOnApply() } else { + SMESH::double_array_var scales, basePoint; + bool linVariation = getScaleParams( scales.out(), basePoint.out() ); groups = meshEditor->ExtrusionSweepObjects( nodes, edges, faces, - aVector, aNbSteps, makeGroups ); + aVector, aNbSteps, + scales, linVariation, basePoint, + makeGroups ); } } catch (...) { @@ -1180,13 +1301,13 @@ void SMESHGUI_ExtrusionDlg::SelectionIntoArgument() if (!GroupButtons->isEnabled()) return; + SALOME_ListIO aList; + mySelectionMgr->selectedObjects(aList); + if ( aList.IsEmpty() || aList.Extent() > 1 ) + return; + if ( SelectVectorButton->isChecked() ) { - SALOME_ListIO aList; - mySelectionMgr->selectedObjects(aList); - if ( aList.IsEmpty() || aList.Extent() > 1 ) - return; - Handle(SALOME_InteractiveObject) IO = aList.First(); TColStd_IndexedMapOfInteger aMapIndex; mySelector->GetIndex(IO,aMapIndex); @@ -1207,6 +1328,56 @@ void SMESHGUI_ExtrusionDlg::SelectionIntoArgument() SpinBox_Vy->SetValue(aNormale.Y()); SpinBox_Vz->SetValue(aNormale.Z()); } + else if ( SelectBasePointButton->isChecked() ) + { + if (!BasePointGrp->isChecked()) + return; + + // try to get shape from selection + Handle(SALOME_InteractiveObject) IO = aList.First(); + + // check if geom vertex is selected + GEOM::GEOM_Object_var aGeomObj = SMESH::IObjectToInterface(IO); + TopoDS_Vertex aVertex; + if (!aGeomObj->_is_nil()) { + if (aGeomObj->IsShape() && GEOMBase::GetShape(aGeomObj, aVertex) && !aVertex.IsNull()) { + gp_Pnt aPnt = BRep_Tool::Pnt(aVertex); + BasePoint_XSpin->SetValue(aPnt.X()); + BasePoint_YSpin->SetValue(aPnt.Y()); + BasePoint_ZSpin->SetValue(aPnt.Z()); + } + } + + if ( aVertex.IsNull() ) + { + // check if smesh node is selected + SMESH::SMESH_Mesh_var aMesh = SMESH::GetMeshByIO(IO); + if (aMesh->_is_nil()) + return; + + QString aString; + int aNbUnits = SMESH::GetNameOfSelectedNodes(mySelector, IO, aString); + // return if more than one node is selected + if (aNbUnits != 1) + return; + + SMESH_Actor* aMeshActor = SMESH::FindActorByObject(aMesh); + if (!aMeshActor) + return; + + SMDS_Mesh* mesh = aMeshActor->GetObject()->GetMesh(); + if (!mesh) + return; + + const SMDS_MeshNode* n = mesh->FindNode(aString.toLong()); + if (!n) + return; + + BasePoint_XSpin->SetValue(n->X()); + BasePoint_YSpin->SetValue(n->Y()); + BasePoint_ZSpin->SetValue(n->Z()); + } + } onDisplaySimulation(true); CheckIsEnable(); @@ -1229,6 +1400,21 @@ void SMESHGUI_ExtrusionDlg::SetEditCurrentArgument() if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI )) aViewWindow->SetSelectionMode(FaceSelection); } + else if ( send == SelectBasePointButton ) + { + SMESH::SetPointRepresentation(true); + if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI )) + aViewWindow->SetSelectionMode(NodeSelection); + + SMESH_TypeFilter* aMeshOrSubMeshFilter = new SMESH_TypeFilter(SMESH::IDSOURCE); + SMESH_NumberFilter* aVertexFilter = new SMESH_NumberFilter ("GEOM", TopAbs_VERTEX, + 1, TopAbs_VERTEX); + QList aListOfFilters; + aListOfFilters << aMeshOrSubMeshFilter << aVertexFilter; + + mySelectionMgr->installFilter(new SMESH_LogicalFilter + (aListOfFilters, SMESH_LogicalFilter::LO_OR, true)); + } connect(mySelectionMgr, SIGNAL(currentSelectionChanged()), this, SLOT(SelectionIntoArgument())); SelectionIntoArgument(); @@ -1316,6 +1502,12 @@ bool SMESHGUI_ExtrusionDlg::isValid() } ok = SpinBox_NbSteps->isValid( msg, true ) && ok; + if ( BasePointGrp->isChecked()) { + ok = BasePoint_XSpin->isValid( msg, true ) && ok; + ok = BasePoint_YSpin->isValid( msg, true ) && ok; + ok = BasePoint_ZSpin->isValid( msg, true ) && ok; + } + if( !ok ) { QString str( tr( "SMESH_INCORRECT_INPUT" ) ); if ( !msg.isEmpty() ) @@ -1369,8 +1561,12 @@ void SMESHGUI_ExtrusionDlg::onDisplaySimulation( bool toDisplayPreview ) } else { + SMESH::double_array_var scales, basePoint; + bool linVariation = getScaleParams( scales.out(), basePoint.out() ); groups = meshEditor->ExtrusionSweepObjects( nodes, edges, faces, - aVector, aNbSteps, makeGroups ); + aVector, aNbSteps, + scales, linVariation, basePoint, + makeGroups ); } SMESH::MeshPreviewStruct_var aMeshPreviewStruct = meshEditor->GetPreviewData(); mySimulation->SetData(aMeshPreviewStruct._retn()); @@ -1411,3 +1607,38 @@ void SMESHGUI_ExtrusionDlg::getExtrusionVector(SMESH::DirStruct& aVector) aVector.PS.z = aNormale.Z()*aVDist; } } + +//======================================================================= +// function : OnScaleAdded() +// purpose : Called when user adds Scale to the list +//======================================================================= +void SMESHGUI_ExtrusionDlg::OnScaleAdded() +{ + QString msg; + if( !ScaleSpin->isValid( msg, true ) ) { + QString str( tr( "SMESH_INCORRECT_INPUT" ) ); + if ( !msg.isEmpty() ) + str += "\n" + msg; + SUIT_MessageBox::critical( this, tr( "SMESH_ERROR" ), str ); + return; + } + ScalesList->addItem(ScaleSpin->text()); + myScalesList.append(ScaleSpin->GetValue()); +} + +//======================================================================= +// function : OnScaleRemoved() +// purpose : Called when user removes Scale(s) from the list +//======================================================================= +void SMESHGUI_ExtrusionDlg::OnScaleRemoved() +{ + QList aList = ScalesList->selectedItems(); + QListWidgetItem* anItem; + int row = 0; + foreach(anItem, aList) { + row = ScalesList->row(anItem); + myScalesList.removeAt(row); + delete anItem; + } + ScalesList->setCurrentRow( row, QItemSelectionModel::Select ); +} diff --git a/src/SMESHGUI/SMESHGUI_ExtrusionDlg.h b/src/SMESHGUI/SMESHGUI_ExtrusionDlg.h index ed94f5c84..b86138e08 100644 --- a/src/SMESHGUI/SMESHGUI_ExtrusionDlg.h +++ b/src/SMESHGUI/SMESHGUI_ExtrusionDlg.h @@ -41,12 +41,14 @@ #include CORBA_SERVER_HEADER(SMESH_MeshEditor) class QButtonGroup; -class QRadioButton; +class QCheckBox; class QGroupBox; class QLabel; class QLineEdit; -class QCheckBox; +class QListWidget; class QPushButton; +class QRadioButton; +class QToolButton; class SMESHGUI; class SMESH_Actor; @@ -59,7 +61,7 @@ class SUIT_SelectionFilter; class SalomeApp_IntSpinBox; //================================================================================= -// class : SMESHGUI_ExtrusionDlg +// class : SMESHGUI_3TypesSelector // purpose : A widget used to select both nodes, edges and faces for // Extrusion and Revolution operations //================================================================================= @@ -143,12 +145,15 @@ private: void getExtrusionVector(SMESH::DirStruct& aVector); void extrusionByNormal(SMESH::SMESH_MeshEditor_ptr meshEditor, const bool makeGroups=false); + bool getScaleParams( SMESH::double_array*& scales, + SMESH::double_array*& basePoint ); bool isValid(); bool isValuesValid(); LightApp_SelectionMgr* mySelectionMgr; /* User shape selection */ SVTK_Selector* mySelector; + QList myScalesList; // widgets SMESHGUI_3TypesSelector* SelectorWdg; @@ -180,6 +185,18 @@ private: QCheckBox* UseInputElemsOnlyCheck; QCheckBox* MakeGroupsCheck; + QCheckBox* LinearScalesCheck; + QGroupBox* ScalesGrp; + QListWidget* ScalesList; + QToolButton* AddScaleButton; + QToolButton* RemoveScaleButton; + SMESHGUI_SpinBox* ScaleSpin; + QGroupBox* BasePointGrp; + QPushButton* SelectBasePointButton; + SMESHGUI_SpinBox* BasePoint_XSpin; + SMESHGUI_SpinBox* BasePoint_YSpin; + SMESHGUI_SpinBox* BasePoint_ZSpin; + QGroupBox* GroupButtons; QPushButton* buttonOk; QPushButton* buttonCancel; @@ -205,6 +222,8 @@ private slots: void ActivateThisDialog(); void onOpenView(); void onCloseView(); + void OnScaleAdded(); + void OnScaleRemoved(); }; diff --git a/src/SMESHGUI/SMESH_msg_en.ts b/src/SMESHGUI/SMESH_msg_en.ts index a235b9cc9..6f6d0c605 100644 --- a/src/SMESHGUI/SMESH_msg_en.ts +++ b/src/SMESHGUI/SMESH_msg_en.ts @@ -5267,6 +5267,18 @@ Please select a group and try again USE_INPUT_ELEMS_ONLY Use only input elements + + SMESH_SCALES + Scale Factors + + + LINEAR_SCALES + Linear Variation of Scale Factors + + + BASE_POINT + Scaling Center + SMESHGUI_FilterDlg diff --git a/src/SMESH_I/SMESH_MeshEditor_i.cxx b/src/SMESH_I/SMESH_MeshEditor_i.cxx index cecee4596..f9fb06334 100644 --- a/src/SMESH_I/SMESH_MeshEditor_i.cxx +++ b/src/SMESH_I/SMESH_MeshEditor_i.cxx @@ -2484,6 +2484,7 @@ namespace MeshEditor_I bool myIsExtrusionByNormal; static int makeFlags( CORBA::Boolean MakeGroups, + CORBA::Boolean LinearVariation = false, CORBA::Boolean ByAverageNormal = false, CORBA::Boolean UseInputElemsOnly = false, CORBA::Long Flags = 0, @@ -2492,18 +2493,24 @@ namespace MeshEditor_I if ( MakeGroups ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS; if ( ByAverageNormal ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BY_AVG_NORMAL; if ( UseInputElemsOnly) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_USE_INPUT_ELEMS_ONLY; + if ( LinearVariation ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_SCALE_LINEAR_VARIATION; if ( MakeBoundary ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BOUNDARY; return Flags; } // standard params - ExtrusionParams(const SMESH::DirStruct & theDir, - CORBA::Long theNbOfSteps, - CORBA::Boolean theMakeGroups): + ExtrusionParams(const SMESH::DirStruct & theDir, + CORBA::Long theNbOfSteps, + const SMESH::double_array & theScaleFactors, + CORBA::Boolean theLinearVariation, + const SMESH::double_array & theBasePoint, + CORBA::Boolean theMakeGroups): ::SMESH_MeshEditor::ExtrusParam ( gp_Vec( theDir.PS.x, theDir.PS.y, theDir.PS.z ), theNbOfSteps, - makeFlags( theMakeGroups )), + toList( theScaleFactors ), + TBasePoint( theBasePoint ), + makeFlags( theMakeGroups, theLinearVariation )), myIsExtrusionByNormal( false ) { } @@ -2517,7 +2524,9 @@ namespace MeshEditor_I theDir.PS.y, theDir.PS.z ), theNbOfSteps, - makeFlags( theMakeGroups, false, false, + std::list(), + 0, + makeFlags( theMakeGroups, false, false, false, theExtrFlags, false ), theSewTolerance ), myIsExtrusionByNormal( false ) @@ -2532,7 +2541,7 @@ namespace MeshEditor_I CORBA::Boolean theMakeGroups ): ::SMESH_MeshEditor::ExtrusParam ( theStepSize, theNbOfSteps, - makeFlags( theMakeGroups, + makeFlags( theMakeGroups, false, theByAverageNormal, theUseInputElemsOnly ), theDim), myIsExtrusionByNormal( true ) @@ -2543,6 +2552,32 @@ namespace MeshEditor_I { Flags() &= ~(::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS); } + + private: + + static std::list toList( const SMESH::double_array & theScaleFactors ) + { + std::list scales; + for ( CORBA::ULong i = 0; i < theScaleFactors.length(); ++i ) + scales.push_back( theScaleFactors[i] ); + return scales; + } + + // structure used to convert SMESH::double_array to gp_XYZ* + struct TBasePoint + { + gp_XYZ *pp, p; + TBasePoint( const SMESH::double_array & theBasePoint ) + { + pp = 0; + if ( theBasePoint.length() == 3 ) + { + p.SetCoord( theBasePoint[0], theBasePoint[1], theBasePoint[2] ); + pp = &p; + } + } + operator const gp_XYZ*() const { return pp; } + }; }; } @@ -2566,13 +2601,17 @@ SMESH_MeshEditor_i::ExtrusionSweepObjects(const SMESH::ListOfIDSources & theNode const SMESH::ListOfIDSources & theFaces, const SMESH::DirStruct & theStepVector, CORBA::Long theNbOfSteps, + const SMESH::double_array & theScaleFactors, + CORBA::Boolean theLinearVariation, + const SMESH::double_array & theBasePoint, CORBA::Boolean theToMakeGroups) throw (SALOME::SALOME_Exception) { SMESH_TRY; initData(); - ExtrusionParams params( theStepVector, theNbOfSteps, theToMakeGroups ); + ExtrusionParams params( theStepVector, theNbOfSteps, theScaleFactors, + theLinearVariation, theBasePoint, theToMakeGroups ); TIDSortedElemSet elemsNodes[2]; for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) { @@ -2916,13 +2955,13 @@ SMESH_MeshEditor_i::ExtrusionAlongPathObjects(const SMESH::ListOfIDSources & the << thePathShape << ", " << theNodeStart << ", " << theHasAngles << ", " - << theAngles << ", " + << TVar( theAngles ) << ", " << theLinearVariation << ", " << theHasRefPoint << ", " << "SMESH.PointStruct( " - << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", " - << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", " - << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ), " + << TVar( theHasRefPoint ? theRefPoint.x : 0 ) << ", " + << TVar( theHasRefPoint ? theRefPoint.y : 0 ) << ", " + << TVar( theHasRefPoint ? theRefPoint.z : 0 ) << " ), " << theMakeGroups << " )"; } else diff --git a/src/SMESH_I/SMESH_MeshEditor_i.hxx b/src/SMESH_I/SMESH_MeshEditor_i.hxx index c3b0a4286..ab953091e 100644 --- a/src/SMESH_I/SMESH_MeshEditor_i.hxx +++ b/src/SMESH_I/SMESH_MeshEditor_i.hxx @@ -330,6 +330,9 @@ public: const SMESH::ListOfIDSources & faces, const SMESH::DirStruct & stepVector, CORBA::Long nbOfSteps, + const SMESH::double_array & theScaleFactors, + CORBA::Boolean theLinearVariation, + const SMESH::double_array & theBasePoint, CORBA::Boolean toMakeGroups) throw (SALOME::SALOME_Exception); diff --git a/src/SMESH_SWIG/smeshBuilder.py b/src/SMESH_SWIG/smeshBuilder.py index f56f9551c..b4da6ea8e 100644 --- a/src/SMESH_SWIG/smeshBuilder.py +++ b/src/SMESH_SWIG/smeshBuilder.py @@ -3820,17 +3820,27 @@ class Mesh: NbOfSteps, Tolerance, MakeGroups, TotalAngle) ## Generates new elements by extrusion of the given elements and nodes - # @param nodes - nodes to extrude: a list including ids, groups, sub-meshes or a mesh - # @param edges - edges to extrude: a list including ids, groups, sub-meshes or a mesh - # @param faces - faces to extrude: a list including ids, groups, sub-meshes or a mesh + # @param nodes nodes to extrude: a list including ids, groups, sub-meshes or a mesh + # @param edges edges to extrude: a list including ids, groups, sub-meshes or a mesh + # @param faces faces to extrude: a list including ids, groups, sub-meshes or a mesh # @param StepVector vector or DirStruct or 3 vector components, defining # the direction and value of extrusion for one step (the total extrusion # length will be NbOfSteps * ||StepVector||) # @param NbOfSteps the number of steps # @param MakeGroups forces the generation of new groups from existing ones + # @param scaleFactors optional scale factors to apply during extrusion + # @param linearVariation if @c True, scaleFactors are spread over all @a scaleFactors, + # else scaleFactors[i] is applied to nodes at the i-th extrusion step + # @param basePoint optional scaling center; if not provided, a gravity center of + # nodes and elements being extruded is used as the scaling center. + # It can be either + # - a list of tree components of the point or + # - a node ID or + # - a GEOM point # @return the list of created groups (SMESH_GroupBase) if MakeGroups=True, empty list otherwise # @ingroup l2_modif_extrurev - def ExtrusionSweepObjects(self, nodes, edges, faces, StepVector, NbOfSteps, MakeGroups=False): + def ExtrusionSweepObjects(self, nodes, edges, faces, StepVector, NbOfSteps, MakeGroups=False, + scaleFactors=[], linearVariation=False, basePoint=[] ): unRegister = genObjUnRegister() nodes = self._getIdSourceList( nodes, SMESH.NODE, unRegister ) edges = self._getIdSourceList( edges, SMESH.EDGE, unRegister ) @@ -3841,12 +3851,22 @@ class Mesh: if isinstance( StepVector, list ): StepVector = self.smeshpyD.MakeDirStruct(*StepVector) + if isinstance( basePoint, int): + xyz = self.GetNodeXYZ( basePoint ) + if not xyz: + raise RuntimeError, "Invalid node ID: %s" % basePoint + basePoint = xyz + if isinstance( basePoint, geomBuilder.GEOM._objref_GEOM_Object ): + basePoint = self.geompyD.PointCoordinates( basePoint ) + NbOfSteps,Parameters,hasVars = ParseParameters(NbOfSteps) Parameters = StepVector.PS.parameters + var_separator + Parameters self.mesh.SetParameters(Parameters) return self.editor.ExtrusionSweepObjects( nodes, edges, faces, - StepVector, NbOfSteps, MakeGroups) + StepVector, NbOfSteps, + scaleFactors, linearVariation, basePoint, + MakeGroups) ## Generates new elements by extrusion of the elements with given ids diff --git a/src/StdMeshers/StdMeshers_RadialQuadrangle_1D2D.cxx b/src/StdMeshers/StdMeshers_RadialQuadrangle_1D2D.cxx index 4f2329d59..9de37716a 100644 --- a/src/StdMeshers/StdMeshers_RadialQuadrangle_1D2D.cxx +++ b/src/StdMeshers/StdMeshers_RadialQuadrangle_1D2D.cxx @@ -732,13 +732,13 @@ protected: void StdMeshers_RadialQuadrangle_1D2D::SubmeshRestored(SMESH_subMesh* faceSubMesh) { - // if ( !faceSubMesh->IsEmpty() ) - // { - // for ( TopExp_Explorer e( faceSubMesh->GetSubShape(), TopAbs_EDGE ); e.More(); e.Next() ) - // { - // markEdgeAsComputedByMe( TopoDS::Edge( e.Current() ), faceSubMesh ); - // } - // } + if ( !faceSubMesh->IsEmpty() ) + { + for ( TopExp_Explorer e( faceSubMesh->GetSubShape(), TopAbs_EDGE ); e.More(); e.Next() ) + { + markEdgeAsComputedByMe( TopoDS::Edge( e.Current() ), faceSubMesh ); + } + } } //======================================================================= @@ -762,12 +762,12 @@ bool StdMeshers_RadialQuadrangle_1D2D::Compute(SMESH_Mesh& aMesh, "of edges is less or equal to 3 and one of them is an ellipse curve)"); // get not yet computed EDGEs - // list< TopoDS_Edge > emptyEdges; - // for ( TopExp_Explorer e( aShape, TopAbs_EDGE ); e.More(); e.Next() ) - // { - // if ( aMesh.GetSubMesh( e.Current() )->IsEmpty() ) - // emptyEdges.push_back( TopoDS::Edge( e.Current() )); - // } + list< TopoDS_Edge > emptyEdges; + for ( TopExp_Explorer e( aShape, TopAbs_EDGE ); e.More(); e.Next() ) + { + if ( aMesh.GetSubMesh( e.Current() )->IsEmpty() ) + emptyEdges.push_back( TopoDS::Edge( e.Current() )); + } TNodeDistributor* algo1d = TNodeDistributor::GetDistributor(aMesh); @@ -941,9 +941,9 @@ bool StdMeshers_RadialQuadrangle_1D2D::Compute(SMESH_Mesh& aMesh, centerUV = nodes2.back().UV(); } - // list< TopoDS_Edge >::iterator ee = emptyEdges.begin(); - // for ( ; ee != emptyEdges.end(); ++ee ) - // markEdgeAsComputedByMe( *ee, aMesh.GetSubMesh( F )); + list< TopoDS_Edge >::iterator ee = emptyEdges.begin(); + for ( ; ee != emptyEdges.end(); ++ee ) + markEdgeAsComputedByMe( *ee, aMesh.GetSubMesh( F )); circSide->GetUVPtStruct(); // let sides take into account just computed nodes linSide1->GetUVPtStruct();