Salome HOME
PR: debug SMDS memimp
[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 vtkUnstructuredGrid* SMESH_VisualObjDef::GetUnstructuredGrid()
536 {
537         MESSAGE("SMESH_VisualObjDef::GetUnstructuredGrid " << myGrid);
538         return myGrid;
539 }
540
541
542 //=================================================================================
543 // function : IsValid
544 // purpose  : Return true if there are some entities
545 //=================================================================================
546 bool SMESH_VisualObjDef::IsValid() const
547 {
548         MESSAGE("SMESH_VisualObjDef::IsValid");
549   return GetNbEntities(SMDSAbs_Node) > 0      || 
550          GetNbEntities(SMDSAbs_0DElement) > 0 || 
551          GetNbEntities(SMDSAbs_Edge) > 0      || 
552          GetNbEntities(SMDSAbs_Face) > 0      ||
553          GetNbEntities(SMDSAbs_Volume) > 0 ;
554 }
555
556 /*
557   Class       : SMESH_MeshObj
558   Description : Class for visualisation of mesh
559 */
560
561 //=================================================================================
562 // function : SMESH_MeshObj
563 // purpose  : Constructor
564 //=================================================================================
565 SMESH_MeshObj::SMESH_MeshObj(SMESH::SMESH_Mesh_ptr theMesh):
566   myClient(SalomeApp_Application::orb(),theMesh)
567 {
568         myEmptyGrid = 0;
569   if ( MYDEBUG ) 
570     MESSAGE("SMESH_MeshObj - this = "<<this<<"; theMesh->_is_nil() = "<<theMesh->_is_nil());
571 }
572
573 //=================================================================================
574 // function : ~SMESH_MeshObj
575 // purpose  : Destructor
576 //=================================================================================
577 SMESH_MeshObj::~SMESH_MeshObj()
578 {
579   if ( MYDEBUG ) 
580     MESSAGE("SMESH_MeshObj - this = "<<this<<"\n");
581 }
582
583 //=================================================================================
584 // function : Update
585 // purpose  : Update mesh and fill grid with new values if necessary 
586 //=================================================================================
587 bool SMESH_MeshObj::Update( int theIsClear )
588 {
589   // Update SMDS_Mesh on client part
590         MESSAGE("SMESH_MeshObj::Update");
591   if ( myClient.Update(theIsClear) || GetUnstructuredGrid()->GetNumberOfPoints()==0) {
592     buildPrs();  // Fill unstructured grid
593     return true;
594   }
595   return false;
596 }
597
598 bool SMESH_MeshObj::NulData()
599 {
600         MESSAGE ("SMESH_MeshObj::NulData() ==================================================================================");
601         if (!myEmptyGrid)
602         {
603           myEmptyGrid = SMDS_UnstructuredGrid::New();
604           myEmptyGrid->Initialize();
605           myEmptyGrid->Allocate();
606           vtkPoints* points = vtkPoints::New();
607           points->SetNumberOfPoints(0);
608           myEmptyGrid->SetPoints( points );
609           points->Delete();
610           myEmptyGrid->BuildLinks();
611         }
612         myGrid->ShallowCopy(myEmptyGrid);
613 }
614 //=================================================================================
615 // function : GetElemDimension
616 // purpose  : Get dimension of element
617 //=================================================================================
618 int SMESH_MeshObj::GetElemDimension( const int theObjId )
619 {
620   const SMDS_MeshElement* anElem = myClient->FindElement( theObjId );
621   if ( anElem == 0 )
622     return 0;
623
624   int aType = anElem->GetType();
625   switch ( aType )
626   {
627     case SMDSAbs_0DElement : return 0;
628     case SMDSAbs_Edge  : return 1;
629     case SMDSAbs_Face  : return 2;
630     case SMDSAbs_Volume: return 3;
631     default            : return 0;
632   }
633 }
634
635 //=================================================================================
636 // function : GetEntities
637 // purpose  : Get entities of specified type. Return number of entities
638 //=================================================================================
639 int SMESH_MeshObj::GetNbEntities( const SMDSAbs_ElementType theType) const
640 {
641   switch ( theType )
642   {
643     case SMDSAbs_Node:
644     {
645       return myClient->NbNodes();
646     }
647     break;
648     case SMDSAbs_0DElement:
649     {
650       return myClient->Nb0DElements();
651     }
652     break;
653     case SMDSAbs_Edge:
654     {
655       return myClient->NbEdges();
656     }
657     break;
658     case SMDSAbs_Face:
659     {
660       return myClient->NbFaces();
661     }
662     break;
663     case SMDSAbs_Volume:
664     {
665       return myClient->NbVolumes();
666     }
667     break;
668     default:
669       return 0;
670     break;
671   }
672 }
673
674 int SMESH_MeshObj::GetEntities( const SMDSAbs_ElementType theType, TEntityList& theObjs ) const
675 {
676   theObjs.clear();
677
678   switch ( theType )
679   {
680     case SMDSAbs_Node:
681     {
682       SMDS_NodeIteratorPtr anIter = myClient->nodesIterator();
683       while ( anIter->more() ) theObjs.push_back( anIter->next() );
684     }
685     break;
686     case SMDSAbs_0DElement:
687     {
688       SMDS_0DElementIteratorPtr anIter = myClient->elements0dIterator();
689       while ( anIter->more() ) theObjs.push_back( anIter->next() );
690     }
691     break;
692     case SMDSAbs_Edge:
693     {
694       SMDS_EdgeIteratorPtr anIter = myClient->edgesIterator();
695       while ( anIter->more() ) theObjs.push_back( anIter->next() );
696     }
697     break;
698     case SMDSAbs_Face:
699     {
700       SMDS_FaceIteratorPtr anIter = myClient->facesIterator();
701       while ( anIter->more() ) theObjs.push_back( anIter->next() );
702     }
703     break;
704     case SMDSAbs_Volume:
705     {
706       SMDS_VolumeIteratorPtr anIter = myClient->volumesIterator();
707       while ( anIter->more() ) theObjs.push_back( anIter->next() );
708     }
709     break;
710     default:
711     break;
712   }
713
714   return theObjs.size();
715 }
716
717 //=================================================================================
718 // function : UpdateFunctor
719 // purpose  : Update functor in accordance with current mesh
720 //=================================================================================
721 void SMESH_MeshObj::UpdateFunctor( const SMESH::Controls::FunctorPtr& theFunctor )
722 {
723   theFunctor->SetMesh( GetMesh() );
724 }
725
726 //=================================================================================
727 // function : IsNodePrs
728 // purpose  : Return true if node presentation is used
729 //=================================================================================
730 bool SMESH_MeshObj::IsNodePrs() const
731 {
732   return myClient->Nb0DElements() == 0 && myClient->NbEdges() == 0 && myClient->NbFaces() == 0 && myClient->NbVolumes() == 0 ;
733 }
734
735
736 /*
737   Class       : SMESH_SubMeshObj
738   Description : Base class for visualisation of submeshes and groups
739 */
740
741 //=================================================================================
742 // function : SMESH_SubMeshObj
743 // purpose  : Constructor
744 //=================================================================================
745 SMESH_SubMeshObj::SMESH_SubMeshObj( SMESH_MeshObj* theMeshObj )
746 {
747   if ( MYDEBUG ) MESSAGE( "SMESH_SubMeshObj - theMeshObj = " << theMeshObj );
748   
749   myMeshObj = theMeshObj;
750 }
751
752 SMESH_SubMeshObj::~SMESH_SubMeshObj()
753 {
754 }
755
756 //=================================================================================
757 // function : GetElemDimension
758 // purpose  : Get dimension of element
759 //=================================================================================
760 int SMESH_SubMeshObj::GetElemDimension( const int theObjId )
761 {
762   return myMeshObj == 0 ? 0 : myMeshObj->GetElemDimension( theObjId );
763 }
764
765 //=================================================================================
766 // function : UpdateFunctor
767 // purpose  : Update functor in accordance with current mesh
768 //=================================================================================
769 void SMESH_SubMeshObj::UpdateFunctor( const SMESH::Controls::FunctorPtr& theFunctor )
770 {
771   theFunctor->SetMesh( myMeshObj->GetMesh() );
772 }
773
774 //=================================================================================
775 // function : Update
776 // purpose  : Update mesh object and fill grid with new values 
777 //=================================================================================
778 bool SMESH_SubMeshObj::Update( int theIsClear )
779 {
780   bool changed = myMeshObj->Update( theIsClear );
781   buildPrs();
782   return changed;
783 }
784
785
786 /*
787   Class       : SMESH_GroupObj
788   Description : Class for visualisation of groups
789 */
790
791 //=================================================================================
792 // function : SMESH_GroupObj
793 // purpose  : Constructor
794 //=================================================================================
795 SMESH_GroupObj::SMESH_GroupObj( SMESH::SMESH_GroupBase_ptr theGroup, 
796                                 SMESH_MeshObj*             theMeshObj )
797 : SMESH_SubMeshObj( theMeshObj ),
798   myGroupServer( SMESH::SMESH_GroupBase::_duplicate(theGroup) )
799 {
800   if ( MYDEBUG ) MESSAGE("SMESH_GroupObj - theGroup->_is_nil() = "<<theGroup->_is_nil());
801   myGroupServer->Register();
802 }
803
804 SMESH_GroupObj::~SMESH_GroupObj()
805 {
806   if ( MYDEBUG ) MESSAGE("~SMESH_GroupObj");
807   myGroupServer->Destroy();
808 }
809
810 //=================================================================================
811 // function : IsNodePrs
812 // purpose  : Return true if node presentation is used
813 //=================================================================================
814 bool SMESH_GroupObj::IsNodePrs() const
815 {
816   return myGroupServer->GetType() == SMESH::NODE;
817 }
818
819 //=================================================================================
820 // function : GetElementType
821 // purpose  : Return type of elements of group
822 //=================================================================================
823 SMDSAbs_ElementType SMESH_GroupObj::GetElementType() const
824 {
825   return SMDSAbs_ElementType(myGroupServer->GetType());
826 }
827
828 //=================================================================================
829 // function : getNodesFromElems
830 // purpose  : Retrieve nodes from elements
831 //=================================================================================
832 static int getNodesFromElems( SMESH::long_array_var&              theElemIds,
833                               const SMDS_Mesh*                    theMesh,
834                               std::list<const SMDS_MeshElement*>& theResList )
835 {
836   set<const SMDS_MeshElement*> aNodeSet;
837
838   for ( CORBA::Long i = 0, n = theElemIds->length(); i < n; i++ )
839   {
840     const SMDS_MeshElement* anElem = theMesh->FindElement( theElemIds[ i ] );
841     if ( anElem != 0 )
842     {
843       SMDS_ElemIteratorPtr anIter = anElem->nodesIterator();
844       while ( anIter->more() )
845       {
846         const SMDS_MeshElement* aNode = anIter->next();
847         if ( aNode != 0 )
848           aNodeSet.insert( aNode );
849       }
850     }
851   }
852
853   set<const SMDS_MeshElement*>::const_iterator anIter;
854   for ( anIter = aNodeSet.begin(); anIter != aNodeSet.end(); ++anIter )
855     theResList.push_back( *anIter );
856
857   return theResList.size();    
858 }
859
860 //=================================================================================
861 // function : getPointers
862 // purpose  : Get std::list<const SMDS_MeshElement*> from list of IDs
863 //=================================================================================
864 static int getPointers( const SMDSAbs_ElementType            theRequestType,
865                         SMESH::long_array_var&              theElemIds,
866                         const SMDS_Mesh*                    theMesh,
867                         std::list<const SMDS_MeshElement*>& theResList )
868 {
869   for ( CORBA::Long i = 0, n = theElemIds->length(); i < n; i++ )
870   {
871     const SMDS_MeshElement* anElem = theRequestType == SMDSAbs_Node
872       ? theMesh->FindNode( theElemIds[ i ] ) : theMesh->FindElement( theElemIds[ i ] );
873
874     if ( anElem != 0 )
875       theResList.push_back( anElem );
876   }
877
878   return theResList.size();
879 }
880
881
882 //=================================================================================
883 // function : GetEntities
884 // purpose  : Get entities of specified type. Return number of entities
885 //=================================================================================
886 int SMESH_GroupObj::GetNbEntities( const SMDSAbs_ElementType theType) const
887 {
888   if(SMDSAbs_ElementType(myGroupServer->GetType()) == theType){
889     return myGroupServer->Size();
890   }
891   return 0;
892 }
893
894 int SMESH_GroupObj::GetEntities( const SMDSAbs_ElementType theType, TEntityList& theResList ) const
895 {
896   theResList.clear();
897   SMDS_Mesh* aMesh = myMeshObj->GetMesh();
898   
899   if ( myGroupServer->Size() == 0 || aMesh == 0 )
900     return 0;
901
902   SMDSAbs_ElementType aGrpType = SMDSAbs_ElementType(myGroupServer->GetType());
903   SMESH::long_array_var anIds = myGroupServer->GetListOfID();
904
905   if ( aGrpType == theType )
906     return getPointers( theType, anIds, aMesh, theResList );
907   else if ( theType == SMDSAbs_Node )
908     return getNodesFromElems( anIds, aMesh, theResList );
909   else
910     return 0;
911 }    
912
913
914
915 /*
916   Class       : SMESH_subMeshObj
917   Description : Class for visualisation of submeshes
918 */
919
920 //=================================================================================
921 // function : SMESH_subMeshObj
922 // purpose  : Constructor
923 //=================================================================================
924 SMESH_subMeshObj::SMESH_subMeshObj( SMESH::SMESH_subMesh_ptr theSubMesh,
925                                     SMESH_MeshObj*           theMeshObj )
926 : SMESH_SubMeshObj( theMeshObj ),
927   mySubMeshServer( SMESH::SMESH_subMesh::_duplicate( theSubMesh ) )
928 {
929   if ( MYDEBUG ) MESSAGE( "SMESH_subMeshObj - theSubMesh->_is_nil() = " << theSubMesh->_is_nil() );
930   
931   mySubMeshServer->Register();
932 }
933
934 SMESH_subMeshObj::~SMESH_subMeshObj()
935 {
936   if ( MYDEBUG ) MESSAGE( "~SMESH_subMeshObj" );
937   mySubMeshServer->Destroy();
938 }
939
940 //=================================================================================
941 // function : GetEntities
942 // purpose  : Get entities of specified type. Return number of entities
943 //=================================================================================
944 int SMESH_subMeshObj::GetNbEntities( const SMDSAbs_ElementType theType) const
945 {
946   switch ( theType )
947   {
948     case SMDSAbs_Node:
949     {
950       return mySubMeshServer->GetNumberOfNodes( false );
951     }
952     break;
953     case SMDSAbs_0DElement:
954     case SMDSAbs_Edge:
955     case SMDSAbs_Face:
956     case SMDSAbs_Volume:
957     {
958       SMESH::long_array_var anIds = 
959         mySubMeshServer->GetElementsByType( SMESH::ElementType(theType) );
960       return anIds->length();
961     }
962     default:
963       return 0;
964     break;
965   }
966 }
967
968 int SMESH_subMeshObj::GetEntities( const SMDSAbs_ElementType theType, TEntityList& theResList ) const
969 {
970   theResList.clear();
971
972   SMDS_Mesh* aMesh = myMeshObj->GetMesh();
973   if ( aMesh == 0 )
974     return 0;
975
976   bool isNodal = IsNodePrs();
977
978   if ( isNodal )
979   {
980     if ( theType == SMDSAbs_Node )
981     {
982       SMESH::long_array_var anIds = mySubMeshServer->GetNodesId();
983       return getPointers( SMDSAbs_Node, anIds, aMesh, theResList );
984     }
985   }
986   else
987   {
988     if ( theType == SMDSAbs_Node )
989     {
990       SMESH::long_array_var anIds = mySubMeshServer->GetElementsId();
991       return getNodesFromElems( anIds, aMesh, theResList );
992     }
993     else
994     {
995       SMESH::long_array_var anIds = 
996         mySubMeshServer->GetElementsByType( SMESH::ElementType(theType) );
997       return getPointers( theType, anIds, aMesh, theResList );
998     }
999   }
1000
1001   return 0;
1002 }
1003
1004 //=================================================================================
1005 // function : IsNodePrs
1006 // purpose  : Return true if node presentation is used
1007 //=================================================================================
1008 bool SMESH_subMeshObj::IsNodePrs() const
1009 {
1010   return mySubMeshServer->GetNumberOfElements() == 0;
1011 }