22877: EDF 10054 SMESH: Add a new filter "BelongToSmeshGroup" for Create Group

This commit is contained in:
eap 2015-04-14 15:39:28 +03:00
parent 62ba95d8ac
commit 5ac2bd91a8
24 changed files with 784 additions and 207 deletions

View File

@ -95,6 +95,7 @@ SET(GOOD_TESTS
filters_ex33.py
filters_ex34.py
filters_ex36.py
filters_belong2group.py
grouping_elements_ex01.py
grouping_elements_ex02.py
grouping_elements_ex03.py

View File

@ -0,0 +1,18 @@
# Belong to Mesh Group criterion
# create mesh
from SMESH_mechanic import *
# create a group of all faces (quadrangles) generated on sub_face3
faces_on_face3 = mesh.MakeGroup("faces_on_face3", SMESH.FACE, SMESH.FT_BelongToGeom,'=',sub_face3)
print "There are %s quadrangles generated on '%s' and included in the group '%s'" % ( faces_on_face3.Size(), sub_face3.GetName(), faces_on_face3.GetName() )
# create a group of all the rest quadrangles, generated on other faces by combining 2 criteria:
# - negated FT_BelongToMeshGroup to select elements not included in faces_on_face3
# - FT_ElemGeomType to select quadrangles
not_on_face3 = smesh.GetCriterion( SMESH.FACE, SMESH.FT_BelongToMeshGroup,'=',faces_on_face3, SMESH.FT_LogicalNOT )
quadrangles = smesh.GetCriterion( SMESH.FACE, SMESH.FT_ElemGeomType,'=',SMESH.Geom_QUADRANGLE )
rest_quads = mesh.MakeGroupByCriteria("rest_quads", [ not_on_face3, quadrangles ])
print "'%s' group includes all the rest %s quadrangles" % ( rest_quads.GetName(), rest_quads.Size() )

View File

@ -11,7 +11,7 @@ Several criteria can be combined together by using logical operators \a
AND and \a OR. In addition, applied filter criterion can be reverted
using logical operator \a NOT.
Mesh filters use the functionality of \ref quality_page "mesh quality controls"
Some filtering criteria use the functionality of \ref quality_page "mesh quality controls"
to filter mesh nodes / elements by specific characteristic (Area, Length, etc).
The functinality of mesh filters is available in both GUI and TUI

View File

@ -24,8 +24,8 @@ menu for setting filters looks a bit differently (see the image below).
Each filter can be applicable to \b Nodes, \b Edges, \b Faces or \b
Volumes. You can combine many criteria in one filter, but they all
must be of the same <b>Entity type</b>.
\n The \b Add button creates a new criterion at the end of the list of
must be of the same <b>Entity type</b>. <br>
The \b Add button creates a new criterion at the end of the list of
criteria. The \b Insert button creates a new criterion before the
selected criterion. The \b Remove button deletes the selected
criterion. The \b Clear button deletes all criteria.
@ -43,11 +43,11 @@ selection of elements in the Viewer to the current filter.
<br>
In the \b Source field you choose if the filter will be applied to
the whole \b Mesh, the <b>Initial Selection</b> or the <b>Current
Group</b>. If \b Mesh is chosen, the elements satisfying the filter
Dialog</b>. If \b Mesh is chosen, the elements satisfying the filter
will be selected in the 3D Viewer. If <b> Initial Selection</b> is
chosen, the filter will be applied to the selected elements and the
elements rejected by the filter will be deselected. If <b>Current
Group</b> is chosen, the filter will be applied to the list of
Dialog</b> is chosen, the filter will be applied to the list of
elements in the current dialog and the elements rejected
by the filter will be removed from the list.
<br>
@ -76,6 +76,9 @@ If the threshold shape is a sub-shape of the main shape of the mesh the
algorithm works faster, if this is any other
shape, the algorithm works slower.
</li><li>
<b>Belong to Mesh Group</b> selects entities included into a mesh group
defined by <b>Threshold Value</b>.
</li><li>
<b>Range of IDs</b> allows selection of entities with the specified
IDs.
<b>Threshold Value</b> can be, for example: "1,2,3,50-60,63,67,70-78"

View File

@ -2,14 +2,16 @@
\page tui_filters_page Filters usage
\tableofcontents
Filters allow picking only the mesh elements satisfying to a
specific condition or a set of conditions. Filters can be used to create
or edit mesh groups, remove elements from the mesh object, control
mesh quality by different parameters, etc.
Several filters can be combined together by using logical operators \a
AND and \a OR. In addition, applied filter criterion can be reverted
using logical operator \a NOT.
Several filtering criteria can be combined together by using logical
operators \a AND and \a OR. In addition, applied filter criterion can
be reverted using logical operator \a NOT.
Mesh filters use the functionality of mesh quality controls to filter
mesh nodes / elements by a specific characteristic (Area, Length, etc).
@ -300,6 +302,16 @@ Filter over-constrained volumes:
\sa \ref tui_over_constrained_faces
\section filter_belong_to_group Belong to Mesh Group
Filter mesh entities (nodes or elements) included in a mesh group
defined by threshold value:
- element type can be any entity type, from \a SMESH.NODE to \a SMESH.VOLUME
- functor type should be \a SMESH.FT_BelongToMeshGroup
- threshold is mesh group object
\tui_script{filters_belong2group.py}
\section filter_belong_to_geom Belong to Geom
Filter mesh entities (nodes or elements) which all nodes lie on the

View File

@ -61,6 +61,7 @@ module SMESH
FT_MultiConnection2D,
FT_Length,
FT_Length2D,
FT_BelongToMeshGroup,
FT_BelongToGeom,
FT_BelongToPlane,
FT_BelongToCylinder,
@ -228,6 +229,17 @@ module SMESH
*/
interface EqualVolumes: Predicate {};
/*!
* Logical functor (predicate) "Belong To Mesh Group".
* Verify whether a mesh element is included into a mesh group
*/
interface BelongToMeshGroup: Predicate
{
void SetGroup( in SMESH::SMESH_GroupBase theGroup );
void SetGroupID( in string theID ); // IOR or StoreName
SMESH::SMESH_GroupBase GetGroup();
};
/*!
* Logical functor (predicate) "Belong To Geometry".
* Verify whether mesh element or node belong to pointed Geom Object
@ -559,59 +571,60 @@ module SMESH
/*!
* Create numerical functors
*/
MinimumAngle CreateMinimumAngle();
AspectRatio CreateAspectRatio();
AspectRatio3D CreateAspectRatio3D();
Warping CreateWarping();
Taper CreateTaper();
Skew CreateSkew();
Area CreateArea();
Volume3D CreateVolume3D();
MinimumAngle CreateMinimumAngle();
AspectRatio CreateAspectRatio();
AspectRatio3D CreateAspectRatio3D();
Warping CreateWarping();
Taper CreateTaper();
Skew CreateSkew();
Area CreateArea();
Volume3D CreateVolume3D();
MaxElementLength2D CreateMaxElementLength2D();
MaxElementLength3D CreateMaxElementLength3D();
Length CreateLength();
Length2D CreateLength2D();
MultiConnection CreateMultiConnection();
MultiConnection2D CreateMultiConnection2D();
BallDiameter CreateBallDiameter();
Length CreateLength();
Length2D CreateLength2D();
MultiConnection CreateMultiConnection();
MultiConnection2D CreateMultiConnection2D();
BallDiameter CreateBallDiameter();
/*!
* Create logical functors ( predicates )
*/
BelongToGeom CreateBelongToGeom();
BelongToPlane CreateBelongToPlane();
BelongToCylinder CreateBelongToCylinder();
* Create logical functors ( predicates )
*/
BelongToMeshGroup CreateBelongToMeshGroup();
BelongToGeom CreateBelongToGeom();
BelongToPlane CreateBelongToPlane();
BelongToCylinder CreateBelongToCylinder();
BelongToGenSurface CreateBelongToGenSurface();
LyingOnGeom CreateLyingOnGeom();
LyingOnGeom CreateLyingOnGeom();
FreeBorders CreateFreeBorders();
FreeEdges CreateFreeEdges();
FreeNodes CreateFreeNodes();
FreeFaces CreateFreeFaces();
FreeBorders CreateFreeBorders();
FreeEdges CreateFreeEdges();
FreeNodes CreateFreeNodes();
FreeFaces CreateFreeFaces();
EqualNodes CreateEqualNodes();
EqualEdges CreateEqualEdges();
EqualFaces CreateEqualFaces();
EqualVolumes CreateEqualVolumes();
EqualNodes CreateEqualNodes();
EqualEdges CreateEqualEdges();
EqualFaces CreateEqualFaces();
EqualVolumes CreateEqualVolumes();
RangeOfIds CreateRangeOfIds();
RangeOfIds CreateRangeOfIds();
BadOrientedVolume CreateBadOrientedVolume();
BareBorderVolume CreateBareBorderVolume();
BareBorderFace CreateBareBorderFace();
BadOrientedVolume CreateBadOrientedVolume();
BareBorderVolume CreateBareBorderVolume();
BareBorderFace CreateBareBorderFace();
OverConstrainedVolume CreateOverConstrainedVolume();
OverConstrainedFace CreateOverConstrainedFace();
LinearOrQuadratic CreateLinearOrQuadratic();
LinearOrQuadratic CreateLinearOrQuadratic();
GroupColor CreateGroupColor();
ElemGeomType CreateElemGeomType();
ElemEntityType CreateElemEntityType();
CoplanarFaces CreateCoplanarFaces();
ConnectedElements CreateConnectedElements();
GroupColor CreateGroupColor();
ElemGeomType CreateElemGeomType();
ElemEntityType CreateElemEntityType();
CoplanarFaces CreateCoplanarFaces();
ConnectedElements CreateConnectedElements();
/*!
* Create comparators ( predicates )
*/
* Create comparators ( predicates )
*/
LessThan CreateLessThan();
MoreThan CreateMoreThan();
EqualTo CreateEqualTo();

View File

@ -121,7 +121,13 @@ module SMESH
* (corresponds to the "hue" parameter of the color - must be in range [0, 360])
*/
long GetColorNumber();
};
/*!
* Returns \c true if \c this group depends on the \a other via
* FT_BelongToMeshGroup predicate or vice versa
*/
boolean IsInDependency( in SMESH_GroupBase other );
};
/*!
* SMESH_Group: interface of a standalone group object
@ -170,7 +176,7 @@ module SMESH
*/
interface SMESH_GroupOnFilter : SMESH_GroupBase
{
void SetFilter( in Filter theFilter);
void SetFilter( in Filter theFilter) raises (SALOME::SALOME_Exception);
Filter GetFilter();
};

