Salome HOME
PR: display submeshes and groups
[modules/smesh.git] / src / OBJECT / SMESH_Object.cxx
index 9bdc652a09b9c260bf07555077489f601875a9c5..1566d3506345202bbbdd1c8d772f2caccd0cd32b 100644 (file)
@@ -1,30 +1,29 @@
-//  SMESH OBJECT : interactive object for SMESH visualization
+//  Copyright (C) 2007-2008  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+//  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+//  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License.
 //
-//  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
-//  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS 
-// 
-//  This library is free software; you can redistribute it and/or 
-//  modify it under the terms of the GNU Lesser General Public 
-//  License as published by the Free Software Foundation; either 
-//  version 2.1 of the License. 
-// 
-//  This library is distributed in the hope that it will be useful, 
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of 
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
-//  Lesser General Public License for more details. 
-// 
-//  You should have received a copy of the GNU Lesser General Public 
-//  License along with this library; if not, write to the Free Software 
-//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA 
-// 
-// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
 //
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 //
+//  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
+//  SMESH OBJECT : interactive object for SMESH visualization
 //  File   : SMESH_Grid.cxx
 //  Author : Nicolas REJNERI
 //  Module : SMESH
-
+//
 #include "SMESH_ObjectDef.h"
 #include "SMESH_ActorUtils.h"
 
@@ -47,7 +46,7 @@
 #include <vtkUnstructuredGrid.h>
 
 #include <memory>
-#include <sstream>     
+#include <sstream>      
 #include <stdexcept>
 #include <set>
 
@@ -64,7 +63,7 @@ using namespace std;
 #endif
 
 #ifdef _DEBUG_
-static int MYDEBUG = 0;
+static int MYDEBUG = 1;
 static int MYDEBUGWITHFILES = 0;
 #else
 static int MYDEBUG = 0;
