1 // Copyright (C) 2007-2008 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 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.salome-platform.org/ or email : webmaster.salome@opencascade.com
22 #ifndef CONNECTIVITY_HXX
23 #define CONNECTIVITY_HXX
30 #include "MEDMEM_Utilities.hxx"
31 #include "MEDMEM_Exception.hxx"
32 #include "MEDMEM_define.hxx"
33 #include "MEDMEM_PolyhedronArray.hxx"
34 #include "MEDMEM_CellModel.hxx"
36 #include <ext/hash_map>
42 using namespace __gnu_cxx;
45 using stdext::hash_map;
49 class MEDSKYLINEARRAY;
53 MEDMEM_EXPORT ostream & operator<<(ostream &os, CONNECTIVITY &my);
56 This class deals with all type of connectivity .\n
60 /* ------------------------------------------- */
61 class MEDMEM_EXPORT CONNECTIVITY
62 /* ------------------------------------------- */
68 size_t operator()(const vector<int>& key) const
71 for (int i=0; i<(int)key.size(); i++)
76 static const size_t bucket_size = 4;
77 static const size_t min_buckets = 8;
78 bool operator()(const vector<int>& key1, const vector<int>& key2) const
80 return ::size_t()(key1) < ::size_t()(key2);
85 typedef hash_map<vector<int>,int, myHashFn > CONNECTIVITY_HashMap;
87 /* ---------------------- */
89 /* ---------------------- */
92 /*! contains MED_CELL MED_FACE or MED_EDGE */
93 MED_EN::medEntityMesh _entity;
94 /*! contains MED_NODAL or MED_DESCEND */
95 MED_EN::medConnectivity _typeConnectivity;
96 /*! count of differents cells types
99 /*! array of all med_geometric_type used by MESH. */
100 MED_EN::medGeometryElement* _geometricTypes;
102 /*! map indexed by med_geometric_type
103 which contains the different
104 'CellModel' used by MESH. */
106 /*! contains the dimension of the entity */
107 int _entityDimension;
109 /*! needed by calculateReverseNodalConnectivity */
112 /*! array of size _numberOfTypes+1 which
113 gives for each cell type the first
114 cell number in _nodal or _descending
115 array (depends on _typeConnectivity)
116 To get cells count for one type, we
117 must minus _count[i+1] and _count[i]
118 ( 0 <= i < _numberOfTypes ).
119 Note that _count[_numberOfTypes] returns
120 total cells count + 1 */
123 /*! pointer to an array which stores the nodal connectivity */
124 MEDSKYLINEARRAY* _nodal;
125 /*! pointer to an array which stores the nodal connectivity only for polygons */
126 MEDSKYLINEARRAY* _polygonsNodal;
127 /*! pointer to an array which stores the nodal connectivity only for polyhedron */
128 POLYHEDRONARRAY* _polyhedronNodal;
129 /*! pointer to an array which stores
130 the descending connectivity */
131 MEDSKYLINEARRAY* _descending;
132 /*! pointer to an array which stores the descending connectivity only for polygons */
133 MEDSKYLINEARRAY* _polygonsDescending;
134 /*! pointer to an array which stores the descending connectivity only for polyhedron */
135 MEDSKYLINEARRAY* _polyhedronDescending;
136 /*! pointer to an array which stores
137 the reverse nodal connectivity */
138 MEDSKYLINEARRAY* _reverseNodalConnectivity;
139 /*! pointer to an array which stores
140 the reverse descending connectivity */
141 MEDSKYLINEARRAY* _reverseDescendingConnectivity;
142 /*! if face or edge, list of 2 cells or
143 2 faces it belongs to.
144 If 2nd number equals 0, we have a
145 boundary entity. We could use
146 MEDSKYLINEARRAY, but we suppose we have
147 always only 2 (or 1) entities. */
148 MEDSKYLINEARRAY* _neighbourhood;
149 /*! connectivity of sub cell if
150 descendant connectivity is calculated */
151 CONNECTIVITY * _constituent;
152 /*! is descending connectivity computed by
153 calculatePartialDescendingConnectivity() */
154 bool _isDescendingConnectivityPartial;
156 /* -------------------- */
158 /* -------------------- */
161 /*! private method :\n
162 does nothing if already exists, else
163 evaluates _nodal from _descending */
164 void calculateNodalConnectivity();
165 /*! private method :\n
166 does nothing if already exists, else
167 evaluates from _nodal */
168 void calculateReverseNodalConnectivity();
169 /*! private method :\n
170 does nothing if already exists, else
171 evaluates _descending from _nodal */
172 void calculateDescendingConnectivity();
174 void calculatePartialDescendingConnectivity();
175 void addToDescendingConnectivity( const set<int>& nodes,
176 multimap<int,int>& descending,
178 const CONNECTIVITY_HashMap & );
180 /*! private method :\n
181 does nothing if already exists, else
182 evaluates from _descending */
183 // void calculateReverseDescendingConnectivity(CONNECTIVITY *myConnectivity);
185 const int* getReverseNodalConnectivity ();
186 const int* getReverseNodalConnectivityIndex ();
187 const int* getReverseDescendingConnectivity ();
188 const int* getReverseDescendingConnectivityIndex ();
190 /*! private method :\n
191 does nothing if already exists, else
192 evaluates _neighbourhood from _descending */
193 void calculateNeighbourhood(CONNECTIVITY &myConnectivity);
195 int getIndexOfEndClassicElementInReverseNodal(const int *reverseNodalValue, const int *reverseNodalIndex, int rk) const;
199 friend class IMED_MESH_RDONLY_DRIVER;
200 friend class MED_MESH_RDONLY_DRIVER21;
201 friend class IMED_MESH_WRONLY_DRIVER;
202 friend class MED_MESH_WRONLY_DRIVER21;
203 friend class MED_MESH_RDONLY_DRIVER22;
204 friend class MED_MESH_WRONLY_DRIVER22;
207 friend ostream & operator<<(ostream &os, CONNECTIVITY &connectivity);
209 // in order to fill CONNECTIVITY of MESH
212 CONNECTIVITY (MED_EN::medEntityMesh Entity=MED_EN::MED_CELL);
213 CONNECTIVITY (int numberOfTypes, MED_EN::medEntityMesh Entity=MED_EN::MED_CELL);
214 CONNECTIVITY (const CONNECTIVITY & m);
215 virtual ~CONNECTIVITY ();
217 void setConstituent (CONNECTIVITY * Constituent)
218 throw (MEDEXCEPTION);
220 void setGeometricTypes (const MED_EN::medGeometryElement * Types,
221 const MED_EN::medEntityMesh Entity)
222 throw (MEDEXCEPTION);
224 void setCount (const int * Count, const MED_EN::medEntityMesh Entity)
225 throw (MEDEXCEPTION);
227 void setNodal (const int * Connectivity,
228 const MED_EN::medEntityMesh Entity,
229 const MED_EN::medGeometryElement Type)
230 throw (MEDEXCEPTION);
232 inline void setNumberOfNodes(int NumberOfNodes);
233 inline int getNumberOfNodes();
234 inline int getEntityDimension() const;
236 inline void setEntityDimension(int EntityDimension);
238 void setPolygonsConnectivity(MED_EN::medConnectivity ConnectivityType,
239 MED_EN::medEntityMesh Entity,
240 const int* PolygonsConnectivity,
241 const int* PolygonsConnectivityIndex,
242 int ConnectivitySize, int NumberOfPolygons);
244 void setPolyhedronConnectivity(MED_EN::medConnectivity ConnectivityType,
245 const int* PolyhedronConnectivity,
246 const int* PolyhedronIndex, int ConnectivitySize,
247 int NumberOfPolyhedron,
248 const int* PolyhedronFacesIndex= (int*) NULL,
249 int NumberOfFaces=0);
251 inline bool existConnectivity (MED_EN::medConnectivity connectivityType,
252 MED_EN::medEntityMesh Entity) const;
253 bool existConnectivityWithPoly (MED_EN::medConnectivity connectivityType,
254 MED_EN::medEntityMesh Entity) const;
256 virtual bool existPolygonsConnectivity (MED_EN::medConnectivity connectivityType,
257 MED_EN::medEntityMesh Entity) const;
259 virtual bool existPolyhedronConnectivity (MED_EN::medConnectivity connectivityType,
260 MED_EN::medEntityMesh Entity) const;
262 virtual void calculateConnectivity (MED_EN::medConnectivity connectivityType,
263 MED_EN::medEntityMesh Entity);
265 virtual void calculateFullDescendingConnectivity(MED_EN::medEntityMesh Entity);
267 virtual void updateFamily (const vector<FAMILY*>& myFamilies);
269 inline MED_EN::medEntityMesh getEntity () const;
271 inline int getNumberOfTypes (MED_EN::medEntityMesh Entity) const;
272 int getNumberOfTypesWithPoly (MED_EN::medEntityMesh Entity) const;
273 const int * getConnectivityOfAnElementWithPoly (MED_EN::medConnectivity ConnectivityType,
274 MED_EN::medEntityMesh Entity,
275 int Number, int &lgth);
277 int getNumberOfPolyType() const;
278 int getNumberOfElementsWithPoly(MED_EN::medEntityMesh Entity, MED_EN::medGeometryElement Type) const;
279 int getNumberOfElementOfPolyType(MED_EN::medEntityMesh Entity) const;
281 inline const MED_EN::medGeometryElement * getGeometricTypes (MED_EN::medEntityMesh Entity) const
282 throw (MEDEXCEPTION);
283 MED_EN::medGeometryElement * getGeometricTypesWithPoly (MED_EN::medEntityMesh Entity) const
284 throw (MEDEXCEPTION);
285 MED_EN::medGeometryElement getElementType (MED_EN::medEntityMesh Entity,
287 MED_EN::medGeometryElement getElementTypeWithPoly (MED_EN::medEntityMesh Entity,
289 inline MED_EN::medGeometryElement getPolyTypeRelativeTo() const;
290 virtual inline const int * getGlobalNumberingIndex (MED_EN::medEntityMesh Entity) const
291 throw (MEDEXCEPTION);
293 virtual const int * getConnectivity (MED_EN::medConnectivity ConnectivityType,
294 MED_EN::medEntityMesh Entity,
295 MED_EN::medGeometryElement Type);
296 virtual int getConnectivityLength (MED_EN::medConnectivity ConnectivityType,
297 MED_EN::medEntityMesh Entity,
298 MED_EN::medGeometryElement Type);
300 virtual const int * getConnectivityIndex (MED_EN::medConnectivity ConnectivityType,
301 MED_EN::medEntityMesh Entity);
303 virtual const int* getPolygonsConnectivity(MED_EN::medConnectivity ConnectivityType,
304 MED_EN::medEntityMesh Entity);
305 virtual const int* getPolygonsConnectivityIndex(MED_EN::medConnectivity ConnectivityType,
306 MED_EN::medEntityMesh Entity);
307 virtual int getNumberOfPolygons(MED_EN::medEntityMesh Entity=MED_EN::MED_ALL_ENTITIES) const;
308 virtual const int* getPolyhedronConnectivity(MED_EN::medConnectivity ConnectivityType) const;
309 virtual const int* getPolyhedronFacesIndex() const;
310 virtual const int* getPolyhedronIndex(MED_EN::medConnectivity ConnectivityType) const;
311 virtual int getNumberOfPolyhedronFaces() const;
312 virtual int getNumberOfPolyhedron() const;
313 int *getNodesOfPolyhedron(int polyhedronId, int& lgthOfTab) const;
314 int **getNodesPerFaceOfPolyhedron(int polyhedronId, int& nbOfFaces, int* & nbOfNodesPerFaces) const;
315 const CELLMODEL & getType (MED_EN::medGeometryElement Type) const;
316 const CELLMODEL * getCellsTypes (MED_EN::medEntityMesh Entity) const
317 throw (MEDEXCEPTION);
318 string * getCellTypeNames (MED_EN::medEntityMesh Entity) const
319 throw (MEDEXCEPTION);
321 int getNumberOfNodesInType (MED_EN::medGeometryElement Type) const;
322 int getNumberOfSubCellInType (MED_EN::medGeometryElement Type) const;
323 virtual int getNumberOf (MED_EN::medEntityMesh Entity,
324 MED_EN::medGeometryElement Type) const;
325 virtual const int* getValue (MED_EN::medConnectivity TypeConnectivity,
326 MED_EN::medGeometryElement Type);
327 virtual const int* getValueIndex (MED_EN::medConnectivity TypeConnectivity);
329 virtual inline const int* getReverseConnectivity (MED_EN::medConnectivity ConnectivityType,
330 MED_EN::medEntityMesh Entity=MED_EN::MED_CELL)
331 throw (MEDEXCEPTION);
332 virtual inline const int* getReverseConnectivityIndex (MED_EN::medConnectivity ConnectivityType,
333 MED_EN::medEntityMesh Entity=MED_EN::MED_CELL)
334 throw (MEDEXCEPTION);
336 const int* getNeighbourhood() const;
337 void invertConnectivityForAFace(int faceId, const int *nodalConnForFace, bool polygonFace=false);
338 bool deepCompare(const CONNECTIVITY& other) const;
342 /*----------------------*/
343 /* Methodes Inline */
344 /*----------------------*/
346 /*! Returns the medEntityMesh */
347 //--------------------------------------------------//
348 inline MED_EN::medEntityMesh CONNECTIVITY::getEntity() const
349 //--------------------------------------------------//
354 /*! Returns the number of different %medGeometryElement types
355 existing in the specified entity. \n
356 Note : Not implemented for MED_ALL_ENTITIES. */
357 //-----------------------------------------------------------------------//
358 inline int CONNECTIVITY::getNumberOfTypes(MED_EN::medEntityMesh Entity) const
359 //-----------------------------------------------------------------------//
361 MESSAGE_MED("CONNECTIVITY::getNumberOfTypes : Entity = "<<Entity<<", _entity = "<<_entity);
363 return _numberOfTypes;
364 else if (_constituent!=NULL)
365 return _constituent->getNumberOfTypes(Entity);
366 else if (_constituent == NULL)
368 MESSAGE_MED("CONNECTIVITY::getNumberOfTypes : _constituent == NULL");
371 (const_cast <CONNECTIVITY *> (this))->calculateDescendingConnectivity();
373 catch (MEDEXCEPTION &)
378 SCRUTE_MED(_entityDimension);
380 if (_entityDimension != 2 && _entityDimension != 3) return 0;
384 _constituent->calculateConnectivity(MED_EN::MED_NODAL,Entity);
386 catch (MEDEXCEPTION &)
391 return _constituent->getNumberOfTypes(Entity);
394 return 0; // because it is the right information (no exception needed)!
397 /*! Returns an array of all %medGeometryElement types existing in the mesh
398 for the given %medEntityMesh.
399 Note : Not implemented for MED_ALL_ENTITIES.
400 Throws an exception if Entity is unknown */
401 //------------------------------------------------------------------------------------------//
402 inline const MED_EN::medGeometryElement* CONNECTIVITY::getGeometricTypes(MED_EN::medEntityMesh Entity) const
404 //------------------------------------------------------------------------------------------//
407 return _geometricTypes;
408 else if (_constituent!=NULL)
409 return _constituent->getGeometricTypes(Entity);
411 throw MEDEXCEPTION("CONNECTIVITY::getGeometricTypes : Entity not defined !");
414 /*! Returns an array containing the accumulated number of entities sorted by the geometric type.\n
418 In case of a CONNECTIVITY containing 3*MED_TRIA3 et 2*MED_QUAD4 : \n
419 int * count = getGlobalNumberingIndex(MED_CELL)\n
420 count[0] is always set to 1\n
421 count[1] is set to 1+3=4\n
422 count[2] is set to 4+2=6 = total number of cells + 1\n
424 Note : Not implemented for MED_ALL_ENTITIES. \n
425 Note : The geometric type order is given by the typedef enum medGeometryElement.
428 //----------------------------------------------------------------------------------//
429 inline const int * CONNECTIVITY::getGlobalNumberingIndex(MED_EN::medEntityMesh Entity) const
431 //----------------------------------------------------------------------------------//
435 else if (_constituent!=NULL)
436 return _constituent->getGlobalNumberingIndex(Entity);
438 throw MEDEXCEPTION("CONNECTIVITY::getGlobalNumberingIndex : Entity not defined !");
441 /*! Returns true if a connectivity exists on elements of type "Entity" */
442 //-----------------------------------------------------------------------------//
443 inline bool CONNECTIVITY::existConnectivity( MED_EN::medConnectivity ConnectivityType,
444 MED_EN::medEntityMesh Entity) const
445 //-----------------------------------------------------------------------------//
447 if (_entity==Entity) {
448 if ((ConnectivityType == MED_EN::MED_NODAL) && (_nodal != (MEDSKYLINEARRAY*)NULL))
450 if ((ConnectivityType==MED_EN::MED_DESCENDING)&(_descending!=(MEDSKYLINEARRAY*)NULL))
452 } else if (_constituent!=NULL)
453 return _constituent->existConnectivity(ConnectivityType,Entity);
457 /*! Returns true if a polygons connectivity exists on elements of type "Entity" */
458 //-----------------------------------------------------------------------------//
459 inline bool CONNECTIVITY::existPolygonsConnectivity(MED_EN::medConnectivity ConnectivityType,
460 MED_EN::medEntityMesh Entity) const
461 //-----------------------------------------------------------------------------//
463 if (_entity == Entity)
465 MESSAGE_MED("existPolygonsConnectivity : _entity == Entity = "<<Entity);
466 if (ConnectivityType == MED_EN::MED_NODAL && _polygonsNodal != (MEDSKYLINEARRAY*) NULL)
468 if (ConnectivityType == MED_EN::MED_DESCENDING && _polygonsDescending != (MEDSKYLINEARRAY*) NULL)
471 else if (_constituent != (CONNECTIVITY*) NULL)
472 return _constituent->existPolygonsConnectivity(ConnectivityType,Entity);
476 /*! Returns true if a polyhedron connectivity exists on elements of type "Entity" */
477 //-----------------------------------------------------------------------------//
478 inline bool CONNECTIVITY::existPolyhedronConnectivity(MED_EN::medConnectivity ConnectivityType,
479 MED_EN::medEntityMesh Entity) const
480 //-----------------------------------------------------------------------------//
482 if (_entity == Entity)
484 MESSAGE_MED("existPolyhedronConnectivity : _entity == Entity = "<<Entity);
485 if (ConnectivityType == MED_EN::MED_NODAL && _polyhedronNodal != (POLYHEDRONARRAY*) NULL)
487 if (ConnectivityType == MED_EN::MED_DESCENDING && _polyhedronDescending != (MEDSKYLINEARRAY*) NULL)
490 else if (_constituent != (CONNECTIVITY*) NULL)
491 return _constituent->existPolyhedronConnectivity(ConnectivityType,Entity);
496 Returns an array containing CELLMODEL foreach element type present
497 in connectivity for given medEntityMesh (similar as getGeometricTypes).\n
498 Throw an execption if the given entity is not defined or if the array is not defined.
500 //-----------------------------------------------------------------------------//
501 inline const CELLMODEL * CONNECTIVITY::getCellsTypes(MED_EN::medEntityMesh Entity) const
503 //-----------------------------------------------------------------------------//
505 if (Entity == _entity)
509 throw MEDEXCEPTION("CONNECTIVITY::getCellsTypes(medEntityMesh) :"
510 " CELLMODEL array is not defined !");
512 if (_constituent != NULL)
513 return _constituent->getCellsTypes(Entity);
515 throw MEDEXCEPTION("CONNECTIVITY::getCellsTypes(medEntityMesh) : Not found Entity !");
518 Returns an array (it should deleted after use) containing the whole list of
519 CELLMODEL Name foreach element type present in connectivity for given
520 medEntityMesh (similar as getGeometricTypes).\n
521 Throw an execption if the given entity is not defined or if the array is not
525 //-----------------------------------------------------------------------------//
526 inline string * CONNECTIVITY::getCellTypeNames(MED_EN::medEntityMesh Entity) const
528 //-----------------------------------------------------------------------------//
530 if (Entity == _entity)
533 string * stringArray = new string[_numberOfTypes];
535 for (int i=0;i<_numberOfTypes;i++)
536 stringArray[i] = _type[i].getName();
541 throw MEDEXCEPTION("CONNECTIVITY::getCellTypeNames(medEntityMesh) :"
542 " CELLMODEL array is not defined !");
544 if (_constituent != NULL)
545 return _constituent->getCellTypeNames(Entity);
547 throw MEDEXCEPTION("CONNECTIVITY::getCellTypeNames(medEntityMesh) : Not found Entity !");
556 //------------------------------------------------------------------------------------------//
557 inline const int* CONNECTIVITY::getReverseConnectivity( MED_EN::medConnectivity ConnectivityType,
558 MED_EN::medEntityMesh Entity)
560 //------------------------------------------------------------------------------------------//
563 if (ConnectivityType==MED_EN::MED_NODAL)
564 return getReverseNodalConnectivity();
565 else if (ConnectivityType==MED_EN::MED_DESCENDING)
566 return getReverseDescendingConnectivity();
568 throw MEDEXCEPTION("MESH::getReverseConnectivity : connectivity mode not supported !");
571 if (NULL==_constituent)
572 calculateDescendingConnectivity();
573 return _constituent->getReverseConnectivity(ConnectivityType,Entity);
577 //-----------------------------------------------------------------------------------------------//
578 inline const int* CONNECTIVITY::getReverseConnectivityIndex(MED_EN::medConnectivity ConnectivityType,
579 MED_EN::medEntityMesh Entity)
581 //-----------------------------------------------------------------------------------------------//
584 if (ConnectivityType==MED_EN::MED_NODAL)
585 return getReverseNodalConnectivityIndex();
586 else if (ConnectivityType==MED_EN::MED_DESCENDING)
587 return getReverseDescendingConnectivityIndex();
589 throw MEDEXCEPTION("MESH::getReverseConnectivityIndex : connectivity mode not supported !");
592 if (NULL==_constituent)
593 calculateDescendingConnectivity();
594 return _constituent->getReverseConnectivityIndex(ConnectivityType,Entity);
598 inline void CONNECTIVITY::setNumberOfNodes(int NumberOfNodes)
600 _numberOfNodes=NumberOfNodes;
603 inline int CONNECTIVITY::getNumberOfNodes()
605 return _numberOfNodes;
608 inline void CONNECTIVITY::setEntityDimension(int EntityDimension)
610 _entityDimension=EntityDimension;
613 int CONNECTIVITY::getEntityDimension() const
615 return _entityDimension;
618 MED_EN::medGeometryElement CONNECTIVITY::getPolyTypeRelativeTo() const
620 if(_entity==MED_EN::MED_CELL && _entityDimension==3)
621 return MED_EN::MED_POLYHEDRA;
622 else if((_entity==MED_EN::MED_CELL && _entityDimension==2) || (_entity==MED_EN::MED_FACE && _entityDimension==2))
623 return MED_EN::MED_POLYGON;
625 throw MEDEXCEPTION("getPolyTypeRelativeTo : ");
631 }//End namespace MEDMEM
633 // namespace __gnu_cxx {
634 // template <> struct hash< std::vector<int> > {
635 // size_t operator()(const std::vector<int>& input) {
637 // for (int i=0; i<input.size();i++)
644 #endif /* CONNECTIVITY_HXX */