Salome HOME
PR: adjust points number
[modules/smesh.git] / src / OBJECT / SMESH_Object.cxx
1 //  Copyright (C) 2007-2008  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 //  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 //  This library is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU Lesser General Public
8 //  License as published by the Free Software Foundation; either
9 //  version 2.1 of the License.
10 //
11 //  This library is distributed in the hope that it will be useful,
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 //  Lesser General Public License for more details.
15 //
16 //  You should have received a copy of the GNU Lesser General Public
17 //  License along with this library; if not, write to the Free Software
18 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 //  SMESH OBJECT : interactive object for SMESH visualization
23 //  File   : SMESH_Grid.cxx
24 //  Author : Nicolas REJNERI
25 //  Module : SMESH
26 //
27 #include "SMESH_ObjectDef.h"
28 #include "SMESH_ActorUtils.h"
29
30 #include "SMDS_Mesh.hxx"
31 #include "SMDS_PolyhedralVolumeOfNodes.hxx"
32 #include "SMESH_Actor.h"
33 #include "SMESH_ControlsDef.hxx"
34 #include "SalomeApp_Application.h"
35 #include "VTKViewer_ExtractUnstructuredGrid.h"
36 #include "VTKViewer_CellLocationsArray.h"
37
38 #include CORBA_SERVER_HEADER(SMESH_Gen)
39 #include CORBA_SERVER_HEADER(SALOME_Exception)
40
41 #include <vtkCell.h>
42 #include <vtkIdList.h>
43 #include <vtkCellArray.h>
44 #include <vtkUnsignedCharArray.h>
45
46 #include <vtkUnstructuredGrid.h>
47
48 #include <memory>
49 #include <sstream>      
50 #include <stdexcept>
51 #include <set>
52
53 #include "utilities.h"
54
55 using namespace std;
56
57 #ifndef EXCEPTION
58 #define EXCEPTION(TYPE, MSG) {\
59   std::ostringstream aStream;\
60   aStream<<__FILE__<<"["<<__LINE__<<"]::"<<MSG;\
61   throw TYPE(aStream.str());\
62 }
63 #endif
64
65 #ifdef _DEBUG_
66 static int MYDEBUG = 1;
67 static int MYDEBUGWITHFILES = 0;
68 #else
69 static int MYDEBUG = 0;
70 static int MYDEBUGWITHFILES = 0;
71 #endif
72
73
74 /*
75   Class       : SMESH_VisualObjDef
76   Description : Base class for all mesh objects to be visuilised
77 */
78
79 //=================================================================================
80 // function : getCellType
81 // purpose  : Get type of VTK cell
82 //=================================================================================
83 static inline vtkIdType getCellType( const SMDSAbs_ElementType theType,
84                                      const bool thePoly,
85                                      const int theNbNodes )
86 {
87   switch( theType )
88   {
89     case SMDSAbs_0DElement: 
90       return VTK_VERTEX;
91
92     case SMDSAbs_Edge: 
93       if( theNbNodes == 2 )         return VTK_LINE;
94       else if ( theNbNodes == 3 )   return VTK_QUADRATIC_EDGE;
95       else return VTK_EMPTY_CELL;
96
97     case SMDSAbs_Face  :
98       if (thePoly && theNbNodes>2 ) return VTK_POLYGON;
99       else if ( theNbNodes == 3 )   return VTK_TRIANGLE;
100       else if ( theNbNodes == 4 )   return VTK_QUAD;
101       else if ( theNbNodes == 6 )   return VTK_QUADRATIC_TRIANGLE;
102       else if ( theNbNodes == 8 )   return VTK_QUADRATIC_QUAD;
103       else return VTK_EMPTY_CELL;
104       
105     case SMDSAbs_Volume:
106       if (thePoly && theNbNodes>3 ) return VTK_CONVEX_POINT_SET;
107       else if ( theNbNodes == 4 )   return VTK_TETRA;
108       else if ( theNbNodes == 5 )   return VTK_PYRAMID;
109       else if ( theNbNodes == 6 )   return VTK_WEDGE;
110       else if ( theNbNodes == 8 )   return VTK_HEXAHEDRON;
111       else if ( theNbNodes == 10 )  {
112         return VTK_QUADRATIC_TETRA;
113       }
114       else if ( theNbNodes == 20 )  {
115         return VTK_QUADRATIC_HEXAHEDRON;
116       }
117       else if ( theNbNodes == 15 )  {
118         return VTK_QUADRATIC_WEDGE;
119       }
120       else if ( theNbNodes==13 )  {
121         return VTK_CONVEX_POINT_SET;
122       }
123       else return VTK_EMPTY_CELL;
124
125     default: return VTK_EMPTY_CELL;
126   }
127 }
128
129 //=================================================================================
130 // functions : SMESH_VisualObjDef
131 // purpose   : Constructor
132 //=================================================================================
133 SMESH_VisualObjDef::SMESH_VisualObjDef()
134 {
135   MESSAGE("---------------------------------------------SMESH_VisualObjDef::SMESH_VisualObjDef");
136   myGrid = vtkUnstructuredGrid::New();
137 }
138 SMESH_VisualObjDef::~SMESH_VisualObjDef()
139 {
140   MESSAGE("---------------------------------------------SMESH_VisualObjDef::~SMESH_VisualObjDef");
141   //if ( MYDEBUG )
142     MESSAGE( "~SMESH_MeshObj - myGrid->GetReferenceCount() = " << myGrid->GetReferenceCount() );
143   myGrid->Delete();
144 }
145
146 //=================================================================================
147 // functions : GetNodeObjId, GetNodeVTKId, GetElemObjId, GetElemVTKId
148 // purpose   : Methods for retrieving VTK IDs by SMDS IDs and  vice versa
149 //=================================================================================
150 vtkIdType SMESH_VisualObjDef::GetNodeObjId( int theVTKID )
151 {
152 //  TMapOfIds::const_iterator i = myVTK2SMDSNodes.find(theVTKID);
153 //  return i == myVTK2SMDSNodes.end() ? -1 : i->second;
154   return theVTKID;
155 }
156
157 vtkIdType SMESH_VisualObjDef::GetNodeVTKId( int theObjID )
158 {
159 //  TMapOfIds::const_iterator i = mySMDS2VTKNodes.find(theObjID);
160 //  return i == mySMDS2VTKNodes.end() ? -1 : i->second;
161   return theObjID;
162 }
163
164 vtkIdType SMESH_VisualObjDef::GetElemObjId( int theVTKID )
165 {
166 //  TMapOfIds::const_iterator i = myVTK2SMDSElems.find(theVTKID);
167 //  return i == myVTK2SMDSElems.end() ? -1 : i->second;
168   return this->GetMesh()->fromVtkToSmds(theVTKID);
169 }
170
171 vtkIdType SMESH_VisualObjDef::GetElemVTKId( int theObjID )
172 {
173 //  TMapOfIds::const_iterator i = mySMDS2VTKElems.find(theObjID);
174 //  return i == mySMDS2VTKElems.end() ? -1 : i->second;
175   return this->GetMesh()->fromSmdsToVtk(theObjID);
176 }
177
178 //=================================================================================
179 // function : SMESH_VisualObjDef::createPoints
180 // purpose  : Create points from nodes
181 //=================================================================================
182
183 //void SMESH_VisualObjDef::createPoints( vtkPoints* thePoints )
184 //{
185 //  if ( thePoints == 0 )
186 //    return;
187 //
188 //  TEntityList aNodes;
189 //  vtkIdType nbNodes = GetEntities( SMDSAbs_Node, aNodes );
190 //  thePoints->SetNumberOfPoints( nbNodes );
191 //
192 //  int nbPoints = 0;
193 //
194 //  TEntityList::const_iterator anIter;
195 //  for ( anIter = aNodes.begin(); anIter != aNodes.end(); ++anIter )
196 //  {
197 //    const SMDS_MeshNode* aNode = ( const SMDS_MeshNode* )(*anIter);
198 //    if ( aNode != 0 )
199 //    {
200 //      thePoints->SetPoint( nbPoints, aNode->X(), aNode->Y(), aNode->Z() );
201 //      int anId = aNode->GetID();
202 //      mySMDS2VTKNodes.insert( TMapOfIds::value_type( anId, nbPoints ) );
203 //      myVTK2SMDSNodes.insert( TMapOfIds::value_type( nbPoints, anId ) );
204 //      nbPoints++;
205 //    }
206 //  }
207 //
208 //  if ( nbPoints != nbNodes )
209 //    thePoints->SetNumberOfPoints( nbPoints );
210 //}
211
212 //=================================================================================
213 // function : buildPrs
214 // purpose  : create VTK cells( fill unstructured grid )
215 //=================================================================================
216 void SMESH_VisualObjDef::buildPrs()
217 {
218 //  try
219 //  {
220 //    mySMDS2VTKNodes.clear();
221 //    myVTK2SMDSNodes.clear();
222 //    mySMDS2VTKElems.clear();
223 //    myVTK2SMDSElems.clear();
224 //
225 //    if ( IsNodePrs() )
226 //      buildNodePrs();
227 //    else
228 //      buildElemPrs();
229 //  }
230 //  catch(...)
231 //  {
232 //    mySMDS2VTKNodes.clear();
233 //    myVTK2SMDSNodes.clear();
234 //    mySMDS2VTKElems.clear();
235 //    myVTK2SMDSElems.clear();
236 //
237 //    myGrid->SetPoints( 0 );
238 //    myGrid->SetCells( 0, 0, 0 );
239 //    throw;
240 //  }
241   MESSAGE("----------------------------------------------------------SMESH_VisualObjDef::buildPrs");
242   vtkUnstructuredGrid *theGrid = GetMesh()->getGrid();
243   myGrid->ShallowCopy(theGrid);
244   MESSAGE(myGrid->GetReferenceCount());
245   MESSAGE( "Update - myGrid->GetNumberOfCells() = "<<myGrid->GetNumberOfCells() );
246   MESSAGE( "Update - myGrid->GetNumberOfPoints() = "<<myGrid->GetNumberOfPoints() );
247   if( MYDEBUGWITHFILES ) SMESH::WriteUnstructuredGrid( myGrid,"/tmp/buildPrs" );
248 }
249
250 //=================================================================================
251 // function : buildNodePrs
252 // purpose  : create VTK cells for nodes
253 //=================================================================================
254
255 //void SMESH_VisualObjDef::buildNodePrs()
256 //{
257 //  // PAL16631: without swap, bad_alloc is not thrown but hung up and crash instead,
258 //  // so check remaining memory size for safety
259 //  SMDS_Mesh::CheckMemory(); // PAL16631
260 //  vtkPoints* aPoints = vtkPoints::New();
261 //  createPoints( aPoints );
262 //  SMDS_Mesh::CheckMemory();
263 //  myGrid->SetPoints( aPoints );
264 //  aPoints->Delete();
265 //
266 //  myGrid->SetCells( 0, 0, 0 );
267 //}
268
269 //=================================================================================
270 // function : buildElemPrs
271 // purpose  : Create VTK cells for elements
272 //=================================================================================
273
274 namespace{
275   typedef std::vector<const SMDS_MeshElement*> TConnect;
276
277   int GetConnect(const SMDS_ElemIteratorPtr& theNodesIter, 
278                  TConnect& theConnect)
279   {
280     theConnect.clear();
281     for(; theNodesIter->more();)
282       theConnect.push_back(theNodesIter->next());
283     return theConnect.size();
284   }
285   
286   inline 
287   void SetId(vtkIdList *theIdList, 
288              const SMESH_VisualObjDef::TMapOfIds& theSMDS2VTKNodes, 
289              const TConnect& theConnect, 
290              int thePosition,
291              int theId)
292   {
293     theIdList->SetId(thePosition,theSMDS2VTKNodes.find(theConnect[theId]->GetID())->second);
294   }
295
296 }
297
298
299 //void SMESH_VisualObjDef::buildElemPrs()
300 //{
301 //  // Create points
302 //
303 //  vtkPoints* aPoints = vtkPoints::New();
304 //  createPoints( aPoints );
305 //  myGrid->SetPoints( aPoints );
306 //  aPoints->Delete();
307 //
308 //  if ( MYDEBUG )
309 //    MESSAGE("Update - myGrid->GetNumberOfPoints() = "<<myGrid->GetNumberOfPoints());
310 //
311 //  // Calculate cells size
312 //
313 //  static SMDSAbs_ElementType aTypes[ 4 ] =
314 //    { SMDSAbs_0DElement, SMDSAbs_Edge, SMDSAbs_Face, SMDSAbs_Volume };
315 //
316 //  // get entity data
317 //  map<SMDSAbs_ElementType,int> nbEnts;
318 //  map<SMDSAbs_ElementType,TEntityList> anEnts;
319 //
320 //  for ( int i = 0; i <= 3; i++ )
321 //    nbEnts[ aTypes[ i ] ] = GetEntities( aTypes[ i ], anEnts[ aTypes[ i ] ] );
322 //
323 //  // PAL16631: without swap, bad_alloc is not thrown but hung up and crash instead,
324 //  // so check remaining memory size for safety
325 //  SMDS_Mesh::CheckMemory(); // PAL16631
326 //
327 //  vtkIdType aCellsSize =  2 * nbEnts[ SMDSAbs_0DElement ] + 3 * nbEnts[ SMDSAbs_Edge ];
328 //
329 //  for ( int i = 2; i <= 3; i++ ) // iterate through faces and volumes
330 //  {
331 //    if ( nbEnts[ aTypes[ i ] ] )
332 //    {
333 //      const TEntityList& aList = anEnts[ aTypes[ i ] ];
334 //      TEntityList::const_iterator anIter;
335 //      for ( anIter = aList.begin(); anIter != aList.end(); ++anIter )
336 //        aCellsSize += (*anIter)->NbNodes() + 1;
337 //    }
338 //  }
339 //
340 //  vtkIdType aNbCells = nbEnts[ SMDSAbs_0DElement ] + nbEnts[ SMDSAbs_Edge ] +
341 //                       nbEnts[ SMDSAbs_Face ] + nbEnts[ SMDSAbs_Volume ];
342 //
343 //  if ( MYDEBUG )
344 //    MESSAGE( "Update - aNbCells = "<<aNbCells<<"; aCellsSize = "<<aCellsSize );
345 //
346 //  // Create cells
347 //
348 //  vtkCellArray* aConnectivity = vtkCellArray::New();
349 //  aConnectivity->Allocate( aCellsSize, 0 );
350 //
351 //  SMDS_Mesh::CheckMemory(); // PAL16631
352 //
353 //  vtkUnsignedCharArray* aCellTypesArray = vtkUnsignedCharArray::New();
354 //  aCellTypesArray->SetNumberOfComponents( 1 );
355 //  aCellTypesArray->Allocate( aNbCells * aCellTypesArray->GetNumberOfComponents() );
356 //
357 //  SMDS_Mesh::CheckMemory(); // PAL16631
358 //
359 //  vtkIdList *anIdList = vtkIdList::New();
360 //  vtkIdType iElem = 0;
361 //
362 //  TConnect aConnect;
363 //  aConnect.reserve(VTK_CELL_SIZE);
364 //
365 //  SMDS_Mesh::CheckMemory(); // PAL16631
366 //
367 //  for ( int i = 0; i <= 3; i++ ) // iterate through 0d elements, edges, faces and volumes
368 //  {
369 //    if ( nbEnts[ aTypes[ i ] ] > 0 )
370 //    {
371 //      const SMDSAbs_ElementType& aType = aTypes[ i ];
372 //      const TEntityList& aList = anEnts[ aType ];
373 //      TEntityList::const_iterator anIter;
374 //      for ( anIter = aList.begin(); anIter != aList.end(); ++anIter )
375 //      {
376 //        const SMDS_MeshElement* anElem = *anIter;
377 //
378 //        vtkIdType aNbNodes = anElem->NbNodes();
379 //        anIdList->SetNumberOfIds( aNbNodes );
380 //
381 //        int anId = anElem->GetID();
382 //
383 //        mySMDS2VTKElems.insert( TMapOfIds::value_type( anId, iElem ) );
384 //        myVTK2SMDSElems.insert( TMapOfIds::value_type( iElem, anId ) );
385 //
386 //        SMDS_ElemIteratorPtr aNodesIter = anElem->nodesIterator();
387 //        switch (aType) {
388 //        case SMDSAbs_Volume:{
389 //          aConnect.clear();
390 //          std::vector<int> aConnectivities;
391 //          // Convertions connectivities from SMDS to VTK
392 //          if (anElem->IsPoly() && aNbNodes > 3) { // POLYEDRE
393 //
394 //            if ( const SMDS_PolyhedralVolumeOfNodes* ph =
395 //                 dynamic_cast<const SMDS_PolyhedralVolumeOfNodes*> (anElem))
396 //            {
397 //              aNbNodes = GetConnect(ph->uniqueNodesIterator(),aConnect);
398 //              anIdList->SetNumberOfIds( aNbNodes );
399 //            }
400 //            for (int k = 0; k < aNbNodes; k++)
401 //              aConnectivities.push_back(k);
402 //
403 //          } else if (aNbNodes == 4) {
404 //            static int anIds[] = {0,2,1,3};
405 //            for (int k = 0; k < aNbNodes; k++) aConnectivities.push_back(anIds[k]);
406 //
407 //          } else if (aNbNodes == 5) {
408 //            static int anIds[] = {0,3,2,1,4};
409 //            for (int k = 0; k < aNbNodes; k++) aConnectivities.push_back(anIds[k]);
410 //
411 //          } else if (aNbNodes == 6) {
412 //            static int anIds[] = {0,1,2,3,4,5};
413 //            for (int k = 0; k < aNbNodes; k++) aConnectivities.push_back(anIds[k]);
414 //
415 //          }
416 //          else if (aNbNodes == 8) {
417 //            static int anIds[] = {0,3,2,1,4,7,6,5};
418 //            for (int k = 0; k < aNbNodes; k++) aConnectivities.push_back(anIds[k]);
419 //
420 //          }
421 //          else if (aNbNodes == 10) {
422 //            static int anIds[] = {0,2,1,3,6,5,4,7,9,8};
423 //            for (int k = 0; k < aNbNodes; k++) aConnectivities.push_back(anIds[k]);
424 //          }
425 //          else if (aNbNodes == 13) {
426 //            static int anIds[] = {0,3,2,1,4,8,7,6,5,9,12,11,10};
427 //            for (int k = 0; k < aNbNodes; k++) aConnectivities.push_back(anIds[k]);
428 //          }
429 //          else if (aNbNodes == 15) {
430 //            //static int anIds[] = {0,2,1,3,5,4,8,7,6,11,10,9,12,14,13};
431 //            static int anIds[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14};
432 //            for (int k = 0; k < aNbNodes; k++) aConnectivities.push_back(anIds[k]);
433 //            //for (int k = 0; k < aNbNodes; k++) {
434 //            //  int nn = aConnectivities[k];
435 //            //  const SMDS_MeshNode* N = static_cast<const SMDS_MeshNode*> (aConnect[nn]);
436 //            //  cout<<"k="<<k<<"  N("<<N->X()<<","<<N->Y()<<","<<N->Z()<<")"<<endl;
437 //            //}
438 //          }
439 //          else if (aNbNodes == 20) {
440 //            static int anIds[] = {0,3,2,1,4,7,6,5,11,10,9,8,15,14,13,12,16,19,18,17};
441 //            for (int k = 0; k < aNbNodes; k++) aConnectivities.push_back(anIds[k]);
442 //          }
443 //          else {
444 //          }
445 //
446 //          if ( aConnect.empty() )
447 //            GetConnect(aNodesIter,aConnect);
448 //
449 //          if (aConnectivities.size() > 0) {
450 //            for (vtkIdType aNodeId = 0; aNodeId < aNbNodes; aNodeId++)
451 //              SetId(anIdList,mySMDS2VTKNodes,aConnect,aNodeId,aConnectivities[aNodeId]);
452 //          }
453 //          break;
454 //        }
455 //        default:
456 //          for( vtkIdType aNodeId = 0; aNodesIter->more(); aNodeId++ ){
457 //            const SMDS_MeshElement* aNode = aNodesIter->next();
458 //            anIdList->SetId( aNodeId, mySMDS2VTKNodes[aNode->GetID()] );
459 //          }
460 //        }
461 //
462 //        aConnectivity->InsertNextCell( anIdList );
463 //        aCellTypesArray->InsertNextValue( getCellType( aType, anElem->IsPoly(), aNbNodes ) );
464 //
465 //        iElem++;
466 //      }
467 //    }
468 //    SMDS_Mesh::CheckMemory(); // PAL16631
469 //  }
470 //
471 //  // Insert cells in grid
472 //
473 //  VTKViewer_CellLocationsArray* aCellLocationsArray = VTKViewer_CellLocationsArray::New();
474 //  aCellLocationsArray->SetNumberOfComponents( 1 );
475 //  aCellLocationsArray->SetNumberOfTuples( aNbCells );
476 //
477 //  SMDS_Mesh::CheckMemory(); // PAL16631
478 //
479 //  aConnectivity->InitTraversal();
480 //  for( vtkIdType idType = 0, *pts, npts; aConnectivity->GetNextCell( npts, pts ); idType++ )
481 //    aCellLocationsArray->SetValue( idType, aConnectivity->GetTraversalLocation( npts ) );
482 //
483 //  myGrid->SetCells( aCellTypesArray, aCellLocationsArray,aConnectivity );
484 //
485 //  aCellLocationsArray->Delete();
486 //  aCellTypesArray->Delete();
487 //  aConnectivity->Delete();
488 //  anIdList->Delete();
489 //
490 //  SMDS_Mesh::CheckMemory(); // PAL16631
491 //}
492
493 //=================================================================================
494 // function : GetEdgeNodes
495 // purpose  : Retrieve ids of nodes from edge of elements ( edge is numbered from 1 )
496 //=================================================================================
497 bool SMESH_VisualObjDef::GetEdgeNodes( const int theElemId,
498                                        const int theEdgeNum,
499                                        int&      theNodeId1,
500                                        int&      theNodeId2 ) const
501 {
502   const SMDS_Mesh* aMesh = GetMesh();
503   if ( aMesh == 0 )
504     return false;
505     
506   const SMDS_MeshElement* anElem = aMesh->FindElement( theElemId );
507   if ( anElem == 0 )
508     return false;
509     
510   int nbNodes = anElem->NbNodes();
511
512   if ( theEdgeNum < 0 || theEdgeNum > 3 || nbNodes != 3 && nbNodes != 4 || theEdgeNum > nbNodes )
513     return false;
514
515   vector<int> anIds( nbNodes );
516   SMDS_ElemIteratorPtr anIter = anElem->nodesIterator();
517   int i = 0;
518   while( anIter->more() )
519     anIds[ i++ ] = anIter->next()->GetID();
520
521   if ( theEdgeNum < nbNodes - 1 )
522   {
523     theNodeId1 = anIds[ theEdgeNum ];
524     theNodeId2 = anIds[ theEdgeNum + 1 ];
525   }
526   else
527   {
528     theNodeId1 = anIds[ nbNodes - 1 ];
529     theNodeId2 = anIds[ 0 ];
530   }
531
532   return true;
533 }
534
535 //=================================================================================
536 // function : IsValid
537 // purpose  : Return true if there are some entities
538 //=================================================================================
539 bool SMESH_VisualObjDef::IsValid() const
540 {
541   return GetNbEntities(SMDSAbs_Node) > 0      || 
542          GetNbEntities(SMDSAbs_0DElement) > 0 || 
543          GetNbEntities(SMDSAbs_Edge) > 0      || 
544          GetNbEntities(SMDSAbs_Face) > 0      ||
545          GetNbEntities(SMDSAbs_Volume) > 0 ;
546 }
547
548 /*
549   Class       : SMESH_MeshObj
550   Description : Class for visualisation of mesh
551 */
552
553 //=================================================================================
554 // function : SMESH_MeshObj
555 // purpose  : Constructor
556 //=================================================================================
557 SMESH_MeshObj::SMESH_MeshObj(SMESH::SMESH_Mesh_ptr theMesh):
558   myClient(SalomeApp_Application::orb(),theMesh)
559 {
560   if ( MYDEBUG ) 
561     MESSAGE("SMESH_MeshObj - this = "<<this<<"; theMesh->_is_nil() = "<<theMesh->_is_nil());
562 }
563
564 //=================================================================================
565 // function : ~SMESH_MeshObj
566 // purpose  : Destructor
567 //=================================================================================
568 SMESH_MeshObj::~SMESH_MeshObj()
569 {
570   if ( MYDEBUG ) 
571     MESSAGE("SMESH_MeshObj - this = "<<this<<"\n");
572 }
573
574 //=================================================================================
575 // function : Update
576 // purpose  : Update mesh and fill grid with new values if necessary 
577 //=================================================================================
578 bool SMESH_MeshObj::Update( int theIsClear )
579 {
580   // Update SMDS_Mesh on client part
581   if ( myClient.Update(theIsClear) || GetUnstructuredGrid()->GetNumberOfPoints()==0) {
582     buildPrs();  // Fill unstructured grid
583     return true;
584   }
585   return false;
586 }
587
588 //=================================================================================
589 // function : GetElemDimension
590 // purpose  : Get dimension of element
591 //=================================================================================
592 int SMESH_MeshObj::GetElemDimension( const int theObjId )
593 {
594   const SMDS_MeshElement* anElem = myClient->FindElement( theObjId );
595   if ( anElem == 0 )
596     return 0;
597
598   int aType = anElem->GetType();
599   switch ( aType )
600   {
601     case SMDSAbs_0DElement : return 0;
602     case SMDSAbs_Edge  : return 1;
603     case SMDSAbs_Face  : return 2;
604     case SMDSAbs_Volume: return 3;
605     default            : return 0;
606   }
607 }
608
609 //=================================================================================
610 // function : GetEntities
611 // purpose  : Get entities of specified type. Return number of entities
612 //=================================================================================
613 int SMESH_MeshObj::GetNbEntities( const SMDSAbs_ElementType theType) const
614 {
615   switch ( theType )
616   {
617     case SMDSAbs_Node:
618     {
619       return myClient->NbNodes();
620     }
621     break;
622     case SMDSAbs_0DElement:
623     {
624       return myClient->Nb0DElements();
625     }
626     break;
627     case SMDSAbs_Edge:
628     {
629       return myClient->NbEdges();
630     }
631     break;
632     case SMDSAbs_Face:
633     {
634       return myClient->NbFaces();
635     }
636     break;
637     case SMDSAbs_Volume:
638     {
639       return myClient->NbVolumes();
640     }
641     break;
642     default:
643       return 0;
644     break;
645   }
646 }
647
648 int SMESH_MeshObj::GetEntities( const SMDSAbs_ElementType theType, TEntityList& theObjs ) const
649 {
650   theObjs.clear();
651
652   switch ( theType )
653   {
654     case SMDSAbs_Node:
655     {
656       SMDS_NodeIteratorPtr anIter = myClient->nodesIterator();
657       while ( anIter->more() ) theObjs.push_back( anIter->next() );
658     }
659     break;
660     case SMDSAbs_0DElement:
661     {
662       SMDS_0DElementIteratorPtr anIter = myClient->elements0dIterator();
663       while ( anIter->more() ) theObjs.push_back( anIter->next() );
664     }
665     break;
666     case SMDSAbs_Edge:
667     {
668       SMDS_EdgeIteratorPtr anIter = myClient->edgesIterator();
669       while ( anIter->more() ) theObjs.push_back( anIter->next() );
670     }
671     break;
672     case SMDSAbs_Face:
673     {
674       SMDS_FaceIteratorPtr anIter = myClient->facesIterator();
675       while ( anIter->more() ) theObjs.push_back( anIter->next() );
676     }
677     break;
678     case SMDSAbs_Volume:
679     {
680       SMDS_VolumeIteratorPtr anIter = myClient->volumesIterator();
681       while ( anIter->more() ) theObjs.push_back( anIter->next() );
682     }
683     break;
684     default:
685     break;
686   }
687
688   return theObjs.size();
689 }
690
691 //=================================================================================
692 // function : UpdateFunctor
693 // purpose  : Update functor in accordance with current mesh
694 //=================================================================================
695 void SMESH_MeshObj::UpdateFunctor( const SMESH::Controls::FunctorPtr& theFunctor )
696 {
697   theFunctor->SetMesh( GetMesh() );
698 }
699
700 //=================================================================================
701 // function : IsNodePrs
702 // purpose  : Return true if node presentation is used
703 //=================================================================================
704 bool SMESH_MeshObj::IsNodePrs() const
705 {
706   return myClient->Nb0DElements() == 0 && myClient->NbEdges() == 0 && myClient->NbFaces() == 0 && myClient->NbVolumes() == 0 ;
707 }
708
709
710 /*
711   Class       : SMESH_SubMeshObj
712   Description : Base class for visualisation of submeshes and groups
713 */
714
715 //=================================================================================
716 // function : SMESH_SubMeshObj
717 // purpose  : Constructor
718 //=================================================================================
719 SMESH_SubMeshObj::SMESH_SubMeshObj( SMESH_MeshObj* theMeshObj )
720 {
721   if ( MYDEBUG ) MESSAGE( "SMESH_SubMeshObj - theMeshObj = " << theMeshObj );
722   
723   myMeshObj = theMeshObj;
724 }
725
726 SMESH_SubMeshObj::~SMESH_SubMeshObj()
727 {
728 }
729
730 //=================================================================================
731 // function : GetElemDimension
732 // purpose  : Get dimension of element
733 //=================================================================================
734 int SMESH_SubMeshObj::GetElemDimension( const int theObjId )
735 {
736   return myMeshObj == 0 ? 0 : myMeshObj->GetElemDimension( theObjId );
737 }
738
739 //=================================================================================
740 // function : UpdateFunctor
741 // purpose  : Update functor in accordance with current mesh
742 //=================================================================================
743 void SMESH_SubMeshObj::UpdateFunctor( const SMESH::Controls::FunctorPtr& theFunctor )
744 {
745   theFunctor->SetMesh( myMeshObj->GetMesh() );
746 }
747
748 //=================================================================================
749 // function : Update
750 // purpose  : Update mesh object and fill grid with new values 
751 //=================================================================================
752 bool SMESH_SubMeshObj::Update( int theIsClear )
753 {
754   bool changed = myMeshObj->Update( theIsClear );
755   buildPrs();
756   return changed;
757 }
758
759
760 /*
761   Class       : SMESH_GroupObj
762   Description : Class for visualisation of groups
763 */
764
765 //=================================================================================
766 // function : SMESH_GroupObj
767 // purpose  : Constructor
768 //=================================================================================
769 SMESH_GroupObj::SMESH_GroupObj( SMESH::SMESH_GroupBase_ptr theGroup, 
770                                 SMESH_MeshObj*             theMeshObj )
771 : SMESH_SubMeshObj( theMeshObj ),
772   myGroupServer( SMESH::SMESH_GroupBase::_duplicate(theGroup) )
773 {
774   if ( MYDEBUG ) MESSAGE("SMESH_GroupObj - theGroup->_is_nil() = "<<theGroup->_is_nil());
775   myGroupServer->Register();
776 }
777
778 SMESH_GroupObj::~SMESH_GroupObj()
779 {
780   if ( MYDEBUG ) MESSAGE("~SMESH_GroupObj");
781   myGroupServer->Destroy();
782 }
783
784 //=================================================================================
785 // function : IsNodePrs
786 // purpose  : Return true if node presentation is used
787 //=================================================================================
788 bool SMESH_GroupObj::IsNodePrs() const
789 {
790   return myGroupServer->GetType() == SMESH::NODE;
791 }
792
793 //=================================================================================
794 // function : GetElementType
795 // purpose  : Return type of elements of group
796 //=================================================================================
797 SMDSAbs_ElementType SMESH_GroupObj::GetElementType() const
798 {
799   return SMDSAbs_ElementType(myGroupServer->GetType());
800 }
801
802 //=================================================================================
803 // function : getNodesFromElems
804 // purpose  : Retrieve nodes from elements
805 //=================================================================================
806 static int getNodesFromElems( SMESH::long_array_var&              theElemIds,
807                               const SMDS_Mesh*                    theMesh,
808                               std::list<const SMDS_MeshElement*>& theResList )
809 {
810   set<const SMDS_MeshElement*> aNodeSet;
811
812   for ( CORBA::Long i = 0, n = theElemIds->length(); i < n; i++ )
813   {
814     const SMDS_MeshElement* anElem = theMesh->FindElement( theElemIds[ i ] );
815     if ( anElem != 0 )
816     {
817       SMDS_ElemIteratorPtr anIter = anElem->nodesIterator();
818       while ( anIter->more() )
819       {
820         const SMDS_MeshElement* aNode = anIter->next();
821         if ( aNode != 0 )
822           aNodeSet.insert( aNode );
823       }
824     }
825   }
826
827   set<const SMDS_MeshElement*>::const_iterator anIter;
828   for ( anIter = aNodeSet.begin(); anIter != aNodeSet.end(); ++anIter )
829     theResList.push_back( *anIter );
830
831   return theResList.size();    
832 }
833
834 //=================================================================================
835 // function : getPointers
836 // purpose  : Get std::list<const SMDS_MeshElement*> from list of IDs
837 //=================================================================================
838 static int getPointers( const SMDSAbs_ElementType            theRequestType,
839                         SMESH::long_array_var&              theElemIds,
840                         const SMDS_Mesh*                    theMesh,
841                         std::list<const SMDS_MeshElement*>& theResList )
842 {
843   for ( CORBA::Long i = 0, n = theElemIds->length(); i < n; i++ )
844   {
845     const SMDS_MeshElement* anElem = theRequestType == SMDSAbs_Node
846       ? theMesh->FindNode( theElemIds[ i ] ) : theMesh->FindElement( theElemIds[ i ] );
847
848     if ( anElem != 0 )
849       theResList.push_back( anElem );
850   }
851
852   return theResList.size();
853 }
854
855
856 //=================================================================================
857 // function : GetEntities
858 // purpose  : Get entities of specified type. Return number of entities
859 //=================================================================================
860 int SMESH_GroupObj::GetNbEntities( const SMDSAbs_ElementType theType) const
861 {
862   if(SMDSAbs_ElementType(myGroupServer->GetType()) == theType){
863     return myGroupServer->Size();
864   }
865   return 0;
866 }
867
868 int SMESH_GroupObj::GetEntities( const SMDSAbs_ElementType theType, TEntityList& theResList ) const
869 {
870   theResList.clear();
871   SMDS_Mesh* aMesh = myMeshObj->GetMesh();
872   
873   if ( myGroupServer->Size() == 0 || aMesh == 0 )
874     return 0;
875
876   SMDSAbs_ElementType aGrpType = SMDSAbs_ElementType(myGroupServer->GetType());
877   SMESH::long_array_var anIds = myGroupServer->GetListOfID();
878
879   if ( aGrpType == theType )
880     return getPointers( theType, anIds, aMesh, theResList );
881   else if ( theType == SMDSAbs_Node )
882     return getNodesFromElems( anIds, aMesh, theResList );
883   else
884     return 0;
885 }    
886
887
888
889 /*
890   Class       : SMESH_subMeshObj
891   Description : Class for visualisation of submeshes
892 */
893
894 //=================================================================================
895 // function : SMESH_subMeshObj
896 // purpose  : Constructor
897 //=================================================================================
898 SMESH_subMeshObj::SMESH_subMeshObj( SMESH::SMESH_subMesh_ptr theSubMesh,
899                                     SMESH_MeshObj*           theMeshObj )
900 : SMESH_SubMeshObj( theMeshObj ),
901   mySubMeshServer( SMESH::SMESH_subMesh::_duplicate( theSubMesh ) )
902 {
903   if ( MYDEBUG ) MESSAGE( "SMESH_subMeshObj - theSubMesh->_is_nil() = " << theSubMesh->_is_nil() );
904   
905   mySubMeshServer->Register();
906 }
907
908 SMESH_subMeshObj::~SMESH_subMeshObj()
909 {
910   if ( MYDEBUG ) MESSAGE( "~SMESH_subMeshObj" );
911   mySubMeshServer->Destroy();
912 }
913
914 //=================================================================================
915 // function : GetEntities
916 // purpose  : Get entities of specified type. Return number of entities
917 //=================================================================================
918 int SMESH_subMeshObj::GetNbEntities( const SMDSAbs_ElementType theType) const
919 {
920   switch ( theType )
921   {
922     case SMDSAbs_Node:
923     {
924       return mySubMeshServer->GetNumberOfNodes( false );
925     }
926     break;
927     case SMDSAbs_0DElement:
928     case SMDSAbs_Edge:
929     case SMDSAbs_Face:
930     case SMDSAbs_Volume:
931     {
932       SMESH::long_array_var anIds = 
933         mySubMeshServer->GetElementsByType( SMESH::ElementType(theType) );
934       return anIds->length();
935     }
936     default:
937       return 0;
938     break;
939   }
940 }
941
942 int SMESH_subMeshObj::GetEntities( const SMDSAbs_ElementType theType, TEntityList& theResList ) const
943 {
944   theResList.clear();
945
946   SMDS_Mesh* aMesh = myMeshObj->GetMesh();
947   if ( aMesh == 0 )
948     return 0;
949
950   bool isNodal = IsNodePrs();
951
952   if ( isNodal )
953   {
954     if ( theType == SMDSAbs_Node )
955     {
956       SMESH::long_array_var anIds = mySubMeshServer->GetNodesId();
957       return getPointers( SMDSAbs_Node, anIds, aMesh, theResList );
958     }
959   }
960   else
961   {
962     if ( theType == SMDSAbs_Node )
963     {
964       SMESH::long_array_var anIds = mySubMeshServer->GetElementsId();
965       return getNodesFromElems( anIds, aMesh, theResList );
966     }
967     else
968     {
969       SMESH::long_array_var anIds = 
970         mySubMeshServer->GetElementsByType( SMESH::ElementType(theType) );
971       return getPointers( theType, anIds, aMesh, theResList );
972     }
973   }
974
975   return 0;
976 }
977
978 //=================================================================================
979 // function : IsNodePrs
980 // purpose  : Return true if node presentation is used
981 //=================================================================================
982 bool SMESH_subMeshObj::IsNodePrs() const
983 {
984   return mySubMeshServer->GetNumberOfElements() == 0;
985 }