Salome HOME
Fix to take into account qudratic edges also.
[modules/smesh.git] / src / OBJECT / SMESH_Object.cxx
index 6621177cc32ed4f904eacaeaba8602d65d28dce2..b4fcbf6dbf6563622362420662bc3275ae7a4b34 100644 (file)
@@ -1,49 +1,53 @@
-//  SMESH OBJECT : interactive object for SMESH visualization
+// Copyright (C) 2007-2013  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.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
+// 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"
 
-#include "SMESH_Object.h"
 #include "SMDS_Mesh.hxx"
-#include "SALOME_ExtractUnstructuredGrid.h"
+#include "SMDS_PolyhedralVolumeOfNodes.hxx"
 #include "SMESH_Actor.h"
+#include "SMESH_ControlsDef.hxx"
+#include "SalomeApp_Application.h"
+#include "VTKViewer_ExtractUnstructuredGrid.h"
+#include "VTKViewer_CellLocationsArray.h"
 
+#include CORBA_SERVER_HEADER(SMESH_Gen)
 #include CORBA_SERVER_HEADER(SALOME_Exception)
 
 #include <vtkCell.h>
 #include <vtkIdList.h>
-#include <vtkIntArray.h>
 #include <vtkCellArray.h>
 #include <vtkUnsignedCharArray.h>
 
 #include <vtkUnstructuredGrid.h>
-#include <vtkUnstructuredGridWriter.h>
-#include <vtkUnstructuredGridReader.h>
 
 #include <memory>
-#include <sstream>     
+#include <sstream>      
 #include <stdexcept>
 #include <set>
 
@@ -60,213 +64,16 @@ using namespace std;
 #endif
 
 #ifdef _DEBUG_
-static int MYDEBUG = 0;
-static int MYDEBUGWITHFILES = 0;
+static int MYDEBUG = 1;
+static int MYDEBUGWITHFILES = 0;//1;
 #else
 static int MYDEBUG = 0;
 static int MYDEBUGWITHFILES = 0;
 #endif
 
 
