Back to index

salome-smesh  6.5.0
SMESH_Object.cxx
Go to the documentation of this file.
00001 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
00002 //
00003 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
00004 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
00005 //
00006 // This library is free software; you can redistribute it and/or
00007 // modify it under the terms of the GNU Lesser General Public
00008 // License as published by the Free Software Foundation; either
00009 // version 2.1 of the License.
00010 //
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 // Lesser General Public License for more details.
00015 //
00016 // You should have received a copy of the GNU Lesser General Public
00017 // License along with this library; if not, write to the Free Software
00018 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00019 //
00020 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
00021 //
00022 
00023 //  SMESH OBJECT : interactive object for SMESH visualization
00024 //  File   : SMESH_Grid.cxx
00025 //  Author : Nicolas REJNERI
00026 //  Module : SMESH
00027 //
00028 #include "SMESH_ObjectDef.h"
00029 #include "SMESH_ActorUtils.h"
00030 
00031 #include "SMDS_Mesh.hxx"
00032 #include "SMDS_PolyhedralVolumeOfNodes.hxx"
00033 #include "SMESH_Actor.h"
00034 #include "SMESH_ControlsDef.hxx"
00035 #include "SalomeApp_Application.h"
00036 #include "VTKViewer_ExtractUnstructuredGrid.h"
00037 #include "VTKViewer_CellLocationsArray.h"
00038 
00039 #include CORBA_SERVER_HEADER(SMESH_Gen)
00040 #include CORBA_SERVER_HEADER(SALOME_Exception)
00041 
00042 #include <vtkCell.h>
00043 #include <vtkIdList.h>
00044 #include <vtkCellArray.h>
00045 #include <vtkUnsignedCharArray.h>
00046 
00047 #include <vtkUnstructuredGrid.h>
00048 
00049 #include <memory>
00050 #include <sstream>      
00051 #include <stdexcept>
00052 #include <set>
00053 
00054 #include "utilities.h"
00055 
00056 using namespace std;
00057 
00058 #ifndef EXCEPTION
00059 #define EXCEPTION(TYPE, MSG) {\
00060   std::ostringstream aStream;\
00061   aStream<<__FILE__<<"["<<__LINE__<<"]::"<<MSG;\
00062   throw TYPE(aStream.str());\
00063 }
00064 #endif
00065 
00066 #ifdef _DEBUG_
00067 static int MYDEBUG = 1;
00068 static int MYDEBUGWITHFILES = 0;//1;
00069 #else
00070 static int MYDEBUG = 0;
00071 static int MYDEBUGWITHFILES = 0;
00072 #endif
00073 
00074 
00075 /*
00076   Class       : SMESH_VisualObjDef
00077   Description : Base class for all mesh objects to be visuilised
00078 */
00079 
00080 //=================================================================================
00081 // function : getCellType
00082 // purpose  : Get type of VTK cell
00083 //=================================================================================
00084 static inline vtkIdType getCellType( const SMDSAbs_ElementType theType,
00085                                      const bool thePoly,
00086                                      const int theNbNodes )
00087 {
00088   switch( theType )
00089   {
00090     case SMDSAbs_0DElement: 
00091       return VTK_VERTEX;
00092 
00093     case SMDSAbs_Edge: 
00094       if( theNbNodes == 2 )         return VTK_LINE;
00095       else if ( theNbNodes == 3 )   return VTK_QUADRATIC_EDGE;
00096       else return VTK_EMPTY_CELL;
00097 
00098     case SMDSAbs_Face  :
00099       if (thePoly && theNbNodes>2 ) return VTK_POLYGON;
00100       else if ( theNbNodes == 3 )   return VTK_TRIANGLE;
00101       else if ( theNbNodes == 4 )   return VTK_QUAD;
00102       else if ( theNbNodes == 6 )   return VTK_QUADRATIC_TRIANGLE;
00103       else if ( theNbNodes == 8 )   return VTK_QUADRATIC_QUAD;
00104       else if ( theNbNodes == 9 )   return VTK_BIQUADRATIC_QUAD;
00105       else return VTK_EMPTY_CELL;
00106       
00107     case SMDSAbs_Volume:
00108       if (thePoly && theNbNodes>3 ) return VTK_POLYHEDRON; //VTK_CONVEX_POINT_SET;
00109       else if ( theNbNodes == 4 )   return VTK_TETRA;
00110       else if ( theNbNodes == 5 )   return VTK_PYRAMID;
00111       else if ( theNbNodes == 6 )   return VTK_WEDGE;
00112       else if ( theNbNodes == 8 )   return VTK_HEXAHEDRON;
00113       else if ( theNbNodes == 12 )  return VTK_HEXAGONAL_PRISM;
00114       else if ( theNbNodes == 10 )  return VTK_QUADRATIC_TETRA;
00115       else if ( theNbNodes == 20 )  return VTK_QUADRATIC_HEXAHEDRON;
00116       else if ( theNbNodes == 27 )  return VTK_TRIQUADRATIC_HEXAHEDRON;
00117       else if ( theNbNodes == 15 )  return VTK_QUADRATIC_WEDGE;
00118       else if ( theNbNodes == 13 )  return VTK_QUADRATIC_PYRAMID; //VTK_CONVEX_POINT_SET;
00119       else return VTK_EMPTY_CELL;
00120 
00121     default: return VTK_EMPTY_CELL;
00122   }
00123 }
00124 
00125 //=================================================================================
00126 // functions : SMESH_VisualObjDef
00127 // purpose   : Constructor
00128 //=================================================================================
00129 SMESH_VisualObjDef::SMESH_VisualObjDef()
00130 {
00131   MESSAGE("---------------------------------------------SMESH_VisualObjDef::SMESH_VisualObjDef");
00132   myGrid = vtkUnstructuredGrid::New();
00133   myLocalGrid = false;
00134   ClearEntitiesFlags();
00135   SMESH::GetEntitiesFromObject(NULL);
00136 }
00137 SMESH_VisualObjDef::~SMESH_VisualObjDef()
00138 {
00139   MESSAGE("---------------------------------------------SMESH_VisualObjDef::~SMESH_VisualObjDef");
00140   //if ( MYDEBUG )
00141     MESSAGE( "~SMESH_MeshObj - myGrid->GetReferenceCount() = " << myGrid->GetReferenceCount() );
00142   myGrid->Delete();
00143 }
00144 
00145 //=================================================================================
00146 // functions : GetNodeObjId, GetNodeVTKId, GetElemObjId, GetElemVTKId
00147 // purpose   : Methods for retrieving VTK IDs by SMDS IDs and  vice versa
00148 //=================================================================================
00149 vtkIdType SMESH_VisualObjDef::GetNodeObjId( int theVTKID )
00150 {
00151         if (myLocalGrid)
00152         {
00153                 TMapOfIds::const_iterator i = myVTK2SMDSNodes.find(theVTKID);
00154                 return i == myVTK2SMDSNodes.end() ? -1 : i->second;
00155         }
00156   return this->GetMesh()->FindNodeVtk(theVTKID)->GetID();
00157 }
00158 
00159 vtkIdType SMESH_VisualObjDef::GetNodeVTKId( int theObjID )
00160 {
00161         if (myLocalGrid)
00162         {
00163                 TMapOfIds::const_iterator i = mySMDS2VTKNodes.find(theObjID);
00164     return i == mySMDS2VTKNodes.end() ? -1 : i->second;
00165         }
00166 
00167         const SMDS_MeshNode* aNode = 0;
00168         if( this->GetMesh() ) {
00169           aNode = this->GetMesh()->FindNode(theObjID);
00170         }
00171         return aNode ? aNode->getVtkId() : -1;
00172 }
00173 
00174 vtkIdType SMESH_VisualObjDef::GetElemObjId( int theVTKID )
00175 {
00176         if (myLocalGrid)
00177         {
00178                 TMapOfIds::const_iterator i = myVTK2SMDSElems.find(theVTKID);
00179                 return i == myVTK2SMDSElems.end() ? -1 : i->second;
00180         }
00181   return this->GetMesh()->fromVtkToSmds(theVTKID);
00182 }
00183 
00184 vtkIdType SMESH_VisualObjDef::GetElemVTKId( int theObjID )
00185 {
00186         if (myLocalGrid)
00187         {
00188                 TMapOfIds::const_iterator i = mySMDS2VTKElems.find(theObjID);
00189                 return i == mySMDS2VTKElems.end() ? -1 : i->second;
00190         }
00191   return this->GetMesh()->FindElement(theObjID)->getVtkId();
00192   //return this->GetMesh()->fromSmdsToVtk(theObjID);
00193 }
00194 
00195 //=================================================================================
00196 // function : SMESH_VisualObjDef::createPoints
00197 // purpose  : Create points from nodes
00198 //=================================================================================
00203 void SMESH_VisualObjDef::createPoints( vtkPoints* thePoints )
00204 {
00205   if ( thePoints == 0 )
00206     return;
00207 
00208   TEntityList aNodes;
00209   vtkIdType nbNodes = GetEntities( SMDSAbs_Node, aNodes );
00210   thePoints->SetNumberOfPoints( nbNodes );
00211 
00212   int nbPoints = 0;
00213 
00214   TEntityList::const_iterator anIter;
00215   for ( anIter = aNodes.begin(); anIter != aNodes.end(); ++anIter )
00216   {
00217     const SMDS_MeshNode* aNode = ( const SMDS_MeshNode* )(*anIter);
00218     if ( aNode != 0 )
00219     {
00220       thePoints->SetPoint( nbPoints, aNode->X(), aNode->Y(), aNode->Z() );
00221       int anId = aNode->GetID();
00222       mySMDS2VTKNodes.insert( TMapOfIds::value_type( anId, nbPoints ) );
00223       myVTK2SMDSNodes.insert( TMapOfIds::value_type( nbPoints, anId ) );
00224       nbPoints++;
00225     }
00226   }
00227 
00228   if ( nbPoints != nbNodes )
00229     thePoints->SetNumberOfPoints( nbPoints );
00230 }
00231 
00232 //=================================================================================
00233 // function : buildPrs
00234 // purpose  : create VTK cells( fill unstructured grid )
00235 //=================================================================================
00236 void SMESH_VisualObjDef::buildPrs(bool buildGrid)
00237 {
00238   MESSAGE("----------------------------------------------------------SMESH_VisualObjDef::buildPrs " << buildGrid);
00239   if (buildGrid)
00240   {
00241         myLocalGrid = true;
00242         try
00243         {
00244                 mySMDS2VTKNodes.clear();
00245                 myVTK2SMDSNodes.clear();
00246                 mySMDS2VTKElems.clear();
00247                 myVTK2SMDSElems.clear();
00248 
00249                 if ( IsNodePrs() )
00250                         buildNodePrs();
00251                 else
00252                         buildElemPrs();
00253         }
00254         catch(...)
00255         {
00256                 mySMDS2VTKNodes.clear();
00257                 myVTK2SMDSNodes.clear();
00258                 mySMDS2VTKElems.clear();
00259                 myVTK2SMDSElems.clear();
00260 
00261                 myGrid->SetPoints( 0 );
00262                 myGrid->SetCells( 0, 0, 0, 0, 0 );
00263                 throw;
00264         }
00265   }
00266   else
00267   {
00268         myLocalGrid = false;
00269         if (!GetMesh()->isCompacted())
00270           {
00271             MESSAGE("*** buildPrs ==> compactMesh!");
00272             GetMesh()->compactMesh();
00273           }
00274         vtkUnstructuredGrid *theGrid = GetMesh()->getGrid();
00275         updateEntitiesFlags();
00276         myGrid->ShallowCopy(theGrid);
00277         //MESSAGE(myGrid->GetReferenceCount());
00278         //MESSAGE( "Update - myGrid->GetNumberOfCells() = "<<myGrid->GetNumberOfCells() );
00279         //MESSAGE( "Update - myGrid->GetNumberOfPoints() = "<<myGrid->GetNumberOfPoints() );
00280         if( MYDEBUGWITHFILES ) SMESH::WriteUnstructuredGrid( myGrid,"buildPrs.vtu" );
00281   }
00282 }
00283 
00284 //=================================================================================
00285 // function : buildNodePrs
00286 // purpose  : create VTK cells for nodes
00287 //=================================================================================
00288 
00289 void SMESH_VisualObjDef::buildNodePrs()
00290 {
00291   // PAL16631: without swap, bad_alloc is not thrown but hung up and crash instead,
00292   // so check remaining memory size for safety
00293   SMDS_Mesh::CheckMemory(); // PAL16631
00294   vtkPoints* aPoints = vtkPoints::New();
00295   createPoints( aPoints );
00296   SMDS_Mesh::CheckMemory();
00297   myGrid->SetPoints( aPoints );
00298   aPoints->Delete();
00299 
00300   myGrid->SetCells( 0, 0, 0, 0, 0 );
00301 }
00302 
00303 //=================================================================================
00304 // function : buildElemPrs
00305 // purpose  : Create VTK cells for elements
00306 //=================================================================================
00307 
00308 namespace{
00309   typedef std::vector<const SMDS_MeshElement*> TConnect;
00310 
00311   int GetConnect(const SMDS_ElemIteratorPtr& theNodesIter, 
00312                  TConnect& theConnect)
00313   {
00314     theConnect.clear();
00315     for(; theNodesIter->more();)
00316       theConnect.push_back(theNodesIter->next());
00317     return theConnect.size();
00318   }
00319   
00320   inline 
00321   void SetId(vtkIdList *theIdList, 
00322              const SMESH_VisualObjDef::TMapOfIds& theSMDS2VTKNodes, 
00323              const TConnect& theConnect, 
00324              int thePosition,
00325              int theId)
00326   {
00327     theIdList->SetId(thePosition,theSMDS2VTKNodes.find(theConnect[theId]->GetID())->second);
00328   }
00329 
00330 }
00331 
00332 
00333 void SMESH_VisualObjDef::buildElemPrs()
00334 {
00335   // Create points
00336 
00337   vtkPoints* aPoints = vtkPoints::New();
00338   createPoints( aPoints );
00339   myGrid->SetPoints( aPoints );
00340   aPoints->Delete();
00341 
00342   if ( MYDEBUG )
00343     MESSAGE("Update - myGrid->GetNumberOfPoints() = "<<myGrid->GetNumberOfPoints());
00344 
00345   // Calculate cells size
00346 
00347   static SMDSAbs_ElementType aTypes[ 4 ] =
00348     { SMDSAbs_0DElement, SMDSAbs_Edge, SMDSAbs_Face, SMDSAbs_Volume };
00349 
00350   // get entity data
00351   map<SMDSAbs_ElementType,int> nbEnts;
00352   map<SMDSAbs_ElementType,TEntityList> anEnts;
00353 
00354   for ( int i = 0; i <= 3; i++ )
00355     nbEnts[ aTypes[ i ] ] = GetEntities( aTypes[ i ], anEnts[ aTypes[ i ] ] );
00356 
00357   // PAL16631: without swap, bad_alloc is not thrown but hung up and crash instead,
00358   // so check remaining memory size for safety
00359   SMDS_Mesh::CheckMemory(); // PAL16631
00360 
00361   vtkIdType aCellsSize =  2 * nbEnts[ SMDSAbs_0DElement ] + 3 * nbEnts[ SMDSAbs_Edge ];
00362 
00363   for ( int i = 2; i <= 3; i++ ) // iterate through faces and volumes
00364   {
00365     if ( nbEnts[ aTypes[ i ] ] )
00366     {
00367       const TEntityList& aList = anEnts[ aTypes[ i ] ];
00368       TEntityList::const_iterator anIter;
00369       for ( anIter = aList.begin(); anIter != aList.end(); ++anIter ) {
00370         if((*anIter)->GetEntityType() != SMDSEntity_Polyhedra &&
00371            (*anIter)->GetEntityType() != SMDSEntity_Quad_Polyhedra) {
00372           aCellsSize += (*anIter)->NbNodes() + 1;
00373         } 
00374         // Special case for the VTK_POLYHEDRON:
00375         // itsinput cellArray is of special format.
00376         //  [nCellFaces, nFace0Pts, i, j, k, nFace1Pts, i, j, k, ...]   
00377         else {
00378           if( const SMDS_VtkVolume* ph = dynamic_cast<const SMDS_VtkVolume*>(*anIter) ) {
00379             int nbFaces = ph->NbFaces();
00380             aCellsSize += (1 + ph->NbFaces());
00381             for( int i = 1; i <= nbFaces; i++ ) {
00382               aCellsSize += ph->NbFaceNodes(i);
00383             }
00384           }
00385         }
00386       }
00387     }
00388   }
00389   
00390   vtkIdType aNbCells = nbEnts[ SMDSAbs_0DElement ] + nbEnts[ SMDSAbs_Edge ] +
00391                        nbEnts[ SMDSAbs_Face ] + nbEnts[ SMDSAbs_Volume ];
00392 
00393   if ( MYDEBUG )
00394     MESSAGE( "Update - aNbCells = "<<aNbCells<<"; aCellsSize = "<<aCellsSize );
00395 
00396   // Create cells
00397 
00398   vtkCellArray* aConnectivity = vtkCellArray::New();
00399   aConnectivity->Allocate( aCellsSize, 0 );
00400 
00401   SMDS_Mesh::CheckMemory(); // PAL16631
00402 
00403   vtkUnsignedCharArray* aCellTypesArray = vtkUnsignedCharArray::New();
00404   aCellTypesArray->SetNumberOfComponents( 1 );
00405   aCellTypesArray->Allocate( aNbCells * aCellTypesArray->GetNumberOfComponents() );
00406 
00407   SMDS_Mesh::CheckMemory(); // PAL16631
00408 
00409   vtkIdList *anIdList = vtkIdList::New();
00410   vtkIdType iElem = 0;
00411 
00412   TConnect aConnect;
00413   aConnect.reserve(VTK_CELL_SIZE);
00414 
00415   SMDS_Mesh::CheckMemory(); // PAL16631
00416 
00417   for ( int i = 0; i <= 3; i++ ) // iterate through 0d elements, edges, faces and volumes
00418   {
00419     if ( nbEnts[ aTypes[ i ] ] > 0 ) {
00420       
00421       const SMDSAbs_ElementType& aType = aTypes[ i ];
00422       const TEntityList& aList = anEnts[ aType ];
00423       TEntityList::const_iterator anIter;
00424       for ( anIter = aList.begin(); anIter != aList.end(); ++anIter )
00425       {
00426         const SMDS_MeshElement* anElem = *anIter;
00427         
00428         vtkIdType aNbNodes = anElem->NbNodes();
00429         anIdList->SetNumberOfIds( aNbNodes );
00430         const vtkIdType vtkElemType = getCellType( aType, anElem->IsPoly(), aNbNodes );
00431         
00432         int anId = anElem->GetID();
00433         
00434         mySMDS2VTKElems.insert( TMapOfIds::value_type( anId, iElem ) );
00435         myVTK2SMDSElems.insert( TMapOfIds::value_type( iElem, anId ) );
00436         
00437         SMDS_ElemIteratorPtr aNodesIter = anElem->nodesIterator();
00438         {
00439           // Convertions connectivities from SMDS to VTK
00440 
00441           if (aType == SMDSAbs_Volume && anElem->IsPoly() && aNbNodes > 3) { // POLYEDRE
00442             anIdList->Reset();
00443             if ( const SMDS_VtkVolume* ph = dynamic_cast<const SMDS_VtkVolume*>(anElem) ) {
00444               int nbFaces = ph->NbFaces();
00445               anIdList->InsertNextId(nbFaces);
00446               for( int i = 1; i <= nbFaces; i++ ) {
00447                 anIdList->InsertNextId(ph->NbFaceNodes(i));
00448                 for(int j = 1; j <= ph->NbFaceNodes(i); j++) {
00449                   const SMDS_MeshNode* n = ph->GetFaceNode(i,j);
00450                   if(n) {
00451                     anIdList->InsertNextId(mySMDS2VTKNodes[n->GetID()]);
00452                   }
00453                 }
00454               }
00455             }
00456           }
00457           else {
00458             const std::vector<int>& aConnectivities =
00459               SMDS_MeshCell::toVtkOrder( VTKCellType( vtkElemType ));
00460             if (aConnectivities.size() > 0) {
00461               aConnect.clear();
00462               GetConnect(aNodesIter,aConnect);
00463               for (vtkIdType aNodeId = 0; aNodeId < aNbNodes; aNodeId++)
00464                 SetId(anIdList,mySMDS2VTKNodes,aConnect,aNodeId,aConnectivities[aNodeId]);
00465             }
00466             else {
00467               for( vtkIdType aNodeId = 0; aNodesIter->more(); aNodeId++ ){
00468                 const SMDS_MeshElement* aNode = aNodesIter->next();
00469                 anIdList->SetId( aNodeId, mySMDS2VTKNodes[aNode->GetID()] );
00470               }
00471             }
00472           }
00473         }
00474         aConnectivity->InsertNextCell( anIdList );
00475         aCellTypesArray->InsertNextValue( vtkElemType );
00476 
00477         iElem++;
00478       }
00479     }
00480     SMDS_Mesh::CheckMemory(); // PAL16631
00481   }
00482 
00483   // Insert cells in grid
00484 
00485   VTKViewer_CellLocationsArray* aCellLocationsArray = VTKViewer_CellLocationsArray::New();
00486   aCellLocationsArray->SetNumberOfComponents( 1 );
00487   aCellLocationsArray->SetNumberOfTuples( aNbCells );
00488 
00489   SMDS_Mesh::CheckMemory(); // PAL16631
00490 
00491   aConnectivity->InitTraversal();
00492   for( vtkIdType idType = 0, *pts, npts; aConnectivity->GetNextCell( npts, pts ); idType++ )
00493     aCellLocationsArray->SetValue( idType, aConnectivity->GetTraversalLocation( npts ) );
00494 
00495   myGrid->SetCells( aCellTypesArray, aCellLocationsArray,aConnectivity );
00496 
00497   aCellLocationsArray->Delete();
00498   aCellTypesArray->Delete();
00499   aConnectivity->Delete();
00500   anIdList->Delete();
00501 
00502   SMDS_Mesh::CheckMemory(); // PAL16631
00503 }
00504 
00505 //=================================================================================
00506 // function : GetEdgeNodes
00507 // purpose  : Retrieve ids of nodes from edge of elements ( edge is numbered from 1 )
00508 //=================================================================================
00509 bool SMESH_VisualObjDef::GetEdgeNodes( const int theElemId,
00510                                        const int theEdgeNum,
00511                                        int&      theNodeId1,
00512                                        int&      theNodeId2 ) const
00513 {
00514   const SMDS_Mesh* aMesh = GetMesh();
00515   if ( aMesh == 0 )
00516     return false;
00517     
00518   const SMDS_MeshElement* anElem = aMesh->FindElement( theElemId );
00519   if ( anElem == 0 )
00520     return false;
00521     
00522   int nbNodes = anElem->NbNodes();
00523 
00524   if ( theEdgeNum < 0 || theEdgeNum > 3 || (nbNodes != 3 && nbNodes != 4) || theEdgeNum > nbNodes )
00525     return false;
00526 
00527   vector<int> anIds( nbNodes );
00528   SMDS_ElemIteratorPtr anIter = anElem->nodesIterator();
00529   int i = 0;
00530   while( anIter->more() )
00531     anIds[ i++ ] = anIter->next()->GetID();
00532 
00533   if ( theEdgeNum < nbNodes - 1 )
00534   {
00535     theNodeId1 = anIds[ theEdgeNum ];
00536     theNodeId2 = anIds[ theEdgeNum + 1 ];
00537   }
00538   else
00539   {
00540     theNodeId1 = anIds[ nbNodes - 1 ];
00541     theNodeId2 = anIds[ 0 ];
00542   }
00543 
00544   return true;
00545 }
00546 
00547 vtkUnstructuredGrid* SMESH_VisualObjDef::GetUnstructuredGrid()
00548 {
00549   if ( !myLocalGrid && !GetMesh()->isCompacted() )
00550   {
00551     GetMesh()->compactMesh();
00552         updateEntitiesFlags();
00553     vtkUnstructuredGrid *theGrid = GetMesh()->getGrid();
00554     myGrid->ShallowCopy(theGrid);
00555   }
00556   return myGrid;
00557 }
00558 
00559 
00560 //=================================================================================
00561 // function : IsValid
00562 // purpose  : Return true if there are some entities
00563 //=================================================================================
00564 bool SMESH_VisualObjDef::IsValid() const
00565 {
00566         //MESSAGE("SMESH_VisualObjDef::IsValid");
00567   return GetNbEntities(SMDSAbs_Node) > 0      || 
00568          GetNbEntities(SMDSAbs_0DElement) > 0 || 
00569          GetNbEntities(SMDSAbs_Edge) > 0      || 
00570          GetNbEntities(SMDSAbs_Face) > 0      ||
00571          GetNbEntities(SMDSAbs_Volume) > 0 ;
00572 }
00573 
00574 //=================================================================================
00575 // function : updateEntitiesFlags
00576 // purpose  : Update entities flags
00577 //=================================================================================
00578 void SMESH_VisualObjDef::updateEntitiesFlags() {
00579 
00580         unsigned int tmp = myEntitiesState;
00581         ClearEntitiesFlags();
00582 
00583         map<SMDSAbs_ElementType,int> entities = SMESH::GetEntitiesFromObject(this);
00584         
00585 
00586         if( myEntitiesCache[SMDSAbs_0DElement] != 0 ||  myEntitiesCache[SMDSAbs_0DElement] >= entities[SMDSAbs_0DElement] )
00587                 myEntitiesState &= ~SMESH_Actor::e0DElements;
00588 
00589         if( myEntitiesCache[SMDSAbs_Edge] != 0 || myEntitiesCache[SMDSAbs_Edge] >= entities[SMDSAbs_Edge] )
00590                 myEntitiesState &= ~SMESH_Actor::eEdges; 
00591 
00592         if( myEntitiesCache[SMDSAbs_Face] != 0 || myEntitiesCache[SMDSAbs_Face] >= entities[SMDSAbs_Face] )
00593                 myEntitiesState &= ~SMESH_Actor::eFaces; 
00594 
00595         if( myEntitiesCache[SMDSAbs_Volume] != 0 || myEntitiesCache[SMDSAbs_Volume] >= entities[SMDSAbs_Volume] )
00596                 myEntitiesState &= ~SMESH_Actor::eVolumes;
00597 
00598         if( tmp != myEntitiesState ) {
00599                 myEntitiesFlag = true;
00600         }
00601         
00602         myEntitiesCache = entities;
00603 }
00604 
00605 //=================================================================================
00606 // function : ClearEntitiesFlags
00607 // purpose  : Clear the entities flags
00608 //=================================================================================
00609 void SMESH_VisualObjDef::ClearEntitiesFlags() {
00610         myEntitiesState = SMESH_Actor::eAllEntity;
00611         myEntitiesFlag = false;
00612 }
00613 
00614 //=================================================================================
00615 // function : GetEntitiesFlag
00616 // purpose  : Return the entities flag
00617 //=================================================================================
00618 bool SMESH_VisualObjDef::GetEntitiesFlag() {
00619         return myEntitiesFlag;
00620 }
00621 
00622 //=================================================================================
00623 // function : GetEntitiesState
00624 // purpose  : Return the entities state
00625 //=================================================================================
00626 unsigned int SMESH_VisualObjDef::GetEntitiesState() {
00627         return myEntitiesState;
00628 }
00629 
00630 /*
00631   Class       : SMESH_MeshObj
00632   Description : Class for visualisation of mesh
00633 */
00634 
00635 //=================================================================================
00636 // function : SMESH_MeshObj
00637 // purpose  : Constructor
00638 //=================================================================================
00639 SMESH_MeshObj::SMESH_MeshObj(SMESH::SMESH_Mesh_ptr theMesh):
00640   myClient(SalomeApp_Application::orb(),theMesh)
00641 {
00642         myEmptyGrid = 0;
00643   if ( MYDEBUG ) 
00644     MESSAGE("SMESH_MeshObj - this = "<<this<<"; theMesh->_is_nil() = "<<theMesh->_is_nil());
00645 }
00646 
00647 //=================================================================================
00648 // function : ~SMESH_MeshObj
00649 // purpose  : Destructor
00650 //=================================================================================
00651 SMESH_MeshObj::~SMESH_MeshObj()
00652 {
00653   if ( MYDEBUG ) 
00654     MESSAGE("SMESH_MeshObj - this = "<<this<<"\n");
00655 }
00656 
00657 //=================================================================================
00658 // function : Update
00659 // purpose  : Update mesh and fill grid with new values if necessary 
00660 //=================================================================================
00661 bool SMESH_MeshObj::Update( int theIsClear )
00662 {
00663   // Update SMDS_Mesh on client part
00664   MESSAGE("SMESH_MeshObj::Update " << this);
00665   if ( myClient.Update(theIsClear) || GetUnstructuredGrid()->GetNumberOfPoints()==0) {
00666     MESSAGE("buildPrs");
00667     buildPrs();  // Fill unstructured grid
00668     return true;
00669   }
00670   return false;
00671 }
00672 
00673 bool SMESH_MeshObj::NulData()
00674 {
00675         MESSAGE ("SMESH_MeshObj::NulData() ==================================================================================");
00676         if (!myEmptyGrid)
00677         {
00678           myEmptyGrid = SMDS_UnstructuredGrid::New();
00679           myEmptyGrid->Initialize();
00680           myEmptyGrid->Allocate();
00681           vtkPoints* points = vtkPoints::New();
00682           points->SetNumberOfPoints(0);
00683           myEmptyGrid->SetPoints( points );
00684           points->Delete();
00685           myEmptyGrid->BuildLinks();
00686         }
00687         myGrid->ShallowCopy(myEmptyGrid);
00688         return true;
00689 }
00690 //=================================================================================
00691 // function : GetElemDimension
00692 // purpose  : Get dimension of element
00693 //=================================================================================
00694 int SMESH_MeshObj::GetElemDimension( const int theObjId )
00695 {
00696   const SMDS_MeshElement* anElem = myClient->FindElement( theObjId );
00697   if ( anElem == 0 )
00698     return 0;
00699 
00700   int aType = anElem->GetType();
00701   switch ( aType )
00702   {
00703     case SMDSAbs_0DElement : return 0;
00704     case SMDSAbs_Edge  : return 1;
00705     case SMDSAbs_Face  : return 2;
00706     case SMDSAbs_Volume: return 3;
00707     default            : return 0;
00708   }
00709 }
00710 
00711 //=================================================================================
00712 // function : GetEntities
00713 // purpose  : Get entities of specified type. Return number of entities
00714 //=================================================================================
00715 int SMESH_MeshObj::GetNbEntities( const SMDSAbs_ElementType theType) const
00716 {
00717   switch ( theType )
00718   {
00719     case SMDSAbs_Node:
00720     {
00721       return myClient->NbNodes();
00722     }
00723     break;
00724     case SMDSAbs_0DElement:
00725     {
00726       return myClient->Nb0DElements();
00727     }
00728     break;
00729     case SMDSAbs_Edge:
00730     {
00731       return myClient->NbEdges();
00732     }
00733     break;
00734     case SMDSAbs_Face:
00735     {
00736       return myClient->NbFaces();
00737     }
00738     break;
00739     case SMDSAbs_Volume:
00740     {
00741       return myClient->NbVolumes();
00742     }
00743     break;
00744     default:
00745       return 0;
00746     break;
00747   }
00748 }
00749 
00750 int SMESH_MeshObj::GetEntities( const SMDSAbs_ElementType theType, TEntityList& theObjs ) const
00751 {
00752   theObjs.clear();
00753 
00754   switch ( theType )
00755   {
00756     case SMDSAbs_Node:
00757     {
00758       SMDS_NodeIteratorPtr anIter = myClient->nodesIterator();
00759       while ( anIter->more() ) theObjs.push_back( anIter->next() );
00760     }
00761     break;
00762     case SMDSAbs_0DElement:
00763     {
00764       SMDS_0DElementIteratorPtr anIter = myClient->elements0dIterator();
00765       while ( anIter->more() ) theObjs.push_back( anIter->next() );
00766     }
00767     break;
00768     case SMDSAbs_Edge:
00769     {
00770       SMDS_EdgeIteratorPtr anIter = myClient->edgesIterator();
00771       while ( anIter->more() ) theObjs.push_back( anIter->next() );
00772     }
00773     break;
00774     case SMDSAbs_Face:
00775     {
00776       SMDS_FaceIteratorPtr anIter = myClient->facesIterator();
00777       while ( anIter->more() ) theObjs.push_back( anIter->next() );
00778     }
00779     break;
00780     case SMDSAbs_Volume:
00781     {
00782       SMDS_VolumeIteratorPtr anIter = myClient->volumesIterator();
00783       while ( anIter->more() ) theObjs.push_back( anIter->next() );
00784     }
00785     break;
00786     default:
00787     break;
00788   }
00789 
00790   return theObjs.size();
00791 }
00792 
00793 //=================================================================================
00794 // function : UpdateFunctor
00795 // purpose  : Update functor in accordance with current mesh
00796 //=================================================================================
00797 void SMESH_MeshObj::UpdateFunctor( const SMESH::Controls::FunctorPtr& theFunctor )
00798 {
00799   theFunctor->SetMesh( GetMesh() );
00800 }
00801 
00802 //=================================================================================
00803 // function : IsNodePrs
00804 // purpose  : Return true if node presentation is used
00805 //=================================================================================
00806 bool SMESH_MeshObj::IsNodePrs() const
00807 {
00808   return myClient->Nb0DElements() == 0 && myClient->NbEdges() == 0 && myClient->NbFaces() == 0 && myClient->NbVolumes() == 0 ;
00809 }
00810 
00811 
00812 /*
00813   Class       : SMESH_SubMeshObj
00814   Description : Base class for visualisation of submeshes and groups
00815 */
00816 
00817 //=================================================================================
00818 // function : SMESH_SubMeshObj
00819 // purpose  : Constructor
00820 //=================================================================================
00821 SMESH_SubMeshObj::SMESH_SubMeshObj( SMESH_MeshObj* theMeshObj )
00822 {
00823   if ( MYDEBUG ) MESSAGE( "SMESH_SubMeshObj - theMeshObj = " << theMeshObj );
00824   
00825   myMeshObj = theMeshObj;
00826 }
00827 
00828 SMESH_SubMeshObj::~SMESH_SubMeshObj()
00829 {
00830 }
00831 
00832 //=================================================================================
00833 // function : GetElemDimension
00834 // purpose  : Get dimension of element
00835 //=================================================================================
00836 int SMESH_SubMeshObj::GetElemDimension( const int theObjId )
00837 {
00838   return myMeshObj == 0 ? 0 : myMeshObj->GetElemDimension( theObjId );
00839 }
00840 
00841 //=================================================================================
00842 // function : UpdateFunctor
00843 // purpose  : Update functor in accordance with current mesh
00844 //=================================================================================
00845 
00846 void SMESH_SubMeshObj::UpdateFunctor( const SMESH::Controls::FunctorPtr& theFunctor )
00847 {
00848   theFunctor->SetMesh( myMeshObj->GetMesh() );
00849 }
00850 
00851 //=================================================================================
00852 // function : Update
00853 // purpose  : Update mesh object and fill grid with new values 
00854 //=================================================================================
00855 bool SMESH_SubMeshObj::Update( int theIsClear )
00856 {
00857   MESSAGE("SMESH_SubMeshObj::Update " << this)
00858   bool changed = myMeshObj->Update( theIsClear );
00859   buildPrs(true);
00860   return changed;
00861 }
00862 
00863 
00864 /*
00865   Class       : SMESH_GroupObj
00866   Description : Class for visualisation of groups
00867 */
00868 
00869 //=================================================================================
00870 // function : SMESH_GroupObj
00871 // purpose  : Constructor
00872 //=================================================================================
00873 SMESH_GroupObj::SMESH_GroupObj( SMESH::SMESH_GroupBase_ptr theGroup, 
00874                                 SMESH_MeshObj*             theMeshObj )
00875 : SMESH_SubMeshObj( theMeshObj ),
00876   myGroupServer( SMESH::SMESH_GroupBase::_duplicate(theGroup) )
00877 {
00878   if ( MYDEBUG ) MESSAGE("SMESH_GroupObj - theGroup->_is_nil() = "<<theGroup->_is_nil());
00879   myGroupServer->Register();
00880 }
00881 
00882 SMESH_GroupObj::~SMESH_GroupObj()
00883 {
00884   if ( MYDEBUG ) MESSAGE("~SMESH_GroupObj");
00885   myGroupServer->UnRegister();
00886 }
00887 
00888 //=================================================================================
00889 // function : IsNodePrs
00890 // purpose  : Return true if node presentation is used
00891 //=================================================================================
00892 bool SMESH_GroupObj::IsNodePrs() const
00893 {
00894   return myGroupServer->GetType() == SMESH::NODE;
00895 }
00896 
00897 //=================================================================================
00898 // function : GetElementType
00899 // purpose  : Return type of elements of group
00900 //=================================================================================
00901 SMDSAbs_ElementType SMESH_GroupObj::GetElementType() const
00902 {
00903   return SMDSAbs_ElementType(myGroupServer->GetType());
00904 }
00905 
00906 //=================================================================================
00907 // function : getNodesFromElems
00908 // purpose  : Retrieve nodes from elements
00909 //=================================================================================
00910 static int getNodesFromElems( SMESH::long_array_var&              theElemIds,
00911                               const SMDS_Mesh*                    theMesh,
00912                               std::list<const SMDS_MeshElement*>& theResList )
00913 {
00914   set<const SMDS_MeshElement*> aNodeSet;
00915 
00916   for ( CORBA::Long i = 0, n = theElemIds->length(); i < n; i++ )
00917   {
00918     const SMDS_MeshElement* anElem = theMesh->FindElement( theElemIds[ i ] );
00919     if ( anElem != 0 )
00920     {
00921       SMDS_ElemIteratorPtr anIter = anElem->nodesIterator();
00922       while ( anIter->more() )
00923       {
00924         const SMDS_MeshElement* aNode = anIter->next();
00925         if ( aNode != 0 )
00926           aNodeSet.insert( aNode );
00927       }
00928     }
00929   }
00930 
00931   set<const SMDS_MeshElement*>::const_iterator anIter;
00932   for ( anIter = aNodeSet.begin(); anIter != aNodeSet.end(); ++anIter )
00933     theResList.push_back( *anIter );
00934 
00935   return theResList.size();    
00936 }
00937 
00938 //=================================================================================
00939 // function : getPointers
00940 // purpose  : Get std::list<const SMDS_MeshElement*> from list of IDs
00941 //=================================================================================
00942 static int getPointers( const SMDSAbs_ElementType            theRequestType,
00943                         SMESH::long_array_var&              theElemIds,
00944                         const SMDS_Mesh*                    theMesh,
00945                         std::list<const SMDS_MeshElement*>& theResList )
00946 {
00947   for ( CORBA::Long i = 0, n = theElemIds->length(); i < n; i++ )
00948   {
00949     const SMDS_MeshElement* anElem = theRequestType == SMDSAbs_Node
00950       ? theMesh->FindNode( theElemIds[ i ] ) : theMesh->FindElement( theElemIds[ i ] );
00951 
00952     if ( anElem != 0 )
00953       theResList.push_back( anElem );
00954   }
00955 
00956   return theResList.size();
00957 }
00958 
00959 
00960 //=================================================================================
00961 // function : GetEntities
00962 // purpose  : Get entities of specified type. Return number of entities
00963 //=================================================================================
00964 int SMESH_GroupObj::GetNbEntities( const SMDSAbs_ElementType theType) const
00965 {
00966   if(SMDSAbs_ElementType(myGroupServer->GetType()) == theType) {
00967     return myGroupServer->Size();
00968   }
00969   if ( theType == SMDSAbs_Node ) {
00970     return myGroupServer->GetNumberOfNodes();
00971   }
00972   return 0;
00973 }
00974 
00975 int SMESH_GroupObj::GetEntities( const SMDSAbs_ElementType theType, TEntityList& theResList ) const
00976 {
00977   theResList.clear();
00978   SMDS_Mesh* aMesh = myMeshObj->GetMesh();
00979   
00980   if ( myGroupServer->Size() == 0 || aMesh == 0 )
00981     return 0;
00982 
00983   SMDSAbs_ElementType aGrpType = SMDSAbs_ElementType(myGroupServer->GetType());
00984   SMESH::long_array_var anIds = myGroupServer->GetListOfID();
00985 
00986   if ( aGrpType == theType )
00987     return getPointers( theType, anIds, aMesh, theResList );
00988   else if ( theType == SMDSAbs_Node )
00989     return getNodesFromElems( anIds, aMesh, theResList );
00990   else
00991     return 0;
00992 }    
00993 
00994 
00995 
00996 /*
00997   Class       : SMESH_subMeshObj
00998   Description : Class for visualisation of submeshes
00999 */
01000 
01001 //=================================================================================
01002 // function : SMESH_subMeshObj
01003 // purpose  : Constructor
01004 //=================================================================================
01005 SMESH_subMeshObj::SMESH_subMeshObj( SMESH::SMESH_subMesh_ptr theSubMesh,
01006                                     SMESH_MeshObj*           theMeshObj )
01007 : SMESH_SubMeshObj( theMeshObj ),
01008   mySubMeshServer( SMESH::SMESH_subMesh::_duplicate( theSubMesh ) )
01009 {
01010   if ( MYDEBUG ) MESSAGE( "SMESH_subMeshObj - theSubMesh->_is_nil() = " << theSubMesh->_is_nil() );
01011   
01012   mySubMeshServer->Register();
01013 }
01014 
01015 SMESH_subMeshObj::~SMESH_subMeshObj()
01016 {
01017   if ( MYDEBUG ) MESSAGE( "~SMESH_subMeshObj" );
01018   mySubMeshServer->UnRegister();
01019 }
01020 
01021 //=================================================================================
01022 // function : GetEntities
01023 // purpose  : Get entities of specified type. Return number of entities
01024 //=================================================================================
01025 int SMESH_subMeshObj::GetNbEntities( const SMDSAbs_ElementType theType) const
01026 {
01027   switch ( theType )
01028   {
01029     case SMDSAbs_Node:
01030     {
01031       return mySubMeshServer->GetNumberOfNodes( /*all=*/true );
01032     }
01033     break;
01034     case SMDSAbs_0DElement:
01035     case SMDSAbs_Edge:
01036     case SMDSAbs_Face:
01037     case SMDSAbs_Volume:
01038     {
01039       SMESH::long_array_var anIds = 
01040         mySubMeshServer->GetElementsByType( SMESH::ElementType(theType) );
01041       return anIds->length();
01042     }
01043     default:
01044       return 0;
01045     break;
01046   }
01047 }
01048 
01049 int SMESH_subMeshObj::GetEntities( const SMDSAbs_ElementType theType, TEntityList& theResList ) const
01050 {
01051   theResList.clear();
01052 
01053   SMDS_Mesh* aMesh = myMeshObj->GetMesh();
01054   if ( aMesh == 0 )
01055     return 0;
01056 
01057   bool isNodal = IsNodePrs();
01058 
01059   if ( isNodal )
01060   {
01061     if ( theType == SMDSAbs_Node )
01062     {
01063       SMESH::long_array_var anIds = mySubMeshServer->GetNodesId();
01064       return getPointers( SMDSAbs_Node, anIds, aMesh, theResList );
01065     }
01066   }
01067   else
01068   {
01069     if ( theType == SMDSAbs_Node )
01070     {
01071       SMESH::long_array_var anIds = mySubMeshServer->GetElementsId();
01072       return getNodesFromElems( anIds, aMesh, theResList );
01073     }
01074     else
01075     {
01076       SMESH::long_array_var anIds = 
01077         mySubMeshServer->GetElementsByType( SMESH::ElementType(theType) );
01078       return getPointers( theType, anIds, aMesh, theResList );
01079     }
01080   }
01081 
01082   return 0;
01083 }
01084 
01085 //=================================================================================
01086 // function : IsNodePrs
01087 // purpose  : Return true if node presentation is used
01088 //=================================================================================
01089 bool SMESH_subMeshObj::IsNodePrs() const
01090 {
01091   return mySubMeshServer->GetNumberOfElements() == 0;
01092 }