1 // SMESH OBJECT : interactive object for SMESH visualization
3 // Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
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.
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.
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
20 // See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org
24 // File : SMESH_Grid.cxx
25 // Author : Nicolas REJNERI
28 #include "SMESH_ObjectDef.h"
29 #include "SMESH_ActorUtils.h"
31 #include "SMDS_Mesh.hxx"
32 #include "SMESH_Actor.h"
33 #include "SMESH_ControlsDef.hxx"
34 #include <VTKViewer_ExtractUnstructuredGrid.h>
36 #include CORBA_SERVER_HEADER(SALOME_Exception)
39 #include <vtkIdList.h>
40 #include <vtkIntArray.h>
41 #include <vtkCellArray.h>
42 #include <vtkUnsignedCharArray.h>
44 #include <vtkUnstructuredGrid.h>
51 #include "utilities.h"
56 #define EXCEPTION(TYPE, MSG) {\
57 std::ostringstream aStream;\
58 aStream<<__FILE__<<"["<<__LINE__<<"]::"<<MSG;\
59 throw TYPE(aStream.str());\
64 static int MYDEBUG = 0;
65 static int MYDEBUGWITHFILES = 0;
67 static int MYDEBUG = 0;
68 static int MYDEBUGWITHFILES = 0;
74 inline const SMDS_MeshNode* FindNode(const SMDS_Mesh* theMesh, int theId){
75 if(const SMDS_MeshNode* anElem = theMesh->FindNode(theId)) return anElem;
76 EXCEPTION(runtime_error,"SMDS_Mesh::FindNode - cannot find a SMDS_MeshNode for ID = "<<theId);
80 inline const SMDS_MeshElement* FindElement(const SMDS_Mesh* theMesh, int theId){
81 if(const SMDS_MeshElement* anElem = theMesh->FindElement(theId)) return anElem;
82 EXCEPTION(runtime_error,"SMDS_Mesh::FindElement - cannot find a SMDS_MeshElement for ID = "<<theId);
86 inline void AddNodesWithID(SMDS_Mesh* theMesh,
87 SMESH::log_array_var& theSeq,
90 const SMESH::double_array& aCoords = theSeq[theId].coords;
91 const SMESH::long_array& anIndexes = theSeq[theId].indexes;
92 CORBA::Long anElemId = 0, aNbElems = theSeq[theId].number;
93 if(3*aNbElems != aCoords.length())
94 EXCEPTION(runtime_error,"AddNodesWithID - 3*aNbElems != aCoords.length()");
95 for(CORBA::Long aCoordId = 0; anElemId < aNbElems; anElemId++, aCoordId+=3){
96 SMDS_MeshElement* anElem = theMesh->AddNodeWithID(aCoords[aCoordId],
101 EXCEPTION(runtime_error,"SMDS_Mesh::FindElement - cannot AddNodeWithID for ID = "<<anElemId);
106 inline void AddEdgesWithID(SMDS_Mesh* theMesh,
107 SMESH::log_array_var& theSeq,
110 const SMESH::long_array& anIndexes = theSeq[theId].indexes;
111 CORBA::Long anElemId = 0, aNbElems = theSeq[theId].number;
112 if(3*aNbElems != anIndexes.length())
113 EXCEPTION(runtime_error,"AddEdgeWithID - 3*aNbElems != aCoords.length()");
114 for(CORBA::Long anIndexId = 0; anElemId < aNbElems; anElemId++, anIndexId+=3){
115 SMDS_MeshElement* anElem = theMesh->AddEdgeWithID(anIndexes[anIndexId+1],
116 anIndexes[anIndexId+2],
117 anIndexes[anIndexId]);
119 EXCEPTION(runtime_error,"SMDS_Mesh::FindElement - cannot AddEdgeWithID for ID = "<<anElemId);
124 inline void AddTriasWithID(SMDS_Mesh* theMesh,
125 SMESH::log_array_var& theSeq,
128 const SMESH::long_array& anIndexes = theSeq[theId].indexes;
129 CORBA::Long anElemId = 0, aNbElems = theSeq[theId].number;
130 if(4*aNbElems != anIndexes.length())
131 EXCEPTION(runtime_error,"AddEdgeWithID - 4*aNbElems != anIndexes.length()");
132 for(CORBA::Long anIndexId = 0; anElemId < aNbElems; anElemId++, anIndexId+=4){
133 SMDS_MeshElement* anElem = theMesh->AddFaceWithID(anIndexes[anIndexId+1],
134 anIndexes[anIndexId+2],
135 anIndexes[anIndexId+3],
136 anIndexes[anIndexId]);
138 EXCEPTION(runtime_error,"SMDS_Mesh::FindElement - cannot AddFaceWithID for ID = "<<anElemId);
143 inline void AddQuadsWithID(SMDS_Mesh* theMesh,
144 SMESH::log_array_var theSeq,
147 const SMESH::long_array& anIndexes = theSeq[theId].indexes;
148 CORBA::Long anElemId = 0, aNbElems = theSeq[theId].number;
149 if(5*aNbElems != anIndexes.length())
150 EXCEPTION(runtime_error,"AddEdgeWithID - 4*aNbElems != anIndexes.length()");
151 for(CORBA::Long anIndexId = 0; anElemId < aNbElems; anElemId++, anIndexId+=5){
152 SMDS_MeshElement* anElem = theMesh->AddFaceWithID(anIndexes[anIndexId+1],
153 anIndexes[anIndexId+2],
154 anIndexes[anIndexId+3],
155 anIndexes[anIndexId+4],
156 anIndexes[anIndexId]);
158 EXCEPTION(runtime_error,"SMDS_Mesh::FindElement - cannot AddFaceWithID for ID = "<<anElemId);
163 inline void AddPolygonsWithID(SMDS_Mesh* theMesh,
164 SMESH::log_array_var& theSeq,
167 const SMESH::long_array& anIndexes = theSeq[theId].indexes;
168 CORBA::Long anIndexId = 0, aNbElems = theSeq[theId].number;
170 for (CORBA::Long anElemId = 0; anElemId < aNbElems; anElemId++) {
171 int aFaceId = anIndexes[anIndexId++];
173 int aNbNodes = anIndexes[anIndexId++];
174 std::vector<int> nodes_ids (aNbNodes);
175 for (int i = 0; i < aNbNodes; i++) {
176 nodes_ids[i] = anIndexes[anIndexId++];
179 SMDS_MeshElement* anElem = theMesh->AddPolygonalFaceWithID(nodes_ids, aFaceId);
181 EXCEPTION(runtime_error, "SMDS_Mesh::FindElement - cannot AddPolygonalFaceWithID for ID = "
187 inline void AddTetrasWithID(SMDS_Mesh* theMesh,
188 SMESH::log_array_var& theSeq,
191 const SMESH::long_array& anIndexes = theSeq[theId].indexes;
192 CORBA::Long anElemId = 0, aNbElems = theSeq[theId].number;
193 if(5*aNbElems != anIndexes.length())
194 EXCEPTION(runtime_error,"AddEdgeWithID - 5*aNbElems != anIndexes.length()");
195 for(CORBA::Long anIndexId = 0; anElemId < aNbElems; anElemId++, anIndexId+=5){
196 SMDS_MeshElement* anElem = theMesh->AddVolumeWithID(anIndexes[anIndexId+1],
197 anIndexes[anIndexId+2],
198 anIndexes[anIndexId+3],
199 anIndexes[anIndexId+4],
200 anIndexes[anIndexId]);
202 EXCEPTION(runtime_error,"SMDS_Mesh::FindElement - cannot AddVolumeWithID for ID = "<<anElemId);
207 inline void AddPiramidsWithID(SMDS_Mesh* theMesh,
208 SMESH::log_array_var& theSeq,
211 const SMESH::long_array& anIndexes = theSeq[theId].indexes;
212 CORBA::Long anElemId = 0, aNbElems = theSeq[theId].number;
213 if(6*aNbElems != anIndexes.length())
214 EXCEPTION(runtime_error,"AddEdgeWithID - 6*aNbElems != anIndexes.length()");
215 for(CORBA::Long anIndexId = 0; anElemId < aNbElems; anElemId++, anIndexId+=6){
216 SMDS_MeshElement* anElem = theMesh->AddVolumeWithID(anIndexes[anIndexId+1],
217 anIndexes[anIndexId+2],
218 anIndexes[anIndexId+3],
219 anIndexes[anIndexId+4],
220 anIndexes[anIndexId+5],
221 anIndexes[anIndexId]);
223 EXCEPTION(runtime_error,"SMDS_Mesh::FindElement - cannot AddVolumeWithID for ID = "<<anElemId);
228 inline void AddPrismsWithID(SMDS_Mesh* theMesh,
229 SMESH::log_array_var& theSeq,
232 const SMESH::long_array& anIndexes = theSeq[theId].indexes;
233 CORBA::Long anElemId = 0, aNbElems = theSeq[theId].number;
234 if(7*aNbElems != anIndexes.length())
235 EXCEPTION(runtime_error,"AddEdgeWithID - 7*aNbElems != anIndexes.length()");
236 for(CORBA::Long anIndexId = 0; anElemId < aNbElems; anElemId++, anIndexId+=7){
237 SMDS_MeshElement* anElem = theMesh->AddVolumeWithID(anIndexes[anIndexId+1],
238 anIndexes[anIndexId+2],
239 anIndexes[anIndexId+3],
240 anIndexes[anIndexId+4],
241 anIndexes[anIndexId+5],
242 anIndexes[anIndexId+6],
243 anIndexes[anIndexId]);
245 EXCEPTION(runtime_error,"SMDS_Mesh::FindElement - cannot AddVolumeWithID for ID = "<<anElemId);
250 inline void AddHexasWithID(SMDS_Mesh* theMesh,
251 SMESH::log_array_var& theSeq,
254 const SMESH::long_array& anIndexes = theSeq[theId].indexes;
255 CORBA::Long anElemId = 0, aNbElems = theSeq[theId].number;
256 if(9*aNbElems != anIndexes.length())
257 EXCEPTION(runtime_error,"AddEdgeWithID - 9*aNbElems != anIndexes.length()");
258 for(CORBA::Long anIndexId = 0; anElemId < aNbElems; anElemId++, anIndexId+=9){
259 SMDS_MeshElement* anElem = theMesh->AddVolumeWithID(anIndexes[anIndexId+1],
260 anIndexes[anIndexId+2],
261 anIndexes[anIndexId+3],
262 anIndexes[anIndexId+4],
263 anIndexes[anIndexId+5],
264 anIndexes[anIndexId+6],
265 anIndexes[anIndexId+7],
266 anIndexes[anIndexId+8],
267 anIndexes[anIndexId]);
269 EXCEPTION(runtime_error,"SMDS_Mesh::FindElement - cannot AddVolumeWithID for ID = "<<anElemId);
274 inline void AddPolyhedronsWithID (SMDS_Mesh* theMesh,
275 SMESH::log_array_var& theSeq,
278 const SMESH::long_array& anIndexes = theSeq[theId].indexes;
279 CORBA::Long anIndexId = 0, aNbElems = theSeq[theId].number;
281 for (CORBA::Long anElemId = 0; anElemId < aNbElems; anElemId++) {
282 int aFaceId = anIndexes[anIndexId++];
284 int aNbNodes = anIndexes[anIndexId++];
285 std::vector<int> nodes_ids (aNbNodes);
286 for (int i = 0; i < aNbNodes; i++) {
287 nodes_ids[i] = anIndexes[anIndexId++];
290 int aNbFaces = anIndexes[anIndexId++];
291 std::vector<int> quantities (aNbFaces);
292 for (int i = 0; i < aNbFaces; i++) {
293 quantities[i] = anIndexes[anIndexId++];
296 SMDS_MeshElement* anElem =
297 theMesh->AddPolyhedralVolumeWithID(nodes_ids, quantities, aFaceId);
299 EXCEPTION(runtime_error, "SMDS_Mesh::FindElement - cannot AddPolyhedralVolumeWithID for ID = "
305 inline void ChangePolyhedronNodes (SMDS_Mesh* theMesh,
306 SMESH::log_array_var& theSeq,
309 const SMESH::long_array& anIndexes = theSeq[theId].indexes;
310 CORBA::Long iind = 0, aNbElems = theSeq[theId].number;
312 for (CORBA::Long anElemId = 0; anElemId < aNbElems; anElemId++)
315 const SMDS_MeshElement* elem = FindElement(theMesh, anIndexes[iind++]);
317 int nbNodes = anIndexes[iind++];
319 std::vector<const SMDS_MeshNode*> aNodes (nbNodes);
320 for (int iNode = 0; iNode < nbNodes; iNode++) {
321 aNodes[iNode] = FindNode(theMesh, anIndexes[iind++]);
324 int nbFaces = anIndexes[iind++];
326 std::vector<int> quantities (nbFaces);
327 for (int iFace = 0; iFace < nbFaces; iFace++) {
328 quantities[iFace] = anIndexes[iind++];
331 theMesh->ChangePolyhedronNodes(elem, aNodes, quantities);
338 Class : SMESH_VisualObjDef
339 Description : Base class for all mesh objects to be visuilised
342 //=================================================================================
343 // function : getCellType
344 // purpose : Get type of VTK cell
345 //=================================================================================
346 static inline vtkIdType getCellType( const SMDSAbs_ElementType theType,
348 const int theNbNodes )
353 return theNbNodes == 2 ? VTK_LINE : VTK_EMPTY_CELL;
356 if (thePoly && theNbNodes>2 ) return VTK_POLYGON;
357 else if ( theNbNodes == 3 ) return VTK_TRIANGLE;
358 else if ( theNbNodes == 4 ) return VTK_QUAD;
359 else return VTK_EMPTY_CELL;
362 if (thePoly && theNbNodes>3 ) return VTK_CONVEX_POINT_SET;
363 else if ( theNbNodes == 4 ) return VTK_TETRA;
364 else if ( theNbNodes == 5 ) return VTK_PYRAMID;
365 else if ( theNbNodes == 6 ) return VTK_WEDGE;
366 else if ( theNbNodes == 8 ) return VTK_HEXAHEDRON;
367 else return VTK_EMPTY_CELL;
369 default: return VTK_EMPTY_CELL;
373 //=================================================================================
374 // functions : SMESH_VisualObjDef
375 // purpose : Constructor
376 //=================================================================================
377 SMESH_VisualObjDef::SMESH_VisualObjDef()
379 myGrid = vtkUnstructuredGrid::New();
381 SMESH_VisualObjDef::~SMESH_VisualObjDef()
384 MESSAGE( "~SMESH_MeshObj - myGrid->GetReferenceCount() = " << myGrid->GetReferenceCount() );
388 //=================================================================================
389 // functions : GetNodeObjId, GetNodeVTKId, GetElemObjId, GetElemVTKId
390 // purpose : Methods for retrieving VTK IDs by SMDS IDs and vice versa
391 //=================================================================================
392 vtkIdType SMESH_VisualObjDef::GetNodeObjId( int theVTKID )
394 return myVTK2SMDSNodes.find(theVTKID) == myVTK2SMDSNodes.end() ? -1 : myVTK2SMDSNodes[theVTKID];
397 vtkIdType SMESH_VisualObjDef::GetNodeVTKId( int theObjID )
399 return mySMDS2VTKNodes.find(theObjID) == mySMDS2VTKNodes.end() ? -1 : mySMDS2VTKNodes[theObjID];
402 vtkIdType SMESH_VisualObjDef::GetElemObjId( int theVTKID )
404 return myVTK2SMDSElems.find(theVTKID) == myVTK2SMDSElems.end() ? -1 : myVTK2SMDSElems[theVTKID];
407 vtkIdType SMESH_VisualObjDef::GetElemVTKId( int theObjID )
409 return mySMDS2VTKElems.find(theObjID) == mySMDS2VTKElems.end() ? -1 : mySMDS2VTKElems[theObjID];
412 //=================================================================================
413 // function : SMESH_VisualObjDef::createPoints
414 // purpose : Create points from nodes
415 //=================================================================================
416 void SMESH_VisualObjDef::createPoints( vtkPoints* thePoints )
418 if ( thePoints == 0 )
422 vtkIdType nbNodes = GetEntities( SMDSAbs_Node, aNodes );
423 thePoints->SetNumberOfPoints( nbNodes );
427 TEntityList::const_iterator anIter;
428 for ( anIter = aNodes.begin(); anIter != aNodes.end(); ++anIter )
430 const SMDS_MeshNode* aNode = ( const SMDS_MeshNode* )(*anIter);
433 thePoints->SetPoint( nbPoints, aNode->X(), aNode->Y(), aNode->Z() );
434 int anId = aNode->GetID();
435 mySMDS2VTKNodes.insert( TMapOfIds::value_type( anId, nbPoints ) );
436 myVTK2SMDSNodes.insert( TMapOfIds::value_type( nbPoints, anId ) );
441 if ( nbPoints != nbNodes )
442 thePoints->SetNumberOfPoints( nbPoints );
445 //=================================================================================
446 // function : buildPrs
447 // purpose : create VTK cells( fill unstructured grid )
448 //=================================================================================
449 void SMESH_VisualObjDef::buildPrs()
453 mySMDS2VTKNodes.clear();
454 myVTK2SMDSNodes.clear();
455 mySMDS2VTKElems.clear();
456 myVTK2SMDSElems.clear();
463 catch( const std::exception& exc )
465 INFOS("Follow exception was cought:\n\t"<<exc.what());
469 INFOS("Unknown exception was cought !!!");
472 if( MYDEBUG ) MESSAGE( "Update - myGrid->GetNumberOfCells() = "<<myGrid->GetNumberOfCells() );
473 if( MYDEBUGWITHFILES ) SMESH::WriteUnstructuredGrid( myGrid,"/tmp/buildPrs" );
476 //=================================================================================
477 // function : buildNodePrs
478 // purpose : create VTK cells for nodes
479 //=================================================================================
480 void SMESH_VisualObjDef::buildNodePrs()
482 vtkPoints* aPoints = vtkPoints::New();
483 createPoints( aPoints );
484 myGrid->SetPoints( aPoints );
487 myGrid->SetCells( 0, 0, 0 );
491 int nbPoints = aPoints->GetNumberOfPoints();
492 vtkIdList *anIdList = vtkIdList::New();
493 anIdList->SetNumberOfIds( 1 );
495 vtkCellArray *aCells = vtkCellArray::New();
496 aCells->Allocate( 2 * nbPoints, 0 );
498 vtkUnsignedCharArray* aCellTypesArray = vtkUnsignedCharArray::New();
499 aCellTypesArray->SetNumberOfComponents( 1 );
500 aCellTypesArray->Allocate( nbPoints );
502 for( vtkIdType aCellId = 0; aCellId < nbPoints; aCellId++ )
504 anIdList->SetId( 0, aCellId );
505 aCells->InsertNextCell( anIdList );
506 aCellTypesArray->InsertNextValue( VTK_VERTEX );
509 vtkIntArray* aCellLocationsArray = vtkIntArray::New();
510 aCellLocationsArray->SetNumberOfComponents( 1 );
511 aCellLocationsArray->SetNumberOfTuples( nbPoints );
513 aCells->InitTraversal();
514 for( vtkIdType i = 0, *pts, npts; aCells->GetNextCell( npts, pts ); i++ )
515 aCellLocationsArray->SetValue( i, aCells->GetTraversalLocation( npts ) );
517 myGrid->SetCells( aCellTypesArray, aCellLocationsArray, aCells );
519 aCellLocationsArray->Delete();
520 aCellTypesArray->Delete();
526 //=================================================================================
527 // function : buildElemPrs
528 // purpose : Create VTK cells for elements
529 //=================================================================================
532 typedef std::vector<const SMDS_MeshElement*> TConnect;
534 int GetConnect(const SMDS_ElemIteratorPtr& theNodesIter,
535 TConnect& theConnect)
538 for(; theNodesIter->more();)
539 theConnect.push_back(theNodesIter->next());
540 return theConnect.size();
544 void SetId(vtkIdList *theIdList,
545 const SMESH_VisualObjDef::TMapOfIds& theSMDS2VTKNodes,
546 const TConnect& theConnect,
550 theIdList->SetId(thePosition,theSMDS2VTKNodes.find(theConnect[theId]->GetID())->second);
556 void SMESH_VisualObjDef::buildElemPrs()
560 vtkPoints* aPoints = vtkPoints::New();
561 createPoints( aPoints );
562 myGrid->SetPoints( aPoints );
566 MESSAGE("Update - myGrid->GetNumberOfPoints() = "<<myGrid->GetNumberOfPoints());
568 // Calculate cells size
570 static SMDSAbs_ElementType aTypes[ 3 ] = { SMDSAbs_Edge, SMDSAbs_Face, SMDSAbs_Volume };
573 map<SMDSAbs_ElementType,int> nbEnts;
574 map<SMDSAbs_ElementType,TEntityList> anEnts;
576 for ( int i = 0; i <= 2; i++ )
577 nbEnts[ aTypes[ i ] ] = GetEntities( aTypes[ i ], anEnts[ aTypes[ i ] ] );
579 vtkIdType aCellsSize = 3 * nbEnts[ SMDSAbs_Edge ];
581 for ( int i = 1; i <= 2; i++ ) // iterate through faces and volumes
583 if ( nbEnts[ aTypes[ i ] ] )
585 const TEntityList& aList = anEnts[ aTypes[ i ] ];
586 TEntityList::const_iterator anIter;
587 for ( anIter = aList.begin(); anIter != aList.end(); ++anIter )
588 aCellsSize += (*anIter)->NbNodes() + 1;
592 vtkIdType aNbCells = nbEnts[ SMDSAbs_Edge ] + nbEnts[ SMDSAbs_Face ] + nbEnts[ SMDSAbs_Volume ];
595 MESSAGE( "Update - aNbCells = "<<aNbCells<<"; aCellsSize = "<<aCellsSize );
599 vtkCellArray* aConnectivity = vtkCellArray::New();
600 aConnectivity->Allocate( aCellsSize, 0 );
602 vtkUnsignedCharArray* aCellTypesArray = vtkUnsignedCharArray::New();
603 aCellTypesArray->SetNumberOfComponents( 1 );
604 aCellTypesArray->Allocate( aNbCells * aCellTypesArray->GetNumberOfComponents() );
606 vtkIdList *anIdList = vtkIdList::New();
610 aConnect.reserve(VTK_CELL_SIZE);
612 for ( int i = 0; i <= 2; i++ ) // iterate through edges, faces and volumes
614 if( nbEnts[ aTypes[ i ] ] > 0 )
616 const SMDSAbs_ElementType& aType = aTypes[ i ];
617 const TEntityList& aList = anEnts[ aType ];
618 TEntityList::const_iterator anIter;
619 for ( anIter = aList.begin(); anIter != aList.end(); ++anIter )
621 const SMDS_MeshElement* anElem = *anIter;
623 vtkIdType aNbNodes = anElem->NbNodes();
624 anIdList->SetNumberOfIds( aNbNodes );
626 int anId = anElem->GetID();
628 mySMDS2VTKElems.insert( TMapOfIds::value_type( anId, iElem ) );
629 myVTK2SMDSElems.insert( TMapOfIds::value_type( iElem, anId ) );
631 SMDS_ElemIteratorPtr aNodesIter = anElem->nodesIterator();
633 case SMDSAbs_Volume:{
634 std::vector<int> aConnectivities;
635 GetConnect(aNodesIter,aConnect);
636 // Convertions connectivities from SMDS to VTK
637 if (anElem->IsPoly() && aNbNodes > 3) { // POLYEDRE
638 for (int k = 0; k < aNbNodes; k++) {
639 aConnectivities.push_back(k);
642 } else if (aNbNodes == 4) {
643 static int anIds[] = {0,2,1,3};
644 for (int k = 0; k < aNbNodes; k++) aConnectivities.push_back(anIds[k]);
646 } else if (aNbNodes == 5) {
647 static int anIds[] = {0,3,2,1,4};
648 for (int k = 0; k < aNbNodes; k++) aConnectivities.push_back(anIds[k]);
650 } else if (aNbNodes == 6) {
651 static int anIds[] = {0,1,2,3,4,5};
652 for (int k = 0; k < aNbNodes; k++) aConnectivities.push_back(anIds[k]);
654 } else if (aNbNodes == 8) {
655 static int anIds[] = {0,3,2,1,4,7,6,5};
656 for (int k = 0; k < aNbNodes; k++) aConnectivities.push_back(anIds[k]);
661 if (aConnectivities.size() > 0) {
662 for (vtkIdType aNodeId = 0; aNodeId < aNbNodes; aNodeId++)
663 SetId(anIdList,mySMDS2VTKNodes,aConnect,aNodeId,aConnectivities[aNodeId]);
668 for( vtkIdType aNodeId = 0; aNodesIter->more(); aNodeId++ ){
669 const SMDS_MeshElement* aNode = aNodesIter->next();
670 anIdList->SetId( aNodeId, mySMDS2VTKNodes[aNode->GetID()] );
674 aConnectivity->InsertNextCell( anIdList );
675 aCellTypesArray->InsertNextValue( getCellType( aType, anElem->IsPoly(), aNbNodes ) );
682 // Insert cells in grid
684 vtkIntArray* aCellLocationsArray = vtkIntArray::New();
685 aCellLocationsArray->SetNumberOfComponents( 1 );
686 aCellLocationsArray->SetNumberOfTuples( aNbCells );
688 aConnectivity->InitTraversal();
689 for( vtkIdType idType = 0, *pts, npts; aConnectivity->GetNextCell( npts, pts ); idType++ )
690 aCellLocationsArray->SetValue( idType, aConnectivity->GetTraversalLocation( npts ) );
692 myGrid->SetCells( aCellTypesArray, aCellLocationsArray,aConnectivity );
694 aCellLocationsArray->Delete();
695 aCellTypesArray->Delete();
696 aConnectivity->Delete();
700 //=================================================================================
701 // function : GetEdgeNodes
702 // purpose : Retrieve ids of nodes from edge of elements ( edge is numbered from 1 )
703 //=================================================================================
704 bool SMESH_VisualObjDef::GetEdgeNodes( const int theElemId,
705 const int theEdgeNum,
707 int& theNodeId2 ) const
709 const SMDS_Mesh* aMesh = GetMesh();
713 const SMDS_MeshElement* anElem = aMesh->FindElement( theElemId );
717 int nbNodes = anElem->NbNodes();
719 if ( theEdgeNum < 0 || theEdgeNum > 3 || nbNodes != 3 && nbNodes != 4 || theEdgeNum > nbNodes )
722 int anIds[ nbNodes ];
723 SMDS_ElemIteratorPtr anIter = anElem->nodesIterator();
725 while( anIter->more() )
726 anIds[ i++ ] = anIter->next()->GetID();
728 if ( theEdgeNum < nbNodes - 1 )
730 theNodeId1 = anIds[ theEdgeNum ];
731 theNodeId2 = anIds[ theEdgeNum + 1 ];
735 theNodeId1 = anIds[ nbNodes - 1 ];
736 theNodeId2 = anIds[ 0 ];
743 Class : SMESH_MeshObj
744 Description : Class for visualisation of mesh
747 //=================================================================================
748 // function : SMESH_MeshObj
749 // purpose : Constructor
750 //=================================================================================
751 SMESH_MeshObj::SMESH_MeshObj(SMESH::SMESH_Mesh_ptr theMesh)
754 MESSAGE("SMESH_MeshObj - theMesh->_is_nil() = "<<theMesh->_is_nil());
756 myMeshServer = SMESH::SMESH_Mesh::_duplicate( theMesh );
757 myMeshServer->Register();
758 myMesh = new SMDS_Mesh();
761 //=================================================================================
762 // function : ~SMESH_MeshObj
763 // purpose : Destructor
764 //=================================================================================
765 SMESH_MeshObj::~SMESH_MeshObj()
767 myMeshServer->Destroy();
771 //=================================================================================
773 // purpose : Update mesh and fill grid with new values if necessary
774 //=================================================================================
775 void SMESH_MeshObj::Update( int theIsClear )
777 // Update SMDS_Mesh on client part
781 SMESH::log_array_var aSeq = myMeshServer->GetLog( theIsClear );
782 CORBA::Long aLength = aSeq->length();
784 if( MYDEBUG ) MESSAGE( "Update: length of the script is "<<aLength );
789 for ( CORBA::Long anId = 0; anId < aLength; anId++)
791 const SMESH::double_array& aCoords = aSeq[anId].coords;
792 const SMESH::long_array& anIndexes = aSeq[anId].indexes;
793 CORBA::Long anElemId = 0, aNbElems = aSeq[anId].number;
794 CORBA::Long aCommand = aSeq[anId].commandType;
798 case SMESH::ADD_NODE : AddNodesWithID ( myMesh, aSeq, anId ); break;
799 case SMESH::ADD_EDGE : AddEdgesWithID ( myMesh, aSeq, anId ); break;
800 case SMESH::ADD_TRIANGLE : AddTriasWithID ( myMesh, aSeq, anId ); break;
801 case SMESH::ADD_QUADRANGLE : AddQuadsWithID ( myMesh, aSeq, anId ); break;
802 case SMESH::ADD_POLYGON : AddPolygonsWithID ( myMesh, aSeq, anId ); break;
803 case SMESH::ADD_TETRAHEDRON: AddTetrasWithID ( myMesh, aSeq, anId ); break;
804 case SMESH::ADD_PYRAMID : AddPiramidsWithID ( myMesh, aSeq, anId ); break;
805 case SMESH::ADD_PRISM : AddPrismsWithID ( myMesh, aSeq, anId ); break;
806 case SMESH::ADD_HEXAHEDRON : AddHexasWithID ( myMesh, aSeq, anId ); break;
807 case SMESH::ADD_POLYHEDRON : AddPolyhedronsWithID( myMesh, aSeq, anId ); break;
809 case SMESH::REMOVE_NODE:
810 for( ; anElemId < aNbElems; anElemId++ )
811 myMesh->RemoveNode( FindNode( myMesh, anIndexes[anElemId] ) );
814 case SMESH::REMOVE_ELEMENT:
815 for( ; anElemId < aNbElems; anElemId++ )
816 myMesh->RemoveElement( FindElement( myMesh, anIndexes[anElemId] ) );
819 case SMESH::MOVE_NODE:
820 for(CORBA::Long aCoordId=0; anElemId < aNbElems; anElemId++, aCoordId+=3)
822 SMDS_MeshNode* node =
823 const_cast<SMDS_MeshNode*>( FindNode( myMesh, anIndexes[anElemId] ));
824 node->setXYZ( aCoords[aCoordId], aCoords[aCoordId+1], aCoords[aCoordId+2] );
828 case SMESH::CHANGE_ELEMENT_NODES:
829 for ( CORBA::Long i = 0; anElemId < aNbElems; anElemId++ )
832 const SMDS_MeshElement* elem = FindElement( myMesh, anIndexes[i++] );
834 int nbNodes = anIndexes[i++];
836 //ASSERT( nbNodes < 9 );
837 const SMDS_MeshNode* aNodes[ nbNodes ];
838 for ( int iNode = 0; iNode < nbNodes; iNode++ )
839 aNodes[ iNode ] = FindNode( myMesh, anIndexes[i++] );
841 myMesh->ChangeElementNodes( elem, aNodes, nbNodes );
845 case SMESH::CHANGE_POLYHEDRON_NODES:
846 ChangePolyhedronNodes(myMesh, aSeq, anId);
848 case SMESH::RENUMBER:
849 for(CORBA::Long i=0; anElemId < aNbElems; anElemId++, i+=3)
851 myMesh->Renumber( anIndexes[i], anIndexes[i+1], anIndexes[i+2] );
859 catch ( SALOME::SALOME_Exception& exc )
861 INFOS("Following exception was cought:\n\t"<<exc.details.text);
863 catch( const std::exception& exc)
865 INFOS("Following exception was cought:\n\t"<<exc.what());
869 INFOS("Unknown exception was cought !!!");
874 MESSAGE("Update - myMesh->NbNodes() = "<<myMesh->NbNodes());
875 MESSAGE("Update - myMesh->NbEdges() = "<<myMesh->NbEdges());
876 MESSAGE("Update - myMesh->NbFaces() = "<<myMesh->NbFaces());
877 MESSAGE("Update - myMesh->NbVolumes() = "<<myMesh->NbVolumes());
880 // Fill unstructured grid
884 //=================================================================================
885 // function : GetElemDimension
886 // purpose : Get dimension of element
887 //=================================================================================
888 int SMESH_MeshObj::GetElemDimension( const int theObjId )
890 const SMDS_MeshElement* anElem = myMesh->FindElement( theObjId );
894 int aType = anElem->GetType();
897 case SMDSAbs_Edge : return 1;
898 case SMDSAbs_Face : return 2;
899 case SMDSAbs_Volume: return 3;
904 //=================================================================================
905 // function : GetEntities
906 // purpose : Get entities of specified type. Return number of entities
907 //=================================================================================
908 int SMESH_MeshObj::GetNbEntities( const SMDSAbs_ElementType theType) const
914 return myMesh->NbNodes();
919 return myMesh->NbEdges();
924 return myMesh->NbFaces();
929 return myMesh->NbVolumes();
938 int SMESH_MeshObj::GetEntities( const SMDSAbs_ElementType theType, TEntityList& theObjs ) const
946 SMDS_NodeIteratorPtr anIter = myMesh->nodesIterator();
947 while ( anIter->more() ) theObjs.push_back( anIter->next() );
952 SMDS_EdgeIteratorPtr anIter = myMesh->edgesIterator();
953 while ( anIter->more() ) theObjs.push_back( anIter->next() );
958 SMDS_FaceIteratorPtr anIter = myMesh->facesIterator();
959 while ( anIter->more() ) theObjs.push_back( anIter->next() );
964 SMDS_VolumeIteratorPtr anIter = myMesh->volumesIterator();
965 while ( anIter->more() ) theObjs.push_back( anIter->next() );
972 return theObjs.size();
975 //=================================================================================
976 // function : UpdateFunctor
977 // purpose : Update functor in accordance with current mesh
978 //=================================================================================
979 void SMESH_MeshObj::UpdateFunctor( const SMESH::Controls::FunctorPtr& theFunctor )
981 theFunctor->SetMesh( GetMesh() );
984 //=================================================================================
985 // function : IsNodePrs
986 // purpose : Return true if node presentation is used
987 //=================================================================================
988 bool SMESH_MeshObj::IsNodePrs() const
990 return myMesh->NbEdges() == 0 &&myMesh->NbFaces() == 0 &&myMesh->NbVolumes() == 0 ;
995 Class : SMESH_SubMeshObj
996 Description : Base class for visualisation of submeshes and groups
999 //=================================================================================
1000 // function : SMESH_SubMeshObj
1001 // purpose : Constructor
1002 //=================================================================================
1003 SMESH_SubMeshObj::SMESH_SubMeshObj( SMESH_MeshObj* theMeshObj )
1005 if ( MYDEBUG ) MESSAGE( "SMESH_SubMeshObj - theMeshObj = " << theMeshObj );
1007 myMeshObj = theMeshObj;
1010 SMESH_SubMeshObj::~SMESH_SubMeshObj()
1014 //=================================================================================
1015 // function : GetElemDimension
1016 // purpose : Get dimension of element
1017 //=================================================================================
1018 int SMESH_SubMeshObj::GetElemDimension( const int theObjId )
1020 return myMeshObj == 0 ? 0 : myMeshObj->GetElemDimension( theObjId );
1023 //=================================================================================
1024 // function : UpdateFunctor
1025 // purpose : Update functor in accordance with current mesh
1026 //=================================================================================
1027 void SMESH_SubMeshObj::UpdateFunctor( const SMESH::Controls::FunctorPtr& theFunctor )
1029 theFunctor->SetMesh( myMeshObj->GetMesh() );
1032 //=================================================================================
1033 // function : Update
1034 // purpose : Update mesh object and fill grid with new values
1035 //=================================================================================
1036 void SMESH_SubMeshObj::Update( int theIsClear )
1038 myMeshObj->Update( theIsClear );
1044 Class : SMESH_GroupObj
1045 Description : Class for visualisation of groups
1048 //=================================================================================
1049 // function : SMESH_GroupObj
1050 // purpose : Constructor
1051 //=================================================================================
1052 SMESH_GroupObj::SMESH_GroupObj( SMESH::SMESH_GroupBase_ptr theGroup,
1053 SMESH_MeshObj* theMeshObj )
1054 : SMESH_SubMeshObj( theMeshObj ),
1055 myGroupServer( SMESH::SMESH_GroupBase::_duplicate(theGroup) )
1057 if ( MYDEBUG ) MESSAGE("SMESH_GroupObj - theGroup->_is_nil() = "<<theGroup->_is_nil());
1058 myGroupServer->Register();
1061 SMESH_GroupObj::~SMESH_GroupObj()
1063 if ( MYDEBUG ) MESSAGE("~SMESH_GroupObj");
1064 myGroupServer->Destroy();
1067 //=================================================================================
1068 // function : IsNodePrs
1069 // purpose : Return true if node presentation is used
1070 //=================================================================================
1071 bool SMESH_GroupObj::IsNodePrs() const
1073 return myGroupServer->GetType() == SMESH::NODE;
1076 //=================================================================================
1077 // function : getNodesFromElems
1078 // purpose : Retrieve nodes from elements
1079 //=================================================================================
1080 static int getNodesFromElems( SMESH::long_array_var& theElemIds,
1081 const SMDS_Mesh* theMesh,
1082 std::list<const SMDS_MeshElement*>& theResList )
1084 set<const SMDS_MeshElement*> aNodeSet;
1086 for ( CORBA::Long i = 0, n = theElemIds->length(); i < n; i++ )
1088 const SMDS_MeshElement* anElem = theMesh->FindElement( theElemIds[ i ] );
1091 SMDS_ElemIteratorPtr anIter = anElem->nodesIterator();
1092 while ( anIter->more() )
1094 const SMDS_MeshElement* aNode = anIter->next();
1096 aNodeSet.insert( aNode );
1101 set<const SMDS_MeshElement*>::const_iterator anIter;
1102 for ( anIter = aNodeSet.begin(); anIter != aNodeSet.end(); ++anIter )
1103 theResList.push_back( *anIter );
1105 return theResList.size();
1108 //=================================================================================
1109 // function : getPointers
1110 // purpose : Get std::list<const SMDS_MeshElement*> from list of IDs
1111 //=================================================================================
1112 static int getPointers( const SMDSAbs_ElementType theRequestType,
1113 SMESH::long_array_var& theElemIds,
1114 const SMDS_Mesh* theMesh,
1115 std::list<const SMDS_MeshElement*>& theResList )
1117 for ( CORBA::Long i = 0, n = theElemIds->length(); i < n; i++ )
1119 const SMDS_MeshElement* anElem = theRequestType == SMDSAbs_Node
1120 ? theMesh->FindNode( theElemIds[ i ] ) : theMesh->FindElement( theElemIds[ i ] );
1123 theResList.push_back( anElem );
1126 return theResList.size();
1130 //=================================================================================
1131 // function : GetEntities
1132 // purpose : Get entities of specified type. Return number of entities
1133 //=================================================================================
1134 int SMESH_GroupObj::GetNbEntities( const SMDSAbs_ElementType theType) const
1136 if(SMDSAbs_ElementType(myGroupServer->GetType()) == theType){
1137 return myGroupServer->Size();
1142 int SMESH_GroupObj::GetEntities( const SMDSAbs_ElementType theType, TEntityList& theResList ) const
1145 SMDS_Mesh* aMesh = myMeshObj->GetMesh();
1147 if ( myGroupServer->Size() == 0 || aMesh == 0 )
1150 SMDSAbs_ElementType aGrpType = SMDSAbs_ElementType(myGroupServer->GetType());
1151 SMESH::long_array_var anIds = myGroupServer->GetListOfID();
1153 if ( aGrpType == theType )
1154 return getPointers( theType, anIds, aMesh, theResList );
1155 else if ( theType == SMDSAbs_Node )
1156 return getNodesFromElems( anIds, aMesh, theResList );
1164 Class : SMESH_subMeshObj
1165 Description : Class for visualisation of submeshes
1168 //=================================================================================
1169 // function : SMESH_subMeshObj
1170 // purpose : Constructor
1171 //=================================================================================
1172 SMESH_subMeshObj::SMESH_subMeshObj( SMESH::SMESH_subMesh_ptr theSubMesh,
1173 SMESH_MeshObj* theMeshObj )
1174 : SMESH_SubMeshObj( theMeshObj ),
1175 mySubMeshServer( SMESH::SMESH_subMesh::_duplicate( theSubMesh ) )
1177 if ( MYDEBUG ) MESSAGE( "SMESH_subMeshObj - theSubMesh->_is_nil() = " << theSubMesh->_is_nil() );
1179 mySubMeshServer->Register();
1182 SMESH_subMeshObj::~SMESH_subMeshObj()
1184 if ( MYDEBUG ) MESSAGE( "~SMESH_subMeshObj" );
1185 mySubMeshServer->Destroy();
1188 //=================================================================================
1189 // function : GetEntities
1190 // purpose : Get entities of specified type. Return number of entities
1191 //=================================================================================
1192 int SMESH_subMeshObj::GetNbEntities( const SMDSAbs_ElementType theType) const
1198 return mySubMeshServer->GetNumberOfNodes( false );
1203 case SMDSAbs_Volume:
1205 SMESH::long_array_var anIds =
1206 mySubMeshServer->GetElementsByType( SMESH::ElementType(theType) );
1207 return anIds->length();
1215 int SMESH_subMeshObj::GetEntities( const SMDSAbs_ElementType theType, TEntityList& theResList ) const
1219 SMDS_Mesh* aMesh = myMeshObj->GetMesh();
1223 bool isNodal = IsNodePrs();
1227 if ( theType == SMDSAbs_Node )
1229 SMESH::long_array_var anIds = mySubMeshServer->GetNodesId();
1230 return getPointers( SMDSAbs_Node, anIds, aMesh, theResList );
1235 if ( theType == SMDSAbs_Node )
1237 SMESH::long_array_var anIds = mySubMeshServer->GetElementsId();
1238 return getNodesFromElems( anIds, aMesh, theResList );
1242 SMESH::long_array_var anIds =
1243 mySubMeshServer->GetElementsByType( SMESH::ElementType(theType) );
1244 return getPointers( theType, anIds, aMesh, theResList );
1251 //=================================================================================
1252 // function : IsNodePrs
1253 // purpose : Return true if node presentation is used
1254 //=================================================================================
1255 bool SMESH_subMeshObj::IsNodePrs() const
1257 return mySubMeshServer->GetNumberOfElements() == 0;