-void WriteUnstructuredGrid(vtkUnstructuredGrid* theGrid, const char* theFileName){
-  vtkUnstructuredGridWriter* aWriter = vtkUnstructuredGridWriter::New();
-  aWriter->SetFileName(theFileName);
-  aWriter->SetInput(theGrid);
-  if(theGrid->GetNumberOfCells()){
-    aWriter->Write();
-  }
-  aWriter->Delete();
-}
-
-
-namespace{
-
-  inline const SMDS_MeshNode* FindNode(const SMDS_Mesh* theMesh, int theId){
-    if(const SMDS_MeshNode* anElem = theMesh->FindNode(theId)) return anElem;
-    EXCEPTION(runtime_error,"SMDS_Mesh::FindNode - cannot find a SMDS_MeshNode for ID = "<<theId);
-  }
-
-
-  inline const SMDS_MeshElement* FindElement(const SMDS_Mesh* theMesh, int theId){
-    if(const SMDS_MeshElement* anElem = theMesh->FindElement(theId)) return anElem;
-    EXCEPTION(runtime_error,"SMDS_Mesh::FindElement - cannot find a SMDS_MeshElement for ID = "<<theId);
-  }
-
-
-  inline void AddNodesWithID(SMDS_Mesh* theMesh, 
-                            SMESH::log_array_var& theSeq,
-                            CORBA::Long theId)
-  {
-    const SMESH::double_array& aCoords = theSeq[theId].coords;
-    const SMESH::long_array& anIndexes = theSeq[theId].indexes;
-    CORBA::Long anElemId = 0, aNbElems = theSeq[theId].number;
-    if(3*aNbElems != aCoords.length())
-      EXCEPTION(runtime_error,"AddNodesWithID - 3*aNbElems != aCoords.length()");
-    for(CORBA::Long aCoordId = 0; anElemId < aNbElems; anElemId++, aCoordId+=3){
-      SMDS_MeshElement* anElem = theMesh->AddNodeWithID(aCoords[aCoordId],
-                                                       aCoords[aCoordId+1],
-                                                       aCoords[aCoordId+2],
-                                                       anIndexes[anElemId]);
-      if(!anElem)
-       EXCEPTION(runtime_error,"SMDS_Mesh::FindElement - cannot AddNodeWithID for ID = "<<anElemId);
-    }
-  }
-
-
-  inline void AddEdgesWithID(SMDS_Mesh* theMesh, 
-                            SMESH::log_array_var& theSeq,
-                            CORBA::Long theId)
-  {
-    const SMESH::double_array& aCoords = theSeq[theId].coords;
-    const SMESH::long_array& anIndexes = theSeq[theId].indexes;
-    CORBA::Long anElemId = 0, aNbElems = theSeq[theId].number;
-    if(3*aNbElems != anIndexes.length())
-      EXCEPTION(runtime_error,"AddEdgeWithID - 3*aNbElems != aCoords.length()");
-    for(CORBA::Long anIndexId = 0; anElemId < aNbElems; anElemId++, anIndexId+=3){
-      SMDS_MeshElement* anElem = theMesh->AddEdgeWithID(anIndexes[anIndexId+1],
-                                                       anIndexes[anIndexId+2],
-                                                       anIndexes[anIndexId]);
-      if(!anElem)
-       EXCEPTION(runtime_error,"SMDS_Mesh::FindElement - cannot AddEdgeWithID for ID = "<<anElemId);
-    }
-  }
-
-
-  inline void AddTriasWithID(SMDS_Mesh* theMesh, 
-                            SMESH::log_array_var& theSeq,
-                            CORBA::Long theId)
-  {
-    const SMESH::double_array& aCoords = theSeq[theId].coords;
-    const SMESH::long_array& anIndexes = theSeq[theId].indexes;
-    CORBA::Long anElemId = 0, aNbElems = theSeq[theId].number;
-    if(4*aNbElems != anIndexes.length())
-      EXCEPTION(runtime_error,"AddEdgeWithID - 4*aNbElems != anIndexes.length()");
-    for(CORBA::Long anIndexId = 0; anElemId < aNbElems; anElemId++, anIndexId+=4){
-      SMDS_MeshElement* anElem = theMesh->AddFaceWithID(anIndexes[anIndexId+1],
-                                                       anIndexes[anIndexId+2],
-                                                       anIndexes[anIndexId+3],
-                                                       anIndexes[anIndexId]);
-      if(!anElem)
-       EXCEPTION(runtime_error,"SMDS_Mesh::FindElement - cannot AddFaceWithID for ID = "<<anElemId);
-    }
-  }
-
-
-  inline void AddQuadsWithID(SMDS_Mesh* theMesh, 
-                            SMESH::log_array_var theSeq,
-                            CORBA::Long theId)
-  {
-    const SMESH::double_array& aCoords = theSeq[theId].coords;
-    const SMESH::long_array& anIndexes = theSeq[theId].indexes;
-    CORBA::Long anElemId = 0, aNbElems = theSeq[theId].number;
-    if(5*aNbElems != anIndexes.length())
-      EXCEPTION(runtime_error,"AddEdgeWithID - 4*aNbElems != anIndexes.length()");
-    for(CORBA::Long anIndexId = 0; anElemId < aNbElems; anElemId++, anIndexId+=5){
-      SMDS_MeshElement* anElem = theMesh->AddFaceWithID(anIndexes[anIndexId+1],
-                                                       anIndexes[anIndexId+2],
-                                                       anIndexes[anIndexId+3],
-                                                       anIndexes[anIndexId+4],
-                                                       anIndexes[anIndexId]);
-      if(!anElem)
-       EXCEPTION(runtime_error,"SMDS_Mesh::FindElement - cannot AddFaceWithID for ID = "<<anElemId);
-    }
-  }
-
-
-  inline void AddTetrasWithID(SMDS_Mesh* theMesh, 
-                             SMESH::log_array_var& theSeq,
-                             CORBA::Long theId)
-  {
-    const SMESH::double_array& aCoords = theSeq[theId].coords;
-    const SMESH::long_array& anIndexes = theSeq[theId].indexes;
-    CORBA::Long anElemId = 0, aNbElems = theSeq[theId].number;
-    if(5*aNbElems != anIndexes.length())
-      EXCEPTION(runtime_error,"AddEdgeWithID - 5*aNbElems != anIndexes.length()");
-    for(CORBA::Long anIndexId = 0; anElemId < aNbElems; anElemId++, anIndexId+=5){
-      SMDS_MeshElement* anElem = theMesh->AddVolumeWithID(anIndexes[anIndexId+1],
-                                                         anIndexes[anIndexId+2],
-                                                         anIndexes[anIndexId+3],
-                                                         anIndexes[anIndexId+4],
-                                                         anIndexes[anIndexId]);
-      if(!anElem)
-       EXCEPTION(runtime_error,"SMDS_Mesh::FindElement - cannot AddFaceWithID for ID = "<<anElemId);
-    }
-  }
-
-
-  inline void AddPiramidsWithID(SMDS_Mesh* theMesh, 
-                               SMESH::log_array_var& theSeq,
-                               CORBA::Long theId)
-  {
-    const SMESH::double_array& aCoords = theSeq[theId].coords;
-    const SMESH::long_array& anIndexes = theSeq[theId].indexes;
-    CORBA::Long anElemId = 0, aNbElems = theSeq[theId].number;
-    if(6*aNbElems != anIndexes.length())
-      EXCEPTION(runtime_error,"AddEdgeWithID - 6*aNbElems != anIndexes.length()");
-    for(CORBA::Long anIndexId = 0; anElemId < aNbElems; anElemId++, anIndexId+=6){
-      SMDS_MeshElement* anElem = theMesh->AddVolumeWithID(anIndexes[anIndexId+1],
-                                                         anIndexes[anIndexId+2],
-                                                         anIndexes[anIndexId+3],
-                                                         anIndexes[anIndexId+4],
-                                                         anIndexes[anIndexId+5],
-                                                         anIndexes[anIndexId]);
-      if(!anElem)
-       EXCEPTION(runtime_error,"SMDS_Mesh::FindElement - cannot AddFaceWithID for ID = "<<anElemId);
-    }
-  }
-
-
-  inline void AddPrismsWithID(SMDS_Mesh* theMesh, 
-                             SMESH::log_array_var& theSeq,
-                             CORBA::Long theId)
-  {
-    const SMESH::double_array& aCoords = theSeq[theId].coords;
-    const SMESH::long_array& anIndexes = theSeq[theId].indexes;
-    CORBA::Long anElemId = 0, aNbElems = theSeq[theId].number;
-    if(7*aNbElems != anIndexes.length())
-      EXCEPTION(runtime_error,"AddEdgeWithID - 7*aNbElems != anIndexes.length()");
-    for(CORBA::Long anIndexId = 0; anElemId < aNbElems; anElemId++, anIndexId+=7){
-      SMDS_MeshElement* anElem = theMesh->AddVolumeWithID(anIndexes[anIndexId+1],
-                                                         anIndexes[anIndexId+2],
-                                                         anIndexes[anIndexId+3],
-                                                         anIndexes[anIndexId+4],
-                                                         anIndexes[anIndexId+5],
-                                                         anIndexes[anIndexId+6],
-                                                         anIndexes[anIndexId]);
-      if(!anElem)
-       EXCEPTION(runtime_error,"SMDS_Mesh::FindElement - cannot AddFaceWithID for ID = "<<anElemId);
-    }
-  }
-
-
-  inline void AddHexasWithID(SMDS_Mesh* theMesh, 
-                            SMESH::log_array_var& theSeq,
-                            CORBA::Long theId)
-  {
-    const SMESH::double_array& aCoords = theSeq[theId].coords;
-    const SMESH::long_array& anIndexes = theSeq[theId].indexes;
-    CORBA::Long anElemId = 0, aNbElems = theSeq[theId].number;
-    if(9*aNbElems != anIndexes.length())
-      EXCEPTION(runtime_error,"AddEdgeWithID - 9*aNbElems != anIndexes.length()");
-    for(CORBA::Long anIndexId = 0; anElemId < aNbElems; anElemId++, anIndexId+=9){
-      SMDS_MeshElement* anElem = theMesh->AddVolumeWithID(anIndexes[anIndexId+1],
-                                                         anIndexes[anIndexId+2],
-                                                         anIndexes[anIndexId+3],
-                                                         anIndexes[anIndexId+4],
-                                                         anIndexes[anIndexId+5],
-                                                         anIndexes[anIndexId+6],
-                                                         anIndexes[anIndexId+7],
-                                                         anIndexes[anIndexId+8],
-                                                         anIndexes[anIndexId]);
-      if(!anElem)
-       EXCEPTION(runtime_error,"SMDS_Mesh::FindElement - cannot AddFaceWithID for ID = "<<anElemId);
-    }
-  }
-
-
-}
 /*
-  Class       : SMESH_VisualObj
+  Class       : SMESH_VisualObjDef
   Description : Base class for all mesh objects to be visuilised
 */
 
