Salome HOME
6621177cc32ed4f904eacaeaba8602d65d28dce2
[modules/smesh.git] / src / OBJECT / SMESH_Object.cxx
1 //  SMESH OBJECT : interactive object for SMESH visualization
2 //
3 //  Copyright (C) 2003  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.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
21 //
22 //
23 //
24 //  File   : SMESH_Grid.cxx
25 //  Author : Nicolas REJNERI
26 //  Module : SMESH
27
28 #include "SMESH_Object.h"
29 #include "SMDS_Mesh.hxx"
30 #include "SALOME_ExtractUnstructuredGrid.h"
31 #include "SMESH_Actor.h"
32
33 #include CORBA_SERVER_HEADER(SALOME_Exception)
34
35 #include <vtkCell.h>
36 #include <vtkIdList.h>
37 #include <vtkIntArray.h>
38 #include <vtkCellArray.h>
39 #include <vtkUnsignedCharArray.h>
40
41 #include <vtkUnstructuredGrid.h>
42 #include <vtkUnstructuredGridWriter.h>
43 #include <vtkUnstructuredGridReader.h>
44
45 #include <memory>
46 #include <sstream>      
47 #include <stdexcept>
48 #include <set>
49
50 #include "utilities.h"
51
52 using namespace std;
53
54 #ifndef EXCEPTION
55 #define EXCEPTION(TYPE, MSG) {\
56   std::ostringstream aStream;\
57   aStream<<__FILE__<<"["<<__LINE__<<"]::"<<MSG;\
58   throw TYPE(aStream.str());\
59 }
60 #endif
61
62 #ifdef _DEBUG_
63 static int MYDEBUG = 0;
64 static int MYDEBUGWITHFILES = 0;
65 #else
66 static int MYDEBUG = 0;
67 static int MYDEBUGWITHFILES = 0;
68 #endif
69
70
71 void WriteUnstructuredGrid(vtkUnstructuredGrid* theGrid, const char* theFileName){
72   vtkUnstructuredGridWriter* aWriter = vtkUnstructuredGridWriter::New();
73   aWriter->SetFileName(theFileName);
74   aWriter->SetInput(theGrid);
75   if(theGrid->GetNumberOfCells()){
76     aWriter->Write();
77   }
78   aWriter->Delete();
79 }
80
81
82 namespace{
83
84   inline const SMDS_MeshNode* FindNode(const SMDS_Mesh* theMesh, int theId){
85     if(const SMDS_MeshNode* anElem = theMesh->FindNode(theId)) return anElem;
86     EXCEPTION(runtime_error,"SMDS_Mesh::FindNode - cannot find a SMDS_MeshNode for ID = "<<theId);
87   }
88
89
90   inline const SMDS_MeshElement* FindElement(const SMDS_Mesh* theMesh, int theId){
91     if(const SMDS_MeshElement* anElem = theMesh->FindElement(theId)) return anElem;
92     EXCEPTION(runtime_error,"SMDS_Mesh::FindElement - cannot find a SMDS_MeshElement for ID = "<<theId);
93   }
94
95
96   inline void AddNodesWithID(SMDS_Mesh* theMesh, 
97                              SMESH::log_array_var& theSeq,
98                              CORBA::Long theId)
99   {
100     const SMESH::double_array& aCoords = theSeq[theId].coords;
101     const SMESH::long_array& anIndexes = theSeq[theId].indexes;
102     CORBA::Long anElemId = 0, aNbElems = theSeq[theId].number;
103     if(3*aNbElems != aCoords.length())
104       EXCEPTION(runtime_error,"AddNodesWithID - 3*aNbElems != aCoords.length()");
105     for(CORBA::Long aCoordId = 0; anElemId < aNbElems; anElemId++, aCoordId+=3){
106       SMDS_MeshElement* anElem = theMesh->AddNodeWithID(aCoords[aCoordId],
107                                                         aCoords[aCoordId+1],
108                                                         aCoords[aCoordId+2],
109                                                         anIndexes[anElemId]);
110       if(!anElem)
111         EXCEPTION(runtime_error,"SMDS_Mesh::FindElement - cannot AddNodeWithID for ID = "<<anElemId);
112     }
113   }
114
115
116   inline void AddEdgesWithID(SMDS_Mesh* theMesh, 
117                              SMESH::log_array_var& theSeq,
118                              CORBA::Long theId)
119   {
120     const SMESH::double_array& aCoords = theSeq[theId].coords;
121     const SMESH::long_array& anIndexes = theSeq[theId].indexes;
122     CORBA::Long anElemId = 0, aNbElems = theSeq[theId].number;
123     if(3*aNbElems != anIndexes.length())
124       EXCEPTION(runtime_error,"AddEdgeWithID - 3*aNbElems != aCoords.length()");
125     for(CORBA::Long anIndexId = 0; anElemId < aNbElems; anElemId++, anIndexId+=3){
126       SMDS_MeshElement* anElem = theMesh->AddEdgeWithID(anIndexes[anIndexId+1],
127                                                         anIndexes[anIndexId+2],
128                                                         anIndexes[anIndexId]);
129       if(!anElem)
130         EXCEPTION(runtime_error,"SMDS_Mesh::FindElement - cannot AddEdgeWithID for ID = "<<anElemId);
131     }
132   }
133
134
135   inline void AddTriasWithID(SMDS_Mesh* theMesh, 
136                              SMESH::log_array_var& theSeq,
137                              CORBA::Long theId)
138   {
139     const SMESH::double_array& aCoords = theSeq[theId].coords;
140     const SMESH::long_array& anIndexes = theSeq[theId].indexes;
141     CORBA::Long anElemId = 0, aNbElems = theSeq[theId].number;
142     if(4*aNbElems != anIndexes.length())
143       EXCEPTION(runtime_error,"AddEdgeWithID - 4*aNbElems != anIndexes.length()");
144     for(CORBA::Long anIndexId = 0; anElemId < aNbElems; anElemId++, anIndexId+=4){
145       SMDS_MeshElement* anElem = theMesh->AddFaceWithID(anIndexes[anIndexId+1],
146                                                         anIndexes[anIndexId+2],
147                                                         anIndexes[anIndexId+3],
148                                                         anIndexes[anIndexId]);
149       if(!anElem)
150         EXCEPTION(runtime_error,"SMDS_Mesh::FindElement - cannot AddFaceWithID for ID = "<<anElemId);
151     }
152   }
153
154
155   inline void AddQuadsWithID(SMDS_Mesh* theMesh, 
156                              SMESH::log_array_var theSeq,
157                              CORBA::Long theId)
158   {
159     const SMESH::double_array& aCoords = theSeq[theId].coords;
160     const SMESH::long_array& anIndexes = theSeq[theId].indexes;
161     CORBA::Long anElemId = 0, aNbElems = theSeq[theId].number;
162     if(5*aNbElems != anIndexes.length())
163       EXCEPTION(runtime_error,"AddEdgeWithID - 4*aNbElems != anIndexes.length()");
164     for(CORBA::Long anIndexId = 0; anElemId < aNbElems; anElemId++, anIndexId+=5){
165       SMDS_MeshElement* anElem = theMesh->AddFaceWithID(anIndexes[anIndexId+1],
166                                                         anIndexes[anIndexId+2],
167                                                         anIndexes[anIndexId+3],
168                                                         anIndexes[anIndexId+4],
169                                                         anIndexes[anIndexId]);
170       if(!anElem)
171         EXCEPTION(runtime_error,"SMDS_Mesh::FindElement - cannot AddFaceWithID for ID = "<<anElemId);
172     }
173   }
174
175
176   inline void AddTetrasWithID(SMDS_Mesh* theMesh, 
177                               SMESH::log_array_var& theSeq,
178                               CORBA::Long theId)
179   {
180     const SMESH::double_array& aCoords = theSeq[theId].coords;
181     const SMESH::long_array& anIndexes = theSeq[theId].indexes;
182     CORBA::Long anElemId = 0, aNbElems = theSeq[theId].number;
183     if(5*aNbElems != anIndexes.length())
184       EXCEPTION(runtime_error,"AddEdgeWithID - 5*aNbElems != anIndexes.length()");
185     for(CORBA::Long anIndexId = 0; anElemId < aNbElems; anElemId++, anIndexId+=5){
186       SMDS_MeshElement* anElem = theMesh->AddVolumeWithID(anIndexes[anIndexId+1],
187                                                           anIndexes[anIndexId+2],
188                                                           anIndexes[anIndexId+3],
189                                                           anIndexes[anIndexId+4],
190                                                           anIndexes[anIndexId]);
191       if(!anElem)
192         EXCEPTION(runtime_error,"SMDS_Mesh::FindElement - cannot AddFaceWithID for ID = "<<anElemId);
193     }
194   }
195
196
197   inline void AddPiramidsWithID(SMDS_Mesh* theMesh, 
198                                 SMESH::log_array_var& theSeq,
199                                 CORBA::Long theId)
200   {
201     const SMESH::double_array& aCoords = theSeq[theId].coords;
202     const SMESH::long_array& anIndexes = theSeq[theId].indexes;
203     CORBA::Long anElemId = 0, aNbElems = theSeq[theId].number;
204     if(6*aNbElems != anIndexes.length())
205       EXCEPTION(runtime_error,"AddEdgeWithID - 6*aNbElems != anIndexes.length()");
206     for(CORBA::Long anIndexId = 0; anElemId < aNbElems; anElemId++, anIndexId+=6){
207       SMDS_MeshElement* anElem = theMesh->AddVolumeWithID(anIndexes[anIndexId+1],
208                                                           anIndexes[anIndexId+2],
209                                                           anIndexes[anIndexId+3],
210                                                           anIndexes[anIndexId+4],
211                                                           anIndexes[anIndexId+5],
212                                                           anIndexes[anIndexId]);
213       if(!anElem)
214         EXCEPTION(runtime_error,"SMDS_Mesh::FindElement - cannot AddFaceWithID for ID = "<<anElemId);
215     }
216   }
217
218
219   inline void AddPrismsWithID(SMDS_Mesh* theMesh, 
220                               SMESH::log_array_var& theSeq,
221                               CORBA::Long theId)
222   {
223     const SMESH::double_array& aCoords = theSeq[theId].coords;
224     const SMESH::long_array& anIndexes = theSeq[theId].indexes;
225     CORBA::Long anElemId = 0, aNbElems = theSeq[theId].number;
226     if(7*aNbElems != anIndexes.length())
227       EXCEPTION(runtime_error,"AddEdgeWithID - 7*aNbElems != anIndexes.length()");
228     for(CORBA::Long anIndexId = 0; anElemId < aNbElems; anElemId++, anIndexId+=7){
229       SMDS_MeshElement* anElem = theMesh->AddVolumeWithID(anIndexes[anIndexId+1],
230                                                           anIndexes[anIndexId+2],
231                                                           anIndexes[anIndexId+3],
232                                                           anIndexes[anIndexId+4],
233                                                           anIndexes[anIndexId+5],
234                                                           anIndexes[anIndexId+6],
235                                                           anIndexes[anIndexId]);
236       if(!anElem)
237         EXCEPTION(runtime_error,"SMDS_Mesh::FindElement - cannot AddFaceWithID for ID = "<<anElemId);
238     }
239   }
240
241
242   inline void AddHexasWithID(SMDS_Mesh* theMesh, 
243                              SMESH::log_array_var& theSeq,
244                              CORBA::Long theId)
245   {
246     const SMESH::double_array& aCoords = theSeq[theId].coords;
247     const SMESH::long_array& anIndexes = theSeq[theId].indexes;
248     CORBA::Long anElemId = 0, aNbElems = theSeq[theId].number;
249     if(9*aNbElems != anIndexes.length())
250       EXCEPTION(runtime_error,"AddEdgeWithID - 9*aNbElems != anIndexes.length()");
251     for(CORBA::Long anIndexId = 0; anElemId < aNbElems; anElemId++, anIndexId+=9){
252       SMDS_MeshElement* anElem = theMesh->AddVolumeWithID(anIndexes[anIndexId+1],
253                                                           anIndexes[anIndexId+2],
254                                                           anIndexes[anIndexId+3],
255                                                           anIndexes[anIndexId+4],
256                                                           anIndexes[anIndexId+5],
257                                                           anIndexes[anIndexId+6],
258                                                           anIndexes[anIndexId+7],
259                                                           anIndexes[anIndexId+8],
260                                                           anIndexes[anIndexId]);
261       if(!anElem)
262         EXCEPTION(runtime_error,"SMDS_Mesh::FindElement - cannot AddFaceWithID for ID = "<<anElemId);
263     }
264   }
265
266
267 }
268 /*
269   Class       : SMESH_VisualObj
270   Description : Base class for all mesh objects to be visuilised
271 */
272
273 //=================================================================================
274 // function : getCellType
275 // purpose  : Get type of VTK cell
276 //=================================================================================
277 static inline vtkIdType getCellType( const SMESH::ElementType theType,
278                                      const int theNbNodes )
279 {
280   switch( theType )
281   {
282     case SMESH::EDGE: return theNbNodes == 2 ? VTK_LINE : VTK_EMPTY_CELL;
283
284     case SMESH::FACE  : if      ( theNbNodes == 3 ) return VTK_TRIANGLE;
285                         else if ( theNbNodes == 4 ) return VTK_QUAD;
286                         else                        return VTK_EMPTY_CELL;
287
288     case SMESH::VOLUME: if      ( theNbNodes == 4 ) return VTK_TETRA;
289                         else if ( theNbNodes == 5 ) return VTK_PYRAMID;
290                         else if ( theNbNodes == 6 ) return VTK_WEDGE;
291                         else if ( theNbNodes == 8 ) return VTK_HEXAHEDRON;
292                         else                        return VTK_EMPTY_CELL;
293
294     default: return VTK_EMPTY_CELL;
295   }
296 }
297
298 //=================================================================================
299 // functions : SMESH_VisualObj
300 // purpose   : Constructor
301 //=================================================================================
302 SMESH_VisualObj::SMESH_VisualObj()
303 {
304   myGrid = vtkUnstructuredGrid::New();
305 }
306 SMESH_VisualObj::~SMESH_VisualObj()
307 {
308   if ( MYDEBUG )
309     MESSAGE( "~SMESH_MeshObj - myGrid->GetReferenceCount() = " << myGrid->GetReferenceCount() );
310   myGrid->Delete();
311 }
312
313 //=================================================================================
314 // functions : GetNodeObjId, GetNodeVTKId, GetElemObjId, GetElemVTKId
315 // purpose   : Methods for retrieving VTK IDs by SMDS IDs and  vice versa
316 //=================================================================================
317 vtkIdType SMESH_VisualObj::GetNodeObjId( int theVTKID )
318 {
319   return myVTK2SMDSNodes.find(theVTKID) == myVTK2SMDSNodes.end() ? -1 : myVTK2SMDSNodes[theVTKID];
320 }
321
322 vtkIdType SMESH_VisualObj::GetNodeVTKId( int theObjID )
323 {
324   return mySMDS2VTKNodes.find(theObjID) == mySMDS2VTKNodes.end() ? -1 : mySMDS2VTKNodes[theObjID];
325 }
326
327 vtkIdType SMESH_VisualObj::GetElemObjId( int theVTKID )
328 {
329   return myVTK2SMDSElems.find(theVTKID) == myVTK2SMDSElems.end() ? -1 : myVTK2SMDSElems[theVTKID];
330 }
331
332 vtkIdType SMESH_VisualObj::GetElemVTKId( int theObjID )
333 {
334   return mySMDS2VTKElems.find(theObjID) == mySMDS2VTKElems.end() ? -1 : mySMDS2VTKElems[theObjID];
335 }
336
337 //=================================================================================
338 // function : SMESH_VisualObj::createPoints
339 // purpose  : Create points from nodes
340 //=================================================================================
341 void SMESH_VisualObj::createPoints( vtkPoints* thePoints )
342 {
343   if ( thePoints == 0 )
344     return;
345
346   TEntityList aNodes;
347   vtkIdType nbNodes = GetEntities( SMESH::NODE, aNodes );
348   thePoints->SetNumberOfPoints( nbNodes );
349   
350   int nbPoints = 0;
351
352   TEntityList::const_iterator anIter;
353   for ( anIter = aNodes.begin(); anIter != aNodes.end(); ++anIter )
354   {
355     const SMDS_MeshNode* aNode = ( const SMDS_MeshNode* )(*anIter);
356     if ( aNode != 0 )
357     {
358       thePoints->SetPoint( nbPoints, aNode->X(), aNode->Y(), aNode->Z() );
359       int anId = aNode->GetID();
360       mySMDS2VTKNodes.insert( TMapOfIds::value_type( anId, nbPoints ) );
361       myVTK2SMDSNodes.insert( TMapOfIds::value_type( nbPoints, anId ) );
362       nbPoints++;
363     }
364   }
365
366   if ( nbPoints != nbNodes )
367     thePoints->SetNumberOfPoints( nbPoints );
368 }
369
370 //=================================================================================
371 // function : buildPrs
372 // purpose  : create VTK cells( fill unstructured grid )
373 //=================================================================================
374 void SMESH_VisualObj::buildPrs()
375 {
376   try
377   {
378     mySMDS2VTKNodes.clear();
379     myVTK2SMDSNodes.clear();
380     mySMDS2VTKElems.clear();
381     myVTK2SMDSElems.clear();
382     
383     if ( IsNodePrs() )
384       buildNodePrs();
385     else
386       buildElemPrs();
387   }
388   catch( const std::exception& exc )
389   {
390     INFOS("Follow exception was cought:\n\t"<<exc.what());
391   }
392   catch(...)
393   {
394     INFOS("Unknown exception was cought !!!");
395   }
396   
397   if( MYDEBUG ) MESSAGE( "Update - myGrid->GetNumberOfCells() = "<<myGrid->GetNumberOfCells() );
398   if( MYDEBUGWITHFILES ) WriteUnstructuredGrid( myGrid,"/tmp/buildPrs" );
399 }
400
401 //=================================================================================
402 // function : buildNodePrs
403 // purpose  : create VTK cells for nodes
404 //=================================================================================
405 void SMESH_VisualObj::buildNodePrs()
406 {
407   vtkPoints* aPoints = vtkPoints::New();
408   createPoints( aPoints );
409   int nbPoints = aPoints->GetNumberOfPoints();
410   myGrid->SetPoints( aPoints );
411   aPoints->Delete();
412
413   myGrid->SetCells( 0, 0, 0 );
414
415   // Create cells
416   /*
417   vtkIdList *anIdList = vtkIdList::New();
418   anIdList->SetNumberOfIds( 1 );
419
420   vtkCellArray *aCells = vtkCellArray::New();
421   aCells->Allocate( 2 * nbPoints, 0 );
422
423   vtkUnsignedCharArray* aCellTypesArray = vtkUnsignedCharArray::New();
424   aCellTypesArray->SetNumberOfComponents( 1 );
425   aCellTypesArray->Allocate( nbPoints );
426
427   for( vtkIdType aCellId = 0; aCellId < nbPoints; aCellId++ )
428   {
429     anIdList->SetId( 0, aCellId );
430     aCells->InsertNextCell( anIdList );
431     aCellTypesArray->InsertNextValue( VTK_VERTEX );
432   }
433
434   vtkIntArray* aCellLocationsArray = vtkIntArray::New();
435   aCellLocationsArray->SetNumberOfComponents( 1 );
436   aCellLocationsArray->SetNumberOfTuples( nbPoints );
437
438   aCells->InitTraversal();
439   for( vtkIdType i = 0, *pts, npts; aCells->GetNextCell( npts, pts ); i++ )
440     aCellLocationsArray->SetValue( i, aCells->GetTraversalLocation( npts ) );
441
442   myGrid->SetCells( aCellTypesArray, aCellLocationsArray, aCells );
443
444   aCellLocationsArray->Delete();
445   aCellTypesArray->Delete();
446   aCells->Delete();
447   anIdList->Delete(); 
448   */
449 }
450
451 //=================================================================================
452 // function : buildElemPrs
453 // purpose  : Create VTK cells for elements
454 //=================================================================================
455 void SMESH_VisualObj::buildElemPrs()
456 {
457   // Create points
458   
459   vtkPoints* aPoints = vtkPoints::New();
460   createPoints( aPoints );
461   myGrid->SetPoints( aPoints );
462   aPoints->Delete();
463     
464   if ( MYDEBUG )
465     MESSAGE("Update - myGrid->GetNumberOfPoints() = "<<myGrid->GetNumberOfPoints());
466
467   // Calculate cells size
468
469   static SMESH::ElementType aTypes[ 3 ] = { SMESH::EDGE, SMESH::FACE, SMESH::VOLUME };
470
471   // get entity data
472   map< int, int >         nbEnts;
473   map< int, TEntityList > anEnts;
474
475   for ( int i = 0; i <= 2; i++ )
476     nbEnts[ aTypes[ i ] ] = GetEntities( aTypes[ i ], anEnts[ aTypes[ i ] ] );
477
478   vtkIdType aCellsSize =  3 * nbEnts[ SMESH::EDGE ];
479
480   for ( int i = 1; i <= 2; i++ ) // iterate through faces and volumes
481   {
482     if ( nbEnts[ aTypes[ i ] ] )
483     {
484       const TEntityList& aList = anEnts[ aTypes[ i ] ];
485       TEntityList::const_iterator anIter;
486       for ( anIter = aList.begin(); anIter != aList.end(); ++anIter )
487         aCellsSize += (*anIter)->NbNodes() + 1;
488     }
489   }
490
491   vtkIdType aNbCells = nbEnts[ SMESH::EDGE ] + nbEnts[ SMESH::FACE ] + nbEnts[ SMESH::VOLUME ];
492   
493   if ( MYDEBUG )
494     MESSAGE( "Update - aNbCells = "<<aNbCells<<"; aCellsSize = "<<aCellsSize );
495
496   // Create cells
497   
498   vtkCellArray* aConnectivity = vtkCellArray::New();
499   aConnectivity->Allocate( aCellsSize, 0 );
500   
501   vtkUnsignedCharArray* aCellTypesArray = vtkUnsignedCharArray::New();
502   aCellTypesArray->SetNumberOfComponents( 1 );
503   aCellTypesArray->Allocate( aNbCells * aCellTypesArray->GetNumberOfComponents() );
504   
505   vtkIdList *anIdList = vtkIdList::New();
506   vtkIdType iElem = 0;
507   
508   for ( int i = 0; i <= 2; i++ ) // iterate through edges, faces and volumes
509   {
510     if( nbEnts[ aTypes[ i ] ] > 0 )
511     {
512       const TEntityList& aList = anEnts[ aTypes[ i ] ];
513       TEntityList::const_iterator anIter;
514       for ( anIter = aList.begin(); anIter != aList.end(); ++anIter )
515       {
516         const SMDS_MeshElement* anElem = *anIter;
517         
518         vtkIdType aNbNodes = anElem->NbNodes();
519         anIdList->SetNumberOfIds( aNbNodes );
520
521         int anId = anElem->GetID();
522
523         mySMDS2VTKElems.insert( TMapOfIds::value_type( anId, iElem ) );
524         myVTK2SMDSElems.insert( TMapOfIds::value_type( iElem, anId ) );
525
526         SMDS_ElemIteratorPtr aNodesIter = anElem->nodesIterator();
527         for( vtkIdType aNodeId = 0; aNodesIter->more(); aNodeId++ )
528         {
529           const SMDS_MeshElement* aNode = aNodesIter->next();
530           anIdList->SetId( aNodeId, mySMDS2VTKNodes[aNode->GetID()] );
531         }
532
533         aConnectivity->InsertNextCell( anIdList );
534         aCellTypesArray->InsertNextValue( getCellType( aTypes[ i ], aNbNodes ) );
535
536         iElem++;
537       }
538     }
539   }
540
541   // Insert cells in grid
542   
543   vtkIntArray* aCellLocationsArray = vtkIntArray::New();
544   aCellLocationsArray->SetNumberOfComponents( 1 );
545   aCellLocationsArray->SetNumberOfTuples( aNbCells );
546   
547   aConnectivity->InitTraversal();
548   for( vtkIdType idType = 0, *pts, npts; aConnectivity->GetNextCell( npts, pts ); idType++ )
549     aCellLocationsArray->SetValue( idType, aConnectivity->GetTraversalLocation( npts ) );
550
551   myGrid->SetCells( aCellTypesArray, aCellLocationsArray,aConnectivity );
552   
553   aCellLocationsArray->Delete();
554   aCellTypesArray->Delete();
555   aConnectivity->Delete();
556   anIdList->Delete();
557 }
558
559 //=================================================================================
560 // function : GetEdgeNodes
561 // purpose  : Retrieve ids of nodes from edge of elements ( edge is numbered from 1 )
562 //=================================================================================
563 bool SMESH_VisualObj::GetEdgeNodes( const int theElemId,
564                                     const int theEdgeNum,
565                                     int&      theNodeId1,
566                                     int&      theNodeId2 ) const
567 {
568   const SMDS_Mesh* aMesh = GetMesh();
569   if ( aMesh == 0 )
570     return false;
571     
572   const SMDS_MeshElement* anElem = aMesh->FindElement( theElemId );
573   if ( anElem == 0 )
574     return false;
575     
576   int nbNodes = anElem->NbNodes();
577
578   if ( theEdgeNum < 1 || theEdgeNum > 4 || nbNodes != 3 && nbNodes != 4 || theEdgeNum > nbNodes )
579     return false;
580
581   int anIds[ nbNodes ];
582   SMDS_ElemIteratorPtr anIter = anElem->nodesIterator();
583   int i = 0;
584   while( anIter->more() )
585     anIds[ i++ ] = anIter->next()->GetID();
586
587   if ( nbNodes != theEdgeNum )
588   {
589     theNodeId1 = anIds[ theEdgeNum - 1 ];
590     theNodeId2 = anIds[ theEdgeNum ];
591   }
592   else
593   {
594     theNodeId1 = anIds[ nbNodes - 1 ];
595     theNodeId2 = anIds[ 0 ];
596   }
597
598   return true;
599 }
600
601 /*
602   Class       : SMESH_MeshObj
603   Description : Class for visualisation of mesh
604 */
605
606 //=================================================================================
607 // function : SMESH_MeshObj
608 // purpose  : Constructor
609 //=================================================================================
610 SMESH_MeshObj::SMESH_MeshObj(SMESH::SMESH_Mesh_ptr theMesh)
611 {
612   if ( MYDEBUG ) 
613     MESSAGE("SMESH_MeshObj - theMesh->_is_nil() = "<<theMesh->_is_nil());
614     
615   myMeshServer = SMESH::SMESH_Mesh::_duplicate( theMesh );
616   myMeshServer->Register();
617   myMesh = new SMDS_Mesh();
618 }
619
620 //=================================================================================
621 // function : ~SMESH_MeshObj
622 // purpose  : Destructor
623 //=================================================================================
624 SMESH_MeshObj::~SMESH_MeshObj()
625 {
626   myMeshServer->Destroy();
627   delete myMesh;
628 }
629
630 //=================================================================================
631 // function : Update
632 // purpose  : Update mesh and fill grid with new values if necessary 
633 //=================================================================================
634 void SMESH_MeshObj::Update( int theIsClear )
635 {
636   // Update SMDS_Mesh on client part
637   
638   try
639   {
640     SMESH::log_array_var aSeq = myMeshServer->GetLog( theIsClear );
641     CORBA::Long aLength = aSeq->length();
642     
643     if( MYDEBUG ) MESSAGE( "Update: length of the script is "<<aLength );
644     
645     if( !aLength )
646       return;
647       
648     for ( CORBA::Long anId = 0; anId < aLength; anId++)
649     {
650       const SMESH::double_array& aCoords = aSeq[anId].coords;
651       const SMESH::long_array& anIndexes = aSeq[anId].indexes;
652       CORBA::Long anElemId = 0, aNbElems = aSeq[anId].number;
653       SMDS_MeshElement* anElem = NULL;
654       CORBA::Long aCommand = aSeq[anId].commandType;
655       
656       switch(aCommand)
657       {
658         case SMESH::ADD_NODE       : AddNodesWithID   ( myMesh, aSeq, anId ); break;
659         case SMESH::ADD_EDGE       : AddEdgesWithID   ( myMesh, aSeq, anId ); break;
660         case SMESH::ADD_TRIANGLE   : AddTriasWithID   ( myMesh, aSeq, anId ); break;
661         case SMESH::ADD_QUADRANGLE : AddQuadsWithID   ( myMesh, aSeq, anId ); break;
662         case SMESH::ADD_TETRAHEDRON: AddTetrasWithID  ( myMesh, aSeq, anId ); break;
663         case SMESH::ADD_PYRAMID    : AddPiramidsWithID( myMesh, aSeq, anId ); break;
664         case SMESH::ADD_PRISM      : AddPrismsWithID  ( myMesh, aSeq, anId ); break;
665         case SMESH::ADD_HEXAHEDRON : AddHexasWithID   ( myMesh, aSeq, anId ); break;
666         
667         case SMESH::REMOVE_NODE:
668           for( ; anElemId < aNbElems; anElemId++ )
669             myMesh->RemoveNode( FindNode( myMesh, anIndexes[anElemId] ) );
670         break;
671         
672         case SMESH::REMOVE_ELEMENT:
673           for( ; anElemId < aNbElems; anElemId++ )
674             myMesh->RemoveElement( FindElement( myMesh, anIndexes[anElemId] ) );
675         break;
676
677         case SMESH::MOVE_NODE:
678           for(CORBA::Long aCoordId=0; anElemId < aNbElems; anElemId++, aCoordId+=3)
679           {
680             SMDS_MeshNode* node =
681               const_cast<SMDS_MeshNode*>( FindNode( myMesh, anIndexes[anElemId] ));
682             node->setXYZ( aCoords[aCoordId], aCoords[aCoordId+1], aCoords[aCoordId+2] );
683           }
684         break;
685
686         case SMESH::CHANGE_ELEMENT_NODES:
687           for ( CORBA::Long i = 0; anElemId < aNbElems; anElemId++ )
688           {
689             // find element
690             const SMDS_MeshElement* elem = FindElement( myMesh, anIndexes[i++] );
691             // nb nodes
692             int nbNodes = anIndexes[i++];
693             // nodes
694             ASSERT( nbNodes < 9 );
695             const SMDS_MeshNode* aNodes[ 8 ];
696             for ( int iNode = 0; iNode < nbNodes; iNode++ )
697               aNodes[ iNode ] = FindNode( myMesh, anIndexes[i++] );
698             // change
699             myMesh->ChangeElementNodes( elem, aNodes, nbNodes );
700           }
701           break;
702
703         case SMESH::RENUMBER:
704           for(CORBA::Long i=0; anElemId < aNbElems; anElemId++, i+=3)
705           {
706             myMesh->Renumber( anIndexes[i], anIndexes[i+1], anIndexes[i+2] );
707           }
708           break;
709           
710         default:;
711       }
712     }
713   }
714   catch ( SALOME::SALOME_Exception& exc )
715   {
716     INFOS("Following exception was cought:\n\t"<<exc.details.text);
717   }
718   catch( const std::exception& exc)
719   {
720     INFOS("Following exception was cought:\n\t"<<exc.what());
721   }
722   catch(...)
723   {
724     INFOS("Unknown exception was cought !!!");
725   }
726   
727   if ( MYDEBUG )
728   {
729     MESSAGE("Update - myMesh->NbNodes() = "<<myMesh->NbNodes());
730     MESSAGE("Update - myMesh->NbEdges() = "<<myMesh->NbEdges());
731     MESSAGE("Update - myMesh->NbFaces() = "<<myMesh->NbFaces());
732     MESSAGE("Update - myMesh->NbVolumes() = "<<myMesh->NbVolumes());
733   }
734
735   // Fill unstructured grid
736   buildPrs();
737 }
738
739 //=================================================================================
740 // function : GetElemDimension
741 // purpose  : Get dimension of element
742 //=================================================================================
743 int SMESH_MeshObj::GetElemDimension( const int theObjId )
744 {
745   const SMDS_MeshElement* anElem = myMesh->FindElement( theObjId );
746   if ( anElem == 0 )
747     return 0;
748
749   int aType = anElem->GetType();
750   switch ( aType )
751   {
752     case SMDSAbs_Edge  : return 1;
753     case SMDSAbs_Face  : return 2;
754     case SMDSAbs_Volume: return 3;
755     default            : return 0;
756   }
757 }
758
759 //=================================================================================
760 // function : GetEntities
761 // purpose  : Get entities of specified type. Return number of entities
762 //=================================================================================
763 int SMESH_MeshObj::GetNbEntities( const SMESH::ElementType theType) const
764 {
765   switch ( theType )
766   {
767     case SMESH::NODE:
768     {
769       return myMesh->NbNodes();
770     }
771     break;
772     case SMESH::EDGE:
773     {
774       return myMesh->NbEdges();
775     }
776     break;
777     case SMESH::FACE:
778     {
779       return myMesh->NbFaces();
780     }
781     break;
782     case SMESH::VOLUME:
783     {
784       return myMesh->NbVolumes();
785     }
786     break;
787     default:
788       return 0;
789     break;
790   }
791 }
792
793 int SMESH_MeshObj::GetEntities( const SMESH::ElementType theType, TEntityList& theObjs ) const
794 {
795   theObjs.clear();
796
797   switch ( theType )
798   {
799     case SMESH::NODE:
800     {
801       SMDS_NodeIteratorPtr anIter = myMesh->nodesIterator();
802       while ( anIter->more() ) theObjs.push_back( anIter->next() );
803     }
804     break;
805     case SMESH::EDGE:
806     {
807       SMDS_EdgeIteratorPtr anIter = myMesh->edgesIterator();
808       while ( anIter->more() ) theObjs.push_back( anIter->next() );
809     }
810     break;
811     case SMESH::FACE:
812     {
813       SMDS_FaceIteratorPtr anIter = myMesh->facesIterator();
814       while ( anIter->more() ) theObjs.push_back( anIter->next() );
815     }
816     break;
817     case SMESH::VOLUME:
818     {
819       SMDS_VolumeIteratorPtr anIter = myMesh->volumesIterator();
820       while ( anIter->more() ) theObjs.push_back( anIter->next() );
821     }
822     break;
823     default:
824     break;
825   }
826
827   return theObjs.size();
828 }
829
830 //=================================================================================
831 // function : UpdateFunctor
832 // purpose  : Update functor in accordance with current mesh
833 //=================================================================================
834 void SMESH_MeshObj::UpdateFunctor( const SMESH::Controls::FunctorPtr& theFunctor )
835 {
836   theFunctor->SetMesh( GetMesh() );
837 }
838
839 //=================================================================================
840 // function : IsNodePrs
841 // purpose  : Return true if node presentation is used
842 //=================================================================================
843 bool SMESH_MeshObj::IsNodePrs() const
844 {
845   return myMesh->NbEdges() == 0 &&myMesh->NbFaces() == 0 &&myMesh->NbVolumes() == 0 ;
846 }
847
848
849 /*
850   Class       : SMESH_SubMeshObj
851   Description : Base class for visualisation of submeshes and groups
852 */
853
854 //=================================================================================
855 // function : SMESH_SubMeshObj
856 // purpose  : Constructor
857 //=================================================================================
858 SMESH_SubMeshObj::SMESH_SubMeshObj( SMESH_MeshObj* theMeshObj )
859 {
860   if ( MYDEBUG ) MESSAGE( "SMESH_SubMeshObj - theMeshObj = " << theMeshObj );
861   
862   myMeshObj = theMeshObj;
863 }
864
865 SMESH_SubMeshObj::~SMESH_SubMeshObj()
866 {
867 }
868
869 //=================================================================================
870 // function : GetElemDimension
871 // purpose  : Get dimension of element
872 //=================================================================================
873 int SMESH_SubMeshObj::GetElemDimension( const int theObjId )
874 {
875   return myMeshObj == 0 ? 0 : myMeshObj->GetElemDimension( theObjId );
876 }
877
878 //=================================================================================
879 // function : UpdateFunctor
880 // purpose  : Update functor in accordance with current mesh
881 //=================================================================================
882 void SMESH_SubMeshObj::UpdateFunctor( const SMESH::Controls::FunctorPtr& theFunctor )
883 {
884   theFunctor->SetMesh( myMeshObj->GetMesh() );
885 }
886
887 //=================================================================================
888 // function : Update
889 // purpose  : Update mesh object and fill grid with new values 
890 //=================================================================================
891 void SMESH_SubMeshObj::Update( int theIsClear )
892 {
893   myMeshObj->Update( theIsClear );
894   buildPrs();
895 }
896
897
898 /*
899   Class       : SMESH_GroupObj
900   Description : Class for visualisation of groups
901 */
902
903 //=================================================================================
904 // function : SMESH_GroupObj
905 // purpose  : Constructor
906 //=================================================================================
907 SMESH_GroupObj::SMESH_GroupObj( SMESH::SMESH_GroupBase_ptr theGroup, 
908                                 SMESH_MeshObj*             theMeshObj )
909 : SMESH_SubMeshObj( theMeshObj ),
910   myGroupServer( SMESH::SMESH_GroupBase::_duplicate(theGroup) )
911 {
912   if ( MYDEBUG ) MESSAGE("SMESH_GroupObj - theGroup->_is_nil() = "<<theGroup->_is_nil());
913   myGroupServer->Register();
914 }
915
916 SMESH_GroupObj::~SMESH_GroupObj()
917 {
918   if ( MYDEBUG ) MESSAGE("~SMESH_GroupObj");
919   myGroupServer->Destroy();
920 }
921
922 //=================================================================================
923 // function : IsNodePrs
924 // purpose  : Return true if node presentation is used
925 //=================================================================================
926 bool SMESH_GroupObj::IsNodePrs() const
927 {
928   return myGroupServer->GetType() == SMESH::NODE;
929 }
930
931 //=================================================================================
932 // function : getNodesFromElems
933 // purpose  : Retrieve nodes from elements
934 //=================================================================================
935 static int getNodesFromElems( SMESH::long_array_var&              theElemIds,
936                               const SMDS_Mesh*                    theMesh,
937                               std::list<const SMDS_MeshElement*>& theResList )
938 {
939   set<const SMDS_MeshElement*> aNodeSet;
940
941   for ( CORBA::Long i = 0, n = theElemIds->length(); i < n; i++ )
942   {
943     const SMDS_MeshElement* anElem = theMesh->FindElement( theElemIds[ i ] );
944     if ( anElem != 0 )
945     {
946       SMDS_ElemIteratorPtr anIter = anElem->nodesIterator();
947       while ( anIter->more() )
948       {
949         const SMDS_MeshElement* aNode = anIter->next();
950         if ( aNode != 0 )
951           aNodeSet.insert( aNode );
952       }
953     }
954   }
955
956   set<const SMDS_MeshElement*>::const_iterator anIter;
957   for ( anIter = aNodeSet.begin(); anIter != aNodeSet.end(); ++anIter )
958     theResList.push_back( *anIter );
959
960   return theResList.size();    
961 }
962
963 //=================================================================================
964 // function : getPointers
965 // purpose  : Get std::list<const SMDS_MeshElement*> from list of IDs
966 //=================================================================================
967 static int getPointers( const SMESH::ElementType            theRequestType,
968                         SMESH::long_array_var&              theElemIds,
969                         const SMDS_Mesh*                    theMesh,
970                         std::list<const SMDS_MeshElement*>& theResList )
971 {
972   for ( CORBA::Long i = 0, n = theElemIds->length(); i < n; i++ )
973   {
974     const SMDS_MeshElement* anElem = theRequestType == SMESH::NODE
975       ? theMesh->FindNode( theElemIds[ i ] ) : theMesh->FindElement( theElemIds[ i ] );
976
977     if ( anElem != 0 )
978       theResList.push_back( anElem );
979   }
980
981   return theResList.size();
982 }
983
984
985 //=================================================================================
986 // function : GetEntities
987 // purpose  : Get entities of specified type. Return number of entities
988 //=================================================================================
989 int SMESH_GroupObj::GetNbEntities( const SMESH::ElementType theType) const
990 {
991   if(myGroupServer->GetType() == theType){
992     return myGroupServer->Size();
993   }
994   return 0;
995 }
996
997 int SMESH_GroupObj::GetEntities( const SMESH::ElementType theType, TEntityList& theResList ) const
998 {
999   theResList.clear();
1000   SMDS_Mesh* aMesh = myMeshObj->GetMesh();
1001   
1002   if ( myGroupServer->Size() == 0 || aMesh == 0 )
1003     return 0;
1004
1005   SMESH::ElementType aGrpType = myGroupServer->GetType();
1006   SMESH::long_array_var anIds = myGroupServer->GetListOfID();
1007
1008   if ( aGrpType == theType )
1009     return getPointers( theType, anIds, aMesh, theResList );
1010   else if ( theType == SMESH::NODE )
1011     return getNodesFromElems( anIds, aMesh, theResList );
1012   else
1013     return 0;
1014 }    
1015
1016
1017
1018 /*
1019   Class       : SMESH_subMeshObj
1020   Description : Class for visualisation of submeshes
1021 */
1022
1023 //=================================================================================
1024 // function : SMESH_subMeshObj
1025 // purpose  : Constructor
1026 //=================================================================================
1027 SMESH_subMeshObj::SMESH_subMeshObj( SMESH::SMESH_subMesh_ptr theSubMesh,
1028                                     SMESH_MeshObj*           theMeshObj )
1029 : SMESH_SubMeshObj( theMeshObj ),
1030   mySubMeshServer( SMESH::SMESH_subMesh::_duplicate( theSubMesh ) )
1031 {
1032   if ( MYDEBUG ) MESSAGE( "SMESH_subMeshObj - theSubMesh->_is_nil() = " << theSubMesh->_is_nil() );
1033   
1034   mySubMeshServer->Register();
1035 }
1036
1037 SMESH_subMeshObj::~SMESH_subMeshObj()
1038 {
1039   if ( MYDEBUG ) MESSAGE( "~SMESH_subMeshObj" );
1040   mySubMeshServer->Destroy();
1041 }
1042
1043 //=================================================================================
1044 // function : GetEntities
1045 // purpose  : Get entities of specified type. Return number of entities
1046 //=================================================================================
1047 int SMESH_subMeshObj::GetNbEntities( const SMESH::ElementType theType) const
1048 {
1049   switch ( theType )
1050   {
1051     case SMESH::NODE:
1052     {
1053       return mySubMeshServer->GetNumberOfNodes( false );
1054     }
1055     break;
1056     case SMESH::EDGE:
1057     case SMESH::FACE:
1058     case SMESH::VOLUME:
1059     {
1060       SMESH::long_array_var anIds = mySubMeshServer->GetElementsByType( theType );
1061       return anIds->length();
1062     }
1063     default:
1064       return 0;
1065     break;
1066   }
1067 }
1068
1069 int SMESH_subMeshObj::GetEntities( const SMESH::ElementType theType, TEntityList& theResList ) const
1070 {
1071   theResList.clear();
1072
1073   SMDS_Mesh* aMesh = myMeshObj->GetMesh();
1074   if ( aMesh == 0 )
1075     return 0;
1076
1077   bool isNodal = IsNodePrs();
1078
1079   if ( isNodal )
1080   {
1081     if ( theType == SMESH::NODE )
1082     {
1083       SMESH::long_array_var anIds = mySubMeshServer->GetNodesId();
1084       return getPointers( SMESH::NODE, anIds, aMesh, theResList );
1085     }
1086   }
1087   else
1088   {
1089     if ( theType == SMESH::NODE )
1090     {
1091       SMESH::long_array_var anIds = mySubMeshServer->GetElementsId();
1092       return getNodesFromElems( anIds, aMesh, theResList );
1093     }
1094     else
1095     {
1096       SMESH::long_array_var anIds = mySubMeshServer->GetElementsByType( theType );
1097       return getPointers( theType, anIds, aMesh, theResList );
1098     }
1099   }
1100
1101   return 0;
1102 }
1103
1104 //=================================================================================
1105 // function : IsNodePrs
1106 // purpose  : Return true if node presentation is used
1107 //=================================================================================
1108 bool SMESH_subMeshObj::IsNodePrs() const
1109 {
1110   return mySubMeshServer->GetNumberOfElements() == 0;
1111 }
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123