View File

@ -3820,9 +3820,55 @@ void ManifoldPart::getFacesByLink( const ManifoldPart::Link& theLink,
}
}
/*
Class : BelongToMeshGroup
Description : Verify whether a mesh element is included into a mesh group
*/
BelongToMeshGroup::BelongToMeshGroup(): myGroup( 0 )
{
}
void BelongToMeshGroup::SetGroup( SMESHDS_GroupBase* g )
{
myGroup = g;
}
void BelongToMeshGroup::SetStoreName( const std::string& sn )
{
myStoreName = sn;
}
void BelongToMeshGroup::SetMesh( const SMDS_Mesh* theMesh )
{
if ( myGroup && myGroup->GetMesh() != theMesh )
{
myGroup = 0;
}
if ( !myGroup && !myStoreName.empty() )
{
if ( const SMESHDS_Mesh* aMesh = dynamic_cast<const SMESHDS_Mesh*>(theMesh))
{
const std::set<SMESHDS_GroupBase*>& grps = aMesh->GetGroups();
std::set<SMESHDS_GroupBase*>::const_iterator g = grps.begin();
for ( ; g != grps.end() && !myGroup; ++g )
if ( *g && myStoreName == (*g)->GetStoreName() )
myGroup = *g;
}
}
}
bool BelongToMeshGroup::IsSatisfy( long theElementId )
{
return myGroup ? myGroup->Contains( theElementId ) : false;
}
SMDSAbs_ElementType BelongToMeshGroup::GetType() const
{
return myGroup ? myGroup->GetType() : SMDSAbs_All;
}
/*
ElementsOnSurface
ElementsOnSurface
*/
ElementsOnSurface::ElementsOnSurface()

View File