@@ -274,38 +81,65 @@ namespace{
 // function : getCellType
 // purpose  : Get type of VTK cell
 //=================================================================================
-static inline vtkIdType getCellType( const SMESH::ElementType theType,
-                                     const int theNbNodes )
+static inline vtkIdType getCellType( const SMDSAbs_ElementType theType,
+                                     const bool                thePoly,
+                                     const int                 theNbNodes )
 {
   switch( theType )
   {
-    case SMESH::EDGE: return theNbNodes == 2 ? VTK_LINE : VTK_EMPTY_CELL;
-
-    case SMESH::FACE  : if      ( theNbNodes == 3 ) return VTK_TRIANGLE;
-                        else if ( theNbNodes == 4 ) return VTK_QUAD;
-                        else                        return VTK_EMPTY_CELL;
-
-    case SMESH::VOLUME: if      ( theNbNodes == 4 ) return VTK_TETRA;
-                        else if ( theNbNodes == 5 ) return VTK_PYRAMID;
-                        else if ( theNbNodes == 6 ) return VTK_WEDGE;
-                        else if ( theNbNodes == 8 ) return VTK_HEXAHEDRON;
-                        else                        return VTK_EMPTY_CELL;
+    case SMDSAbs_0DElement:         return VTK_VERTEX;
+
+    case SMDSAbs_Ball:              return VTK_POLY_VERTEX;
+
+    case SMDSAbs_Edge: 
+      if( theNbNodes == 2 )         return VTK_LINE;
+      else if ( theNbNodes == 3 )   return VTK_QUADRATIC_EDGE;
+      else return VTK_EMPTY_CELL;
+
+    case SMDSAbs_Face  :
+      if (thePoly && theNbNodes>2 ) return VTK_POLYGON;
+      else if ( theNbNodes == 3 )   return VTK_TRIANGLE;
+      else if ( theNbNodes == 4 )   return VTK_QUAD;
+      else if ( theNbNodes == 6 )   return VTK_QUADRATIC_TRIANGLE;
+      else if ( theNbNodes == 8 )   return VTK_QUADRATIC_QUAD;
+      else if ( theNbNodes == 9 )   return VTK_BIQUADRATIC_QUAD;
+      else if ( theNbNodes == 7 )   return VTK_BIQUADRATIC_TRIANGLE;
+      else return VTK_EMPTY_CELL;
+      
+    case SMDSAbs_Volume:
+      if (thePoly && theNbNodes>3 ) return VTK_POLYHEDRON; //VTK_CONVEX_POINT_SET;
+      else if ( theNbNodes == 4 )   return VTK_TETRA;
+      else if ( theNbNodes == 5 )   return VTK_PYRAMID;
+      else if ( theNbNodes == 6 )   return VTK_WEDGE;
+      else if ( theNbNodes == 8 )   return VTK_HEXAHEDRON;
+      else if ( theNbNodes == 12 )  return VTK_HEXAGONAL_PRISM;
+      else if ( theNbNodes == 10 )  return VTK_QUADRATIC_TETRA;
+      else if ( theNbNodes == 20 )  return VTK_QUADRATIC_HEXAHEDRON;
+      else if ( theNbNodes == 27 )  return VTK_TRIQUADRATIC_HEXAHEDRON;
+      else if ( theNbNodes == 15 )  return VTK_QUADRATIC_WEDGE;
+      else if ( theNbNodes == 13 )  return VTK_QUADRATIC_PYRAMID; //VTK_CONVEX_POINT_SET;
+      else return VTK_EMPTY_CELL;
 
     default: return VTK_EMPTY_CELL;
   }
 }
 
 //=================================================================================
-// functions : SMESH_VisualObj
+// functions : SMESH_VisualObjDef
 // purpose   : Constructor
 //=================================================================================
-SMESH_VisualObj::SMESH_VisualObj()
+SMESH_VisualObjDef::SMESH_VisualObjDef()
 {
+  MESSAGE("---------------------------------------------SMESH_VisualObjDef::SMESH_VisualObjDef");
   myGrid = vtkUnstructuredGrid::New();
+  myLocalGrid = false;
+  ClearEntitiesFlags();
+  SMESH::GetEntitiesFromObject(NULL);
 }
-SMESH_VisualObj::~SMESH_VisualObj()
+SMESH_VisualObjDef::~SMESH_VisualObjDef()
 {
-  if ( MYDEBUG )
+  MESSAGE("---------------------------------------------SMESH_VisualObjDef::~SMESH_VisualObjDef");
+  //if ( MYDEBUG )
     MESSAGE( "~SMESH_MeshObj - myGrid->GetReferenceCount() = " << myGrid->GetReferenceCount() );
   myGrid->Delete();
 }
@@ -314,39 +148,69 @@ SMESH_VisualObj::~SMESH_VisualObj()
 // functions : GetNodeObjId, GetNodeVTKId, GetElemObjId, GetElemVTKId
 // purpose   : Methods for retrieving VTK IDs by SMDS IDs and  vice versa
 //=================================================================================
-vtkIdType SMESH_VisualObj::GetNodeObjId( int theVTKID )
+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 this->GetMesh()->FindNodeVtk(theVTKID)->GetID();
 }
 
-vtkIdType SMESH_VisualObj::GetNodeVTKId( int theObjID )
+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;
+        }
+
+        const SMDS_MeshNode* aNode = 0;
+        if( this->GetMesh() ) {
+          aNode = this->GetMesh()->FindNode(theObjID);
+        }
+        return aNode ? aNode->getVtkId() : -1;
 }
 
-vtkIdType SMESH_VisualObj::GetElemObjId( int theVTKID )
+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_VisualObj::GetElemVTKId( int theObjID )
+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()->FindElement(theObjID)->getVtkId();
+  //return this->GetMesh()->fromSmdsToVtk(theObjID);
 }
 
 //=================================================================================
-// function : SMESH_VisualObj::createPoints
+// function : SMESH_VisualObjDef::createPoints
 // purpose  : Create points from nodes
 //=================================================================================
-void SMESH_VisualObj::createPoints( vtkPoints* thePoints )
+/*! 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 )
     return;
 
   TEntityList aNodes;
-  vtkIdType nbNodes = GetEntities( SMESH::NODE, aNodes );
+  vtkIdType nbNodes = GetEntities( SMDSAbs_Node, aNodes );
   thePoints->SetNumberOfPoints( nbNodes );
-  
+
   int nbPoints = 0;
 
   TEntityList::const_iterator anIter;
@@ -371,111 +235,138 @@ void SMESH_VisualObj::createPoints( vtkPoints* thePoints )
 // function : buildPrs
 // purpose  : create VTK cells( fill unstructured grid )
 //=================================================================================
-void SMESH_VisualObj::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();
-  }
-  catch( const std::exception& exc )
-  {
-    INFOS("Follow exception was cought:\n\t"<<exc.what());
+        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, 0, 0 );
+                throw;
+        }
   }
-  catch(...)
+  else
   {
-    INFOS("Unknown exception was cought !!!");
+        myLocalGrid = false;
+        if (!GetMesh()->isCompacted())
+          {
+            MESSAGE("*** buildPrs ==> compactMesh!");
+            GetMesh()->compactMesh();
+          }
+        vtkUnstructuredGrid *theGrid = GetMesh()->getGrid();
+        updateEntitiesFlags();
+        myGrid->ShallowCopy(theGrid);
+        //MESSAGE(myGrid->GetReferenceCount());
+        //MESSAGE( "Update - myGrid->GetNumberOfCells() = "<<myGrid->GetNumberOfCells() );
+        //MESSAGE( "Update - myGrid->GetNumberOfPoints() = "<<myGrid->GetNumberOfPoints() );
+        if( MYDEBUGWITHFILES ) SMESH::WriteUnstructuredGrid( myGrid,"buildPrs.vtu" );
   }
-  
-  if( MYDEBUG ) MESSAGE( "Update - myGrid->GetNumberOfCells() = "<<myGrid->GetNumberOfCells() );
-  if( MYDEBUGWITHFILES ) WriteUnstructuredGrid( myGrid,"/tmp/buildPrs" );
 }
 
 //=================================================================================
 // function : buildNodePrs
 // purpose  : create VTK cells for nodes
 //=================================================================================
-void SMESH_VisualObj::buildNodePrs()
+
+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
   vtkPoints* aPoints = vtkPoints::New();
   createPoints( aPoints );
-  int nbPoints = aPoints->GetNumberOfPoints();
+  SMDS_Mesh::CheckMemory();
   myGrid->SetPoints( aPoints );
   aPoints->Delete();
 
-  myGrid->SetCells( 0, 0, 0 );
-
-  // Create cells
-  /*
-  vtkIdList *anIdList = vtkIdList::New();
-  anIdList->SetNumberOfIds( 1 );
+  myGrid->SetCells( 0, 0, 0, 0, 0 );
+}
 
-  vtkCellArray *aCells = vtkCellArray::New();
-  aCells->Allocate( 2 * nbPoints, 0 );
+//=================================================================================
+// function : buildElemPrs
+// purpose  : Create VTK cells for elements
+//=================================================================================
 
-  vtkUnsignedCharArray* aCellTypesArray = vtkUnsignedCharArray::New();
-  aCellTypesArray->SetNumberOfComponents( 1 );
-  aCellTypesArray->Allocate( nbPoints );
+namespace{
+  typedef std::vector<const SMDS_MeshElement*> TConnect;
 
-  for( vtkIdType aCellId = 0; aCellId < nbPoints; aCellId++ )
+  int GetConnect(const SMDS_ElemIteratorPtr& theNodesIter, 
+                 TConnect& theConnect)
   {
-    anIdList->SetId( 0, aCellId );
-    aCells->InsertNextCell( anIdList );
-    aCellTypesArray->InsertNextValue( VTK_VERTEX );
+    theConnect.clear();
+    for(; theNodesIter->more();)
+      theConnect.push_back(theNodesIter->next());
+    return theConnect.size();
+  }
+  
+  inline 
+  void SetId(vtkIdList *theIdList, 
+             const SMESH_VisualObjDef::TMapOfIds& theSMDS2VTKNodes, 
+             const TConnect& theConnect, 
+             int thePosition,
+             int theId)
+  {
+    theIdList->SetId(thePosition,theSMDS2VTKNodes.find(theConnect[theId]->GetID())->second);
   }
 
-  vtkIntArray* aCellLocationsArray = vtkIntArray::New();
-  aCellLocationsArray->SetNumberOfComponents( 1 );
-  aCellLocationsArray->SetNumberOfTuples( nbPoints );
-
-  aCells->InitTraversal();
-  for( vtkIdType i = 0, *pts, npts; aCells->GetNextCell( npts, pts ); i++ )
-    aCellLocationsArray->SetValue( i, aCells->GetTraversalLocation( npts ) );
-
-  myGrid->SetCells( aCellTypesArray, aCellLocationsArray, aCells );
-
-  aCellLocationsArray->Delete();
-  aCellTypesArray->Delete();
-  aCells->Delete();
-  anIdList->Delete(); 
-  */
 }
 
