Salome HOME
52609: Geometric progression works wrong with "Reversed edges" option used + Propagation
[modules/smesh.git] / src / Controls / SMESH_Controls.cxx
index e7e61b1132ced57e492509ed67d9371d752296b8..42c668044def6d2b04df05bb2536ab948c218c0e 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2013  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2014  CEA/DEN, EDF R&D, OPEN CASCADE
 //
 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
@@ -6,7 +6,7 @@
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Lesser General Public
 // License as published by the Free Software Foundation; either
-// version 2.1 of the License.
+// version 2.1 of the License, or (at your option) any later version.
 //
 // This library is distributed in the hope that it will be useful,
 // but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -1526,7 +1526,7 @@ SMDSAbs_ElementType Length::GetType() const
 */
 //================================================================================
 
-double Length2D::GetValue( long theElementId)
+double Length2D::GetValue( long theElementId )
 {
   TSequenceOfXYZ P;
 
@@ -1558,7 +1558,7 @@ double Length2D::GetValue( long theElementId)
         double L1 = getDistance(P( 1 ),P( 2 ));
         double L2 = getDistance(P( 2 ),P( 3 ));
         double L3 = getDistance(P( 3 ),P( 1 ));
-        aVal = Max(L1,Max(L2,L3));
+        aVal = Min(L1,Min(L2,L3));
         break;
       }
       else if (len == 4){ // quadrangles
@@ -1566,14 +1566,14 @@ double Length2D::GetValue( long theElementId)
         double L2 = getDistance(P( 2 ),P( 3 ));
         double L3 = getDistance(P( 3 ),P( 4 ));
         double L4 = getDistance(P( 4 ),P( 1 ));
-        aVal = Max(Max(L1,L2),Max(L3,L4));
+        aVal = Min(Min(L1,L2),Min(L3,L4));
         break;
       }
       if (len == 6){ // quadratic triangles
         double L1 = getDistance(P( 1 ),P( 2 )) + getDistance(P( 2 ),P( 3 ));
         double L2 = getDistance(P( 3 ),P( 4 )) + getDistance(P( 4 ),P( 5 ));
         double L3 = getDistance(P( 5 ),P( 6 )) + getDistance(P( 6 ),P( 1 ));
-        aVal = Max(L1,Max(L2,L3));
+        aVal = Min(L1,Min(L2,L3));
         //cout<<"L1="<<L1<<" L2="<<L2<<"L3="<<L3<<" aVal="<<aVal<<endl;
         break;
       }
@@ -1582,7 +1582,7 @@ double Length2D::GetValue( long theElementId)
         double L2 = getDistance(P( 3 ),P( 4 )) + getDistance(P( 4 ),P( 5 ));
         double L3 = getDistance(P( 5 ),P( 6 )) + getDistance(P( 6 ),P( 7 ));
         double L4 = getDistance(P( 7 ),P( 8 )) + getDistance(P( 8 ),P( 1 ));
-        aVal = Max(Max(L1,L2),Max(L3,L4));
+        aVal = Min(Min(L1,L2),Min(L3,L4));
         break;
       }
     case SMDSAbs_Volume:
@@ -1593,7 +1593,7 @@ double Length2D::GetValue( long theElementId)
         double L4 = getDistance(P( 1 ),P( 4 ));
         double L5 = getDistance(P( 2 ),P( 4 ));
         double L6 = getDistance(P( 3 ),P( 4 ));