@ -54,6 +54,7 @@ class SMDS_Mesh;
class SMESHDS_Mesh;
class SMESHDS_SubMesh;
class SMESHDS_GroupBase;
class gp_Pnt;
@ -763,8 +764,8 @@ namespace SMESH{
TMapOfLink& theNonManifold,
SMDS_MeshFace* theNextFace ) const;
void getFacesByLink( const Link& theLink,
TVectorOfFacePtr& theFaces ) const;
void getFacesByLink( const Link& theLink,
TVectorOfFacePtr& theFaces ) const;
private:
const SMDS_Mesh* myMesh;
@ -779,6 +780,27 @@ namespace SMESH{
};
typedef boost::shared_ptr<ManifoldPart> ManifoldPartPtr;
/*
Class : BelongToMeshGroup
Description : Verify whether a mesh element is included into a mesh group
*/
class SMESHCONTROLS_EXPORT BelongToMeshGroup : public virtual Predicate
{
public:
BelongToMeshGroup();
virtual void SetMesh( const SMDS_Mesh* theMesh );
virtual bool IsSatisfy( long theElementId );
virtual SMDSAbs_ElementType GetType() const;
void SetGroup( SMESHDS_GroupBase* g );
void SetStoreName( const std::string& sn );
const SMESHDS_GroupBase* GetGroup() const { return myGroup; }
private:
SMESHDS_GroupBase* myGroup;
std::string myStoreName;
};
typedef boost::shared_ptr<BelongToMeshGroup> BelongToMeshGroupPtr;
/*
Class : ElementsOnSurface
@ -809,7 +831,6 @@ namespace SMESH{
TMeshModifTracer myMeshModifTracer;
TColStd_MapOfInteger myIds;
SMDSAbs_ElementType myType;
//Handle(Geom_Surface) mySurf;
TopoDS_Face mySurf;
double myToler;
bool myUseBoundaries;

View File

@ -48,7 +48,7 @@ namespace SMESH{
/*
Class : Functor
Description : Root of all Functors
Description : Root of all Functors defined in ../Controls/SMESH_ControlsDef.hxx
*/
class SMESHCONTROLS_EXPORT Functor
{

View File

@ -56,10 +56,11 @@
#include <LightApp_Application.h>
#include <LightApp_SelectionMgr.h>
#include <SalomeApp_Tools.h>
#include <SalomeApp_Study.h>
#include <SalomeApp_IntSpinBox.h>
#include <SalomeApp_Application.h>
#include <SalomeApp_DoubleSpinBox.h>
#include <SalomeApp_IntSpinBox.h>
#include <SalomeApp_Study.h>
#include <SalomeApp_Tools.h>
#include <SALOME_ListIO.hxx>
@ -1134,6 +1135,7 @@ bool SMESHGUI_FilterTable::IsValid (const bool theMess, const int theEntityType)
errMsg = tr( "GROUPCOLOR_ERROR" );
}
else if (aCriterion == SMESH::FT_RangeOfIds ||
aCriterion == SMESH::FT_BelongToMeshGroup ||
aCriterion == SMESH::FT_BelongToGeom ||
aCriterion == SMESH::FT_BelongToPlane ||
aCriterion == SMESH::FT_BelongToCylinder ||
@ -1283,6 +1285,7 @@ void SMESHGUI_FilterTable::GetCriterion (const int theRow,
}
}
else if ( aCriterionType != SMESH::FT_RangeOfIds &&
aCriterionType != SMESH::FT_BelongToMeshGroup &&
aCriterionType != SMESH::FT_BelongToGeom &&
aCriterionType != SMESH::FT_BelongToPlane &&
aCriterionType != SMESH::FT_BelongToCylinder &&
@ -1382,6 +1385,7 @@ void SMESHGUI_FilterTable::SetCriterion (const int theRow,
}
}
else if (theCriterion.Type != SMESH::FT_RangeOfIds &&
theCriterion.Type != SMESH::FT_BelongToMeshGroup &&
theCriterion.Type != SMESH::FT_BelongToGeom &&
theCriterion.Type != SMESH::FT_BelongToPlane &&
theCriterion.Type != SMESH::FT_BelongToCylinder &&
@ -1398,6 +1402,7 @@ void SMESHGUI_FilterTable::SetCriterion (const int theRow,
theCriterion.Type != SMESH::FT_OverConstrainedVolume &&
theCriterion.Type != SMESH::FT_LinearOrQuadratic)
{
// Numberic criterion
aTable->item( theRow, 2 )->setText(QString("%1").arg(theCriterion.Threshold, 0, 'g', 15));
}
else
@ -1813,13 +1818,15 @@ void SMESHGUI_FilterTable::onCriterionChanged (const int row, const int col, con
case SMESH::FT_Length:
case SMESH::FT_Length2D: anIsDoubleCriterion = true; break;
case SMESH::FT_BelongToMeshGroup: break;
case SMESH::FT_BelongToGeom:
case SMESH::FT_BelongToPlane:
case SMESH::FT_BelongToCylinder:
case SMESH::FT_BelongToGenSurface:
case SMESH::FT_LyingOnGeom: nbCompareSigns = 1; isThresholdEditable = true; break;
case SMESH::FT_LyingOnGeom: nbCompareSigns = 0; isThresholdEditable = true; break;
case SMESH::FT_RangeOfIds: nbCompareSigns = 1; isThresholdEditable = true; break;
case SMESH::FT_RangeOfIds: nbCompareSigns = 0; isThresholdEditable = true; break;
case SMESH::FT_BadOrientedVolume:
case SMESH::FT_BareBorderVolume:
@ -2162,6 +2169,7 @@ const QMap<int, QString>& SMESHGUI_FilterTable::getCriteria (const int theType)
if (aCriteria.isEmpty())
{
aCriteria[ SMESH::FT_RangeOfIds ] = tr("RANGE_OF_IDS");
aCriteria[ SMESH::FT_BelongToMeshGroup ] = tr("BELONG_TO_MESH_GROUP");
aCriteria[ SMESH::FT_BelongToGeom ] = tr("BELONG_TO_GEOM");
aCriteria[ SMESH::FT_BelongToPlane ] = tr("BELONG_TO_PLANE");
aCriteria[ SMESH::FT_BelongToCylinder ] = tr("BELONG_TO_CYLINDER");
@ -2183,6 +2191,7 @@ const QMap<int, QString>& SMESHGUI_FilterTable::getCriteria (const int theType)
aCriteria[ SMESH::FT_MultiConnection ] = tr("MULTI_BORDERS");
aCriteria[ SMESH::FT_Length ] = tr("LENGTH");
aCriteria[ SMESH::FT_RangeOfIds ] = tr("RANGE_OF_IDS");
aCriteria[ SMESH::FT_BelongToMeshGroup ] = tr("BELONG_TO_MESH_GROUP");
aCriteria[ SMESH::FT_BelongToGeom ] = tr("BELONG_TO_GEOM");
aCriteria[ SMESH::FT_BelongToPlane ] = tr("BELONG_TO_PLANE");
aCriteria[ SMESH::FT_BelongToCylinder ] = tr("BELONG_TO_CYLINDER");
@ -2211,6 +2220,7 @@ const QMap<int, QString>& SMESHGUI_FilterTable::getCriteria (const int theType)
aCriteria[ SMESH::FT_MaxElementLength2D ] = tr("MAX_ELEMENT_LENGTH_2D");
aCriteria[ SMESH::FT_FreeEdges ] = tr("FREE_EDGES");
aCriteria[ SMESH::FT_RangeOfIds ] = tr("RANGE_OF_IDS");
aCriteria[ SMESH::FT_BelongToMeshGroup ] = tr("BELONG_TO_MESH_GROUP");
aCriteria[ SMESH::FT_BelongToGeom ] = tr("BELONG_TO_GEOM");
aCriteria[ SMESH::FT_BelongToPlane ] = tr("BELONG_TO_PLANE");
aCriteria[ SMESH::FT_BelongToCylinder ] = tr("BELONG_TO_CYLINDER");
@ -2238,6 +2248,7 @@ const QMap<int, QString>& SMESHGUI_FilterTable::getCriteria (const int theType)
{
aCriteria[ SMESH::FT_AspectRatio3D ] = tr("ASPECT_RATIO_3D");
aCriteria[ SMESH::FT_RangeOfIds ] = tr("RANGE_OF_IDS");
aCriteria[ SMESH::FT_BelongToMeshGroup ] = tr("BELONG_TO_MESH_GROUP");
aCriteria[ SMESH::FT_BelongToGeom ] = tr("BELONG_TO_GEOM");
aCriteria[ SMESH::FT_LyingOnGeom ] = tr("LYING_ON_GEOM");
aCriteria[ SMESH::FT_BadOrientedVolume ] = tr("BAD_ORIENTED_VOLUME");
@ -2260,6 +2271,7 @@ const QMap<int, QString>& SMESHGUI_FilterTable::getCriteria (const int theType)
if (aCriteria.isEmpty())
{
aCriteria[ SMESH::FT_RangeOfIds ] = tr("RANGE_OF_IDS");
aCriteria[ SMESH::FT_BelongToMeshGroup ] = tr("BELONG_TO_MESH_GROUP");
aCriteria[ SMESH::FT_BelongToGeom ] = tr("BELONG_TO_GEOM");
aCriteria[ SMESH::FT_BelongToPlane ] = tr("BELONG_TO_PLANE");
aCriteria[ SMESH::FT_BelongToCylinder ] = tr("BELONG_TO_CYLINDER");
@ -2276,6 +2288,7 @@ const QMap<int, QString>& SMESHGUI_FilterTable::getCriteria (const int theType)
{
aCriteria[ SMESH::FT_BallDiameter ] = tr("BALL_DIAMETER");
aCriteria[ SMESH::FT_RangeOfIds ] = tr("RANGE_OF_IDS");
aCriteria[ SMESH::FT_BelongToMeshGroup ] = tr("BELONG_TO_MESH_GROUP");
aCriteria[ SMESH::FT_BelongToGeom ] = tr("BELONG_TO_GEOM");
aCriteria[ SMESH::FT_BelongToPlane ] = tr("BELONG_TO_PLANE");
aCriteria[ SMESH::FT_BelongToCylinder ] = tr("BELONG_TO_CYLINDER");
@ -2291,6 +2304,7 @@ const QMap<int, QString>& SMESHGUI_FilterTable::getCriteria (const int theType)
if (aCriteria.isEmpty())
{
aCriteria[ SMESH::FT_RangeOfIds ] = tr("RANGE_OF_IDS");
aCriteria[ SMESH::FT_BelongToMeshGroup ] = tr("BELONG_TO_MESH_GROUP");
aCriteria[ SMESH::FT_BelongToGeom ] = tr("BELONG_TO_GEOM");
aCriteria[ SMESH::FT_BelongToPlane ] = tr("BELONG_TO_PLANE");
aCriteria[ SMESH::FT_BelongToCylinder ] = tr("BELONG_TO_CYLINDER");
@ -2306,6 +2320,7 @@ const QMap<int, QString>& SMESHGUI_FilterTable::getCriteria (const int theType)
if (aCriteria.isEmpty())
{
aCriteria[ SMESH::FT_RangeOfIds ] = tr("RANGE_OF_IDS");
aCriteria[ SMESH::FT_BelongToMeshGroup ] = tr("BELONG_TO_MESH_GROUP");
aCriteria[ SMESH::FT_BelongToGeom ] = tr("BELONG_TO_GEOM");
aCriteria[ SMESH::FT_LyingOnGeom ] = tr("LYING_ON_GEOM");
aCriteria[ SMESH::FT_LinearOrQuadratic ] = tr("LINEAR");
@ -2869,6 +2884,7 @@ void SMESHGUI_FilterDlg::Init (const QList<int>& theTypes, const bool setInViewe
mySourceWg = 0;
myTypes = theTypes;
myMesh = SMESH::SMESH_Mesh::_nil();
myGroup = SMESH::SMESH_GroupOnFilter::_nil();
myIObjects.Clear();
myIsSelectionChanged = false;
myToRestoreSelMode = false;
@ -3147,8 +3163,7 @@ bool SMESHGUI_FilterDlg::isValid() const
if (aType == SMESH::FT_BelongToCylinder ||
aType == SMESH::FT_BelongToPlane ||
aType == SMESH::FT_BelongToGenSurface ) {
CORBA::Object_var anObject = SMESH::SObjectToObject(aList[ 0 ]);
//GEOM::GEOM_Object_var aGeomObj = GEOM::GEOM_Object::_narrow(aList[ 0 ]->GetObject());
CORBA::Object_var anObject = SMESH::SObjectToObject(aList[ 0 ]);
GEOM::GEOM_Object_var aGeomObj = GEOM::GEOM_Object::_narrow(anObject);
if (!aGeomObj->_is_nil()) {
TopoDS_Shape aFace;
@ -3252,6 +3267,15 @@ void SMESHGUI_FilterDlg::SetMesh (SMESH::SMESH_Mesh_var theMesh)
myButtons[BTN_Apply]->setEnabled(isEnable);
}
//=======================================================================
// name : SMESHGUI_FilterDlg::SetGroup
// Purpose : Set a group being edited
//=======================================================================
void SMESHGUI_FilterDlg::SetGroup(SMESH::SMESH_GroupOnFilter_var group)
{
myGroup = group;
}
//=======================================================================
// name : SMESHGUI_FilterDlg::SetSelection
// Purpose : Get filtered ids
@ -3659,10 +3683,10 @@ void SMESHGUI_FilterDlg::onSelectionDone()
const int type = myTable->GetCriterionType(aRow);
QList<int> types;
types << SMESH::FT_BelongToGeom << SMESH::FT_BelongToPlane
<< SMESH::FT_BelongToCylinder << SMESH::FT_BelongToGenSurface
<< SMESH::FT_LyingOnGeom << SMESH::FT_CoplanarFaces
<< SMESH::FT_ConnectedElements;
types << SMESH::FT_BelongToGeom << SMESH::FT_BelongToPlane
<< SMESH::FT_BelongToCylinder << SMESH::FT_BelongToGenSurface
<< SMESH::FT_LyingOnGeom << SMESH::FT_CoplanarFaces
<< SMESH::FT_ConnectedElements << SMESH::FT_BelongToMeshGroup;
if ( !types.contains( type ))
return;
@ -3694,6 +3718,29 @@ void SMESHGUI_FilterDlg::onSelectionDone()
}
break;
}
case SMESH::FT_BelongToMeshGroup: // get a group name and IOR
{
SMESH::SMESH_GroupBase_var grp = SMESH::IObjectToInterface<SMESH::SMESH_GroupBase>(anIO);
if ( !grp->_is_nil() )
{
if ( !myMesh->_is_nil() )
{
SMESH::SMESH_Mesh_var mesh = grp->GetMesh();
if ( ! myMesh->_is_equivalent( mesh ))
return;
}
if ( !myGroup->_is_nil() && myGroup->IsInDependency( grp ))
return; // avoid cyclic dependencies between Groups on Filter
SalomeApp_Application* app = dynamic_cast<SalomeApp_Application*>
( SUIT_Session::session()->activeApplication() );
if( !app ) return;
CORBA::String_var IOR = app->orb()->object_to_string( grp );
myTable->SetThreshold(aRow, SMESH::toQStr( grp->GetName() ));
myTable->SetID (aRow, IOR.in() );
}
}
default: // get a GEOM object
{
GEOM::GEOM_Object_var anObj = SMESH::IObjectToInterface<GEOM::GEOM_Object>(anIO);
@ -3785,6 +3832,23 @@ void SMESHGUI_FilterDlg::updateSelection()
myIsSelectionChanged = true;
}
else if ( aCriterionType == SMESH::FT_BelongToMeshGroup )
{
SMESH_TypeFilter* typeFilter = 0;
switch ( myTable->GetType() )
{
case SMESH::NODE : typeFilter = new SMESH_TypeFilter( SMESH::GROUP_NODE ); break;
case SMESH::ELEM0D : typeFilter = new SMESH_TypeFilter( SMESH::GROUP_0D ); break;
case SMESH::BALL : typeFilter = new SMESH_TypeFilter( SMESH::GROUP_BALL ); break;
case SMESH::EDGE : typeFilter = new SMESH_TypeFilter( SMESH::GROUP_EDGE ); break;
case SMESH::FACE : typeFilter = new SMESH_TypeFilter( SMESH::GROUP_FACE ); break;
case SMESH::VOLUME : typeFilter = new SMESH_TypeFilter( SMESH::GROUP_VOLUME ); break;
case SMESH::ALL : typeFilter = new SMESH_TypeFilter( SMESH::GROUP ); break;
default : typeFilter = 0;
}
if ( typeFilter )
mySelectionMgr->installFilter( typeFilter );
}
else if ( aCriterionType == SMESH::FT_ConnectedElements )
{
QList<SUIT_SelectionFilter*> fList;

View File

@ -228,6 +228,7 @@ public:
void SetSelection();
void SetMesh (SMESH::SMESH_Mesh_var);
void SetGroup (SMESH::SMESH_GroupOnFilter_var);
void SetSourceWg( QWidget*, const bool initOnApply = true );
void SetEnabled( bool setInViewer, bool diffSources );
@ -297,6 +298,7 @@ private:
LightApp_SelectionMgr* mySelectionMgr;
SVTK_Selector* mySelector;
SMESH::SMESH_Mesh_var myMesh;
SMESH::SMESH_GroupOnFilter_var myGroup;
bool myInitSourceWgOnApply;
bool myInsertEnabled;
bool myDiffSourcesEnabled;

View File

@ -1205,11 +1205,11 @@ void SMESHGUI_FilterLibraryDlg::onSelectionDone()
return;
const int type = myTable->GetCriterionType(aRow);
QList<int> types;
types << SMESH::FT_BelongToGeom << SMESH::FT_BelongToPlane
<< SMESH::FT_BelongToCylinder << SMESH::FT_BelongToGenSurface
<< SMESH::FT_LyingOnGeom << SMESH::FT_CoplanarFaces
<< SMESH::FT_ConnectedElements;
QList<int> types;
types << SMESH::FT_BelongToGeom << SMESH::FT_BelongToPlane
<< SMESH::FT_BelongToCylinder << SMESH::FT_BelongToGenSurface
<< SMESH::FT_LyingOnGeom << SMESH::FT_CoplanarFaces
<< SMESH::FT_ConnectedElements << SMESH::FT_BelongToMeshGroup;
if ( !types.contains( type ))
return;
@ -1241,6 +1241,10 @@ void SMESHGUI_FilterLibraryDlg::onSelectionDone()
}
break;
}
case SMESH::FT_BelongToMeshGroup: // get a group name and IOR
{
myTable->SetThreshold(aRow, anIO->getName() );
}
default: // get a GEOM object
{
GEOM::GEOM_Object_var anObj = SMESH::IObjectToInterface<GEOM::GEOM_Object>(anIO);

View File

@ -1197,7 +1197,10 @@ bool SMESHGUI_GroupDlg::onApply()
}
// update a visible group accoding to a changed contents
if ( !isConversion && anActor->GetVisibility() )
{
SMESH::Update( anIO, true );
SMESH::RepaintCurrentView();
}
}
}
}
@ -1762,10 +1765,10 @@ void SMESHGUI_GroupDlg::setFilters()
myFilterDlg->SetEnabled( /*setInViewer=*/isStandalone,
/*diffSources=*/isStandalone );
myFilterDlg->SetMesh( myMesh );
myFilterDlg->SetGroup( myGroupOnFilter );
myFilterDlg->SetSelection();
myFilterDlg->SetSourceWg( myElements, false );
myFilterDlg->show();
}

View File

@ -28,16 +28,15 @@
#include "SMESHGUI_VTKUtils.h"
#include "SMESHGUI.h"
#include "SMESHGUI_Utils.h"
#include "SMESHGUI_Filter.h"
#include "SMESH_ControlsDef.hxx"
#include <SMESH_Actor.h>
#include <SMESH_ActorUtils.h>
#include "SMESH_NodeLabelActor.h"
#include "SMESHGUI_Utils.h"
#include "SMDS_Mesh.hxx"
#include "SMESH_Actor.h"
#include "SMESH_ActorUtils.h"
#include "SMESH_CellLabelActor.h"
#include <SMESH_ObjectDef.h>
#include <SMDS_Mesh.hxx>
#include "SMESH_ControlsDef.hxx"
#include "SMESH_NodeLabelActor.h"
#include "SMESH_ObjectDef.h"
// SALOME GUI includes
#include <SUIT_Desktop.h>

View File

@ -5421,6 +5421,10 @@ Please check input data and try again</translation>
<source>OVER_CONSTRAINED_FACE</source>
<translation>Over-constrained faces</translation>
</message>
<message>
<source>BELONG_TO_MESH_GROUP</source>
<translation>Belong to Mesh Group</translation>
</message>
<message>
<source>BELONG_TO_CYLINDER</source>
<translation>Belong to Cylinder</translation>

View File

@ -423,6 +423,7 @@ namespace SMESH
case FT_MultiConnection2D: myStream<< "aMultiConnection2D"; break;
case FT_Length: myStream<< "aLength"; break;
case FT_Length2D: myStream<< "aLength2D"; break;
case FT_BelongToMeshGroup: myStream<< "aBelongToMeshGroup"; break;
case FT_BelongToGeom: myStream<< "aBelongToGeom"; break;
case FT_BelongToPlane: myStream<< "aBelongToPlane"; break;
case FT_BelongToCylinder: myStream<< "aBelongToCylinder"; break;

View File

@ -31,6 +31,7 @@
#include "SMDS_Mesh.hxx"
#include "SMDS_MeshElement.hxx"
#include "SMDS_MeshNode.hxx"
#include "SMESHDS_GroupBase.hxx"
#include "SMESHDS_Mesh.hxx"
#include "SMESH_Gen_i.hxx"
#include "SMESH_Group_i.hxx"
@ -722,6 +723,108 @@ FunctorType OverConstrainedFace_i::GetFunctorType()
return SMESH::FT_OverConstrainedFace;
}
/*
Class : BelongToMeshGroup_i
Description : Verify whether a mesh element is included into a mesh group
*/
BelongToMeshGroup_i::BelongToMeshGroup_i()
{
myBelongToMeshGroup = Controls::BelongToMeshGroupPtr( new Controls::BelongToMeshGroup() );
myFunctorPtr = myPredicatePtr = myBelongToMeshGroup;
}
BelongToMeshGroup_i::~BelongToMeshGroup_i()
{
SetGroup( SMESH::SMESH_GroupBase::_nil() );
}
void BelongToMeshGroup_i::SetGroup( SMESH::SMESH_GroupBase_ptr theGroup )
{
if ( myGroup->_is_equivalent( theGroup ))
return;
if ( ! myGroup->_is_nil() )
myGroup->UnRegister();
myGroup = SMESH_GroupBase::_duplicate( theGroup );
myBelongToMeshGroup->SetGroup( 0 );
if ( SMESH_GroupBase_i* gr_i = SMESH::DownCast< SMESH_GroupBase_i* >( myGroup ))
{
myBelongToMeshGroup->SetGroup( gr_i->GetGroupDS() );
myGroup->Register();
}
}
void BelongToMeshGroup_i::SetGroupID( const char* theID ) // IOR or StoreName
{
myID = theID;
if ( strncmp( "IOR:", myID.c_str(), 4 ) == 0 ) // transient mode, no GUI
{
CORBA::Object_var obj = SMESH_Gen_i::GetORB()->string_to_object( myID.c_str() );
SetGroup( SMESH::SMESH_GroupBase::_narrow( obj ));
}
else if ( strncmp( ":0", myID.c_str(), 2 ) == 0 ) // transient mode + GUI
{
SMESH_Gen_i* aSMESHGen = SMESH_Gen_i::GetSMESHGen();
SALOMEDS::Study_var aStudy = aSMESHGen->GetCurrentStudy();
if ( !aStudy->_is_nil() ) {
SALOMEDS::SObject_wrap aSObj = aStudy->FindObjectID( myID.c_str() );
if ( !aSObj->_is_nil() ) {
CORBA::Object_var obj = aSObj->GetObject();
SetGroup( SMESH::SMESH_GroupBase::_narrow( obj ));
}
}
}
else if ( !myID.empty() ) // persistent mode
{
myBelongToMeshGroup->SetStoreName( myID );
}
}
std::string BelongToMeshGroup_i::GetGroupID()
{
if ( myGroup->_is_nil() )
SMESH::SMESH_GroupBase_var( GetGroup() );
if ( !myGroup->_is_nil() )
myID = SMESH_Gen_i::GetORB()->object_to_string( myGroup );
return myID;
}
SMESH::SMESH_GroupBase_ptr BelongToMeshGroup_i::GetGroup()
{
if ( myGroup->_is_nil() && myBelongToMeshGroup->GetGroup() )
{
// search for a group in a current study
SMESH_Gen_i* aSMESHGen = SMESH_Gen_i::GetSMESHGen();
if ( StudyContext* sc = aSMESHGen->GetCurrentStudyContext() )
{
int id = 1;
std::string ior;
while (true)
{
ior = sc->getIORbyId( id++ );
if ( ior.empty() ) break;
CORBA::Object_var obj = aSMESHGen->GetORB()->string_to_object( ior.c_str() );
if ( SMESH_GroupBase_i* g_i = SMESH::DownCast<SMESH_GroupBase_i*>( obj ))
if ( g_i->GetGroupDS() == myBelongToMeshGroup->GetGroup() )
{
SetGroup( g_i->_this() );
break;
}
}
}
}
return SMESH::SMESH_GroupBase::_duplicate( myGroup );
}
FunctorType BelongToMeshGroup_i::GetFunctorType()
{
return SMESH::FT_BelongToMeshGroup;
}
/*
Class : BelongToGeom_i
Description : Predicate for selection on geometrical support
@ -1772,6 +1875,7 @@ Predicate_i* LogicalNOT_i::GetPredicate_i()
}
/*
Class : LogicalBinary_i
Description : Base class for binary logical predicate
@ -2023,6 +2127,14 @@ BallDiameter_ptr FilterManager_i::CreateBallDiameter()
return anObj._retn();
}
BelongToMeshGroup_ptr FilterManager_i::CreateBelongToMeshGroup()
{
SMESH::BelongToMeshGroup_i* aServant = new SMESH::BelongToMeshGroup_i();
SMESH::BelongToMeshGroup_var anObj = aServant->_this();
TPythonDump()<<aServant<<" = "<<this<<".CreateBelongToMeshGroup()";
return anObj._retn();
}
BelongToGeom_ptr FilterManager_i::CreateBelongToGeom()
{
SMESH::BelongToGeom_i* aServant = new SMESH::BelongToGeom_i();
@ -2339,7 +2451,8 @@ Filter_i::~Filter_i()
if(!CORBA::is_nil(myMesh))
myMesh->UnRegister();
//TPythonDump()<<this<<".UnRegister()";
myPredicate = 0;
FindBaseObjects();
}
//=======================================================================
@ -2361,9 +2474,7 @@ void Filter_i::SetPredicate( Predicate_ptr thePredicate )
myPredicate->GetPredicate()->SetMesh( aMesh );
TPythonDump()<<this<<".SetPredicate("<<myPredicate<<")";
}
std::list<TPredicateChangeWaiter*>::iterator i = myWaiters.begin();
for ( ; i != myWaiters.end(); ++i )
(*i)->PredicateChanged();
NotifyerAndWaiter::Modified();
}
//=======================================================================
@ -2550,28 +2661,35 @@ SALOMEDS::TMPFile* Filter_i::GetVtkUgStream()
SALOMEDS::TMPFile_var SeqFile;
return SeqFile._retn();
}
//================================================================================
/*!
* \brief Stores an object to be notified on change of predicate
*/
//================================================================================
void Filter_i::AddWaiter( TPredicateChangeWaiter* waiter )
//=======================================================================
// name : getCriteria
// Purpose : Retrieve criterions from predicate
//=======================================================================
static inline void getPrediacates( Predicate_i* thePred,
std::vector<Predicate_i*> & thePredVec )
{
if ( waiter )
myWaiters.push_back( waiter );
}
const int aFType = thePred->GetFunctorType();
//================================================================================
/*!
* \brief Removes an object to be notified on change of predicate
*/
//================================================================================
void Filter_i::RemoveWaiter( TPredicateChangeWaiter* waiter )
{
myWaiters.remove( waiter );
switch ( aFType )
{
case FT_LogicalNOT:
{
Predicate_i* aPred = ( dynamic_cast<LogicalNOT_i*>( thePred ) )->GetPredicate_i();
getPrediacates( aPred, thePredVec );
break;
}
case FT_LogicalAND:
case FT_LogicalOR:
{
Predicate_i* aPred1 = ( dynamic_cast<LogicalBinary_i*>( thePred ) )->GetPredicate1_i();
Predicate_i* aPred2 = ( dynamic_cast<LogicalBinary_i*>( thePred ) )->GetPredicate2_i();
getPrediacates( aPred1, thePredVec );
getPrediacates( aPred2, thePredVec );
break;
}
default:;
}
thePredVec.push_back( thePred );
}
//=======================================================================
@ -2581,7 +2699,7 @@ void Filter_i::RemoveWaiter( TPredicateChangeWaiter* waiter )
static inline bool getCriteria( Predicate_i* thePred,
SMESH::Filter::Criteria_out theCriteria )
{
int aFType = thePred->GetFunctorType();
const int aFType = thePred->GetFunctorType();
switch ( aFType )
{
@ -2635,6 +2753,17 @@ static inline bool getCriteria( Predicate_i* thePred,
{
return true;
}
case FT_BelongToMeshGroup:
{
BelongToMeshGroup_i* aPred = dynamic_cast<BelongToMeshGroup_i*>( thePred );
SMESH::SMESH_GroupBase_var grp = aPred->GetGroup();
if ( !grp->_is_nil() )
{
theCriteria[ i ].ThresholdStr = grp->GetName();
theCriteria[ i ].ThresholdID = aPred->GetGroupID().c_str();
}
return true;
}
case FT_BelongToGeom:
{
BelongToGeom_i* aPred = dynamic_cast<BelongToGeom_i*>( thePred );
@ -2873,6 +3002,13 @@ CORBA::Boolean Filter_i::SetCriteria( const SMESH::Filter::Criteria& theCriteria
case SMESH::FT_EqualVolumes:
aPredicate = aFilterMgr->CreateEqualVolumes();
break;
case SMESH::FT_BelongToMeshGroup:
{
SMESH::BelongToMeshGroup_ptr tmpPred = aFilterMgr->CreateBelongToMeshGroup();
tmpPred->SetGroupID( aThresholdID );
aPredicate = tmpPred;
}
break;
case SMESH::FT_BelongToGeom:
{
SMESH::BelongToGeom_ptr tmpPred = aFilterMgr->CreateBelongToGeom();
@ -3136,6 +3272,75 @@ Predicate_ptr Filter_i::GetPredicate()
}
}
//================================================================================
/*!
* \brief Find groups it depends on
*/
//================================================================================
void Filter_i::FindBaseObjects()
{
// release current groups
for ( size_t i = 0; i < myBaseGroups.size(); ++i )
if ( myBaseGroups[i] )
{
myBaseGroups[i]->RemoveModifWaiter( this );
myBaseGroups[i]->UnRegister();
}
// remember new groups
myBaseGroups.clear();
if ( myPredicate )
{
std::vector<Predicate_i*> predicates;
getPrediacates( myPredicate, predicates );
for ( size_t i = 0; i < predicates.size(); ++i )
if ( BelongToMeshGroup_i* bmg = dynamic_cast< BelongToMeshGroup_i* >( predicates[i] ))
{
SMESH::SMESH_GroupBase_var g = bmg->GetGroup();
SMESH_GroupBase_i* g_i = SMESH::DownCast< SMESH_GroupBase_i*>( g );
if ( g_i )
{
g_i->AddModifWaiter( this );
g_i->Register();
myBaseGroups.push_back( g_i );
}
}
}
}
//================================================================================
/*!
* \brief When notified on removal of myBaseGroups[i], remove a reference to a
* group from a predicate
*/
//================================================================================
void Filter_i::OnBaseObjModified(NotifyerAndWaiter* group, bool removed)
{
if ( !removed )
return; // a GroupOnFilter holding this filter is notified automatically
if ( myPredicate )
{
std::vector<Predicate_i*> predicates;
getPrediacates( myPredicate, predicates );
for ( size_t i = 0; i < predicates.size(); ++i )
if ( BelongToMeshGroup_i* bmg = dynamic_cast< BelongToMeshGroup_i* >( predicates[i] ))
{
SMESH::SMESH_GroupBase_var g = bmg->GetGroup();
SMESH_GroupBase_i* g_i = SMESH::DownCast< SMESH_GroupBase_i*>( g );
if ( g_i == group )
{
bmg->SetGroup( SMESH::SMESH_GroupBase::_nil() );
bmg->SetGroupID( "" );
}
}
}
FindBaseObjects(); // release and update myBaseGroups;
}
/*
FILTER LIBRARY
*/
@ -3195,50 +3400,51 @@ static inline LDOMString toString( CORBA::Long theType )
{
switch ( theType )
{
case FT_AspectRatio : return "Aspect ratio";
case FT_Warping : return "Warping";
case FT_MinimumAngle : return "Minimum angle";
case FT_Taper : return "Taper";
case FT_Skew : return "Skew";
case FT_Area : return "Area";
case FT_Volume3D : return "Volume3D";
case FT_MaxElementLength2D: return "Max element length 2D";
case FT_MaxElementLength3D: return "Max element length 3D";
case FT_BelongToGeom : return "Belong to Geom";
case FT_BelongToPlane : return "Belong to Plane";
case FT_BelongToCylinder: return "Belong to Cylinder";
case FT_BelongToGenSurface: return "Belong to Generic Surface";
case FT_LyingOnGeom : return "Lying on Geom";
case FT_BadOrientedVolume:return "Bad Oriented Volume";
case FT_BareBorderVolume: return "Volumes with bare border";
case FT_BareBorderFace : return "Faces with bare border";
case FT_OverConstrainedVolume: return "Over-constrained Volumes";
case FT_OverConstrainedFace : return "Over-constrained Faces";
case FT_RangeOfIds : return "Range of IDs";
case FT_FreeBorders : return "Free borders";
case FT_FreeEdges : return "Free edges";
case FT_FreeFaces : return "Free faces";
case FT_FreeNodes : return "Free nodes";
case FT_EqualNodes : return "Equal nodes";
case FT_EqualEdges : return "Equal edges";
case FT_EqualFaces : return "Equal faces";
case FT_EqualVolumes : return "Equal volumes";
case FT_MultiConnection : return "Borders at multi-connections";
case FT_MultiConnection2D:return "Borders at multi-connections 2D";
case FT_Length : return "Length";
case FT_Length2D : return "Length 2D";
case FT_LessThan : return "Less than";
case FT_MoreThan : return "More than";
case FT_EqualTo : return "Equal to";
case FT_LogicalNOT : return "Not";
case FT_LogicalAND : return "And";
case FT_LogicalOR : return "Or";
case FT_GroupColor : return "Color of Group";
case FT_LinearOrQuadratic : return "Linear or Quadratic";
case FT_ElemGeomType : return "Element geomtry type";
case FT_EntityType : return "Entity type";
case FT_Undefined : return "";
default : return "";
case FT_AspectRatio : return "Aspect ratio";
case FT_Warping : return "Warping";
case FT_MinimumAngle : return "Minimum angle";
case FT_Taper : return "Taper";
case FT_Skew : return "Skew";
case FT_Area : return "Area";
case FT_Volume3D : return "Volume3D";
case FT_MaxElementLength2D : return "Max element length 2D";
case FT_MaxElementLength3D : return "Max element length 3D";
case FT_BelongToMeshGroup : return "Belong to Mesh Group";
case FT_BelongToGeom : return "Belong to Geom";
case FT_BelongToPlane : return "Belong to Plane";
case FT_BelongToCylinder : return "Belong to Cylinder";
case FT_BelongToGenSurface : return "Belong to Generic Surface";
case FT_LyingOnGeom : return "Lying on Geom";
case FT_BadOrientedVolume : return "Bad Oriented Volume";
case FT_BareBorderVolume : return "Volumes with bare border";
case FT_BareBorderFace : return "Faces with bare border";
case FT_OverConstrainedVolume : return "Over-constrained Volumes";
case FT_OverConstrainedFace : return "Over-constrained Faces";
case FT_RangeOfIds : return "Range of IDs";
case FT_FreeBorders : return "Free borders";
case FT_FreeEdges : return "Free edges";
case FT_FreeFaces : return "Free faces";
case FT_FreeNodes : return "Free nodes";
case FT_EqualNodes : return "Equal nodes";
case FT_EqualEdges : return "Equal edges";
case FT_EqualFaces : return "Equal faces";
case FT_EqualVolumes : return "Equal volumes";
case FT_MultiConnection : return "Borders at multi-connections";
case FT_MultiConnection2D :return "Borders at multi-connections 2D";
case FT_Length : return "Length";
case FT_Length2D : return "Length 2D";
case FT_LessThan : return "Less than";
case FT_MoreThan : return "More than";
case FT_EqualTo : return "Equal to";
case FT_LogicalNOT : return "Not";
case FT_LogicalAND : return "And";
case FT_LogicalOR : return "Or";
case FT_GroupColor : return "Color of Group";
case FT_LinearOrQuadratic : return "Linear or Quadratic";
case FT_ElemGeomType : return "Element geomtry type";
case FT_EntityType : return "Entity type";
case FT_Undefined : return "";
default : return "";
}
}
@ -3257,6 +3463,7 @@ static inline SMESH::FunctorType toFunctorType( const LDOMString& theStr )
else if ( theStr.equals( "Volume3D" ) ) return FT_Volume3D;
else if ( theStr.equals( "Max element length 2D" ) ) return FT_MaxElementLength2D;
else if ( theStr.equals( "Max element length 3D" ) ) return FT_MaxElementLength3D;
else if ( theStr.equals( "Belong to Mesh Group" ) ) return FT_BelongToMeshGroup;
else if ( theStr.equals( "Belong to Geom" ) ) return FT_BelongToGeom;
else if ( theStr.equals( "Belong to Plane" ) ) return FT_BelongToPlane;
else if ( theStr.equals( "Belong to Cylinder" ) ) return FT_BelongToCylinder;
@ -3838,6 +4045,7 @@ static const char** getFunctNames()
"FT_MultiConnection2D",
"FT_Length",
"FT_Length2D",
"FT_BelongToMeshGroup",
"FT_BelongToGeom",
"FT_BelongToPlane",
"FT_BelongToCylinder",
@ -3865,7 +4073,7 @@ static const char** getFunctNames()
"FT_Undefined"};
#ifdef _DEBUG_
// check if functName is complete, compilation failure mains that enum FunctorType changed
// check if functName is complete, compilation failure means that enum FunctorType changed
const int nbFunctors = sizeof(functName) / sizeof(const char*);
int _assert[( nbFunctors == SMESH::FT_Undefined + 1 ) ? 1 : -1 ];
#endif
@ -3905,3 +4113,62 @@ SMESH::FunctorType SMESH::StringToFunctorType(const char* str)
return SMESH::FunctorType( ft );
}
//================================================================================
/*!
* \brief calls OnBaseObjModified(), if who != this, and myWaiters[i]->Modified(who)
*/
//================================================================================
void NotifyerAndWaiter::Modified( bool removed, NotifyerAndWaiter* who )
{
if ( who != 0 && who != this )
OnBaseObjModified( who, removed );
else
who = this;
std::list<NotifyerAndWaiter*> waiters = myWaiters; // myWaiters can be changed by Modified()
std::list<NotifyerAndWaiter*>::iterator i = waiters.begin();
for ( ; i != waiters.end(); ++i )
(*i)->Modified( removed, who );
}
//================================================================================
/*!
* \brief Stores an object to be notified on change of predicate
*/
//================================================================================
void NotifyerAndWaiter::AddModifWaiter( NotifyerAndWaiter* waiter )
{
if ( waiter )
myWaiters.push_back( waiter );
}
//================================================================================
/*!
* \brief Removes an object to be notified on change of predicate
*/
//================================================================================
void NotifyerAndWaiter::RemoveModifWaiter( NotifyerAndWaiter* waiter )
{
myWaiters.remove( waiter );
}
//================================================================================
/*!
* \brief Checks if a waiter is among myWaiters, maybe nested
*/
//================================================================================
bool NotifyerAndWaiter::ContainModifWaiter( NotifyerAndWaiter* waiter )
{
bool is = ( waiter == this );
std::list<NotifyerAndWaiter*>::iterator w = myWaiters.begin();
for ( ; !is && w != myWaiters.end(); ++w )
is = (*w)->ContainModifWaiter( waiter );
return is;
}

View File

@ -41,8 +41,31 @@
#include <list>
class SMESH_GroupBase_i;
namespace SMESH
{
/*!
* \brief Object notified on change of base objects and
* notifying dependent objects in its turn.
* This interface is used to track the following dependencies:
* - GroupOnFiler depending on Filter predicates
* - Filter depending on a Group via FT_BelongToMeshGroup predicate
*/
struct NotifyerAndWaiter
{
virtual void OnBaseObjModified(NotifyerAndWaiter* obj, bool removed) {};
// specific reaction on modification of a base object
void Modified( bool removed=false, NotifyerAndWaiter* who = 0);
// calls OnBaseObjModified(), if who != 0, and myWaiters[i]->Modified(who)
void AddModifWaiter ( NotifyerAndWaiter* waiter ); // adds a dependent object to notify
void RemoveModifWaiter ( NotifyerAndWaiter* waiter ); // CALL IT when a waiter dies!!!
bool ContainModifWaiter( NotifyerAndWaiter* waiter );
std::list<NotifyerAndWaiter*> myWaiters;
};
// ================================================================================
/*
FUNCTORS
@ -370,6 +393,28 @@ namespace SMESH
FunctorType GetFunctorType();
};
/*
Class : BelongToMeshGroup_i
Description : Verify whether a mesh element is included into a mesh group
*/
class SMESH_I_EXPORT BelongToMeshGroup_i: public virtual POA_SMESH::BelongToMeshGroup,
public virtual Predicate_i
{
std::string myID; // IOR or StoreName
SMESH::SMESH_GroupBase_var myGroup;
Controls::BelongToMeshGroupPtr myBelongToMeshGroup;
public:
BelongToMeshGroup_i();
~BelongToMeshGroup_i();
void SetGroup( SMESH::SMESH_GroupBase_ptr theGroup );
void SetGroupID( const char* theID ); // IOR or StoreName
SMESH::SMESH_GroupBase_ptr GetGroup();
std::string GetGroupID();
FunctorType GetFunctorType();
//virtual void SetMesh( SMESH_Mesh_ptr theMesh );
};
/*
Class : BelongToGeom_i
Description : Predicate for selection on geometrical support
@ -896,7 +941,8 @@ namespace SMESH
FILTER
*/
class SMESH_I_EXPORT Filter_i: public virtual POA_SMESH::Filter,
public virtual SALOME::GenericObj_i
public virtual SALOME::GenericObj_i,
public NotifyerAndWaiter
{
public:
Filter_i();
@ -943,6 +989,12 @@ namespace SMESH
Predicate_i* GetPredicate_i();
void FindBaseObjects();
// finds groups it depends on
virtual void OnBaseObjModified(NotifyerAndWaiter* group, bool removed);
// notified on change of myBaseGroups[i]
// =========================
// SMESH_IDSource interface
// =========================
@ -953,22 +1005,13 @@ namespace SMESH
virtual SMESH::SMESH_Mesh_ptr GetMesh();
virtual bool IsMeshInfoCorrect() { return true; }
virtual SALOMEDS::TMPFile* GetVtkUgStream();
/*!
* \brief Object notified on change of predicate
*/
struct TPredicateChangeWaiter
{
virtual void PredicateChanged() = 0;
};
void AddWaiter( TPredicateChangeWaiter* waiter );
void RemoveWaiter( TPredicateChangeWaiter* waiter );
private:
Controls::Filter myFilter;
Predicate_i* myPredicate;
SMESH_Mesh_var myMesh;
std::list<TPredicateChangeWaiter*> myWaiters;
std::vector< SMESH_GroupBase_i* > myBaseGroups;
};
@ -1036,6 +1079,7 @@ namespace SMESH
MultiConnection2D_ptr CreateMultiConnection2D();
BallDiameter_ptr CreateBallDiameter();
BelongToMeshGroup_ptr CreateBelongToMeshGroup();
BelongToGeom_ptr CreateBelongToGeom();
BelongToPlane_ptr CreateBelongToPlane();
BelongToCylinder_ptr CreateBelongToCylinder();

View File

@ -4073,6 +4073,7 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
list< pair< SMESH_Hypothesis_i*, string > > hypDataList;
list< pair< SMESH_Mesh_i*, HDFgroup* > > meshGroupList;
list< SMESH::Filter_var > filters;
// get total number of top-level groups
int aNbGroups = aFile->nInternalObjects();
@ -4715,6 +4716,7 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
if ( strlen( persistStr ) > 0 ) {
filter = SMESH_GroupOnFilter_i::StringToFilter( persistStr );
predicate = SMESH_GroupOnFilter_i::GetPredicate( filter );
filters.push_back( filter );
}
}
@ -4761,11 +4763,6 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
Quantity_Color aColor( anRGB[0], anRGB[1], anRGB[2], Quantity_TOC_RGB );
aGroupBaseDS->SetColor( aColor );
}
// Fill group with contents from MED file
// SMESHDS_Group* aGrp = dynamic_cast<SMESHDS_Group*>( aGroupBaseDS );
// if ( aGrp )
// myReader.GetGroup( aGrp );
}
}
aGroup->CloseOnDisk();
@ -4824,6 +4821,13 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
ComputeStateEngine (SMESH_subMesh::SUBMESH_RESTORED);
}
// let filters detect dependency on mesh groups via FT_BelongToMeshGroup predicate (22877)
list< SMESH::Filter_var >::iterator f = filters.begin();
for ( ; f != filters.end(); ++f )
if ( SMESH::Filter_i * fi = SMESH::DownCast< SMESH::Filter_i*>( *f ))
fi->FindBaseObjects();
// close mesh group
if(aTopGroup)
aTopGroup->CloseOnDisk();