@@ -82,11 +81,14 @@ static int MYDEBUGWITHFILES = 0;
 // purpose  : Get type of VTK cell
 //=================================================================================
 static inline vtkIdType getCellType( const SMDSAbs_ElementType theType,
-                                    const bool thePoly,
+                                     const bool thePoly,
                                      const int theNbNodes )
 {
   switch( theType )
   {
+    case SMDSAbs_0DElement: 
+      return VTK_VERTEX;
+
     case SMDSAbs_Edge: 
       if( theNbNodes == 2 )         return VTK_LINE;
       else if ( theNbNodes == 3 )   return VTK_QUADRATIC_EDGE;
@@ -112,7 +114,10 @@ static inline vtkIdType getCellType( const SMDSAbs_ElementType theType,
       else if ( theNbNodes == 20 )  {
         return VTK_QUADRATIC_HEXAHEDRON;
       }
-      else if ( theNbNodes==13 || theNbNodes==15 )  {
+      else if ( theNbNodes == 15 )  {
+        return VTK_QUADRATIC_WEDGE;
+      }
+      else if ( theNbNodes==13 )  {
         return VTK_CONVEX_POINT_SET;
       }
       else return VTK_EMPTY_CELL;
@@ -127,11 +132,14 @@ static inline vtkIdType getCellType( const SMDSAbs_ElementType theType,
 //=================================================================================
 SMESH_VisualObjDef::SMESH_VisualObjDef()
 {
+  MESSAGE("---------------------------------------------SMESH_VisualObjDef::SMESH_VisualObjDef");
   myGrid = vtkUnstructuredGrid::New();
+  myLocalGrid = false;
 }
 SMESH_VisualObjDef::~SMESH_VisualObjDef()
 {
-  if ( MYDEBUG )
+  MESSAGE("---------------------------------------------SMESH_VisualObjDef::~SMESH_VisualObjDef");
+  //if ( MYDEBUG )
     MESSAGE( "~SMESH_MeshObj - myGrid->GetReferenceCount() = " << myGrid->GetReferenceCount() );
   myGrid->Delete();
 }
@@ -142,28 +150,52 @@ SMESH_VisualObjDef::~SMESH_VisualObjDef()
 //=================================================================================
 vtkIdType SMESH_VisualObjDef::GetNodeObjId( int theVTKID )
 {
-  return myVTK2SMDSNodes.find(theVTKID) == myVTK2SMDSNodes.end() ? -1 : myVTK2SMDSNodes[theVTKID];
+       if (myLocalGrid)
+       {
+               TMapOfIds::const_iterator i = myVTK2SMDSNodes.find(theVTKID);
+               return i == myVTK2SMDSNodes.end() ? -1 : i->second;
+       }
+  return theVTKID;
 }
 
 vtkIdType SMESH_VisualObjDef::GetNodeVTKId( int theObjID )
 {
-  return mySMDS2VTKNodes.find(theObjID) == mySMDS2VTKNodes.end() ? -1 : mySMDS2VTKNodes[theObjID];
+       if (myLocalGrid)
+       {
+               TMapOfIds::const_iterator i = mySMDS2VTKNodes.find(theObjID);
+    return i == mySMDS2VTKNodes.end() ? -1 : i->second;
+       }
+  return theObjID;
 }
 
 vtkIdType SMESH_VisualObjDef::GetElemObjId( int theVTKID )
 {
-  return myVTK2SMDSElems.find(theVTKID) == myVTK2SMDSElems.end() ? -1 : myVTK2SMDSElems[theVTKID];
+       if (myLocalGrid)
+       {
+               TMapOfIds::const_iterator i = myVTK2SMDSElems.find(theVTKID);
+               return i == myVTK2SMDSElems.end() ? -1 : i->second;
+       }
+  return this->GetMesh()->fromVtkToSmds(theVTKID);
 }
 
 vtkIdType SMESH_VisualObjDef::GetElemVTKId( int theObjID )
 {
-  return mySMDS2VTKElems.find(theObjID) == mySMDS2VTKElems.end() ? -1 : mySMDS2VTKElems[theObjID];
+       if (myLocalGrid)
+       {
+               TMapOfIds::const_iterator i = mySMDS2VTKElems.find(theObjID);
+               return i == mySMDS2VTKElems.end() ? -1 : i->second;
+       }
+  return this->GetMesh()->fromSmdsToVtk(theObjID);
 }
 
 //=================================================================================
 // function : SMESH_VisualObjDef::createPoints
 // purpose  : Create points from nodes
 //=================================================================================
+/*! fills a vtkPoints structure for a submesh.
+ *  fills a std::list of SMDS_MeshElements*, then extract the points.
+ *  fills also conversion id maps between SMDS and VTK.
+ */
 void SMESH_VisualObjDef::createPoints( vtkPoints* thePoints )
 {
   if ( thePoints == 0 )
@@ -172,7 +204,7 @@ void SMESH_VisualObjDef::createPoints( vtkPoints* thePoints )
   TEntityList aNodes;
   vtkIdType nbNodes = GetEntities( SMDSAbs_Node, aNodes );
   thePoints->SetNumberOfPoints( nbNodes );
-  
+
   int nbPoints = 0;
 
   TEntityList::const_iterator anIter;
@@ -197,48 +229,61 @@ void SMESH_VisualObjDef::createPoints( vtkPoints* thePoints )
 // function : buildPrs
 // purpose  : create VTK cells( fill unstructured grid )
 //=================================================================================
-void SMESH_VisualObjDef::buildPrs()
+void SMESH_VisualObjDef::buildPrs(bool buildGrid)
 {
-  try 
+  MESSAGE("----------------------------------------------------------SMESH_VisualObjDef::buildPrs " << buildGrid);
+  if (buildGrid)
   {
-    mySMDS2VTKNodes.clear();
-    myVTK2SMDSNodes.clear();
-    mySMDS2VTKElems.clear();
-    myVTK2SMDSElems.clear();
-    
-    if ( IsNodePrs() )
-      buildNodePrs();
-    else
-      buildElemPrs();
+       myLocalGrid = true;
+       try
+       {
+               mySMDS2VTKNodes.clear();
+               myVTK2SMDSNodes.clear();
+               mySMDS2VTKElems.clear();
+               myVTK2SMDSElems.clear();
+
+               if ( IsNodePrs() )
+                       buildNodePrs();
+               else
+                       buildElemPrs();
+       }
+       catch(...)
+       {
+               mySMDS2VTKNodes.clear();
+               myVTK2SMDSNodes.clear();
+               mySMDS2VTKElems.clear();
+               myVTK2SMDSElems.clear();
+
+               myGrid->SetPoints( 0 );
+               myGrid->SetCells( 0, 0, 0 );
+               throw;
+       }
   }
-  catch(...)
+  else
   {
-    mySMDS2VTKNodes.clear();
-    myVTK2SMDSNodes.clear();
-    mySMDS2VTKElems.clear();
-    myVTK2SMDSElems.clear();
-
-    myGrid->SetPoints( 0 );
-    myGrid->SetCells( 0, 0, 0 );
-    throw;
+       myLocalGrid = false;
+       vtkUnstructuredGrid *theGrid = GetMesh()->getGrid();
+       myGrid->ShallowCopy(theGrid);
+       MESSAGE(myGrid->GetReferenceCount());
+       MESSAGE( "Update - myGrid->GetNumberOfCells() = "<<myGrid->GetNumberOfCells() );
+       MESSAGE( "Update - myGrid->GetNumberOfPoints() = "<<myGrid->GetNumberOfPoints() );
+       if( MYDEBUGWITHFILES ) SMESH::WriteUnstructuredGrid( myGrid,"/tmp/buildPrs" );
   }
-  
-  if( MYDEBUG ) MESSAGE( "Update - myGrid->GetNumberOfCells() = "<<myGrid->GetNumberOfCells() );
-  if( MYDEBUGWITHFILES ) SMESH::WriteUnstructuredGrid( myGrid,"/tmp/buildPrs" );
 }
 
 //=================================================================================
 // function : buildNodePrs
 // purpose  : create VTK cells for nodes
 //=================================================================================
+
 void SMESH_VisualObjDef::buildNodePrs()
 {
   // PAL16631: without swap, bad_alloc is not thrown but hung up and crash instead,
   // so check remaining memory size for safety
-  SMDS_Mesh::CheckMemory(); // PAL16631
+  // SMDS_Mesh::CheckMemory(); // PAL16631
   vtkPoints* aPoints = vtkPoints::New();
   createPoints( aPoints );
-  SMDS_Mesh::CheckMemory();
+  // SMDS_Mesh::CheckMemory();
   myGrid->SetPoints( aPoints );
   aPoints->Delete();
 
@@ -254,7 +299,7 @@ namespace{
   typedef std::vector<const SMDS_MeshElement*> TConnect;
 
   int GetConnect(const SMDS_ElemIteratorPtr& theNodesIter, 
-                TConnect& theConnect)
+                 TConnect& theConnect)
   {
     theConnect.clear();
     for(; theNodesIter->more();)
@@ -264,10 +309,10 @@ namespace{
   
   inline 
   void SetId(vtkIdList *theIdList, 
-            const SMESH_VisualObjDef::TMapOfIds& theSMDS2VTKNodes, 
-            const TConnect& theConnect, 
-            int thePosition,
-            int theId)
+             const SMESH_VisualObjDef::TMapOfIds& theSMDS2VTKNodes, 
+             const TConnect& theConnect, 
+             int thePosition,
+             int theId)
   {
     theIdList->SetId(thePosition,theSMDS2VTKNodes.find(theConnect[theId]->GetID())->second);
   }
@@ -278,33 +323,34 @@ namespace{
 void SMESH_VisualObjDef::buildElemPrs()
 {
   // Create points
-  
+
   vtkPoints* aPoints = vtkPoints::New();
   createPoints( aPoints );
   myGrid->SetPoints( aPoints );
   aPoints->Delete();
-    
+
   if ( MYDEBUG )
     MESSAGE("Update - myGrid->GetNumberOfPoints() = "<<myGrid->GetNumberOfPoints());
 
   // Calculate cells size
 
-  static SMDSAbs_ElementType aTypes[ 3 ] = { SMDSAbs_Edge, SMDSAbs_Face, SMDSAbs_Volume };
+  static SMDSAbs_ElementType aTypes[ 4 ] =
+    { SMDSAbs_0DElement, SMDSAbs_Edge, SMDSAbs_Face, SMDSAbs_Volume };
 
   // get entity data
   map<SMDSAbs_ElementType,int> nbEnts;
   map<SMDSAbs_ElementType,TEntityList> anEnts;
 
-  for ( int i = 0; i <= 2; i++ )
+  for ( int i = 0; i <= 3; i++ )
     nbEnts[ aTypes[ i ] ] = GetEntities( aTypes[ i ], anEnts[ aTypes[ i ] ] );
 
   // PAL16631: without swap, bad_alloc is not thrown but hung up and crash instead,
   // so check remaining memory size for safety
-  SMDS_Mesh::CheckMemory(); // PAL16631
+  // SMDS_Mesh::CheckMemory(); // PAL16631
 
-  vtkIdType aCellsSize =  3 * nbEnts[ SMDSAbs_Edge ];
+  vtkIdType aCellsSize =  2 * nbEnts[ SMDSAbs_0DElement ] + 3 * nbEnts[ SMDSAbs_Edge ];
 
-  for ( int i = 1; i <= 2; i++ ) // iterate through faces and volumes
+  for ( int i = 2; i <= 3; i++ ) // iterate through faces and volumes
   {
     if ( nbEnts[ aTypes[ i ] ] )
     {
@@ -315,23 +361,24 @@ void SMESH_VisualObjDef::buildElemPrs()
     }
   }
 
-  vtkIdType aNbCells = nbEnts[ SMDSAbs_Edge ] + nbEnts[ SMDSAbs_Face ] + nbEnts[ SMDSAbs_Volume ];
-  
+  vtkIdType aNbCells = nbEnts[ SMDSAbs_0DElement ] + nbEnts[ SMDSAbs_Edge ] +
+                       nbEnts[ SMDSAbs_Face ] + nbEnts[ SMDSAbs_Volume ];
+
   if ( MYDEBUG )
     MESSAGE( "Update - aNbCells = "<<aNbCells<<"; aCellsSize = "<<aCellsSize );
 
   // Create cells
-  
+
   vtkCellArray* aConnectivity = vtkCellArray::New();
   aConnectivity->Allocate( aCellsSize, 0 );
-  
-  SMDS_Mesh::CheckMemory(); // PAL16631
+
+  // SMDS_Mesh::CheckMemory(); // PAL16631
 
   vtkUnsignedCharArray* aCellTypesArray = vtkUnsignedCharArray::New();
   aCellTypesArray->SetNumberOfComponents( 1 );
   aCellTypesArray->Allocate( aNbCells * aCellTypesArray->GetNumberOfComponents() );
-  
-  SMDS_Mesh::CheckMemory(); // PAL16631
+
+  // SMDS_Mesh::CheckMemory(); // PAL16631
 
   vtkIdList *anIdList = vtkIdList::New();
   vtkIdType iElem = 0;
@@ -339,11 +386,11 @@ void SMESH_VisualObjDef::buildElemPrs()
   TConnect aConnect;
   aConnect.reserve(VTK_CELL_SIZE);
 
-  SMDS_Mesh::CheckMemory(); // PAL16631
+  // SMDS_Mesh::CheckMemory(); // PAL16631
 
-  for ( int i = 0; i <= 2; i++ ) // iterate through edges, faces and volumes
+  for ( int i = 0; i <= 3; i++ ) // iterate through 0d elements, edges, faces and volumes
   {
-    if( nbEnts[ aTypes[ i ] ] > 0 )
+    if ( nbEnts[ aTypes[ i ] ] > 0 )
     {
       const SMDSAbs_ElementType& aType = aTypes[ i ];
       const TEntityList& aList = anEnts[ aType ];
@@ -351,7 +398,7 @@ void SMESH_VisualObjDef::buildElemPrs()
       for ( anIter = aList.begin(); anIter != aList.end(); ++anIter )
       {
         const SMDS_MeshElement* anElem = *anIter;
-        
+
         vtkIdType aNbNodes = anElem->NbNodes();
         anIdList->SetNumberOfIds( aNbNodes );
 
@@ -361,12 +408,12 @@ void SMESH_VisualObjDef::buildElemPrs()
         myVTK2SMDSElems.insert( TMapOfIds::value_type( iElem, anId ) );
 
         SMDS_ElemIteratorPtr aNodesIter = anElem->nodesIterator();
-       switch(aType){
-       case SMDSAbs_Volume:{
+        switch (aType) {
+        case SMDSAbs_Volume:{
           aConnect.clear();
-         std::vector<int> aConnectivities;
-         // Convertions connectivities from SMDS to VTK
-         if (anElem->IsPoly() && aNbNodes > 3) { // POLYEDRE
+          std::vector<int> aConnectivities;
+          // Convertions connectivities from SMDS to VTK
+          if (anElem->IsPoly() && aNbNodes > 3) { // POLYEDRE
 
             if ( const SMDS_PolyhedralVolumeOfNodes* ph =
                  dynamic_cast<const SMDS_PolyhedralVolumeOfNodes*> (anElem))
@@ -374,66 +421,67 @@ void SMESH_VisualObjDef::buildElemPrs()
               aNbNodes = GetConnect(ph->uniqueNodesIterator(),aConnect);
               anIdList->SetNumberOfIds( aNbNodes );
             }
-           for (int k = 0; k < aNbNodes; k++)
-             aConnectivities.push_back(k);
+            for (int k = 0; k < aNbNodes; k++)
+              aConnectivities.push_back(k);
 
           } else if (aNbNodes == 4) {
-           static int anIds[] = {0,2,1,3};
-           for (int k = 0; k < aNbNodes; k++) aConnectivities.push_back(anIds[k]);
+            static int anIds[] = {0,2,1,3};
+            for (int k = 0; k < aNbNodes; k++) aConnectivities.push_back(anIds[k]);
 
-         } else if (aNbNodes == 5) {
-           static int anIds[] = {0,3,2,1,4};
-           for (int k = 0; k < aNbNodes; k++) aConnectivities.push_back(anIds[k]);
+          } else if (aNbNodes == 5) {
+            static int anIds[] = {0,3,2,1,4};
+            for (int k = 0; k < aNbNodes; k++) aConnectivities.push_back(anIds[k]);
 
-         } else if (aNbNodes == 6) {
-           static int anIds[] = {0,1,2,3,4,5};
-           for (int k = 0; k < aNbNodes; k++) aConnectivities.push_back(anIds[k]);
+          } else if (aNbNodes == 6) {
+            static int anIds[] = {0,1,2,3,4,5};
+            for (int k = 0; k < aNbNodes; k++) aConnectivities.push_back(anIds[k]);
 
-         }
+          }
           else if (aNbNodes == 8) {
-           static int anIds[] = {0,3,2,1,4,7,6,5};
-           for (int k = 0; k < aNbNodes; k++) aConnectivities.push_back(anIds[k]);
+            static int anIds[] = {0,3,2,1,4,7,6,5};
+            for (int k = 0; k < aNbNodes; k++) aConnectivities.push_back(anIds[k]);
 
-         }
+          }
           else if (aNbNodes == 10) {
-           static int anIds[] = {0,2,1,3,6,5,4,7,9,8};
-           for (int k = 0; k < aNbNodes; k++) aConnectivities.push_back(anIds[k]);
-         }
+            static int anIds[] = {0,2,1,3,6,5,4,7,9,8};
+            for (int k = 0; k < aNbNodes; k++) aConnectivities.push_back(anIds[k]);
+          }
           else if (aNbNodes == 13) {
-           static int anIds[] = {0,3,2,1,4,8,7,6,5,9,12,11,10};
-           for (int k = 0; k < aNbNodes; k++) aConnectivities.push_back(anIds[k]);
-         }
+            static int anIds[] = {0,3,2,1,4,8,7,6,5,9,12,11,10};
+            for (int k = 0; k < aNbNodes; k++) aConnectivities.push_back(anIds[k]);
+          }
           else if (aNbNodes == 15) {
-           static int anIds[] = {0,2,1,3,5,4,8,7,6,11,10,9,12,14,13};
-           for (int k = 0; k < aNbNodes; k++) aConnectivities.push_back(anIds[k]);
-           //for (int k = 0; k < aNbNodes; k++) {
+            //static int anIds[] = {0,2,1,3,5,4,8,7,6,11,10,9,12,14,13};
+            static int anIds[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14};
+            for (int k = 0; k < aNbNodes; k++) aConnectivities.push_back(anIds[k]);
+            //for (int k = 0; k < aNbNodes; k++) {
             //  int nn = aConnectivities[k];
             //  const SMDS_MeshNode* N = static_cast<const SMDS_MeshNode*> (aConnect[nn]);
             //  cout<<"k="<<k<<"  N("<<N->X()<<","<<N->Y()<<","<<N->Z()<<")"<<endl;
             //}
-         }
+          }
           else if (aNbNodes == 20) {
-           static int anIds[] = {0,3,2,1,4,7,6,5,11,10,9,8,15,14,13,12,16,19,18,17};
-           for (int k = 0; k < aNbNodes; k++) aConnectivities.push_back(anIds[k]);
-         }
+            static int anIds[] = {0,3,2,1,4,7,6,5,11,10,9,8,15,14,13,12,16,19,18,17};
+            for (int k = 0; k < aNbNodes; k++) aConnectivities.push_back(anIds[k]);
+          }
           else {
           }
 
           if ( aConnect.empty() )
             GetConnect(aNodesIter,aConnect);
 
-         if (aConnectivities.size() > 0) {
-           for (vtkIdType aNodeId = 0; aNodeId < aNbNodes; aNodeId++)
-             SetId(anIdList,mySMDS2VTKNodes,aConnect,aNodeId,aConnectivities[aNodeId]);
-         }
-         break;
-       }
-       default:
-         for( vtkIdType aNodeId = 0; aNodesIter->more(); aNodeId++ ){
-           const SMDS_MeshElement* aNode = aNodesIter->next();
-           anIdList->SetId( aNodeId, mySMDS2VTKNodes[aNode->GetID()] );
-         }
-       }
+          if (aConnectivities.size() > 0) {
+            for (vtkIdType aNodeId = 0; aNodeId < aNbNodes; aNodeId++)
+              SetId(anIdList,mySMDS2VTKNodes,aConnect,aNodeId,aConnectivities[aNodeId]);
+          }
+          break;
+        }
+        default:
+          for( vtkIdType aNodeId = 0; aNodesIter->more(); aNodeId++ ){
+            const SMDS_MeshElement* aNode = aNodesIter->next();
+            anIdList->SetId( aNodeId, mySMDS2VTKNodes[aNode->GetID()] );
+          }
+        }
 
         aConnectivity->InsertNextCell( anIdList );
         aCellTypesArray->InsertNextValue( getCellType( aType, anElem->IsPoly(), aNbNodes ) );
@@ -441,29 +489,29 @@ void SMESH_VisualObjDef::buildElemPrs()
         iElem++;
       }
     }
-    SMDS_Mesh::CheckMemory(); // PAL16631
+    // SMDS_Mesh::CheckMemory(); // PAL16631
   }
 
   // Insert cells in grid
-  
+
   VTKViewer_CellLocationsArray* aCellLocationsArray = VTKViewer_CellLocationsArray::New();
   aCellLocationsArray->SetNumberOfComponents( 1 );
   aCellLocationsArray->SetNumberOfTuples( aNbCells );
-  
-  SMDS_Mesh::CheckMemory(); // PAL16631
+
+  // SMDS_Mesh::CheckMemory(); // PAL16631
 
   aConnectivity->InitTraversal();
   for( vtkIdType idType = 0, *pts, npts; aConnectivity->GetNextCell( npts, pts ); idType++ )
     aCellLocationsArray->SetValue( idType, aConnectivity->GetTraversalLocation( npts ) );
 
   myGrid->SetCells( aCellTypesArray, aCellLocationsArray,aConnectivity );
-  
+
   aCellLocationsArray->Delete();
   aCellTypesArray->Delete();
   aConnectivity->Delete();
   anIdList->Delete();
 
-  SMDS_Mesh::CheckMemory(); // PAL16631
+  // SMDS_Mesh::CheckMemory(); // PAL16631
 }
 
 //=================================================================================
@@ -471,9 +519,9 @@ void SMESH_VisualObjDef::buildElemPrs()
 // purpose  : Retrieve ids of nodes from edge of elements ( edge is numbered from 1 )
 //=================================================================================
 bool SMESH_VisualObjDef::GetEdgeNodes( const int theElemId,
-                                      const int theEdgeNum,
-                                      int&      theNodeId1,
-                                      int&      theNodeId2 ) const
+                                       const int theEdgeNum,
+                                       int&      theNodeId1,
+                                       int&      theNodeId2 ) const
 {
   const SMDS_Mesh* aMesh = GetMesh();
   if ( aMesh == 0 )
@@ -508,6 +556,27 @@ bool SMESH_VisualObjDef::GetEdgeNodes( const int theElemId,
   return true;
 }
 
+vtkUnstructuredGrid* SMESH_VisualObjDef::GetUnstructuredGrid()
+{
+       MESSAGE("SMESH_VisualObjDef::GetUnstructuredGrid " << myGrid);
+       return myGrid;
+}
+
+
+//=================================================================================
+// function : IsValid
+// purpose  : Return true if there are some entities
+//=================================================================================
+bool SMESH_VisualObjDef::IsValid() const
+{
+       MESSAGE("SMESH_VisualObjDef::IsValid");
+  return GetNbEntities(SMDSAbs_Node) > 0      || 
+         GetNbEntities(SMDSAbs_0DElement) > 0 || 
+         GetNbEntities(SMDSAbs_Edge) > 0      || 
+         GetNbEntities(SMDSAbs_Face) > 0      ||
+         GetNbEntities(SMDSAbs_Volume) > 0 ;
+}
+
 /*
   Class       : SMESH_MeshObj
   Description : Class for visualisation of mesh
@@ -520,6 +589,7 @@ bool SMESH_VisualObjDef::GetEdgeNodes( const int theElemId,
 SMESH_MeshObj::SMESH_MeshObj(SMESH::SMESH_Mesh_ptr theMesh):
   myClient(SalomeApp_Application::orb(),theMesh)
 {
+       myEmptyGrid = 0;
   if ( MYDEBUG ) 
     MESSAGE("SMESH_MeshObj - this = "<<this<<"; theMesh->_is_nil() = "<<theMesh->_is_nil());
 }
@@ -541,6 +611,7 @@ SMESH_MeshObj::~SMESH_MeshObj()
 bool SMESH_MeshObj::Update( int theIsClear )
 {
   // Update SMDS_Mesh on client part
+       MESSAGE("SMESH_MeshObj::Update " << this);
   if ( myClient.Update(theIsClear) || GetUnstructuredGrid()->GetNumberOfPoints()==0) {
     buildPrs();  // Fill unstructured grid
     return true;
@@ -548,6 +619,22 @@ bool SMESH_MeshObj::Update( int theIsClear )
   return false;
 }
 
+bool SMESH_MeshObj::NulData()
+{
+       MESSAGE ("SMESH_MeshObj::NulData() ==================================================================================");
+       if (!myEmptyGrid)
+       {
+         myEmptyGrid = SMDS_UnstructuredGrid::New();
+         myEmptyGrid->Initialize();
+         myEmptyGrid->Allocate();
+         vtkPoints* points = vtkPoints::New();
+         points->SetNumberOfPoints(0);
+         myEmptyGrid->SetPoints( points );
+         points->Delete();
+         myEmptyGrid->BuildLinks();
+       }
+       myGrid->ShallowCopy(myEmptyGrid);
+}
 //=================================================================================
 // function : GetElemDimension
 // purpose  : Get dimension of element
@@ -561,6 +648,7 @@ int SMESH_MeshObj::GetElemDimension( const int theObjId )
   int aType = anElem->GetType();
   switch ( aType )
   {
+    case SMDSAbs_0DElement : return 0;
     case SMDSAbs_Edge  : return 1;
     case SMDSAbs_Face  : return 2;
     case SMDSAbs_Volume: return 3;
@@ -581,6 +669,11 @@ int SMESH_MeshObj::GetNbEntities( const SMDSAbs_ElementType theType) const
       return myClient->NbNodes();
     }
     break;
+    case SMDSAbs_0DElement:
+    {
+      return myClient->Nb0DElements();
+    }
+    break;
     case SMDSAbs_Edge:
     {
       return myClient->NbEdges();
@@ -614,6 +707,12 @@ int SMESH_MeshObj::GetEntities( const SMDSAbs_ElementType theType, TEntityList&
       while ( anIter->more() ) theObjs.push_back( anIter->next() );
     }
     break;
+    case SMDSAbs_0DElement:
+    {
+      SMDS_0DElementIteratorPtr anIter = myClient->elements0dIterator();
+      while ( anIter->more() ) theObjs.push_back( anIter->next() );
+    }
+    break;
     case SMDSAbs_Edge:
     {
       SMDS_EdgeIteratorPtr anIter = myClient->edgesIterator();
@@ -654,7 +753,7 @@ void SMESH_MeshObj::UpdateFunctor( const SMESH::Controls::FunctorPtr& theFunctor
 //=================================================================================
 bool SMESH_MeshObj::IsNodePrs() const
 {
-  return myClient->NbEdges() == 0 &&myClient->NbFaces() == 0 && myClient->NbVolumes() == 0 ;
+  return myClient->Nb0DElements() == 0 && myClient->NbEdges() == 0 && myClient->NbFaces() == 0 && myClient->NbVolumes() == 0 ;
 }
 
 
@@ -702,8 +801,9 @@ void SMESH_SubMeshObj::UpdateFunctor( const SMESH::Controls::FunctorPtr& theFunc
 //=================================================================================
 bool SMESH_SubMeshObj::Update( int theIsClear )
 {
+       MESSAGE("SMESH_SubMeshObj::Update " << this)
   bool changed = myMeshObj->Update( theIsClear );
-  buildPrs();
+  buildPrs(true);
   return changed;
 }
 
@@ -741,6 +841,15 @@ bool SMESH_GroupObj::IsNodePrs() const
   return myGroupServer->GetType() == SMESH::NODE;
 }
 
+//=================================================================================
+// function : GetElementType
+// purpose  : Return type of elements of group
+//=================================================================================
+SMDSAbs_ElementType SMESH_GroupObj::GetElementType() const
+{
+  return SMDSAbs_ElementType(myGroupServer->GetType());
+}
+
 //=================================================================================
 // function : getNodesFromElems
 // purpose  : Retrieve nodes from elements
@@ -866,12 +975,13 @@ int SMESH_subMeshObj::GetNbEntities( const SMDSAbs_ElementType theType) const
       return mySubMeshServer->GetNumberOfNodes( false );
     }
     break;
+    case SMDSAbs_0DElement:
     case SMDSAbs_Edge:
     case SMDSAbs_Face:
     case SMDSAbs_Volume:
     {
       SMESH::long_array_var anIds = 
-       mySubMeshServer->GetElementsByType( SMESH::ElementType(theType) );
+        mySubMeshServer->GetElementsByType( SMESH::ElementType(theType) );
       return anIds->length();
     }
     default:
@@ -908,7 +1018,7 @@ int SMESH_subMeshObj::GetEntities( const SMDSAbs_ElementType theType, TEntityLis
     else
     {
       SMESH::long_array_var anIds = 
-       mySubMeshServer->GetElementsByType( SMESH::ElementType(theType) );
+        mySubMeshServer->GetElementsByType( SMESH::ElementType(theType) );
       return getPointers( theType, anIds, aMesh, theResList );
     }
   }