-//=================================================================================
-// function : buildElemPrs
-// purpose  : Create VTK cells for elements
-//=================================================================================
-void SMESH_VisualObj::buildElemPrs()
+
+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 SMESH::ElementType aTypes[ 3 ] = { SMESH::EDGE, SMESH::FACE, SMESH::VOLUME };
+  const int nbTypes = 5;
+  static SMDSAbs_ElementType aTypes[ nbTypes ] =
+    { SMDSAbs_Edge, SMDSAbs_Face, SMDSAbs_Volume, SMDSAbs_Ball, SMDSAbs_0DElement };
 
   // get entity data
-  map< int, int >         nbEnts;
-  map< int, TEntityList > anEnts;
+  map<SMDSAbs_ElementType,int> nbEnts;
+  map<SMDSAbs_ElementType,TEntityList> anEnts;
+
+  vtkIdType aNbCells = 0;
 
-  for ( int i = 0; i <= 2; i++ )
+  for ( int i = 0; i < nbTypes; i++ )
+  {
     nbEnts[ aTypes[ i ] ] = GetEntities( aTypes[ i ], anEnts[ aTypes[ i ] ] );
+    aNbCells += nbEnts[ 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
 
-  vtkIdType aCellsSize =  3 * nbEnts[ SMESH::EDGE ];
+  vtkIdType aCellsSize =  2 * nbEnts[ SMDSAbs_0DElement ] + 3 * nbEnts[ SMDSAbs_Edge ];
+  aCellsSize += 2 * nbEnts[ SMDSAbs_Ball ];
 
   for ( int i = 1; i <= 2; i++ ) // iterate through faces and volumes
   {
@@ -483,33 +374,56 @@ void SMESH_VisualObj::buildElemPrs()
     {
       const TEntityList& aList = anEnts[ aTypes[ i ] ];
       TEntityList::const_iterator anIter;
-      for ( anIter = aList.begin(); anIter != aList.end(); ++anIter )
-        aCellsSize += (*anIter)->NbNodes() + 1;
+      for ( anIter = aList.begin(); anIter != aList.end(); ++anIter ) {
+        if((*anIter)->GetEntityType() != SMDSEntity_Polyhedra &&
+           (*anIter)->GetEntityType() != SMDSEntity_Quad_Polyhedra) {
+          aCellsSize += (*anIter)->NbNodes() + 1;
+        } 
+        // Special case for the VTK_POLYHEDRON:
+        // itsinput cellArray is of special format.
+        //  [nCellFaces, nFace0Pts, i, j, k, nFace1Pts, i, j, k, ...]   
+        else {
+          if( const SMDS_VtkVolume* ph = dynamic_cast<const SMDS_VtkVolume*>(*anIter) ) {
+            int nbFaces = ph->NbFaces();
+            aCellsSize += (1 + ph->NbFaces());
+            for( int i = 1; i <= nbFaces; i++ ) {
+              aCellsSize += ph->NbFaceNodes(i);
+            }
+          }
+        }
+      }
     }
   }
-
-  vtkIdType aNbCells = nbEnts[ SMESH::EDGE ] + nbEnts[ SMESH::FACE ] + nbEnts[ SMESH::VOLUME ];
-  
   if ( MYDEBUG )
     MESSAGE( "Update - aNbCells = "<<aNbCells<<"; aCellsSize = "<<aCellsSize );
 
   // Create cells
-  
+
   vtkCellArray* aConnectivity = vtkCellArray::New();
   aConnectivity->Allocate( aCellsSize, 0 );
-  
+
+  SMDS_Mesh::CheckMemory(); // PAL16631
+
   vtkUnsignedCharArray* aCellTypesArray = vtkUnsignedCharArray::New();
   aCellTypesArray->SetNumberOfComponents( 1 );
   aCellTypesArray->Allocate( aNbCells * aCellTypesArray->GetNumberOfComponents() );
-  
+
+  SMDS_Mesh::CheckMemory(); // PAL16631
+
   vtkIdList *anIdList = vtkIdList::New();
   vtkIdType iElem = 0;
-  
-  for ( int i = 0; i <= 2; i++ ) // iterate through edges, faces and volumes
+
+  TConnect aConnect;
+  aConnect.reserve(VTK_CELL_SIZE);
+
+  SMDS_Mesh::CheckMemory(); // PAL16631
+
+  for ( int i = 0; i < nbTypes; i++ ) // iterate through all types of elements
   {
-    if( nbEnts[ aTypes[ i ] ] > 0 )
-    {
-      const TEntityList& aList = anEnts[ aTypes[ i ] ];
+    if ( nbEnts[ aTypes[ i ] ] > 0 ) {
+      
+      const SMDSAbs_ElementType& aType = aTypes[ i ];
+      const TEntityList& aList = anEnts[ aType ];
       TEntityList::const_iterator anIter;
       for ( anIter = aList.begin(); anIter != aList.end(); ++anIter )
       {
@@ -517,53 +431,89 @@ void SMESH_VisualObj::buildElemPrs()
         
         vtkIdType aNbNodes = anElem->NbNodes();
         anIdList->SetNumberOfIds( aNbNodes );
-
+        const vtkIdType vtkElemType = getCellType( aType, anElem->IsPoly(), aNbNodes );
+        
         int anId = anElem->GetID();
-
+        
         mySMDS2VTKElems.insert( TMapOfIds::value_type( anId, iElem ) );
         myVTK2SMDSElems.insert( TMapOfIds::value_type( iElem, anId ) );
-
+        
         SMDS_ElemIteratorPtr aNodesIter = anElem->nodesIterator();
-        for( vtkIdType aNodeId = 0; aNodesIter->more(); aNodeId++ )
         {
-          const SMDS_MeshElement* aNode = aNodesIter->next();
-          anIdList->SetId( aNodeId, mySMDS2VTKNodes[aNode->GetID()] );
+          // Convertions connectivities from SMDS to VTK
+
+          if (aType == SMDSAbs_Volume && anElem->IsPoly() && aNbNodes > 3) { // POLYEDRE
+            anIdList->Reset();
+            if ( const SMDS_VtkVolume* ph = dynamic_cast<const SMDS_VtkVolume*>(anElem) ) {
+              int nbFaces = ph->NbFaces();
+              anIdList->InsertNextId(nbFaces);
+              for( int i = 1; i <= nbFaces; i++ ) {
+                anIdList->InsertNextId(ph->NbFaceNodes(i));
+                for(int j = 1; j <= ph->NbFaceNodes(i); j++) {
+                  const SMDS_MeshNode* n = ph->GetFaceNode(i,j);
+                  if(n) {
+                    anIdList->InsertNextId(mySMDS2VTKNodes[n->GetID()]);
+                  }
+                }
+              }
+            }
+          }
+          else {
+            const std::vector<int>& aConnectivities =
+              SMDS_MeshCell::toVtkOrder( VTKCellType( vtkElemType ));
+            if (aConnectivities.size() > 0) {
+              aConnect.clear();
+              GetConnect(aNodesIter,aConnect);
+              for (vtkIdType aNodeId = 0; aNodeId < aNbNodes; aNodeId++)
+                SetId(anIdList,mySMDS2VTKNodes,aConnect,aNodeId,aConnectivities[aNodeId]);
+            }
+            else {
+              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( aTypes[ i ], aNbNodes ) );
+        aCellTypesArray->InsertNextValue( vtkElemType );
 
         iElem++;
       }
     }
+    SMDS_Mesh::CheckMemory(); // PAL16631
   }
 
   // Insert cells in grid
-  
-  vtkIntArray* aCellLocationsArray = vtkIntArray::New();
+
+  VTKViewer_CellLocationsArray* aCellLocationsArray = VTKViewer_CellLocationsArray::New();
   aCellLocationsArray->SetNumberOfComponents( 1 );
   aCellLocationsArray->SetNumberOfTuples( aNbCells );
-  
+
+  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
 }
 
 //=================================================================================
 // function : GetEdgeNodes
 // purpose  : Retrieve ids of nodes from edge of elements ( edge is numbered from 1 )
 //=================================================================================
-bool SMESH_VisualObj::GetEdgeNodes( const int theElemId,
-                                    const int theEdgeNum,
-                                    int&      theNodeId1,
-                                    int&      theNodeId2 ) const
+bool SMESH_VisualObjDef::GetEdgeNodes( const int theElemId,
+                                       const int theEdgeNum,
+                                       int&      theNodeId1,
+                                       int&      theNodeId2 ) const
 {
   const SMDS_Mesh* aMesh = GetMesh();
   if ( aMesh == 0 )
@@ -573,21 +523,21 @@ bool SMESH_VisualObj::GetEdgeNodes( const int theElemId,
   if ( anElem == 0 )
     return false;
     
-  int nbNodes = anElem->NbNodes();
+  int nbNodes = anElem->NbCornerNodes();
 
-  if ( theEdgeNum < 1 || theEdgeNum > 4 || nbNodes != 3 && nbNodes != 4 || theEdgeNum > nbNodes )
+  if ( theEdgeNum < 0 || theEdgeNum > 3 || (nbNodes != 3 && nbNodes != 4) || theEdgeNum > nbNodes )
     return false;
 
-  int anIds[ nbNodes ];
+  vector<int> anIds( nbNodes );
   SMDS_ElemIteratorPtr anIter = anElem->nodesIterator();
   int i = 0;
-  while( anIter->more() )
+  while( anIter->more() && i < nbNodes )
     anIds[ i++ ] = anIter->next()->GetID();
 
-  if ( nbNodes != theEdgeNum )
+  if ( theEdgeNum < nbNodes - 1 )
   {
-    theNodeId1 = anIds[ theEdgeNum - 1 ];
-    theNodeId2 = anIds[ theEdgeNum ];
+    theNodeId1 = anIds[ theEdgeNum ];
+    theNodeId2 = anIds[ theEdgeNum + 1 ];
   }
   else
   {
@@ -598,6 +548,93 @@ bool SMESH_VisualObj::GetEdgeNodes( const int theElemId,
   return true;
 }
 
+vtkUnstructuredGrid* SMESH_VisualObjDef::GetUnstructuredGrid()
+{
+  if ( !myLocalGrid && !GetMesh()->isCompacted() )
+  {
+    GetMesh()->compactMesh();
+        updateEntitiesFlags();
+    vtkUnstructuredGrid *theGrid = GetMesh()->getGrid();
+    myGrid->ShallowCopy(theGrid);
+  }
+  return myGrid;
+}
+
+
+//=================================================================================
+// function : IsValid
+// purpose  : Return true if there are some entities
+//=================================================================================
+bool SMESH_VisualObjDef::IsValid() const
+{
+        //MESSAGE("SMESH_VisualObjDef::IsValid");
+  return ( GetNbEntities(SMDSAbs_0DElement) > 0 || 
+           GetNbEntities(SMDSAbs_Ball     ) > 0 || 
+           GetNbEntities(SMDSAbs_Edge     ) > 0 || 
+           GetNbEntities(SMDSAbs_Face     ) > 0 ||
+           GetNbEntities(SMDSAbs_Volume   ) > 0 ||
+           GetNbEntities(SMDSAbs_Node     ) > 0 );
+}
+
+//=================================================================================
+// function : updateEntitiesFlags
+// purpose  : Update entities flags
+//=================================================================================
+void SMESH_VisualObjDef::updateEntitiesFlags() {
+
+        unsigned int tmp = myEntitiesState;
+        ClearEntitiesFlags();
+
+        map<SMDSAbs_ElementType,int> entities = SMESH::GetEntitiesFromObject(this);
+        
+
+        if( myEntitiesCache[SMDSAbs_0DElement] != 0 ||  myEntitiesCache[SMDSAbs_0DElement] >= entities[SMDSAbs_0DElement] )
+                myEntitiesState &= ~SMESH_Actor::e0DElements;
+
+        if( myEntitiesCache[SMDSAbs_Ball] != 0 ||  myEntitiesCache[SMDSAbs_Ball] >= entities[SMDSAbs_Ball] )
+                myEntitiesState &= ~SMESH_Actor::eBallElem;
+
+        if( myEntitiesCache[SMDSAbs_Edge] != 0 || myEntitiesCache[SMDSAbs_Edge] >= entities[SMDSAbs_Edge] )
+                myEntitiesState &= ~SMESH_Actor::eEdges; 
+
+        if( myEntitiesCache[SMDSAbs_Face] != 0 || myEntitiesCache[SMDSAbs_Face] >= entities[SMDSAbs_Face] )
+                myEntitiesState &= ~SMESH_Actor::eFaces; 
+
+        if( myEntitiesCache[SMDSAbs_Volume] != 0 || myEntitiesCache[SMDSAbs_Volume] >= entities[SMDSAbs_Volume] )
+                myEntitiesState &= ~SMESH_Actor::eVolumes;
+
+        if( tmp != myEntitiesState ) {
+                myEntitiesFlag = true;
+        }
+        
+        myEntitiesCache = entities;
+}
+
+//=================================================================================
+// function : ClearEntitiesFlags
+// purpose  : Clear the entities flags
+//=================================================================================
+void SMESH_VisualObjDef::ClearEntitiesFlags() {
+        myEntitiesState = SMESH_Actor::eAllEntity;
+        myEntitiesFlag = false;
+}
+
+//=================================================================================
+// function : GetEntitiesFlag
+// purpose  : Return the entities flag
+//=================================================================================
+bool SMESH_VisualObjDef::GetEntitiesFlag() {
+        return myEntitiesFlag;
+}
+
+//=================================================================================
+// function : GetEntitiesState
+// purpose  : Return the entities state
+//=================================================================================
+unsigned int SMESH_VisualObjDef::GetEntitiesState() {
+        return myEntitiesState;
+}
+
 /*
   Class       : SMESH_MeshObj
   Description : Class for visualisation of mesh
@@ -607,14 +644,12 @@ bool SMESH_VisualObj::GetEdgeNodes( const int theElemId,
 // function : SMESH_MeshObj
 // purpose  : Constructor
 //=================================================================================
-SMESH_MeshObj::SMESH_MeshObj(SMESH::SMESH_Mesh_ptr theMesh)
+SMESH_MeshObj::SMESH_MeshObj(SMESH::SMESH_Mesh_ptr theMesh):
+  myClient(SalomeApp_Application::orb(),theMesh)
 {
+        myEmptyGrid = 0;
   if ( MYDEBUG ) 
-    MESSAGE("SMESH_MeshObj - theMesh->_is_nil() = "<<theMesh->_is_nil());
-    
-  myMeshServer = SMESH::SMESH_Mesh::_duplicate( theMesh );
-  myMeshServer->Register();
-  myMesh = new SMDS_Mesh();
+    MESSAGE("SMESH_MeshObj - this = "<<this<<"; theMesh->_is_nil() = "<<theMesh->_is_nil());
 }
 
 //=================================================================================
@@ -623,132 +658,60 @@ SMESH_MeshObj::SMESH_MeshObj(SMESH::SMESH_Mesh_ptr theMesh)
 //=================================================================================
 SMESH_MeshObj::~SMESH_MeshObj()
 {
-  myMeshServer->Destroy();
-  delete myMesh;
+  if ( MYDEBUG ) 
+    MESSAGE("SMESH_MeshObj - this = "<<this<<"\n");
+  if ( myEmptyGrid )
+    myEmptyGrid->Delete();
 }
 
 //=================================================================================
 // function : Update
 // purpose  : Update mesh and fill grid with new values if necessary 
 //=================================================================================
-void SMESH_MeshObj::Update( int theIsClear )
+bool SMESH_MeshObj::Update( int theIsClear )
 {
   // Update SMDS_Mesh on client part
-  
-  try
-  {
-    SMESH::log_array_var aSeq = myMeshServer->GetLog( theIsClear );
-    CORBA::Long aLength = aSeq->length();
-    
-    if( MYDEBUG ) MESSAGE( "Update: length of the script is "<<aLength );
-    
-    if( !aLength )
-      return;
-      
-    for ( CORBA::Long anId = 0; anId < aLength; anId++)
-    {
-      const SMESH::double_array& aCoords = aSeq[anId].coords;
-      const SMESH::long_array& anIndexes = aSeq[anId].indexes;
-      CORBA::Long anElemId = 0, aNbElems = aSeq[anId].number;
-      SMDS_MeshElement* anElem = NULL;
-      CORBA::Long aCommand = aSeq[anId].commandType;
-      
-      switch(aCommand)
-      {
-        case SMESH::ADD_NODE       : AddNodesWithID   ( myMesh, aSeq, anId ); break;
-        case SMESH::ADD_EDGE       : AddEdgesWithID   ( myMesh, aSeq, anId ); break;
-        case SMESH::ADD_TRIANGLE   : AddTriasWithID   ( myMesh, aSeq, anId ); break;
-        case SMESH::ADD_QUADRANGLE : AddQuadsWithID   ( myMesh, aSeq, anId ); break;
-        case SMESH::ADD_TETRAHEDRON: AddTetrasWithID  ( myMesh, aSeq, anId ); break;
-        case SMESH::ADD_PYRAMID    : AddPiramidsWithID( myMesh, aSeq, anId ); break;
-        case SMESH::ADD_PRISM      : AddPrismsWithID  ( myMesh, aSeq, anId ); break;
-        case SMESH::ADD_HEXAHEDRON : AddHexasWithID   ( myMesh, aSeq, anId ); break;
-        
-        case SMESH::REMOVE_NODE:
-          for( ; anElemId < aNbElems; anElemId++ )
-            myMesh->RemoveNode( FindNode( myMesh, anIndexes[anElemId] ) );
-        break;
-        
-        case SMESH::REMOVE_ELEMENT:
-          for( ; anElemId < aNbElems; anElemId++ )
-            myMesh->RemoveElement( FindElement( myMesh, anIndexes[anElemId] ) );
-        break;
-
-        case SMESH::MOVE_NODE:
-          for(CORBA::Long aCoordId=0; anElemId < aNbElems; anElemId++, aCoordId+=3)
-          {
-            SMDS_MeshNode* node =
-              const_cast<SMDS_MeshNode*>( FindNode( myMesh, anIndexes[anElemId] ));
-            node->setXYZ( aCoords[aCoordId], aCoords[aCoordId+1], aCoords[aCoordId+2] );
-          }
-        break;
-
-        case SMESH::CHANGE_ELEMENT_NODES:
-          for ( CORBA::Long i = 0; anElemId < aNbElems; anElemId++ )
-          {
-            // find element
-            const SMDS_MeshElement* elem = FindElement( myMesh, anIndexes[i++] );
-            // nb nodes
-            int nbNodes = anIndexes[i++];
-            // nodes
-            ASSERT( nbNodes < 9 );
-            const SMDS_MeshNode* aNodes[ 8 ];
-            for ( int iNode = 0; iNode < nbNodes; iNode++ )
-              aNodes[ iNode ] = FindNode( myMesh, anIndexes[i++] );
-            // change
-            myMesh->ChangeElementNodes( elem, aNodes, nbNodes );
-          }
-          break;
-
-        case SMESH::RENUMBER:
-          for(CORBA::Long i=0; anElemId < aNbElems; anElemId++, i+=3)
-          {
-            myMesh->Renumber( anIndexes[i], anIndexes[i+1], anIndexes[i+2] );
-          }
-          break;
-          
-        default:;
-      }
-    }
-  }
-  catch ( SALOME::SALOME_Exception& exc )
-  {
-    INFOS("Following exception was cought:\n\t"<<exc.details.text);
-  }
-  catch( const std::exception& exc)
-  {
-    INFOS("Following exception was cought:\n\t"<<exc.what());
-  }
-  catch(...)
-  {
-    INFOS("Unknown exception was cought !!!");
-  }
-  
-  if ( MYDEBUG )
-  {
-    MESSAGE("Update - myMesh->NbNodes() = "<<myMesh->NbNodes());
-    MESSAGE("Update - myMesh->NbEdges() = "<<myMesh->NbEdges());
-    MESSAGE("Update - myMesh->NbFaces() = "<<myMesh->NbFaces());
-    MESSAGE("Update - myMesh->NbVolumes() = "<<myMesh->NbVolumes());
+  MESSAGE("SMESH_MeshObj::Update " << this);
+  if ( myClient.Update(theIsClear) || GetUnstructuredGrid()->GetNumberOfPoints()==0) {
+    MESSAGE("buildPrs");
+    buildPrs();  // Fill unstructured grid
+    return true;
   }
-
-  // Fill unstructured grid
-  buildPrs();
+  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);
+        return true;
+}
 //=================================================================================
 // function : GetElemDimension
 // purpose  : Get dimension of element
 //=================================================================================
 int SMESH_MeshObj::GetElemDimension( const int theObjId )
 {
-  const SMDS_MeshElement* anElem = myMesh->FindElement( theObjId );
+  const SMDS_MeshElement* anElem = myClient->FindElement( theObjId );
   if ( anElem == 0 )
     return 0;
 
   int aType = anElem->GetType();
   switch ( aType )
   {
+    case SMDSAbs_0DElement : return 0;
+    case SMDSAbs_Ball : return 0;
     case SMDSAbs_Edge  : return 1;
     case SMDSAbs_Face  : return 2;
     case SMDSAbs_Volume: return 3;
@@ -760,28 +723,37 @@ int SMESH_MeshObj::GetElemDimension( const int theObjId )
 // function : GetEntities
 // purpose  : Get entities of specified type. Return number of entities
 //=================================================================================
-int SMESH_MeshObj::GetNbEntities( const SMESH::ElementType theType) const
+int SMESH_MeshObj::GetNbEntities( const SMDSAbs_ElementType theType) const
 {
   switch ( theType )
   {
-    case SMESH::NODE:
+    case SMDSAbs_Node:
+    {
+      return myClient->NbNodes();
+    }
+    break;
+    case SMDSAbs_0DElement:
     {
-      return myMesh->NbNodes();
+      return myClient->Nb0DElements();
+    }
+    case SMDSAbs_Ball:
+    {
+      return myClient->NbBalls();
     }
     break;
-    case SMESH::EDGE:
+    case SMDSAbs_Edge:
     {
-      return myMesh->NbEdges();
+      return myClient->NbEdges();
     }
     break;
-    case SMESH::FACE:
+    case SMDSAbs_Face:
     {
-      return myMesh->NbFaces();
+      return myClient->NbFaces();
     }
     break;
-    case SMESH::VOLUME:
+    case SMDSAbs_Volume:
     {
-      return myMesh->NbVolumes();
+      return myClient->NbVolumes();
     }
     break;
     default:
@@ -790,33 +762,45 @@ int SMESH_MeshObj::GetNbEntities( const SMESH::ElementType theType) const
   }
 }
 
-int SMESH_MeshObj::GetEntities( const SMESH::ElementType theType, TEntityList& theObjs ) const
+int SMESH_MeshObj::GetEntities( const SMDSAbs_ElementType theType, TEntityList& theObjs ) const
 {
   theObjs.clear();
 
   switch ( theType )
   {
-    case SMESH::NODE:
+    case SMDSAbs_Node:
     {
-      SMDS_NodeIteratorPtr anIter = myMesh->nodesIterator();
+      SMDS_NodeIteratorPtr anIter = myClient->nodesIterator();
       while ( anIter->more() ) theObjs.push_back( anIter->next() );
     }
     break;
-    case SMESH::EDGE:
+    case SMDSAbs_0DElement:
     {
-      SMDS_EdgeIteratorPtr anIter = myMesh->edgesIterator();
+      SMDS_ElemIteratorPtr anIter = myClient->elementsIterator(SMDSAbs_0DElement);
       while ( anIter->more() ) theObjs.push_back( anIter->next() );
     }
     break;
-    case SMESH::FACE:
+    case SMDSAbs_Ball:
     {
-      SMDS_FaceIteratorPtr anIter = myMesh->facesIterator();
+      SMDS_ElemIteratorPtr anIter = myClient->elementGeomIterator(SMDSGeom_BALL);
       while ( anIter->more() ) theObjs.push_back( anIter->next() );
     }
     break;
-    case SMESH::VOLUME:
+    case SMDSAbs_Edge:
     {
-      SMDS_VolumeIteratorPtr anIter = myMesh->volumesIterator();
+      SMDS_EdgeIteratorPtr anIter = myClient->edgesIterator();
+      while ( anIter->more() ) theObjs.push_back( anIter->next() );
+    }
+    break;
+    case SMDSAbs_Face:
+    {
+      SMDS_FaceIteratorPtr anIter = myClient->facesIterator();
+      while ( anIter->more() ) theObjs.push_back( anIter->next() );
+    }
+    break;
+    case SMDSAbs_Volume:
+    {
+      SMDS_VolumeIteratorPtr anIter = myClient->volumesIterator();
       while ( anIter->more() ) theObjs.push_back( anIter->next() );
     }
     break;
@@ -842,7 +826,7 @@ void SMESH_MeshObj::UpdateFunctor( const SMESH::Controls::FunctorPtr& theFunctor
 //=================================================================================
 bool SMESH_MeshObj::IsNodePrs() const
 {
-  return myMesh->NbEdges() == 0 &&myMesh->NbFaces() == 0 &&myMesh->NbVolumes() == 0 ;
+  return myClient->Nb0DElements() + myClient->NbEdges() + myClient->NbFaces() + myClient->NbVolumes() + myClient->NbBalls() == 0 ;
 }
 
 
@@ -879,6 +863,7 @@ int SMESH_SubMeshObj::GetElemDimension( const int theObjId )
 // function : UpdateFunctor
 // purpose  : Update functor in accordance with current mesh
 //=================================================================================
+
 void SMESH_SubMeshObj::UpdateFunctor( const SMESH::Controls::FunctorPtr& theFunctor )
 {
   theFunctor->SetMesh( myMeshObj->GetMesh() );
@@ -888,10 +873,12 @@ void SMESH_SubMeshObj::UpdateFunctor( const SMESH::Controls::FunctorPtr& theFunc
 // function : Update
 // purpose  : Update mesh object and fill grid with new values 
 //=================================================================================
-void SMESH_SubMeshObj::Update( int theIsClear )
+bool SMESH_SubMeshObj::Update( int theIsClear )
 {
-  myMeshObj->Update( theIsClear );
-  buildPrs();
+  MESSAGE("SMESH_SubMeshObj::Update " << this)
+  bool changed = myMeshObj->Update( theIsClear );
+  buildPrs(true);
+  return changed;
 }
 
 
@@ -916,7 +903,7 @@ SMESH_GroupObj::SMESH_GroupObj( SMESH::SMESH_GroupBase_ptr theGroup,
 SMESH_GroupObj::~SMESH_GroupObj()
 {
   if ( MYDEBUG ) MESSAGE("~SMESH_GroupObj");
-  myGroupServer->Destroy();
+  myGroupServer->UnRegister();
 }
 
 //=================================================================================
@@ -928,6 +915,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
@@ -964,14 +960,14 @@ static int getNodesFromElems( SMESH::long_array_var&              theElemIds,
 // function : getPointers
 // purpose  : Get std::list<const SMDS_MeshElement*> from list of IDs
 //=================================================================================
-static int getPointers( const SMESH::ElementType            theRequestType,
+static int getPointers( const SMDSAbs_ElementType            theRequestType,
                         SMESH::long_array_var&              theElemIds,
                         const SMDS_Mesh*                    theMesh,
                         std::list<const SMDS_MeshElement*>& theResList )
 {
   for ( CORBA::Long i = 0, n = theElemIds->length(); i < n; i++ )
   {
-    const SMDS_MeshElement* anElem = theRequestType == SMESH::NODE
+    const SMDS_MeshElement* anElem = theRequestType == SMDSAbs_Node
       ? theMesh->FindNode( theElemIds[ i ] ) : theMesh->FindElement( theElemIds[ i ] );
 
     if ( anElem != 0 )
@@ -986,32 +982,40 @@ static int getPointers( const SMESH::ElementType            theRequestType,
 // function : GetEntities
 // purpose  : Get entities of specified type. Return number of entities
 //=================================================================================
-int SMESH_GroupObj::GetNbEntities( const SMESH::ElementType theType) const
+int SMESH_GroupObj::GetNbEntities( const SMDSAbs_ElementType theType) const
 {
-  if(myGroupServer->GetType() == theType){
+  if(SMDSAbs_ElementType(myGroupServer->GetType()) == theType) {
     return myGroupServer->Size();
   }
+  if ( theType == SMDSAbs_Node ) {
+    return myGroupServer->GetNumberOfNodes();
+  }
   return 0;
 }
 
-int SMESH_GroupObj::GetEntities( const SMESH::ElementType theType, TEntityList& theResList ) const
+int SMESH_GroupObj::GetEntities( const SMDSAbs_ElementType theType, TEntityList& theResList ) const
 {
   theResList.clear();
   SMDS_Mesh* aMesh = myMeshObj->GetMesh();
   
-  if ( myGroupServer->Size() == 0 || aMesh == 0 )
+  if ( aMesh == 0 )
+    return 0;
+
+  SMDSAbs_ElementType aGrpType = SMDSAbs_ElementType(myGroupServer->GetType());
+  if ( aGrpType != theType && theType != SMDSAbs_Node )
     return 0;
 
-  SMESH::ElementType aGrpType = myGroupServer->GetType();
   SMESH::long_array_var anIds = myGroupServer->GetListOfID();
+  if ( anIds->length() == 0 )
+    return 0;
 
   if ( aGrpType == theType )
     return getPointers( theType, anIds, aMesh, theResList );
-  else if ( theType == SMESH::NODE )
+  else if ( theType == SMDSAbs_Node )
     return getNodesFromElems( anIds, aMesh, theResList );
   else
     return 0;
-}    
+}
 
 
 
@@ -1037,27 +1041,30 @@ SMESH_subMeshObj::SMESH_subMeshObj( SMESH::SMESH_subMesh_ptr theSubMesh,
 SMESH_subMeshObj::~SMESH_subMeshObj()
 {
   if ( MYDEBUG ) MESSAGE( "~SMESH_subMeshObj" );
-  mySubMeshServer->Destroy();
+  mySubMeshServer->UnRegister();
 }
 
 //=================================================================================
 // function : GetEntities
 // purpose  : Get entities of specified type. Return number of entities
 //=================================================================================
-int SMESH_subMeshObj::GetNbEntities( const SMESH::ElementType theType) const
+int SMESH_subMeshObj::GetNbEntities( const SMDSAbs_ElementType theType) const
 {
   switch ( theType )
   {
-    case SMESH::NODE:
+    case SMDSAbs_Node:
     {
-      return mySubMeshServer->GetNumberOfNodes( false );
+      return mySubMeshServer->GetNumberOfNodes( /*all=*/true );
     }
     break;
-    case SMESH::EDGE:
-    case SMESH::FACE:
-    case SMESH::VOLUME:
+    case SMDSAbs_Ball:
+    case SMDSAbs_0DElement:
+    case SMDSAbs_Edge:
+    case SMDSAbs_Face:
+    case SMDSAbs_Volume:
     {
-      SMESH::long_array_var anIds = mySubMeshServer->GetElementsByType( theType );
+      SMESH::long_array_var anIds = 
+        mySubMeshServer->GetElementsByType( SMESH::ElementType(theType) );
       return anIds->length();
     }
     default:
@@ -1066,7 +1073,7 @@ int SMESH_subMeshObj::GetNbEntities( const SMESH::ElementType theType) const
   }
 }
 
-int SMESH_subMeshObj::GetEntities( const SMESH::ElementType theType, TEntityList& theResList ) const
+int SMESH_subMeshObj::GetEntities( const SMDSAbs_ElementType theType, TEntityList& theResList ) const
 {
   theResList.clear();
 
@@ -1078,22 +1085,23 @@ int SMESH_subMeshObj::GetEntities( const SMESH::ElementType theType, TEntityList
 
   if ( isNodal )
   {
-    if ( theType == SMESH::NODE )
+    if ( theType == SMDSAbs_Node )
     {
       SMESH::long_array_var anIds = mySubMeshServer->GetNodesId();
-      return getPointers( SMESH::NODE, anIds, aMesh, theResList );
+      return getPointers( SMDSAbs_Node, anIds, aMesh, theResList );
     }
   }
   else
   {
-    if ( theType == SMESH::NODE )
+    if ( theType == SMDSAbs_Node )
     {
       SMESH::long_array_var anIds = mySubMeshServer->GetElementsId();
       return getNodesFromElems( anIds, aMesh, theResList );
     }
     else
     {
-      SMESH::long_array_var anIds = mySubMeshServer->GetElementsByType( theType );
+      SMESH::long_array_var anIds = 
+        mySubMeshServer->GetElementsByType( SMESH::ElementType(theType) );
       return getPointers( theType, anIds, aMesh, theResList );
     }
   }
@@ -1109,15 +1117,3 @@ bool SMESH_subMeshObj::IsNodePrs() const
 {
   return mySubMeshServer->GetNumberOfElements() == 0;
 }
-
-
-
-
-
-
-
-
-
-
-
-