View File

@ -244,6 +244,21 @@ CORBA::Boolean SMESH_GroupBase_i::IsEmpty()
return true;
}
//=============================================================================
/*
* Returns \c true if \c this group depends on the \a other via
* FT_BelongToMeshGroup predicate or vice versa
*/
//=============================================================================
bool SMESH_GroupBase_i::IsInDependency( SMESH::SMESH_GroupBase_ptr other )
{
if ( NotifyerAndWaiter* nw = SMESH::DownCast< NotifyerAndWaiter* >( other ))
return ( nw->ContainModifWaiter( this ) || this->ContainModifWaiter( nw ));
return false;
}
//=============================================================================
/*!
*
@ -264,6 +279,8 @@ void SMESH_Group_i::Clear()
aGroupDS->Clear();
return;
}
Modified(); // notify dependent Filter with FT_BelongToMeshGroup criterion
MESSAGE("attempt to clear a vague group");
}
@ -308,6 +325,8 @@ CORBA::Long SMESH_Group_i::Add( const SMESH::long_array& theIDs )
if (aGroupDS->Add(anID))
nbAdd++;
}
if ( nbAdd )
Modified(); // notify dependent Filter with FT_BelongToMeshGroup criterion
return nbAdd;
}
MESSAGE("attempt to add elements to a vague group");
@ -338,6 +357,8 @@ CORBA::Long SMESH_Group_i::Remove( const SMESH::long_array& theIDs )
if (aGroupDS->Remove(anID))
nbDel++;
}
if ( nbDel )
Modified(); // notify dependent Filter with FT_BelongToMeshGroup criterion
return nbDel;
}
MESSAGE("attempt to remove elements from a vague group");
@ -355,6 +376,7 @@ typedef bool (SMESHDS_Group::*TFunChangeGroup)(const int);
CORBA::Long
ChangeByPredicate( SMESH::Predicate_i* thePredicate,
SMESHDS_GroupBase* theGroupBase,
NotifyerAndWaiter* theGroupImpl,
TFunChangeGroup theFun)
{
CORBA::Long aNb = 0;
@ -367,6 +389,8 @@ ChangeByPredicate( SMESH::Predicate_i* thePredicate,
for(; i < iEnd; i++)
if((aGroupDS->*theFun)(aSequence[i]))
aNb++;
if ( aNb )
theGroupImpl->Modified();
return aNb;
}
return aNb;
@ -382,7 +406,7 @@ AddByPredicate( SMESH::Predicate_ptr thePredicate )
if(SMESH::Predicate_i* aPredicate = SMESH::GetPredicate(thePredicate)){
TPythonDump() << SMESH::SMESH_Group_var(_this())
<< ".AddByPredicate( " << aPredicate << " )";
return ChangeByPredicate( aPredicate, GetGroupDS(), &SMESHDS_Group::Add );
return ChangeByPredicate( aPredicate, GetGroupDS(), this, &SMESHDS_Group::Add );
}
return 0;
}
@ -397,7 +421,7 @@ RemoveByPredicate( SMESH::Predicate_ptr thePredicate )
if(SMESH::Predicate_i* aPredicate = SMESH::GetPredicate(thePredicate)){
TPythonDump() << SMESH::SMESH_Group_var(_this())
<< ".RemoveByPredicate( " << aPredicate << " )";
return ChangeByPredicate(aPredicate,GetGroupDS(),&SMESHDS_Group::Remove);
return ChangeByPredicate(aPredicate,GetGroupDS(),this, &SMESHDS_Group::Remove);
}
return 0;
}
@ -419,12 +443,15 @@ CORBA::Long SMESH_Group_i::AddFrom( SMESH::SMESH_IDSource_ptr theSource )
// Update Python script
pd << "nbAdd = " << SMESH::SMESH_Group_var(_this()) << ".AddFrom( " << theSource << " )";
return prevNb - Size();
if ( prevNb != Size() )
Modified(); // notify dependent Filter with FT_BelongToMeshGroup criterion
return Size() - prevNb;
}
//=============================================================================
/*!
*
*
*/
//=============================================================================
@ -784,6 +811,7 @@ SMESH_PredicatePtr SMESH_GroupOnFilter_i::GetPredicate( SMESH::Filter_ptr filter
//================================================================================
void SMESH_GroupOnFilter_i::SetFilter(SMESH::Filter_ptr theFilter)
throw (SALOME::SALOME_Exception)
{
if ( myFilter->_is_equivalent( theFilter ))
return;
@ -796,17 +824,34 @@ void SMESH_GroupOnFilter_i::SetFilter(SMESH::Filter_ptr theFilter)
myFilter = SMESH::Filter::_duplicate( theFilter );
if ( !myFilter->_is_nil() )
{
myFilter->Register();
if ( SMESH::Filter_i* f = SMESH::DownCast< SMESH::Filter_i* >( myFilter ))
{
// make filter notify me about change of either a predicate or a base group
f->FindBaseObjects();
if ( f->ContainModifWaiter( this ) ||
this->ContainModifWaiter( f ))
{
SetFilter( SMESH::Filter::_nil() );
THROW_SALOME_CORBA_EXCEPTION( "Cyclic dependency between Groups on Filter",
SALOME::BAD_PARAM );
}
f->AddModifWaiter( this );
}
myFilter->SetMesh( SMESH::SMESH_Mesh::_nil() ); // to UnRegister() the mesh
}
if ( SMESHDS_GroupOnFilter* grDS = dynamic_cast< SMESHDS_GroupOnFilter*>( GetGroupDS() ))
{
grDS->SetPredicate( GetPredicate( myFilter ));
Modified(); // notify dependent Filter with FT_BelongToMeshGroup criterion
}
TPythonDump()<< SMESH::SMESH_GroupOnFilter_var(_this()) <<".SetFilter( "<<theFilter<<" )";
if ( myFilter )
{
myFilter->SetMesh( SMESH::SMESH_Mesh::_nil() ); // to UnRegister() the mesh
myFilter->Register();
SMESH::DownCast< SMESH::Filter_i* >( myFilter )->AddWaiter( this );
}
}
//================================================================================
@ -900,9 +945,17 @@ std::string SMESH_GroupOnFilter_i::FilterToString() const
result << criteria->length() << SEPAR;
for ( unsigned i = 0; i < criteria->length(); ++i )
{
SMESH::Filter::Criterion& crit = criteria[ i ];
if ( SMESH::FunctorType( crit.Type ) == SMESH::FT_BelongToMeshGroup )
{
CORBA::Object_var obj = SMESH_Gen_i::GetORB()->string_to_object( crit.ThresholdID );
if ( SMESH_GroupBase_i * g = SMESH::DownCast< SMESH_GroupBase_i*>( obj ))
if ( SMESHDS_GroupBase* gDS = g->GetGroupDS() )
crit.ThresholdID = gDS->GetStoreName();
}
// write FunctorType as string but not as number to assure correct
// persistence if enum FunctorType is modified by insertion in the middle
SMESH::Filter::Criterion& crit = criteria[ i ];
result << SMESH::FunctorTypeToString( SMESH::FunctorType( crit.Type )) << SEPAR;
result << SMESH::FunctorTypeToString( SMESH::FunctorType( crit.Compare )) << SEPAR;
result << crit.Threshold << SEPAR;
@ -987,22 +1040,22 @@ SMESH_GroupOnFilter_i::~SMESH_GroupOnFilter_i()
{
if ( ! myFilter->_is_nil() )
{
SMESH::DownCast< SMESH::Filter_i* >( myFilter )->RemoveWaiter( this );
SMESH::DownCast< SMESH::Filter_i* >( myFilter )->RemoveModifWaiter( this );
myFilter->UnRegister();
}
}
//================================================================================
/*!
* \brief Method calleds when a predicate of myFilter changes
* \brief Method called when a predicate of myFilter changes
*/
//================================================================================
void SMESH_GroupOnFilter_i::PredicateChanged()
void SMESH_GroupOnFilter_i::OnBaseObjModified(NotifyerAndWaiter* filter, bool /*removed*/)
{
if ( myPreMeshInfo )
myPreMeshInfo->FullLoadFromFile();
if ( SMESHDS_GroupOnFilter* grDS = dynamic_cast< SMESHDS_GroupOnFilter*>( GetGroupDS() ))
grDS->SetPredicate( GetPredicate( myFilter ));
grDS->SetPredicate( GetPredicate( myFilter )); // group resets its cache
}

View File

@ -48,7 +48,8 @@ class SMESH_PreMeshInfo;
// ===========
class SMESH_I_EXPORT SMESH_GroupBase_i:
public virtual POA_SMESH::SMESH_GroupBase,
public virtual SALOME::GenericObj_i
public virtual SALOME::GenericObj_i,
public SMESH::NotifyerAndWaiter // defined in SMESH_Filter_i.hxx
{
public:
SMESH_GroupBase_i(PortableServer::POA_ptr thePOA,
@ -100,6 +101,13 @@ class SMESH_I_EXPORT SMESH_GroupBase_i:
*/
virtual SALOMEDS::TMPFile* GetVtkUgStream();
/*!
* Returns \c true if \c this group depends on the \a other via
* FT_BelongToMeshGroup predicate or vice versa
*/
virtual CORBA::Boolean IsInDependency( SMESH::SMESH_GroupBase_ptr other );
// Internal C++ interface
int GetLocalID() const { return myLocalID; }
SMESH_Mesh_i* GetMeshServant() const { return myMeshServant; }
@ -173,8 +181,7 @@ class SMESH_I_EXPORT SMESH_GroupOnGeom_i:
class SMESH_I_EXPORT SMESH_GroupOnFilter_i:
public virtual POA_SMESH::SMESH_GroupOnFilter,
public SMESH_GroupBase_i,
public SMESH::Filter_i::TPredicateChangeWaiter
public SMESH_GroupBase_i
{
public:
SMESH_GroupOnFilter_i( PortableServer::POA_ptr thePOA,
@ -189,13 +196,13 @@ class SMESH_I_EXPORT SMESH_GroupOnFilter_i:
static SMESH_PredicatePtr GetPredicate( SMESH::Filter_ptr );
// CORBA interface implementation
void SetFilter(SMESH::Filter_ptr theFilter);
void SetFilter(SMESH::Filter_ptr theFilter) throw (SALOME::SALOME_Exception);
SMESH::Filter_ptr GetFilter();
virtual SMESH::long_array* GetListOfID();
virtual SMESH::long_array* GetMeshInfo();
// method of SMESH::Filter_i::TPredicateChangeWaiter
virtual void PredicateChanged();
// method of SMESH::NotifyerAndWaiter to update self when myFilter changes
virtual void OnBaseObjModified(NotifyerAndWaiter* filter, bool);
private:
SMESH::Filter_var myFilter;

View File

@ -1057,6 +1057,7 @@ void SMESH_Mesh_i::RemoveGroup( SMESH::SMESH_GroupBase_ptr theGroup )
builder->RemoveObjectWithChildren( aGroupSO );
}
}
aGroup->Modified(/*removed=*/true); // notify dependent Filter with FT_BelongToMeshGroup criterion
// Remove the group from SMESH data structures
removeGroup( aGroup->GetLocalID() );

View File

@ -732,7 +732,7 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
if CritType in [FT_BelongToGeom, FT_BelongToPlane, FT_BelongToGenSurface,
FT_BelongToCylinder, FT_LyingOnGeom]:
# Checks that Threshold is GEOM object
# Check that Threshold is GEOM object
if isinstance(aThreshold, geomBuilder.GEOM._objref_GEOM_Object):
aCriterion.ThresholdStr = GetName(aThreshold)
aCriterion.ThresholdID = aThreshold.GetStudyEntry()
@ -745,21 +745,28 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
elif isinstance( aThreshold, str ):
aCriterion.ThresholdStr = aThreshold
else:
print "Error: The Threshold should be a shape."
return None
raise TypeError, "The Threshold should be a shape."
if isinstance(UnaryOp,float):
aCriterion.Tolerance = UnaryOp
UnaryOp = FT_Undefined
pass
elif CritType == FT_BelongToMeshGroup:
# Check that Threshold is a group
if isinstance(aThreshold, SMESH._objref_SMESH_GroupBase):
if aThreshold.GetType() != elementType:
raise ValueError, "Group type mismatches Element type"
aCriterion.ThresholdStr = aThreshold.GetName()
aCriterion.ThresholdID = salome.orb.object_to_string( aThreshold )
else:
raise TypeError, "The Threshold should be a Mesh Group"
elif CritType == FT_RangeOfIds:
# Checks that Threshold is string
# Check that Threshold is string
if isinstance(aThreshold, str):
aCriterion.ThresholdStr = aThreshold
else:
print "Error: The Threshold should be a string."
return None
raise TypeError, "The Threshold should be a string."
elif CritType == FT_CoplanarFaces:
# Checks the Threshold
# Check the Threshold
if isinstance(aThreshold, int):
aCriterion.ThresholdID = str(aThreshold)
elif isinstance(aThreshold, str):
@ -768,10 +775,10 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
raise ValueError, "Invalid ID of mesh face: '%s'"%aThreshold
aCriterion.ThresholdID = aThreshold
else:
raise ValueError,\
raise TypeError,\
"The Threshold should be an ID of mesh face and not '%s'"%aThreshold
elif CritType == FT_ConnectedElements:
# Checks the Threshold
# Check the Threshold
if isinstance(aThreshold, geomBuilder.GEOM._objref_GEOM_Object): # shape
aCriterion.ThresholdID = aThreshold.GetStudyEntry()
if not aCriterion.ThresholdID:
@ -791,11 +798,11 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
else:
aCriterion.ThresholdStr = aThreshold # hope that it's point coordinates
else:
raise ValueError,\
raise TypeError,\
"The Threshold should either a VERTEX, or a node ID, "\
"or a list of point coordinates and not '%s'"%aThreshold
elif CritType == FT_ElemGeomType:
# Checks the Threshold
# Check the Threshold
try:
aCriterion.Threshold = self.EnumToLong(aThreshold)
assert( aThreshold in SMESH.GeometryType._items )
@ -803,12 +810,11 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
if isinstance(aThreshold, int):
aCriterion.Threshold = aThreshold
else:
print "Error: The Threshold should be an integer or SMESH.GeometryType."
return None
raise TypeError, "The Threshold should be an integer or SMESH.GeometryType."
pass
pass
elif CritType == FT_EntityType:
# Checks the Threshold
# Check the Threshold
try:
aCriterion.Threshold = self.EnumToLong(aThreshold)
assert( aThreshold in SMESH.EntityType._items )
@ -816,18 +822,16 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
if isinstance(aThreshold, int):
aCriterion.Threshold = aThreshold
else:
print "Error: The Threshold should be an integer or SMESH.EntityType."
return None
raise TypeError, "The Threshold should be an integer or SMESH.EntityType."
pass
pass
elif CritType == FT_GroupColor:
# Checks the Threshold
# Check the Threshold
try:
aCriterion.ThresholdStr = self.ColorToString(aThreshold)
except:
print "Error: The threshold value should be of SALOMEDS.Color type"
return None
raise TypeError, "The threshold value should be of SALOMEDS.Color type"
pass
elif CritType in [FT_FreeBorders, FT_FreeEdges, FT_FreeNodes, FT_FreeFaces,
FT_LinearOrQuadratic, FT_BadOrientedVolume,
@ -845,7 +849,7 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
aThreshold = float(aThreshold)
aCriterion.Threshold = aThreshold
except:
print "Error: The Threshold should be a number."
raise TypeError, "The Threshold should be a number."
return None
if Threshold == FT_LogicalNOT or UnaryOp == FT_LogicalNOT: