+ SMDS_ElemIteratorPtr anIter;
+ if ( aFace->IsQuadratic() ) {
+ anIter = dynamic_cast<const SMDS_VtkFace*>
+ (aFace)->interlacedNodesElemIterator();
+ }
+ else {
+ anIter = aFace->nodesIterator();
+ }
+ if ( !anIter )
+ return false;
+
+ int i = 0, nbNodes = aFace->NbNodes();
+ std::vector <const SMDS_MeshNode*> aNodes( nbNodes+1 );
+ while( anIter->more() )
+ {
+ const SMDS_MeshNode* aNode = (SMDS_MeshNode*)anIter->next();
+ if ( aNode == 0 )
+ return false;
+ aNodes[ i++ ] = aNode;
+ }
+ aNodes[ nbNodes ] = aNodes[ 0 ];
+
+ for ( i = 0; i < nbNodes; i++ )
+ if ( IsFreeEdge( &aNodes[ i ], theId ) )
+ return true;
+
+ return false;
+}
+
+SMDSAbs_ElementType FreeEdges::GetType() const
+{
+ return SMDSAbs_Face;
+}
+
+FreeEdges::Border::Border(long theElemId, long thePntId1, long thePntId2):
+ myElemId(theElemId)
+{
+ myPntId[0] = thePntId1; myPntId[1] = thePntId2;
+ if(thePntId1 > thePntId2){
+ myPntId[1] = thePntId1; myPntId[0] = thePntId2;
+ }
+}
+
+bool FreeEdges::Border::operator<(const FreeEdges::Border& x) const{
+ if(myPntId[0] < x.myPntId[0]) return true;
+ if(myPntId[0] == x.myPntId[0])
+ if(myPntId[1] < x.myPntId[1]) return true;
+ return false;
+}
+
+inline void UpdateBorders(const FreeEdges::Border& theBorder,
+ FreeEdges::TBorders& theRegistry,
+ FreeEdges::TBorders& theContainer)
+{
+ if(theRegistry.find(theBorder) == theRegistry.end()){
+ theRegistry.insert(theBorder);
+ theContainer.insert(theBorder);
+ }else{
+ theContainer.erase(theBorder);
+ }
+}
+
+void FreeEdges::GetBoreders(TBorders& theBorders)
+{
+ TBorders aRegistry;
+ SMDS_FaceIteratorPtr anIter = myMesh->facesIterator();
+ for(; anIter->more(); ){
+ const SMDS_MeshFace* anElem = anIter->next();
+ long anElemId = anElem->GetID();
+ SMDS_ElemIteratorPtr aNodesIter;
+ if ( anElem->IsQuadratic() )
+ aNodesIter = static_cast<const SMDS_VtkFace*>(anElem)->
+ interlacedNodesElemIterator();
+ else
+ aNodesIter = anElem->nodesIterator();
+ long aNodeId[2];
+ const SMDS_MeshElement* aNode;
+ if(aNodesIter->more()){
+ aNode = aNodesIter->next();
+ aNodeId[0] = aNodeId[1] = aNode->GetID();
+ }
+ for(; aNodesIter->more(); ){
+ aNode = aNodesIter->next();
+ long anId = aNode->GetID();
+ Border aBorder(anElemId,aNodeId[1],anId);
+ aNodeId[1] = anId;
+ UpdateBorders(aBorder,aRegistry,theBorders);
+ }
+ Border aBorder(anElemId,aNodeId[0],aNodeId[1]);
+ UpdateBorders(aBorder,aRegistry,theBorders);
+ }
+}
+
+//================================================================================
+/*
+ Class : FreeNodes
+ Description : Predicate for free nodes
+*/
+//================================================================================
+
+FreeNodes::FreeNodes()
+{
+ myMesh = 0;
+}
+
+void FreeNodes::SetMesh( const SMDS_Mesh* theMesh )
+{
+ myMesh = theMesh;
+}
+
+bool FreeNodes::IsSatisfy( long theNodeId )
+{
+ const SMDS_MeshNode* aNode = myMesh->FindNode( theNodeId );
+ if (!aNode)
+ return false;
+
+ return (aNode->NbInverseElements() < 1);
+}
+
+SMDSAbs_ElementType FreeNodes::GetType() const
+{
+ return SMDSAbs_Node;
+}
+
+
+//================================================================================
+/*
+ Class : FreeFaces
+ Description : Predicate for free faces
+*/
+//================================================================================
+
+FreeFaces::FreeFaces()
+{
+ myMesh = 0;
+}
+
+void FreeFaces::SetMesh( const SMDS_Mesh* theMesh )
+{
+ myMesh = theMesh;
+}
+
+bool FreeFaces::IsSatisfy( long theId )
+{
+ if (!myMesh) return false;
+ // check that faces nodes refers to less than two common volumes
+ const SMDS_MeshElement* aFace = myMesh->FindElement( theId );
+ if ( !aFace || aFace->GetType() != SMDSAbs_Face )
+ return false;
+
+ int nbNode = aFace->NbNodes();
+
+ // collect volumes check that number of volumss with count equal nbNode not less than 2
+ typedef map< SMDS_MeshElement*, int > TMapOfVolume; // map of volume counters
+ typedef map< SMDS_MeshElement*, int >::iterator TItrMapOfVolume; // iterator
+ TMapOfVolume mapOfVol;
+
+ SMDS_ElemIteratorPtr nodeItr = aFace->nodesIterator();
+ while ( nodeItr->more() ) {
+ const SMDS_MeshNode* aNode = static_cast<const SMDS_MeshNode*>(nodeItr->next());
+ if ( !aNode ) continue;
+ SMDS_ElemIteratorPtr volItr = aNode->GetInverseElementIterator(SMDSAbs_Volume);
+ while ( volItr->more() ) {
+ SMDS_MeshElement* aVol = (SMDS_MeshElement*)volItr->next();
+ TItrMapOfVolume itr = mapOfVol.insert(make_pair(aVol, 0)).first;
+ (*itr).second++;
+ }
+ }
+ int nbVol = 0;
+ TItrMapOfVolume volItr = mapOfVol.begin();
+ TItrMapOfVolume volEnd = mapOfVol.end();
+ for ( ; volItr != volEnd; ++volItr )
+ if ( (*volItr).second >= nbNode )
+ nbVol++;
+ // face is not free if number of volumes constructed on thier nodes more than one
+ return (nbVol < 2);
+}
+
+SMDSAbs_ElementType FreeFaces::GetType() const
+{
+ return SMDSAbs_Face;
+}
+
+//================================================================================
+/*
+ Class : LinearOrQuadratic
+ Description : Predicate to verify whether a mesh element is linear
+*/
+//================================================================================
+
+LinearOrQuadratic::LinearOrQuadratic()
+{
+ myMesh = 0;
+}
+
+void LinearOrQuadratic::SetMesh( const SMDS_Mesh* theMesh )
+{
+ myMesh = theMesh;
+}
+
+bool LinearOrQuadratic::IsSatisfy( long theId )
+{
+ if (!myMesh) return false;
+ const SMDS_MeshElement* anElem = myMesh->FindElement( theId );
+ if ( !anElem || (myType != SMDSAbs_All && anElem->GetType() != myType) )
+ return false;
+ return (!anElem->IsQuadratic());
+}
+
+void LinearOrQuadratic::SetType( SMDSAbs_ElementType theType )
+{
+ myType = theType;
+}
+
+SMDSAbs_ElementType LinearOrQuadratic::GetType() const
+{
+ return myType;
+}
+
+//================================================================================
+/*
+ Class : GroupColor
+ Description : Functor for check color of group to whic mesh element belongs to
+*/
+//================================================================================
+
+GroupColor::GroupColor()
+{
+}
+
+bool GroupColor::IsSatisfy( long theId )
+{
+ return (myIDs.find( theId ) != myIDs.end());
+}
+
+void GroupColor::SetType( SMDSAbs_ElementType theType )
+{
+ myType = theType;
+}
+
+SMDSAbs_ElementType GroupColor::GetType() const
+{
+ return myType;
+}
+
+static bool isEqual( const Quantity_Color& theColor1,
+ const Quantity_Color& theColor2 )
+{
+ // tolerance to compare colors
+ const double tol = 5*1e-3;
+ return ( fabs( theColor1.Red() - theColor2.Red() ) < tol &&
+ fabs( theColor1.Green() - theColor2.Green() ) < tol &&
+ fabs( theColor1.Blue() - theColor2.Blue() ) < tol );
+}
+
+
+void GroupColor::SetMesh( const SMDS_Mesh* theMesh )
+{
+ myIDs.clear();
+
+ const SMESHDS_Mesh* aMesh = dynamic_cast<const SMESHDS_Mesh*>(theMesh);
+ if ( !aMesh )
+ return;
+
+ int nbGrp = aMesh->GetNbGroups();
+ if ( !nbGrp )
+ return;
+
+ // iterates on groups and find necessary elements ids
+ const std::set<SMESHDS_GroupBase*>& aGroups = aMesh->GetGroups();
+ set<SMESHDS_GroupBase*>::const_iterator GrIt = aGroups.begin();
+ for (; GrIt != aGroups.end(); GrIt++) {
+ SMESHDS_GroupBase* aGrp = (*GrIt);
+ if ( !aGrp )
+ continue;
+ // check type and color of group
+ if ( !isEqual( myColor, aGrp->GetColor() ) )
+ continue;
+ if ( myType != SMDSAbs_All && myType != (SMDSAbs_ElementType)aGrp->GetType() )
+ continue;
+
+ SMDSAbs_ElementType aGrpElType = (SMDSAbs_ElementType)aGrp->GetType();
+ if ( myType == aGrpElType || (myType == SMDSAbs_All && aGrpElType != SMDSAbs_Node) ) {
+ // add elements IDS into control
+ int aSize = aGrp->Extent();
+ for (int i = 0; i < aSize; i++)
+ myIDs.insert( aGrp->GetID(i+1) );
+ }
+ }
+}
+
+void GroupColor::SetColorStr( const TCollection_AsciiString& theStr )
+{
+ Kernel_Utils::Localizer loc;
+ TCollection_AsciiString aStr = theStr;
+ aStr.RemoveAll( ' ' );
+ aStr.RemoveAll( '\t' );
+ for ( int aPos = aStr.Search( ";;" ); aPos != -1; aPos = aStr.Search( ";;" ) )
+ aStr.Remove( aPos, 2 );
+ Standard_Real clr[3];
+ clr[0] = clr[1] = clr[2] = 0.;
+ for ( int i = 0; i < 3; i++ ) {
+ TCollection_AsciiString tmpStr = aStr.Token( ";", i+1 );
+ if ( !tmpStr.IsEmpty() && tmpStr.IsRealValue() )
+ clr[i] = tmpStr.RealValue();
+ }
+ myColor = Quantity_Color( clr[0], clr[1], clr[2], Quantity_TOC_RGB );
+}
+
+//=======================================================================
+// name : GetRangeStr
+// Purpose : Get range as a string.
+// Example: "1,2,3,50-60,63,67,70-"
+//=======================================================================
+
+void GroupColor::GetColorStr( TCollection_AsciiString& theResStr ) const
+{
+ theResStr.Clear();
+ theResStr += TCollection_AsciiString( myColor.Red() );
+ theResStr += TCollection_AsciiString( ";" ) + TCollection_AsciiString( myColor.Green() );
+ theResStr += TCollection_AsciiString( ";" ) + TCollection_AsciiString( myColor.Blue() );
+}
+
+//================================================================================
+/*
+ Class : ElemGeomType
+ Description : Predicate to check element geometry type
+*/
+//================================================================================
+
+ElemGeomType::ElemGeomType()
+{
+ myMesh = 0;
+ myType = SMDSAbs_All;
+ myGeomType = SMDSGeom_TRIANGLE;
+}
+
+void ElemGeomType::SetMesh( const SMDS_Mesh* theMesh )
+{
+ myMesh = theMesh;
+}
+
+bool ElemGeomType::IsSatisfy( long theId )
+{
+ if (!myMesh) return false;
+ const SMDS_MeshElement* anElem = myMesh->FindElement( theId );
+ if ( !anElem )
+ return false;
+ const SMDSAbs_ElementType anElemType = anElem->GetType();
+ if ( myType != SMDSAbs_All && anElemType != myType )
+ return false;
+ bool isOk = ( anElem->GetGeomType() == myGeomType );
+ return isOk;
+}
+
+void ElemGeomType::SetType( SMDSAbs_ElementType theType )
+{
+ myType = theType;
+}
+
+SMDSAbs_ElementType ElemGeomType::GetType() const
+{
+ return myType;
+}
+
+void ElemGeomType::SetGeomType( SMDSAbs_GeometryType theType )
+{
+ myGeomType = theType;
+}
+
+SMDSAbs_GeometryType ElemGeomType::GetGeomType() const
+{
+ return myGeomType;
+}
+
+//================================================================================
+/*
+ Class : ElemEntityType
+ Description : Predicate to check element entity type
+*/
+//================================================================================
+
+ElemEntityType::ElemEntityType():
+ myMesh( 0 ),
+ myType( SMDSAbs_All ),
+ myEntityType( SMDSEntity_0D )
+{
+}
+
+void ElemEntityType::SetMesh( const SMDS_Mesh* theMesh )
+{
+ myMesh = theMesh;
+}
+
+bool ElemEntityType::IsSatisfy( long theId )
+{
+ if ( !myMesh ) return false;
+ if ( myType == SMDSAbs_Node )
+ return myMesh->FindNode( theId );
+ const SMDS_MeshElement* anElem = myMesh->FindElement( theId );
+ return ( anElem &&
+ myEntityType == anElem->GetEntityType() );
+}
+
+void ElemEntityType::SetType( SMDSAbs_ElementType theType )
+{
+ myType = theType;
+}
+
+SMDSAbs_ElementType ElemEntityType::GetType() const
+{
+ return myType;
+}
+
+void ElemEntityType::SetElemEntityType( SMDSAbs_EntityType theEntityType )
+{
+ myEntityType = theEntityType;
+}
+
+SMDSAbs_EntityType ElemEntityType::GetElemEntityType() const
+{
+ return myEntityType;
+}
+
+//================================================================================
+/*!
+ * \brief Class ConnectedElements
+ */
+//================================================================================
+
+ConnectedElements::ConnectedElements():
+ myNodeID(0), myType( SMDSAbs_All ), myOkIDsReady( false ) {}
+
+SMDSAbs_ElementType ConnectedElements::GetType() const
+{ return myType; }
+
+int ConnectedElements::GetNode() const
+{ return myXYZ.empty() ? myNodeID : 0; } // myNodeID can be found by myXYZ
+
+std::vector<double> ConnectedElements::GetPoint() const
+{ return myXYZ; }
+
+void ConnectedElements::clearOkIDs()
+{ myOkIDsReady = false; myOkIDs.clear(); }
+
+void ConnectedElements::SetType( SMDSAbs_ElementType theType )
+{
+ if ( myType != theType || myMeshModifTracer.IsMeshModified() )
+ clearOkIDs();
+ myType = theType;
+}
+
+void ConnectedElements::SetMesh( const SMDS_Mesh* theMesh )
+{
+ myMeshModifTracer.SetMesh( theMesh );
+ if ( myMeshModifTracer.IsMeshModified() )