-        aVal = Max(Max(Max(L1,L2),Max(L3,L4)),Max(L5,L6));
+        aVal = Min(Min(Min(L1,L2),Min(L3,L4)),Min(L5,L6));
         break;
       }
       else if (len == 5){ // piramids
@@ -1606,8 +1606,8 @@ double Length2D::GetValue( long theElementId)
         double L7 = getDistance(P( 3 ),P( 5 ));
         double L8 = getDistance(P( 4 ),P( 5 ));
 
-        aVal = Max(Max(Max(L1,L2),Max(L3,L4)),Max(L5,L6));
-        aVal = Max(aVal,Max(L7,L8));
+        aVal = Min(Min(Min(L1,L2),Min(L3,L4)),Min(L5,L6));
+        aVal = Min(aVal,Min(L7,L8));
         break;
       }
       else if (len == 6){ // pentaidres
@@ -1621,8 +1621,8 @@ double Length2D::GetValue( long theElementId)
         double L8 = getDistance(P( 2 ),P( 5 ));
         double L9 = getDistance(P( 3 ),P( 6 ));
 
-        aVal = Max(Max(Max(L1,L2),Max(L3,L4)),Max(L5,L6));
-        aVal = Max(aVal,Max(Max(L7,L8),L9));
+        aVal = Min(Min(Min(L1,L2),Min(L3,L4)),Min(L5,L6));
+        aVal = Min(aVal,Min(Min(L7,L8),L9));
         break;
       }
       else if (len == 8){ // hexaider
@@ -1639,9 +1639,9 @@ double Length2D::GetValue( long theElementId)
         double L11= getDistance(P( 3 ),P( 7 ));
         double L12= getDistance(P( 4 ),P( 8 ));
 
-        aVal = Max(Max(Max(L1,L2),Max(L3,L4)),Max(L5,L6));
-        aVal = Max(aVal,Max(Max(L7,L8),Max(L9,L10)));
-        aVal = Max(aVal,Max(L11,L12));
+        aVal = Min(Min(Min(L1,L2),Min(L3,L4)),Min(L5,L6));
+        aVal = Min(aVal,Min(Min(L7,L8),Min(L9,L10)));
+        aVal = Min(aVal,Min(L11,L12));
         break;
 
       }
@@ -1653,7 +1653,7 @@ double Length2D::GetValue( long theElementId)
         double L4 = getDistance(P( 1 ),P( 8 )) + getDistance(P( 8 ),P( 4 ));
         double L5 = getDistance(P( 2 ),P( 9 )) + getDistance(P( 9 ),P( 4 ));
         double L6 = getDistance(P( 3 ),P( 10 )) + getDistance(P( 10 ),P( 4 ));
-        aVal = Max(Max(Max(L1,L2),Max(L3,L4)),Max(L5,L6));
+        aVal = Min(Min(Min(L1,L2),Min(L3,L4)),Min(L5,L6));
         break;
       }
       else if (len == 13){ // quadratic piramids
@@ -1665,8 +1665,8 @@ double Length2D::GetValue( long theElementId)
         double L6 = getDistance(P( 2 ),P( 11 )) + getDistance(P( 11 ),P( 5 ));
         double L7 = getDistance(P( 3 ),P( 12 )) + getDistance(P( 12 ),P( 5 ));
         double L8 = getDistance(P( 4 ),P( 13 )) + getDistance(P( 13 ),P( 5 ));
-        aVal = Max(Max(Max(L1,L2),Max(L3,L4)),Max(L5,L6));
-        aVal = Max(aVal,Max(L7,L8));
+        aVal = Min(Min(Min(L1,L2),Min(L3,L4)),Min(L5,L6));
+        aVal = Min(aVal,Min(L7,L8));
         break;
       }
       else if (len == 15){ // quadratic pentaidres
@@ -1679,8 +1679,8 @@ double Length2D::GetValue( long theElementId)
         double L7 = getDistance(P( 1 ),P( 13 )) + getDistance(P( 13 ),P( 4 ));
         double L8 = getDistance(P( 2 ),P( 14 )) + getDistance(P( 14 ),P( 5 ));
         double L9 = getDistance(P( 3 ),P( 15 )) + getDistance(P( 15 ),P( 6 ));
-        aVal = Max(Max(Max(L1,L2),Max(L3,L4)),Max(L5,L6));
-        aVal = Max(aVal,Max(Max(L7,L8),L9));
+        aVal = Min(Min(Min(L1,L2),Min(L3,L4)),Min(L5,L6));
+        aVal = Min(aVal,Min(Min(L7,L8),L9));
         break;
       }
       else if (len == 20){ // quadratic hexaider
@@ -1696,9 +1696,9 @@ double Length2D::GetValue( long theElementId)
         double L10= getDistance(P( 2 ),P( 18 )) + getDistance(P( 18 ),P( 6 ));
         double L11= getDistance(P( 3 ),P( 19 )) + getDistance(P( 19 ),P( 7 ));
         double L12= getDistance(P( 4 ),P( 20 )) + getDistance(P( 20 ),P( 8 ));
-        aVal = Max(Max(Max(L1,L2),Max(L3,L4)),Max(L5,L6));
-        aVal = Max(aVal,Max(Max(L7,L8),Max(L9,L10)));
-        aVal = Max(aVal,Max(L11,L12));
+        aVal = Min(Min(Min(L1,L2),Min(L3,L4)),Min(L5,L6));
+        aVal = Min(aVal,Min(Min(L7,L8),Min(L9,L10)));
+        aVal = Min(aVal,Min(L11,L12));
         break;
 
       }
@@ -1706,7 +1706,7 @@ double Length2D::GetValue( long theElementId)
     default: aVal=-1;
     }
 
-    if (aVal <0){
+    if (aVal < 0 ) {
       return 0.;
     }
 
@@ -1724,7 +1724,7 @@ double Length2D::GetValue( long theElementId)
 
 double Length2D::GetBadRate( double Value, int /*nbNodes*/ ) const
 {
-  // meaningless as it is not quality control functor
+  // meaningless as it is not quality control functor
   return Value;
 }
 
@@ -1954,6 +1954,7 @@ bool MultiConnection2D::Value::operator<(const MultiConnection2D::Value& x) cons
 }
 
 void MultiConnection2D::GetValues(MValues& theValues){
+  if ( !myMesh ) return;
   SMDS_FaceIteratorPtr anIter = myMesh->facesIterator();
   for(; anIter->more(); ){
     const SMDS_MeshFace* anElem = anIter->next();
@@ -3134,11 +3135,14 @@ bool RangeOfIds::SetRangeStr( const TCollection_AsciiString& theStr )
   myIds.Clear();
 
   TCollection_AsciiString aStr = theStr;
-  aStr.RemoveAll( ' ' );
-  aStr.RemoveAll( '\t' );
+  //aStr.RemoveAll( ' ' );
+  //aStr.RemoveAll( '\t' );
+  for ( int i = 1; i <= aStr.Length(); ++i )
+    if ( isspace( aStr.Value( i )))
+      aStr.SetValue( i, ',');
 
   for ( int aPos = aStr.Search( ",," ); aPos != -1; aPos = aStr.Search( ",," ) )
-    aStr.Remove( aPos, 2 );
+    aStr.Remove( aPos, 1 );
 
   TCollection_AsciiString tmpStr = aStr.Token( ",", 1 );
   int i = 1;
@@ -3995,7 +3999,41 @@ void ElementsOnShape::SetAllNodes (bool theAllNodes)
 
 void ElementsOnShape::SetMesh (const SMDS_Mesh* theMesh)
 {
-  myMesh = theMesh;
+  myMeshModifTracer.SetMesh( theMesh );
+  if ( myMeshModifTracer.IsMeshModified())
+  {
+    size_t nbNodes = theMesh ? theMesh->NbNodes() : 0;
+    if ( myNodeIsChecked.size() == nbNodes )
+    {
+      std::fill( myNodeIsChecked.begin(), myNodeIsChecked.end(), false );
+    }
+    else
+    {
+      SMESHUtils::FreeVector( myNodeIsChecked );
+      SMESHUtils::FreeVector( myNodeIsOut );
+      myNodeIsChecked.resize( nbNodes, false );
+      myNodeIsOut.resize( nbNodes );
+    }
+  }
+}
+
+bool ElementsOnShape::getNodeIsOut( const SMDS_MeshNode* n, bool& isOut )
+{
+  if ( n->GetID() >= (int) myNodeIsChecked.size() ||
+       !myNodeIsChecked[ n->GetID() ])
+    return false;
+
+  isOut = myNodeIsOut[ n->GetID() ];
+  return true;
+}
+
+void ElementsOnShape::setNodeIsOut( const SMDS_MeshNode* n, bool  isOut )
+{
+  if ( n->GetID() < (int) myNodeIsChecked.size() )
+  {
+    myNodeIsChecked[ n->GetID() ] = true;
+    myNodeIsOut    [ n->GetID() ] = isOut;
+  }
 }
 
 void ElementsOnShape::SetShape (const TopoDS_Shape&       theShape,
@@ -4004,7 +4042,7 @@ void ElementsOnShape::SetShape (const TopoDS_Shape&       theShape,
   myType  = theType;
   myShape = theShape;
   if ( myShape.IsNull() ) return;
-  
+
   TopTools_IndexedMapOfShape shapesMap;
   TopAbs_ShapeEnum shapeTypes[4] = { TopAbs_SOLID, TopAbs_FACE, TopAbs_EDGE, TopAbs_VERTEX };
   TopExp_Explorer sub;
@@ -4022,6 +4060,16 @@ void ElementsOnShape::SetShape (const TopoDS_Shape&       theShape,
   myClassifiers.resize( shapesMap.Extent() );
   for ( int i = 0; i < shapesMap.Extent(); ++i )
     myClassifiers[ i ] = new TClassifier( shapesMap( i+1 ), myToler );
+
+  if ( theType == SMDSAbs_Node )
+  {
+    SMESHUtils::FreeVector( myNodeIsChecked );
+    SMESHUtils::FreeVector( myNodeIsOut );
+  }
+  else
+  {
+    std::fill( myNodeIsChecked.begin(), myNodeIsChecked.end(), false );
+  }
 }
 
 void ElementsOnShape::clearClassifiers()
@@ -4033,38 +4081,45 @@ void ElementsOnShape::clearClassifiers()
 
 bool ElementsOnShape::IsSatisfy (long elemId)
 {
+  const SMDS_Mesh*        mesh = myMeshModifTracer.GetMesh();
   const SMDS_MeshElement* elem =
-    ( myType == SMDSAbs_Node ? myMesh->FindNode( elemId ) : myMesh->FindElement( elemId ));
+    ( myType == SMDSAbs_Node ? mesh->FindNode( elemId ) : mesh->FindElement( elemId ));
   if ( !elem || myClassifiers.empty() )
     return false;
 
-  for ( size_t i = 0; i < myClassifiers.size(); ++i )
+  bool isSatisfy = myAllNodesFlag, isNodeOut;
+
+  gp_XYZ centerXYZ (0, 0, 0);
+
+  SMDS_ElemIteratorPtr aNodeItr = elem->nodesIterator();
+  while (aNodeItr->more() && (isSatisfy == myAllNodesFlag))
   {
-    SMDS_ElemIteratorPtr aNodeItr = elem->nodesIterator();
-    bool isSatisfy = myAllNodesFlag;
-    
-    gp_XYZ centerXYZ (0, 0, 0);
+    SMESH_TNodeXYZ aPnt( aNodeItr->next() );
+    centerXYZ += aPnt;
 
-    while (aNodeItr->more() && (isSatisfy == myAllNodesFlag))
+    isNodeOut = true;
+    if ( !getNodeIsOut( aPnt._node, isNodeOut ))
     {
-      SMESH_TNodeXYZ aPnt ( aNodeItr->next() );
-      centerXYZ += aPnt;
-      isSatisfy = ! myClassifiers[i]->IsOut( aPnt );
+      for ( size_t i = 0; i < myClassifiers.size() && isNodeOut; ++i )
+        isNodeOut = myClassifiers[i]->IsOut( aPnt );
+
+      setNodeIsOut( aPnt._node, isNodeOut );
     }
+    isSatisfy = !isNodeOut;
+  }
 
-    // Check the center point for volumes MantisBug 0020168
-    if (isSatisfy &&
-        myAllNodesFlag &&
-        myClassifiers[i]->ShapeType() == TopAbs_SOLID)
-    {
-      centerXYZ /= elem->NbNodes();
+  // Check the center point for volumes MantisBug 0020168
+  if (isSatisfy &&
+      myAllNodesFlag &&
+      myClassifiers[0]->ShapeType() == TopAbs_SOLID)
+  {
+    centerXYZ /= elem->NbNodes();
+    isSatisfy = false;
+    for ( size_t i = 0; i < myClassifiers.size() && !isSatisfy; ++i )
       isSatisfy = ! myClassifiers[i]->IsOut( centerXYZ );
-    }
-    if ( isSatisfy )
-      return true;
   }
 
-  return false;
+  return isSatisfy;
 }
 
 TopAbs_ShapeEnum ElementsOnShape::TClassifier::ShapeType() const
@@ -4247,11 +4302,11 @@ void BelongToGeom::init()
     myIsSubshape = IsSubShape(aMap, myShape);
   }
 
-  if (!myIsSubshape)
+  //if (!myIsSubshape) // to be always ready to check an element not bound to geometry
   {
     myElementsOnShapePtr.reset(new ElementsOnShape());
     myElementsOnShapePtr->SetTolerance(myTolerance);
-    myElementsOnShapePtr->SetAllNodes(true); // belong, while false means "lays on"
+    myElementsOnShapePtr->SetAllNodes(true); // "belong", while false means "lays on"
     myElementsOnShapePtr->SetMesh(myMeshDS);
     myElementsOnShapePtr->SetShape(myShape, myType);
   }
@@ -4292,36 +4347,43 @@ bool BelongToGeom::IsSatisfy (long theId)
   {
     if( const SMDS_MeshNode* aNode = myMeshDS->FindNode( theId ) )
     {
+      if ( aNode->getshapeId() < 1 )
+        return myElementsOnShapePtr->IsSatisfy(theId);
+
       const SMDS_PositionPtr& aPosition = aNode->GetPosition();
       SMDS_TypeOfPosition aTypeOfPosition = aPosition->GetTypeOfPosition();
       switch( aTypeOfPosition )
       {
-      case SMDS_TOP_VERTEX : return IsContains( myMeshDS,myShape,aNode,TopAbs_VERTEX );
-      case SMDS_TOP_EDGE   : return IsContains( myMeshDS,myShape,aNode,TopAbs_EDGE );
-      case SMDS_TOP_FACE   : return IsContains( myMeshDS,myShape,aNode,TopAbs_FACE );
-      case SMDS_TOP_3DSPACE: return IsContains( myMeshDS,myShape,aNode,TopAbs_SHELL );
+      case SMDS_TOP_VERTEX : return ( IsContains( myMeshDS,myShape,aNode,TopAbs_VERTEX ));
+      case SMDS_TOP_EDGE   : return ( IsContains( myMeshDS,myShape,aNode,TopAbs_EDGE ));
+      case SMDS_TOP_FACE   : return ( IsContains( myMeshDS,myShape,aNode,TopAbs_FACE ));
+      case SMDS_TOP_3DSPACE: return ( IsContains( myMeshDS,myShape,aNode,TopAbs_SOLID ) ||
+                                      IsContains( myMeshDS,myShape,aNode,TopAbs_SHELL ));
       }
     }
   }
   else
   {
-    if( const SMDS_MeshElement* anElem = myMeshDS->FindElement( theId ) )
+    if ( const SMDS_MeshElement* anElem = myMeshDS->FindElement( theId ))
     {
+      if ( anElem->getshapeId() < 1 )
+        return myElementsOnShapePtr->IsSatisfy(theId);
+
       if( myType == SMDSAbs_All )
       {
-        return IsContains( myMeshDS,myShape,anElem,TopAbs_EDGE ) ||
-               IsContains( myMeshDS,myShape,anElem,TopAbs_FACE ) ||
-               IsContains( myMeshDS,myShape,anElem,TopAbs_SHELL )||
-               IsContains( myMeshDS,myShape,anElem,TopAbs_SOLID );
+        return IsContains( myMeshDS,myShape,anElem,TopAbs_EDGE ) ||
+                 IsContains( myMeshDS,myShape,anElem,TopAbs_FACE ) ||
+                 IsContains( myMeshDS,myShape,anElem,TopAbs_SOLID )||
+                 IsContains( myMeshDS,myShape,anElem,TopAbs_SHELL ));
       }
       else if( myType == anElem->GetType() )
       {
         switch( myType )
         {
-        case SMDSAbs_Edge  : return IsContains( myMeshDS,myShape,anElem,TopAbs_EDGE );
-        case SMDSAbs_Face  : return IsContains( myMeshDS,myShape,anElem,TopAbs_FACE );
-        case SMDSAbs_Volume: return IsContains( myMeshDS,myShape,anElem,TopAbs_SHELL )||
-                                    IsContains( myMeshDS,myShape,anElem,TopAbs_SOLID );
+        case SMDSAbs_Edge  : return ( IsContains( myMeshDS,myShape,anElem,TopAbs_EDGE ));
+        case SMDSAbs_Face  : return ( IsContains( myMeshDS,myShape,anElem,TopAbs_FACE ));
+        case SMDSAbs_Volume: return ( IsContains( myMeshDS,myShape,anElem,TopAbs_SOLID )||
+                                      IsContains( myMeshDS,myShape,anElem,TopAbs_SHELL ));
         }
       }
     }