+ if ( !node1 || !node2 || !node3) return 0;
+ if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+ if(hasConstructionEdges())
+ {
+ SMDS_MeshEdge *edge1, *edge2, *edge3;
+ edge1=FindEdgeOrCreate(node1,node2);
+ edge2=FindEdgeOrCreate(node2,node3);
+ edge3=FindEdgeOrCreate(node3,node1);
+
+ //int ID = myElementIDFactory->GetFreeID(); // -PR- voir si on range cet element
+ SMDS_MeshFace * face = new SMDS_FaceOfEdges(edge1,edge2,edge3);
+ adjustmyCellsCapacity(ID);
+ myCells[ID] = face;
+ myInfo.myNbTriangles++;
+ return face;
+ }
+ else
+ {
+ // --- retrieve nodes ID
+ myNodeIds.resize(3);
+ myNodeIds[0] = node1->getVtkId();
+ myNodeIds[1] = node2->getVtkId();
+ myNodeIds[2] = node3->getVtkId();
+
+ SMDS_MeshFace * face = 0;
+ SMDS_VtkFace *facevtk = myFacePool->getNew();
+ facevtk->init(myNodeIds, this); // put in vtkUnstructuredGrid
+ if (!this->registerElement(ID,facevtk))
+ {
+ this->myGrid->GetCellTypesArray()->SetValue(facevtk->getVtkId(), VTK_EMPTY_CELL);
+ myFacePool->destroy(facevtk);
+ return 0;
+ }
+ face = facevtk;
+ adjustmyCellsCapacity(ID);
+ myCells[ID] = face;
+ myInfo.myNbTriangles++;
+ return face;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///Create a quadrangle and add it to the current mesh. This methode do not bind
+///a ID to the create triangle.
+///////////////////////////////////////////////////////////////////////////////
+SMDS_MeshFace * SMDS_Mesh::createQuadrangle(const SMDS_MeshNode * node1,
+ const SMDS_MeshNode * node2,
+ const SMDS_MeshNode * node3,
+ const SMDS_MeshNode * node4,
+ int ID)
+{
+ if ( !node1 || !node2 || !node3 || !node4 ) return 0;
+ if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+ if(hasConstructionEdges())
+ {
+ SMDS_MeshEdge *edge1, *edge2, *edge3, *edge4;
+ edge1=FindEdgeOrCreate(node1,node2);
+ edge2=FindEdgeOrCreate(node2,node3);
+ edge3=FindEdgeOrCreate(node3,node4);
+ edge4=FindEdgeOrCreate(node4,node1);
+
+ SMDS_MeshFace * face = new SMDS_FaceOfEdges(edge1,edge2,edge3,edge4);
+ adjustmyCellsCapacity(ID);
+ myCells[ID] = face;
+ myInfo.myNbQuadrangles++;
+ return face;
+ }
+ else
+ {
+ // --- retrieve nodes ID
+ myNodeIds.resize(4);
+ myNodeIds[0] = node1->getVtkId();
+ myNodeIds[1] = node2->getVtkId();
+ myNodeIds[2] = node3->getVtkId();
+ myNodeIds[3] = node4->getVtkId();
+
+ SMDS_MeshFace * face = 0;
+ SMDS_VtkFace *facevtk = myFacePool->getNew();
+ facevtk->init(myNodeIds, this);
+ if (!this->registerElement(ID,facevtk))
+ {
+ this->myGrid->GetCellTypesArray()->SetValue(facevtk->getVtkId(), VTK_EMPTY_CELL);
+ myFacePool->destroy(facevtk);
+ return 0;
+ }
+ face = facevtk;
+ adjustmyCellsCapacity(ID);
+ myCells[ID] = face;
+ myInfo.myNbQuadrangles++;
+ return face;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Remove a node and all the elements which own this node
+///////////////////////////////////////////////////////////////////////////////
+
+void SMDS_Mesh::RemoveNode(const SMDS_MeshNode * node)
+{
+ RemoveElement(node, true);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Remove an edge and all the elements which own this edge
+///////////////////////////////////////////////////////////////////////////////
+
+void SMDS_Mesh::Remove0DElement(const SMDS_Mesh0DElement * elem0d)
+{
+ RemoveElement(elem0d,true);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Remove an edge and all the elements which own this edge
+///////////////////////////////////////////////////////////////////////////////
+
+void SMDS_Mesh::RemoveEdge(const SMDS_MeshEdge * edge)
+{
+ RemoveElement(edge,true);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Remove an face and all the elements which own this face
+///////////////////////////////////////////////////////////////////////////////
+
+void SMDS_Mesh::RemoveFace(const SMDS_MeshFace * face)
+{
+ RemoveElement(face, true);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Remove a volume
+///////////////////////////////////////////////////////////////////////////////
+
+void SMDS_Mesh::RemoveVolume(const SMDS_MeshVolume * volume)
+{
+ RemoveElement(volume, true);
+}
+
+//=======================================================================
+//function : RemoveFromParent
+//purpose :
+//=======================================================================
+
+bool SMDS_Mesh::RemoveFromParent()
+{
+ if (myParent==NULL) return false;
+ else return (myParent->RemoveSubMesh(this));
+}
+
+//=======================================================================
+//function : RemoveSubMesh
+//purpose :
+//=======================================================================
+
+bool SMDS_Mesh::RemoveSubMesh(const SMDS_Mesh * aMesh)
+{
+ bool found = false;
+
+ list<SMDS_Mesh *>::iterator itmsh=myChildren.begin();
+ for (; itmsh!=myChildren.end() && !found; itmsh++)
+ {
+ SMDS_Mesh * submesh = *itmsh;
+ if (submesh == aMesh)
+ {
+ found = true;
+ myChildren.erase(itmsh);
+ }
+ }
+
+ return found;
+}
+
+//=======================================================================
+//function : ChangeElementNodes
+//purpose :
+//=======================================================================
+
+bool SMDS_Mesh::ChangeElementNodes(const SMDS_MeshElement * element,
+ const SMDS_MeshNode * nodes[],
+ const int nbnodes)
+{
+ // keep current nodes of elem
+ set<const SMDS_MeshNode*> oldNodes( element->begin_nodes(), element->end_nodes() );
+
+ // change nodes
+ bool Ok = false;
+ SMDS_MeshCell* cell = dynamic_cast<SMDS_MeshCell*>((SMDS_MeshElement*) element);
+ if (cell)
+ {
+ Ok = cell->vtkOrder(nodes, nbnodes);
+ Ok = cell->ChangeNodes(nodes, nbnodes);
+ }
+
+ if ( Ok ) { // update InverseElements
+
+ set<const SMDS_MeshNode*>::iterator it;
+
+ // AddInverseElement to new nodes
+ for ( int i = 0; i < nbnodes; i++ ) {
+ it = oldNodes.find( nodes[i] );
+ if ( it == oldNodes.end() )
+ // new node
+ const_cast<SMDS_MeshNode*>( nodes[i] )->AddInverseElement( cell );
+ else
+ // remove from oldNodes a node that remains in elem
+ oldNodes.erase( it );
+ }
+ // RemoveInverseElement from the nodes removed from elem
+ for ( it = oldNodes.begin(); it != oldNodes.end(); it++ )
+ {
+ SMDS_MeshNode * n = const_cast<SMDS_MeshNode *>( *it );
+ n->RemoveInverseElement( cell );
+ }
+ }
+
+ return Ok;
+}
+
+//=======================================================================
+//function : ChangePolyhedronNodes
+//purpose : to change nodes of polyhedral volume
+//=======================================================================
+bool SMDS_Mesh::ChangePolyhedronNodes (const SMDS_MeshElement * elem,
+ const vector<const SMDS_MeshNode*>& nodes,
+ const vector<int> & quantities)
+{
+ if (elem->GetType() != SMDSAbs_Volume) {
+ MESSAGE("WRONG ELEM TYPE");
+ return false;
+ }
+
+ const SMDS_VtkVolume* vol = dynamic_cast<const SMDS_VtkVolume*>(elem);
+ if (!vol) {
+ return false;
+ }
+
+ // keep current nodes of elem
+ set<const SMDS_MeshElement*> oldNodes;
+ SMDS_ElemIteratorPtr itn = elem->nodesIterator();
+ while (itn->more()) {
+ oldNodes.insert(itn->next());
+ }
+
+ // change nodes
+ // TODO remove this function
+ //bool Ok = const_cast<SMDS_VtkVolume*>(vol)->ChangeNodes(nodes, quantities);
+ bool Ok = false;
+ if (!Ok) {
+ return false;
+ }
+
+ // update InverseElements
+
+ // AddInverseElement to new nodes
+ int nbnodes = nodes.size();
+ set<const SMDS_MeshElement*>::iterator it;
+ for (int i = 0; i < nbnodes; i++) {
+ it = oldNodes.find(nodes[i]);
+ if (it == oldNodes.end()) {
+ // new node
+ const_cast<SMDS_MeshNode*>(nodes[i])->AddInverseElement(elem);
+ } else {
+ // remove from oldNodes a node that remains in elem
+ oldNodes.erase(it);
+ }
+ }
+
+ // RemoveInverseElement from the nodes removed from elem
+ for (it = oldNodes.begin(); it != oldNodes.end(); it++) {
+ SMDS_MeshNode * n = static_cast<SMDS_MeshNode *>
+ (const_cast<SMDS_MeshElement *>( *it ));
+ n->RemoveInverseElement(elem);
+ }
+
+ return Ok;
+}
+
+
+//=======================================================================
+//function : Find0DElement
+//purpose :
+//=======================================================================
+const SMDS_Mesh0DElement* SMDS_Mesh::Find0DElement(int idnode) const
+{
+ const SMDS_MeshNode * node = FindNode(idnode);
+ if(node == NULL) return NULL;
+ return Find0DElement(node);
+}
+
+const SMDS_Mesh0DElement* SMDS_Mesh::Find0DElement(const SMDS_MeshNode * node)
+{
+ if (!node) return 0;
+ const SMDS_Mesh0DElement* toReturn = NULL;
+ SMDS_ElemIteratorPtr it1 = node->GetInverseElementIterator(SMDSAbs_0DElement);
+ while (it1->more() && (toReturn == NULL)) {
+ const SMDS_MeshElement* e = it1->next();
+ if (e->NbNodes() == 1) {
+ toReturn = static_cast<const SMDS_Mesh0DElement*>(e);
+ }
+ }
+ return toReturn;
+}
+
+//=======================================================================
+//function : FindBall
+//purpose :
+//=======================================================================
+
+const SMDS_BallElement* SMDS_Mesh::FindBall(int idnode) const
+{
+ const SMDS_MeshNode * node = FindNode(idnode);
+ if(node == NULL) return NULL;
+ return FindBall(node);
+}
+
+const SMDS_BallElement* SMDS_Mesh::FindBall(const SMDS_MeshNode * node)
+{
+ if (!node) return 0;
+ const SMDS_BallElement* toReturn = NULL;
+ SMDS_ElemIteratorPtr it1 = node->GetInverseElementIterator(SMDSAbs_Ball);
+ while (it1->more() && (toReturn == NULL)) {
+ const SMDS_MeshElement* e = it1->next();
+ if (e->GetGeomType() == SMDSGeom_BALL)
+ toReturn = static_cast<const SMDS_BallElement*>(e);
+ }
+ return toReturn;
+}
+
+//=======================================================================
+//function : Find0DElementOrCreate
+//purpose :
+//=======================================================================
+//SMDS_Mesh0DElement* SMDS_Mesh::Find0DElementOrCreate(const SMDS_MeshNode * node)
+//{
+// if (!node) return 0;
+// SMDS_Mesh0DElement * toReturn = NULL;
+// toReturn = const_cast<SMDS_Mesh0DElement*>(Find0DElement(node));
+// if (toReturn == NULL) {
+// //if (my0DElements.Extent() % CHECKMEMORY_INTERVAL == 0) CheckMemory();
+// toReturn = new SMDS_Mesh0DElement(node);
+// my0DElements.Add(toReturn);
+// myInfo.myNb0DElements++;
+// }
+// return toReturn;
+//}
+
+
+//=======================================================================
+//function : FindEdge
+//purpose :
+//=======================================================================
+
+const SMDS_MeshEdge* SMDS_Mesh::FindEdge(int idnode1, int idnode2) const
+{
+ const SMDS_MeshNode * node1=FindNode(idnode1);
+ const SMDS_MeshNode * node2=FindNode(idnode2);
+ if((node1==NULL)||(node2==NULL)) return NULL;
+ return FindEdge(node1,node2);
+}
+
+//#include "Profiler.h"
+const SMDS_MeshEdge* SMDS_Mesh::FindEdge(const SMDS_MeshNode * node1,
+ const SMDS_MeshNode * node2)
+{
+ if ( !node1 ) return 0;
+ const SMDS_MeshEdge * toReturn=NULL;
+ //PROFILER_Init();
+ //PROFILER_Set();
+ SMDS_ElemIteratorPtr it1=node1->GetInverseElementIterator(SMDSAbs_Edge);
+ //PROFILER_Get(0);
+ //PROFILER_Set();
+ while(it1->more()) {
+ const SMDS_MeshElement * e = it1->next();
+ if ( e->NbNodes() == 2 && e->GetNodeIndex( node2 ) >= 0 ) {
+ toReturn = static_cast<const SMDS_MeshEdge*>( e );
+ break;
+ }
+ }
+ //PROFILER_Get(1);
+ return toReturn;
+}
+
+
+//=======================================================================
+//function : FindEdgeOrCreate
+//purpose :
+//=======================================================================
+
+SMDS_MeshEdge* SMDS_Mesh::FindEdgeOrCreate(const SMDS_MeshNode * node1,
+ const SMDS_MeshNode * node2)
+{
+ if ( !node1 || !node2) return 0;
+ SMDS_MeshEdge * toReturn=NULL;
+ toReturn=const_cast<SMDS_MeshEdge*>(FindEdge(node1,node2));
+ if(toReturn==NULL) {
+ if ( NbEdges() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+ int ID = myElementIDFactory->GetFreeID(); // -PR- voir si on range cet element
+ adjustmyCellsCapacity(ID);
+ myNodeIds.resize(2);
+ myNodeIds[0] = node1->getVtkId();
+ myNodeIds[1] = node2->getVtkId();
+
+ SMDS_VtkEdge *edgevtk = myEdgePool->getNew();
+ edgevtk->init(myNodeIds, this);
+ if (!this->registerElement(ID,edgevtk))
+ {
+ this->myGrid->GetCellTypesArray()->SetValue(edgevtk->getVtkId(), VTK_EMPTY_CELL);
+ myEdgePool->destroy(edgevtk);
+ return 0;
+ }
+ toReturn = edgevtk;
+ myCells[ID] = toReturn;
+ myInfo.myNbEdges++;
+ }
+ return toReturn;
+}
+
+
+//=======================================================================
+//function : FindEdge
+//purpose :
+//=======================================================================
+
+const SMDS_MeshEdge* SMDS_Mesh::FindEdge(int idnode1, int idnode2,
+ int idnode3) const
+{
+ const SMDS_MeshNode * node1=FindNode(idnode1);
+ const SMDS_MeshNode * node2=FindNode(idnode2);
+ const SMDS_MeshNode * node3=FindNode(idnode3);
+ return FindEdge(node1,node2,node3);
+}
+
+const SMDS_MeshEdge* SMDS_Mesh::FindEdge(const SMDS_MeshNode * node1,
+ const SMDS_MeshNode * node2,
+ const SMDS_MeshNode * node3)
+{
+ if ( !node1 ) return 0;
+ SMDS_ElemIteratorPtr it1 = node1->GetInverseElementIterator(SMDSAbs_Edge);
+ while(it1->more()) {
+ const SMDS_MeshElement * e = it1->next();
+ if ( e->NbNodes() == 3 ) {
+ SMDS_ElemIteratorPtr it2 = e->nodesIterator();
+ while(it2->more()) {
+ const SMDS_MeshElement* n = it2->next();
+ if( n!=node1 &&
+ n!=node2 &&
+ n!=node3 )
+ {
+ e = 0;
+ break;
+ }
+ }
+ if ( e )
+ return static_cast<const SMDS_MeshEdge *> (e);
+ }
+ }
+ return 0;
+}
+
+
+//=======================================================================
+//function : FindFace
+//purpose :
+//=======================================================================
+
+const SMDS_MeshFace* SMDS_Mesh::FindFace(int idnode1, int idnode2,
+ int idnode3) const
+{
+ const SMDS_MeshNode * node1=FindNode(idnode1);
+ const SMDS_MeshNode * node2=FindNode(idnode2);
+ const SMDS_MeshNode * node3=FindNode(idnode3);
+ return FindFace(node1, node2, node3);
+}
+
+const SMDS_MeshFace* SMDS_Mesh::FindFace(const SMDS_MeshNode *node1,
+ const SMDS_MeshNode *node2,
+ const SMDS_MeshNode *node3)
+{
+ if ( !node1 ) return 0;
+ SMDS_ElemIteratorPtr it1 = node1->GetInverseElementIterator(SMDSAbs_Face);
+ while(it1->more()) {
+ const SMDS_MeshElement * e = it1->next();
+ if ( e->NbNodes() == 3 ) {
+ SMDS_ElemIteratorPtr it2 = e->nodesIterator();
+ while(it2->more()) {
+ const SMDS_MeshElement* n = it2->next();
+ if( n!=node1 &&
+ n!=node2 &&
+ n!=node3 )
+ {
+ e = 0;
+ break;
+ }
+ }
+ if ( e )
+ return static_cast<const SMDS_MeshFace *> (e);
+ }
+ }
+ return 0;
+}
+
+SMDS_MeshFace* SMDS_Mesh::FindFaceOrCreate(const SMDS_MeshNode *node1,
+ const SMDS_MeshNode *node2,
+ const SMDS_MeshNode *node3)
+{
+ SMDS_MeshFace * toReturn=NULL;
+ toReturn = const_cast<SMDS_MeshFace*>(FindFace(node1,node2,node3));
+ if(toReturn==NULL) {
+ int ID = myElementIDFactory->GetFreeID();
+ toReturn = createTriangle(node1,node2,node3, ID);
+ }
+ return toReturn;
+}
+
+
+//=======================================================================
+//function : FindFace
+//purpose :
+//=======================================================================
+
+const SMDS_MeshFace* SMDS_Mesh::FindFace(int idnode1, int idnode2,
+ int idnode3, int idnode4) const
+{
+ const SMDS_MeshNode * node1=FindNode(idnode1);
+ const SMDS_MeshNode * node2=FindNode(idnode2);
+ const SMDS_MeshNode * node3=FindNode(idnode3);
+ const SMDS_MeshNode * node4=FindNode(idnode4);
+ return FindFace(node1, node2, node3, node4);
+}
+
+const SMDS_MeshFace* SMDS_Mesh::FindFace(const SMDS_MeshNode *node1,
+ const SMDS_MeshNode *node2,
+ const SMDS_MeshNode *node3,
+ const SMDS_MeshNode *node4)
+{
+ if ( !node1 ) return 0;
+ SMDS_ElemIteratorPtr it1 = node1->GetInverseElementIterator(SMDSAbs_Face);
+ while(it1->more()) {
+ const SMDS_MeshElement * e = it1->next();
+ if ( e->NbNodes() == 4 ) {
+ SMDS_ElemIteratorPtr it2 = e->nodesIterator();
+ while(it2->more()) {
+ const SMDS_MeshElement* n = it2->next();
+ if( n!=node1 &&
+ n!=node2 &&
+ n!=node3 &&
+ n!=node4 )
+ {
+ e = 0;
+ break;
+ }
+ }
+ if ( e )
+ return static_cast<const SMDS_MeshFace *> (e);
+ }
+ }
+ return 0;
+}
+
+SMDS_MeshFace* SMDS_Mesh::FindFaceOrCreate(const SMDS_MeshNode *node1,
+ const SMDS_MeshNode *node2,
+ const SMDS_MeshNode *node3,
+ const SMDS_MeshNode *node4)
+{
+ SMDS_MeshFace * toReturn=NULL;
+ toReturn=const_cast<SMDS_MeshFace*>(FindFace(node1,node2,node3,node4));
+ if(toReturn==NULL) {
+ int ID = myElementIDFactory->GetFreeID();
+ toReturn=createQuadrangle(node1,node2,node3,node4,ID);
+ }
+ return toReturn;
+}
+
+
+//=======================================================================
+//function : FindFace
+//purpose :quadratic triangle
+//=======================================================================
+
+const SMDS_MeshFace* SMDS_Mesh::FindFace(int idnode1, int idnode2,
+ int idnode3, int idnode4,
+ int idnode5, int idnode6) const
+{
+ const SMDS_MeshNode * node1 = FindNode(idnode1);
+ const SMDS_MeshNode * node2 = FindNode(idnode2);
+ const SMDS_MeshNode * node3 = FindNode(idnode3);
+ const SMDS_MeshNode * node4 = FindNode(idnode4);
+ const SMDS_MeshNode * node5 = FindNode(idnode5);
+ const SMDS_MeshNode * node6 = FindNode(idnode6);
+ return FindFace(node1, node2, node3, node4, node5, node6);
+}
+
+const SMDS_MeshFace* SMDS_Mesh::FindFace(const SMDS_MeshNode *node1,
+ const SMDS_MeshNode *node2,
+ const SMDS_MeshNode *node3,
+ const SMDS_MeshNode *node4,
+ const SMDS_MeshNode *node5,
+ const SMDS_MeshNode *node6)
+{
+ if ( !node1 ) return 0;
+ SMDS_ElemIteratorPtr it1 = node1->GetInverseElementIterator(SMDSAbs_Face);
+ while(it1->more()) {
+ const SMDS_MeshElement * e = it1->next();
+ if ( e->NbNodes() == 6 ) {
+ SMDS_ElemIteratorPtr it2 = e->nodesIterator();
+ while(it2->more()) {
+ const SMDS_MeshElement* n = it2->next();
+ if( n!=node1 &&
+ n!=node2 &&
+ n!=node3 &&
+ n!=node4 &&
+ n!=node5 &&
+ n!=node6 )
+ {
+ e = 0;
+ break;
+ }
+ }
+ if ( e )
+ return static_cast<const SMDS_MeshFace *> (e);
+ }
+ }
+ return 0;
+}
+
+
+//=======================================================================
+//function : FindFace
+//purpose : quadratic quadrangle
+//=======================================================================
+
+const SMDS_MeshFace* SMDS_Mesh::FindFace(int idnode1, int idnode2,
+ int idnode3, int idnode4,
+ int idnode5, int idnode6,
+ int idnode7, int idnode8) const
+{
+ const SMDS_MeshNode * node1 = FindNode(idnode1);
+ const SMDS_MeshNode * node2 = FindNode(idnode2);
+ const SMDS_MeshNode * node3 = FindNode(idnode3);
+ const SMDS_MeshNode * node4 = FindNode(idnode4);
+ const SMDS_MeshNode * node5 = FindNode(idnode5);
+ const SMDS_MeshNode * node6 = FindNode(idnode6);
+ const SMDS_MeshNode * node7 = FindNode(idnode7);
+ const SMDS_MeshNode * node8 = FindNode(idnode8);
+ return FindFace(node1, node2, node3, node4, node5, node6, node7, node8);
+}
+
+const SMDS_MeshFace* SMDS_Mesh::FindFace(const SMDS_MeshNode *node1,
+ const SMDS_MeshNode *node2,
+ const SMDS_MeshNode *node3,
+ const SMDS_MeshNode *node4,
+ const SMDS_MeshNode *node5,
+ const SMDS_MeshNode *node6,
+ const SMDS_MeshNode *node7,
+ const SMDS_MeshNode *node8)
+{
+ if ( !node1 ) return 0;
+ SMDS_ElemIteratorPtr it1 = node1->GetInverseElementIterator(SMDSAbs_Face);
+ while(it1->more()) {
+ const SMDS_MeshElement * e = it1->next();
+ if ( e->NbNodes() == 8 ) {
+ SMDS_ElemIteratorPtr it2 = e->nodesIterator();
+ while(it2->more()) {
+ const SMDS_MeshElement* n = it2->next();
+ if( n!=node1 &&
+ n!=node2 &&
+ n!=node3 &&
+ n!=node4 &&
+ n!=node5 &&
+ n!=node6 &&
+ n!=node7 &&
+ n!=node8 )
+ {
+ e = 0;
+ break;
+ }
+ }
+ if ( e )
+ return static_cast<const SMDS_MeshFace *> (e);
+ }
+ }
+ return 0;
+}
+
+
+//=======================================================================
+//function : FindElement
+//purpose :
+//=======================================================================
+
+const SMDS_MeshElement* SMDS_Mesh::FindElement(int IDelem) const
+{
+ if ( IDelem <= 0 || IDelem >= (int)myCells.size() )
+ {
+ return 0;
+ }
+ return myCells[IDelem];
+}
+
+//=======================================================================
+//function : FindFace
+//purpose : find polygon
+//=======================================================================
+
+const SMDS_MeshFace* SMDS_Mesh::FindFace (const vector<int>& nodes_ids) const
+{
+ int nbnodes = nodes_ids.size();
+ vector<const SMDS_MeshNode *> poly_nodes (nbnodes);
+ for (int inode = 0; inode < nbnodes; inode++) {
+ const SMDS_MeshNode * node = FindNode(nodes_ids[inode]);
+ if (node == NULL) return NULL;
+ poly_nodes[inode] = node;
+ }
+ return FindFace(poly_nodes);
+}
+
+const SMDS_MeshFace* SMDS_Mesh::FindFace (const vector<const SMDS_MeshNode *>& nodes)
+{
+ return (const SMDS_MeshFace*) FindElement( nodes, SMDSAbs_Face );
+}
+
+
+//================================================================================
+/*!
+ * \brief Return element based on all given nodes
+ * \param nodes - node of element
+ * \param type - type of element
+ * \param noMedium - true if medium nodes of quadratic element are not included in <nodes>
+ * \retval const SMDS_MeshElement* - found element or NULL
+ */
+//================================================================================
+
+const SMDS_MeshElement* SMDS_Mesh::FindElement (const vector<const SMDS_MeshNode *>& nodes,
+ const SMDSAbs_ElementType type,
+ const bool noMedium)
+{
+ if ( nodes.size() > 0 && nodes[0] )
+ {
+ SMDS_ElemIteratorPtr itF = nodes[0]->GetInverseElementIterator(type);
+ while (itF->more())
+ {
+ const SMDS_MeshElement* e = itF->next();
+ int nbNodesToCheck = noMedium ? e->NbCornerNodes() : e->NbNodes();
+ if ( nbNodesToCheck == (int)nodes.size() )
+ {
+ for ( size_t i = 1; e && i < nodes.size(); ++i )
+ {
+ int nodeIndex = e->GetNodeIndex( nodes[ i ]);
+ if ( nodeIndex < 0 || nodeIndex >= nbNodesToCheck )
+ e = 0;
+ }
+ if ( e )
+ return e;
+ }
+ }
+ }
+ return NULL;
+}
+
+//=======================================================================
+//function : DumpNodes
+//purpose :
+//=======================================================================
+
+void SMDS_Mesh::DumpNodes() const
+{
+ SMDS_NodeIteratorPtr itnode=nodesIterator();
+ while(itnode->more()) ; //MESSAGE(itnode->next());
+}
+
+//=======================================================================
+//function : Dump0DElements
+//purpose :
+//=======================================================================
+void SMDS_Mesh::Dump0DElements() const
+{
+ SMDS_ElemIteratorPtr it0d = elementsIterator(SMDSAbs_0DElement);
+ while(it0d->more()) ; //MESSAGE(it0d->next());
+}
+
+//=======================================================================
+//function : DumpEdges
+//purpose :
+//=======================================================================
+
+void SMDS_Mesh::DumpEdges() const
+{
+ SMDS_EdgeIteratorPtr itedge=edgesIterator();
+ while(itedge->more()) ; //MESSAGE(itedge->next());
+}
+
+//=======================================================================
+//function : DumpFaces
+//purpose :
+//=======================================================================
+
+void SMDS_Mesh::DumpFaces() const
+{
+ SMDS_FaceIteratorPtr itface=facesIterator();
+ while(itface->more()) ; //MESSAGE(itface->next());
+}
+
+//=======================================================================
+//function : DumpVolumes
+//purpose :
+//=======================================================================
+
+void SMDS_Mesh::DumpVolumes() const
+{
+ SMDS_VolumeIteratorPtr itvol=volumesIterator();
+ while(itvol->more()) ; //MESSAGE(itvol->next());
+}
+
+//=======================================================================
+//function : DebugStats
+//purpose :
+//=======================================================================
+
+void SMDS_Mesh::DebugStats() const
+{
+ MESSAGE("Debug stats of mesh : ");
+
+ MESSAGE("===== NODES ====="<<NbNodes());
+ MESSAGE("===== 0DELEMS ====="<<Nb0DElements());
+ MESSAGE("===== EDGES ====="<<NbEdges());
+ MESSAGE("===== FACES ====="<<NbFaces());
+ MESSAGE("===== VOLUMES ====="<<NbVolumes());
+
+ MESSAGE("End Debug stats of mesh ");
+
+ //#ifdef DEB
+
+ SMDS_NodeIteratorPtr itnode=nodesIterator();
+ int sizeofnodes = 0;
+ int sizeoffaces = 0;
+
+ while(itnode->more())
+ {
+ const SMDS_MeshNode *node = itnode->next();
+
+ sizeofnodes += sizeof(*node);
+
+ SMDS_ElemIteratorPtr it = node->GetInverseElementIterator();
+ while(it->more())
+ {
+ const SMDS_MeshElement *me = it->next();
+ sizeofnodes += sizeof(me);
+ }
+ }
+
+ SMDS_FaceIteratorPtr itface=facesIterator();
+ while(itface->more())
+ {
+ const SMDS_MeshElement *face = itface->next();
+ sizeoffaces += sizeof(*face);
+ }
+
+ MESSAGE("total size of node elements = " << sizeofnodes);;
+ MESSAGE("total size of face elements = " << sizeoffaces);;
+
+ //#endif
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Return the number of nodes
+///////////////////////////////////////////////////////////////////////////////
+int SMDS_Mesh::NbNodes() const
+{
+ return myInfo.NbNodes();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Return the number of elements
+///////////////////////////////////////////////////////////////////////////////
+int SMDS_Mesh::NbElements() const
+{
+ return myInfo.NbElements();
+}
+///////////////////////////////////////////////////////////////////////////////
+/// Return the number of 0D elements
+///////////////////////////////////////////////////////////////////////////////
+int SMDS_Mesh::Nb0DElements() const
+{
+ return myInfo.Nb0DElements();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Return the number of 0D elements
+///////////////////////////////////////////////////////////////////////////////
+int SMDS_Mesh::NbBalls() const
+{
+ return myInfo.NbBalls();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Return the number of edges (including construction edges)
+///////////////////////////////////////////////////////////////////////////////
+int SMDS_Mesh::NbEdges() const
+{
+ return myInfo.NbEdges();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Return the number of faces (including construction faces)
+///////////////////////////////////////////////////////////////////////////////
+int SMDS_Mesh::NbFaces() const
+{
+ return myInfo.NbFaces();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Return the number of volumes
+///////////////////////////////////////////////////////////////////////////////
+int SMDS_Mesh::NbVolumes() const
+{
+ return myInfo.NbVolumes();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Return the number of child mesh of this mesh.
+/// Note that the tree structure of SMDS_Mesh is unused in SMESH
+///////////////////////////////////////////////////////////////////////////////
+int SMDS_Mesh::NbSubMesh() const
+{
+ return myChildren.size();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Destroy the mesh and all its elements
+/// All pointer on elements owned by this mesh become illegals.
+///////////////////////////////////////////////////////////////////////////////
+SMDS_Mesh::~SMDS_Mesh()
+{
+ list<SMDS_Mesh*>::iterator itc=myChildren.begin();
+ while(itc!=myChildren.end())
+ {
+ delete *itc;
+ itc++;
+ }
+
+ if(myParent==NULL)
+ {
+ delete myNodeIDFactory;
+ delete myElementIDFactory;
+ }
+ else
+ {
+ SMDS_ElemIteratorPtr eIt = elementsIterator();
+ while ( eIt->more() )
+ {
+ const SMDS_MeshElement *elem = eIt->next();
+ myElementIDFactory->ReleaseID(elem->GetID(), elem->getVtkId());
+ }
+ SMDS_NodeIteratorPtr itn = nodesIterator();
+ while (itn->more())
+ {
+ const SMDS_MeshNode *node = itn->next();
+ ((SMDS_MeshNode*)node)->SetPosition(SMDS_SpacePosition::originSpacePosition());
+ myNodeIDFactory->ReleaseID(node->GetID(), node->getVtkId());
+ }
+ }
+ myGrid->Delete();
+
+ delete myNodePool;
+ delete myVolumePool;
+ delete myFacePool;
+ delete myEdgePool;
+ delete myBallPool;
+}
+
+//================================================================================
+/*!
+ * \brief Clear all data
+ */
+//================================================================================
+
+void SMDS_Mesh::Clear()
+{
+ if (myParent!=NULL)
+ {
+ SMDS_ElemIteratorPtr eIt = elementsIterator();
+ while ( eIt->more() )
+ {
+ const SMDS_MeshElement *elem = eIt->next();
+ myElementIDFactory->ReleaseID(elem->GetID(), elem->getVtkId());
+ }
+ SMDS_NodeIteratorPtr itn = nodesIterator();
+ while (itn->more())
+ {
+ const SMDS_MeshNode *node = itn->next();
+ myNodeIDFactory->ReleaseID(node->GetID(), node->getVtkId());
+ }
+ }
+ else
+ {
+ myNodeIDFactory->Clear();
+ myElementIDFactory->Clear();
+ }
+
+ myVolumePool->clear();
+ myFacePool->clear();
+ myEdgePool->clear();
+ myBallPool->clear();
+
+ clearVector( myCells );
+ clearVector( myCellIdVtkToSmds );
+
+ SMDS_NodeIteratorPtr itn = nodesIterator();
+ while (itn->more())
+ {
+ SMDS_MeshNode *node = (SMDS_MeshNode*)(itn->next());
+ node->SetPosition(SMDS_SpacePosition::originSpacePosition());
+ //myNodePool->destroy(node);
+ }
+ myNodePool->clear();
+ clearVector( myNodes );
+
+ list<SMDS_Mesh*>::iterator itc=myChildren.begin();
+ while(itc!=myChildren.end())
+ (*itc)->Clear();
+
+ myModified = false;
+ myModifTime++;
+ xmin = 0; xmax = 0;
+ ymin = 0; ymax = 0;
+ zmin = 0; zmax = 0;
+
+ myInfo.Clear();
+
+ myGrid->Initialize();
+ myGrid->Allocate();
+ vtkPoints* points = vtkPoints::New();
+ // rnv: to fix bug "21125: EDF 1233 SMESH: Degrardation of precision in a test case for quadratic conversion"
+ // using double type for storing coordinates of nodes instead float.
+ points->SetDataType(VTK_DOUBLE);
+ points->SetNumberOfPoints( 0 );
+ myGrid->SetPoints( points );
+ points->Delete();
+ myGrid->DeleteLinks();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Return true if this mesh create faces with edges.
+/// A false returned value mean that faces are created with nodes. A concequence
+/// is, iteration on edges (SMDS_Element::edgesIterator) will be unavailable.
+///////////////////////////////////////////////////////////////////////////////
+bool SMDS_Mesh::hasConstructionEdges()
+{
+ return myHasConstructionEdges;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Return true if this mesh create volumes with faces
+/// A false returned value mean that volumes are created with nodes or edges.
+/// (see hasConstructionEdges)
+/// A concequence is, iteration on faces (SMDS_Element::facesIterator) will be
+/// unavailable.
+///////////////////////////////////////////////////////////////////////////////
+bool SMDS_Mesh::hasConstructionFaces()
+{
+ return myHasConstructionFaces;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Return true if nodes are linked to the finit elements, they are belonging to.
+/// Currently, It always return true.
+///////////////////////////////////////////////////////////////////////////////
+bool SMDS_Mesh::hasInverseElements()
+{
+ return myHasInverseElements;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Make this mesh creating construction edges (see hasConstructionEdges)
+/// @param b true to have construction edges, else false.
+///////////////////////////////////////////////////////////////////////////////
+void SMDS_Mesh::setConstructionEdges(bool b)
+{
+ myHasConstructionEdges=b;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Make this mesh creating construction faces (see hasConstructionFaces)
+/// @param b true to have construction faces, else false.
+///////////////////////////////////////////////////////////////////////////////
+void SMDS_Mesh::setConstructionFaces(bool b)
+{
+ myHasConstructionFaces=b;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Make this mesh creating link from nodes to elements (see hasInverseElements)
+/// @param b true to link nodes to elements, else false.
+///////////////////////////////////////////////////////////////////////////////
+void SMDS_Mesh::setInverseElements(bool b)
+{
+ if(!b) MESSAGE("Error : inverseElement=false not implemented");
+ myHasInverseElements=b;
+}
+
+namespace {
+
+ //================================================================================
+ /*!
+ * \brief Iterator on elements in id increasing order
+ */
+ //================================================================================
+
+ template <typename ELEM=const SMDS_MeshElement*>
+ class IdSortedIterator : public SMDS_Iterator<ELEM>
+ {
+ SMDS_MeshElementIDFactory& myIDFact;
+ int myID, myMaxID, myNbFound, myTotalNb;
+ SMDSAbs_ElementType myType;
+ ELEM myElem;
+
+ public:
+ IdSortedIterator(const SMDS_MeshElementIDFactory& fact,
+ const SMDSAbs_ElementType type, // SMDSAbs_All NOT allowed!!!
+ const int totalNb)
+ :myIDFact( fact ),
+ myID(1), myMaxID( myIDFact.GetMaxID() ),myNbFound(0), myTotalNb( totalNb ),
+ myType( type ),
+ myElem(0)
+ {
+ next();
+ }
+ bool more()
+ {
+ return myElem;
+ }
+ ELEM next()
+ {
+ ELEM current = myElem;
+
+ for ( myElem = 0; !myElem && myNbFound < myTotalNb && myID <= myMaxID; ++myID )
+ if ((myElem = (ELEM) myIDFact.MeshElement( myID ))
+ && myElem->GetType() != myType )
+ myElem = 0;
+
+ myNbFound += bool(myElem);
+
+ return current;
+ }
+ };
+
+ //================================================================================
+ /*!
+ * \brief Iterator on vector of elements, possibly being resized while iteration
+ */
+ //================================================================================
+
+ template<typename RETURN_VALUE,
+ typename VECTOR_VALUE=SMDS_MeshCell*,
+ typename VALUE_FILTER=SMDS::NonNullFilter<VECTOR_VALUE> >
+ class ElemVecIterator: public SMDS_Iterator<RETURN_VALUE>
+ {
+ const std::vector<VECTOR_VALUE>& _vector;
+ size_t _index;
+ bool _more;
+ VALUE_FILTER _filter;
+ public:
+ ElemVecIterator(const std::vector<VECTOR_VALUE>& vec,
+ const VALUE_FILTER& filter=VALUE_FILTER() )
+ :_vector( vec ), _index(0), _more( !vec.empty() ), _filter( filter )
+ {
+ if ( _more && !_filter( _vector[ _index ]))
+ next();
+ }
+ virtual bool more()
+ {
+ return _more;
+ }
+ virtual RETURN_VALUE next()
+ {
+ if ( !_more ) return NULL;
+ VECTOR_VALUE current = _vector[ _index ];
+ _more = 0;
+ while ( !_more && ++_index < _vector.size() )
+ _more = _filter( _vector[ _index ]);
+ return (RETURN_VALUE) current;
+ }
+ };
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Return an iterator on nodes of the current mesh factory
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_NodeIteratorPtr SMDS_Mesh::nodesIterator(bool idInceasingOrder) const
+{
+ // naturally always sorted by ID
+ typedef ElemVecIterator<const SMDS_MeshNode*, SMDS_MeshNode*> TIterator;
+ return SMDS_NodeIteratorPtr( new TIterator(myNodes));
+}
+
+SMDS_ElemIteratorPtr SMDS_Mesh::elementGeomIterator(SMDSAbs_GeometryType type) const
+{
+ // naturally always sorted by ID
+ typedef ElemVecIterator
+ < const SMDS_MeshElement*, SMDS_MeshCell*, SMDS_MeshElement::GeomFilter > TIterator;
+ return SMDS_ElemIteratorPtr
+ (new TIterator(myCells, SMDS_MeshElement::GeomFilter( type )));
+}
+
+SMDS_ElemIteratorPtr SMDS_Mesh::elementEntityIterator(SMDSAbs_EntityType type) const
+{
+ if ( type == SMDSEntity_Node )
+ {
+ typedef ElemVecIterator<const SMDS_MeshElement*, SMDS_MeshNode*> TIterator;
+ return SMDS_ElemIteratorPtr( new TIterator(myNodes));
+ }
+ // naturally always sorted by ID
+ typedef ElemVecIterator
+ < const SMDS_MeshElement*, SMDS_MeshCell*, SMDS_MeshElement::EntityFilter > TIterator;
+ return SMDS_ElemIteratorPtr
+ (new TIterator(myCells, SMDS_MeshElement::EntityFilter( type )));
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Return an iterator on elements of the current mesh factory
+///////////////////////////////////////////////////////////////////////////////
+SMDS_ElemIteratorPtr SMDS_Mesh::elementsIterator(SMDSAbs_ElementType type) const
+{
+ // naturally always sorted by ID
+ switch ( type ) {
+
+ case SMDSAbs_All:
+ return SMDS_ElemIteratorPtr (new ElemVecIterator<const SMDS_MeshElement*>(myCells));
+
+ case SMDSAbs_Node:
+ return SMDS_ElemIteratorPtr
+ ( new ElemVecIterator<const SMDS_MeshElement*, SMDS_MeshNode*>( myNodes ));
+
+ default:
+ typedef ElemVecIterator
+ < const SMDS_MeshElement*, SMDS_MeshCell*, SMDS_MeshElement::TypeFilter > TIterator;
+ return SMDS_ElemIteratorPtr (new TIterator(myCells, SMDS_MeshElement::TypeFilter( type )));
+ }
+ return SMDS_ElemIteratorPtr();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///Return an iterator on edges of the current mesh.
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_EdgeIteratorPtr SMDS_Mesh::edgesIterator(bool idInceasingOrder) const
+{
+ // naturally always sorted by ID
+ typedef ElemVecIterator
+ < const SMDS_MeshEdge*, SMDS_MeshCell*, SMDS_MeshElement::TypeFilter > TIterator;
+ return SMDS_EdgeIteratorPtr
+ (new TIterator(myCells, SMDS_MeshElement::TypeFilter( SMDSAbs_Edge )));
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///Return an iterator on faces of the current mesh.
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_FaceIteratorPtr SMDS_Mesh::facesIterator(bool idInceasingOrder) const
+{
+ // naturally always sorted by ID
+ typedef ElemVecIterator
+ < const SMDS_MeshFace*, SMDS_MeshCell*, SMDS_MeshElement::TypeFilter > TIterator;
+ return SMDS_FaceIteratorPtr
+ (new TIterator(myCells, SMDS_MeshElement::TypeFilter( SMDSAbs_Face )));
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///Return an iterator on volumes of the current mesh.
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_VolumeIteratorPtr SMDS_Mesh::volumesIterator(bool idInceasingOrder) const
+{
+ // naturally always sorted by ID
+ typedef ElemVecIterator
+ < const SMDS_MeshVolume*, SMDS_MeshCell*, SMDS_MeshElement::TypeFilter > TIterator;
+ return SMDS_VolumeIteratorPtr
+ (new TIterator(myCells, SMDS_MeshElement::TypeFilter( SMDSAbs_Volume )));
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Do intersection of sets (more than 2)
+///////////////////////////////////////////////////////////////////////////////
+static set<const SMDS_MeshElement*> * intersectionOfSets(
+ set<const SMDS_MeshElement*> vs[], int numberOfSets)
+{
+ set<const SMDS_MeshElement*>* rsetA=new set<const SMDS_MeshElement*>(vs[0]);
+ set<const SMDS_MeshElement*>* rsetB;
+
+ for(int i=0; i<numberOfSets-1; i++)
+ {
+ rsetB=new set<const SMDS_MeshElement*>();
+ set_intersection(
+ rsetA->begin(), rsetA->end(),
+ vs[i+1].begin(), vs[i+1].end(),
+ inserter(*rsetB, rsetB->begin()));
+ delete rsetA;
+ rsetA=rsetB;
+ }
+ return rsetA;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Return the list of finite elements owning the given element: elements
+/// containing all the nodes of the given element, for instance faces and
+/// volumes containing a given edge.
+///////////////////////////////////////////////////////////////////////////////
+static set<const SMDS_MeshElement*> * getFinitElements(const SMDS_MeshElement * element)
+{
+ int numberOfSets=element->NbNodes();
+ set<const SMDS_MeshElement*> *initSet = new set<const SMDS_MeshElement*>[numberOfSets];
+
+ SMDS_ElemIteratorPtr itNodes=element->nodesIterator();
+
+ int i = 0;
+ while ( itNodes->more() )
+ {
+ const SMDS_MeshElement* node = itNodes->next();
+ MYASSERT(node);
+ const SMDS_MeshNode * n=static_cast<const SMDS_MeshNode*>(node);
+ SMDS_ElemIteratorPtr itFe = n->GetInverseElementIterator();
+
+ while ( itFe->more() )
+ {
+ const SMDS_MeshElement* elem = itFe->next();
+ MYASSERT(elem);
+ initSet[i].insert(elem);
+ }
+
+ i++;
+ }
+ set<const SMDS_MeshElement*> *retSet = intersectionOfSets( initSet, numberOfSets );
+ delete [] initSet;
+ return retSet;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Return the list of nodes used only by the given elements
+///////////////////////////////////////////////////////////////////////////////
+static set<const SMDS_MeshElement*> * getExclusiveNodes(set<const SMDS_MeshElement*>& elements)
+{
+ set<const SMDS_MeshElement*> * toReturn=new set<const SMDS_MeshElement*>();
+ set<const SMDS_MeshElement*>::iterator itElements=elements.begin();
+
+ while(itElements!=elements.end())
+ {
+ SMDS_ElemIteratorPtr itNodes = (*itElements)->nodesIterator();
+ itElements++;
+
+ while(itNodes->more())
+ {
+ const SMDS_MeshNode * n=static_cast<const SMDS_MeshNode*>(itNodes->next());
+ SMDS_ElemIteratorPtr itFe = n->GetInverseElementIterator();
+ set<const SMDS_MeshElement*> s;
+ while(itFe->more())
+ s.insert(itFe->next());
+ if(s==elements) toReturn->insert(n);
+ }
+ }
+ return toReturn;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///Find the children of an element that are made of given nodes
+///@param setOfChildren The set in which matching children will be inserted
+///@param element The element were to search matching children
+///@param nodes The nodes that the children must have to be selected
+///////////////////////////////////////////////////////////////////////////////
+void SMDS_Mesh::addChildrenWithNodes(set<const SMDS_MeshElement*>& setOfChildren,
+ const SMDS_MeshElement * element,
+ set<const SMDS_MeshElement*>& nodes)
+{
+ switch(element->GetType())
+ {
+ case SMDSAbs_Node:
+ MESSAGE("Internal Error: This should not happen");
+ break;
+ case SMDSAbs_0DElement:
+ case SMDSAbs_Ball:
+ {
+ }
+ break;
+ case SMDSAbs_Edge:
+ {
+ SMDS_ElemIteratorPtr itn=element->nodesIterator();
+ while(itn->more())
+ {
+ const SMDS_MeshElement * e=itn->next();
+ if(nodes.find(e)!=nodes.end())
+ {
+ setOfChildren.insert(element);
+ break;
+ }
+ }
+ } break;
+ case SMDSAbs_Face:
+ {
+ SMDS_ElemIteratorPtr itn=element->nodesIterator();
+ while(itn->more())
+ {
+ const SMDS_MeshElement * e=itn->next();
+ if(nodes.find(e)!=nodes.end())
+ {
+ setOfChildren.insert(element);
+ break;
+ }
+ }
+ if(hasConstructionEdges())
+ {
+ SMDS_ElemIteratorPtr ite=element->edgesIterator();
+ while(ite->more())
+ addChildrenWithNodes(setOfChildren, ite->next(), nodes);
+ }
+ } break;
+ case SMDSAbs_Volume:
+ {
+ if(hasConstructionFaces())
+ {
+ SMDS_ElemIteratorPtr ite=element->facesIterator();
+ while(ite->more())
+ addChildrenWithNodes(setOfChildren, ite->next(), nodes);
+ }
+ else if(hasConstructionEdges())
+ {
+ SMDS_ElemIteratorPtr ite=element->edgesIterator();
+ while(ite->more())
+ addChildrenWithNodes(setOfChildren, ite->next(), nodes);
+ }
+ }
+ case SMDSAbs_NbElementTypes:
+ case SMDSAbs_All: break;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///@param elem The element to delete
+///@param removenodes if true remaining nodes will be removed
+///////////////////////////////////////////////////////////////////////////////
+void SMDS_Mesh::RemoveElement(const SMDS_MeshElement * elem,
+ const bool removenodes)
+{
+ list<const SMDS_MeshElement *> removedElems;
+ list<const SMDS_MeshElement *> removedNodes;
+ RemoveElement( elem, removedElems, removedNodes, removenodes );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///@param elem The element to delete
+///@param removedElems to be filled with all removed elements
+///@param removedNodes to be filled with all removed nodes
+///@param removenodes if true remaining nodes will be removed
+///////////////////////////////////////////////////////////////////////////////
+void SMDS_Mesh::RemoveElement(const SMDS_MeshElement * elem,
+ list<const SMDS_MeshElement *>& removedElems,
+ list<const SMDS_MeshElement *>& removedNodes,
+ bool removenodes)
+{
+ // get finite elements built on elem
+ set<const SMDS_MeshElement*> * s1;
+ if ( (elem->GetType() == SMDSAbs_0DElement)
+ || ((elem->GetType() == SMDSAbs_Edge) && !hasConstructionEdges())
+ || ((elem->GetType() == SMDSAbs_Face) && !hasConstructionFaces())
+ || (elem->GetType() == SMDSAbs_Volume) )
+ {
+ s1 = new set<const SMDS_MeshElement*> ();
+ s1->insert(elem);
+ }
+ else
+ s1 = getFinitElements(elem);
+
+ // get exclusive nodes (which would become free afterwards)
+ set<const SMDS_MeshElement*> * s2;
+ if (elem->GetType() == SMDSAbs_Node) // a node is removed
+ {
+ // do not remove nodes except elem
+ s2 = new set<const SMDS_MeshElement*> ();
+ s2->insert(elem);
+ removenodes = true;
+ }
+ else
+ s2 = getExclusiveNodes(*s1);
+
+ // form the set of finite and construction elements to remove
+ set<const SMDS_MeshElement*> s3;
+ set<const SMDS_MeshElement*>::iterator it = s1->begin();
+ while (it != s1->end())
+ {
+ addChildrenWithNodes(s3, *it, *s2);
+ s3.insert(*it);
+ it++;
+ }
+ if (elem->GetType() != SMDSAbs_Node)
+ s3.insert(elem);
+
+ // remove finite and construction elements
+ it = s3.begin();
+ while (it != s3.end())
+ {
+ // Remove element from <InverseElements> of its nodes
+ SMDS_ElemIteratorPtr itn = (*it)->nodesIterator();
+ while (itn->more())
+ {
+ SMDS_MeshNode * n = static_cast<SMDS_MeshNode *> (const_cast<SMDS_MeshElement *> (itn->next()));
+ n->RemoveInverseElement((*it));
+ }
+ int IdToRemove = (*it)->GetID();
+ int vtkid = (*it)->getVtkId();
+ switch ((*it)->GetType())
+ {
+ case SMDSAbs_Node:
+ MYASSERT("Internal Error: This should not happen");
+ break;
+ case SMDSAbs_0DElement:
+ if (IdToRemove >= 0)
+ {
+ myCells[IdToRemove] = 0; // -PR- ici ou dans myElementIDFactory->ReleaseID ?
+ myInfo.remove(*it);
+ }
+ removedElems.push_back((*it));
+ myElementIDFactory->ReleaseID(IdToRemove, vtkid);
+ delete (*it);
+ break;
+ case SMDSAbs_Edge:
+ if (IdToRemove >= 0)
+ {
+ myCells[IdToRemove] = 0;
+ myInfo.RemoveEdge(*it);
+ }
+ removedElems.push_back((*it));
+ myElementIDFactory->ReleaseID(IdToRemove, vtkid);
+ if (const SMDS_VtkEdge* vtkElem = dynamic_cast<const SMDS_VtkEdge*>(*it))
+ myEdgePool->destroy((SMDS_VtkEdge*) vtkElem);
+ else {
+ ((SMDS_MeshElement*) *it)->init( -1, -1, -1 ); // avoid reuse
+ delete (*it);
+ }
+ break;
+ case SMDSAbs_Face:
+ if (IdToRemove >= 0)
+ {
+ myCells[IdToRemove] = 0;
+ myInfo.RemoveFace(*it);
+ }
+ removedElems.push_back((*it));
+ myElementIDFactory->ReleaseID(IdToRemove, vtkid);
+ if (const SMDS_VtkFace* vtkElem = dynamic_cast<const SMDS_VtkFace*>(*it))
+ myFacePool->destroy((SMDS_VtkFace*) vtkElem);
+ else {
+ ((SMDS_MeshElement*) *it)->init( -1, -1, -1 ); // avoid reuse
+ delete (*it);
+ }
+ break;
+ case SMDSAbs_Volume:
+ if (IdToRemove >= 0)
+ {
+ myCells[IdToRemove] = 0;
+ myInfo.RemoveVolume(*it);
+ }
+ removedElems.push_back((*it));
+ myElementIDFactory->ReleaseID(IdToRemove, vtkid);
+ if (const SMDS_VtkVolume* vtkElem = dynamic_cast<const SMDS_VtkVolume*>(*it))
+ myVolumePool->destroy((SMDS_VtkVolume*) vtkElem);
+ else {
+ ((SMDS_MeshElement*) *it)->init( -1, -1, -1 ); // avoid reuse
+ delete (*it);
+ }
+ break;
+ case SMDSAbs_Ball:
+ if (IdToRemove >= 0)
+ {
+ myCells[IdToRemove] = 0;
+ myInfo.remove(*it);
+ }
+ removedElems.push_back((*it));
+ myElementIDFactory->ReleaseID(IdToRemove, vtkid);
+ if (const SMDS_BallElement* vtkElem = dynamic_cast<const SMDS_BallElement*>(*it))
+ myBallPool->destroy(const_cast<SMDS_BallElement*>( vtkElem ));
+ else {
+ ((SMDS_MeshElement*) *it)->init( -1, -1, -1 ); // avoid reuse
+ delete (*it);
+ }
+ break;
+
+ case SMDSAbs_All: // avoid compilation warning
+ case SMDSAbs_NbElementTypes: break;
+ }
+ if (vtkid >= 0)
+ {
+ this->myGrid->GetCellTypesArray()->SetValue(vtkid, VTK_EMPTY_CELL);
+ }
+ it++;
+ }
+
+ // remove exclusive (free) nodes
+ if (removenodes)
+ {
+ it = s2->begin();
+ while (it != s2->end())
+ {
+ int IdToRemove = (*it)->GetID();
+ if (IdToRemove >= 0)
+ {
+ myNodes[IdToRemove] = 0;
+ myInfo.myNbNodes--;
+ }
+ myNodeIDFactory->ReleaseID((*it)->GetID(), (*it)->getVtkId());
+ removedNodes.push_back((*it));
+ if (const SMDS_MeshNode* vtkElem = dynamic_cast<const SMDS_MeshNode*>(*it))
+ {
+ ((SMDS_MeshNode*)vtkElem)->SetPosition(SMDS_SpacePosition::originSpacePosition());
+ myNodePool->destroy((SMDS_MeshNode*) vtkElem);
+ }
+ else
+ delete (*it);
+ it++;
+ }
+ }
+
+ delete s2;
+ delete s1;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+///@param elem The element to delete
+///////////////////////////////////////////////////////////////////////////////
+void SMDS_Mesh::RemoveFreeElement(const SMDS_MeshElement * elem)
+{
+ int elemId = elem->GetID();
+ int vtkId = elem->getVtkId();
+ SMDSAbs_ElementType aType = elem->GetType();
+ SMDS_MeshElement* todest = (SMDS_MeshElement*)(elem);
+ if ( aType == SMDSAbs_Node )
+ {
+ // only free node can be removed by this method
+ const SMDS_MeshNode* n = static_cast<SMDS_MeshNode*>(todest);
+ if ( n->NbInverseElements() == 0 ) { // free node
+ myNodes[elemId] = 0;
+ myInfo.myNbNodes--;
+ ((SMDS_MeshNode*) n)->SetPosition(SMDS_SpacePosition::originSpacePosition());
+ ((SMDS_MeshNode*) n)->SMDS_MeshElement::init( -1, -1, -1 ); // avoid reuse
+ myNodePool->destroy(static_cast<SMDS_MeshNode*>(todest));
+ myNodeIDFactory->ReleaseID(elemId, vtkId);
+ }
+ }
+ else
+ {
+ if (hasConstructionEdges() || hasConstructionFaces())
+ // this methods is only for meshes without descendants
+ return;
+
+ // Remove element from <InverseElements> of its nodes
+ SMDS_ElemIteratorPtr itn = elem->nodesIterator();
+ while (itn->more()) {
+ SMDS_MeshNode * n = static_cast<SMDS_MeshNode *>
+ (const_cast<SMDS_MeshElement *>(itn->next()));
+ n->RemoveInverseElement(elem);
+ }
+
+ // in meshes without descendants elements are always free
+ switch (aType) {
+ case SMDSAbs_0DElement:
+ myCells[elemId] = 0;
+ myInfo.remove(elem);
+ delete elem;
+ elem = 0;
+ break;
+ case SMDSAbs_Edge:
+ myCells[elemId] = 0;
+ myInfo.RemoveEdge(elem);
+ myEdgePool->destroy(static_cast<SMDS_VtkEdge*>(todest));
+ break;
+ case SMDSAbs_Face:
+ myCells[elemId] = 0;
+ myInfo.RemoveFace(elem);
+ myFacePool->destroy(static_cast<SMDS_VtkFace*>(todest));
+ break;
+ case SMDSAbs_Volume:
+ myCells[elemId] = 0;
+ myInfo.RemoveVolume(elem);
+ myVolumePool->destroy(static_cast<SMDS_VtkVolume*>(todest));
+ break;
+ case SMDSAbs_Ball:
+ myCells[elemId] = 0;
+ myInfo.remove(elem);
+ myBallPool->destroy(static_cast<SMDS_BallElement*>(todest));
+ break;
+ default:
+ break;
+ }
+ myElementIDFactory->ReleaseID(elemId, vtkId);
+
+ this->myGrid->GetCellTypesArray()->SetValue(vtkId, VTK_EMPTY_CELL);
+ // --- to do: keep vtkid in a list of reusable cells
+
+ if ( elem )
+ ((SMDS_MeshElement*) elem)->init( -1, -1, -1 ); // avoid reuse
+ }
+}
+
+/*!
+ * Checks if the element is present in mesh.
+ * Useful to determine dead pointers.
+ */
+bool SMDS_Mesh::Contains (const SMDS_MeshElement* elem) const
+{
+ // we should not rely on validity of *elem, so iterate on containers
+ // of all types in the hope of finding <elem> somewhere there
+ SMDS_NodeIteratorPtr itn = nodesIterator();
+ while (itn->more())
+ if (elem == itn->next())
+ return true;
+ SMDS_ElemIteratorPtr ite = elementsIterator();
+ while (ite->more())
+ if (elem == ite->next())
+ return true;
+ return false;
+}
+
+//=======================================================================
+//function : MaxNodeID
+//purpose :
+//=======================================================================
+
+int SMDS_Mesh::MaxNodeID() const
+{
+ return myNodeIDFactory->GetMaxID();
+}
+
+//=======================================================================
+//function : MinNodeID
+//purpose :
+//=======================================================================
+
+int SMDS_Mesh::MinNodeID() const
+{
+ return myNodeIDFactory->GetMinID();
+}
+
+//=======================================================================
+//function : MaxElementID
+//purpose :
+//=======================================================================
+
+int SMDS_Mesh::MaxElementID() const
+{
+ return myElementIDFactory->GetMaxID();