+
+#include "SMDS_ElementFactory.hxx"
+#include "SMDS_ElementHolder.hxx"
+#include "SMDS_SetIterator.hxx"
+#include "SMDS_SpacePosition.hxx"
+#include "SMDS_UnstructuredGrid.hxx"
+
+#include <utilities.h>
+
+#include <vtkUnstructuredGrid.h>
+//#include <vtkUnstructuredGridWriter.h>
+#include <vtkCell.h>
+#include <vtkUnsignedCharArray.h>
+#include <vtkCellLinks.h>
+#include <vtkIdList.h>
+
+#include <algorithm>
+#include <iostream>
+#include <fstream>
+
+#include <boost/make_shared.hpp>
+
+#if !defined WIN32 && !defined __APPLE__
+#include <sys/sysinfo.h>
+#endif
+
+// number of added entities to check memory after
+#define CHECKMEMORY_INTERVAL 100000
+
+#define MYASSERT(val) if (!(val)) throw SALOME_Exception(LOCALIZED("assertion not verified"));
+
+int SMDS_Mesh::chunkSize = 1024;
+
+//================================================================================
+/*!
+ * \brief Raise an exception if free memory (ram+swap) too low
+ * \param doNotRaise - if true, suppress exception, just return free memory size
+ * \retval int - amount of available memory in MB or negative number in failure case
+ */
+//================================================================================
+
+int SMDS_Mesh::CheckMemory(const bool doNotRaise) throw (std::bad_alloc)
+{
+ return -1;
+#if !defined WIN32 && !defined __APPLE__
+ struct sysinfo si;
+ int err = sysinfo( &si );
+ if ( err )
+ return -1;
+
+ const unsigned long Mbyte = 1024 * 1024;
+
+ static int limit = -1;
+ if ( limit < 0 ) {
+ if ( si.totalswap == 0 )
+ {
+ int status = system("SMDS_MemoryLimit"); // it returns lower limit of free RAM
+ if (status >= 0 ) {
+ limit = WEXITSTATUS(status);
+ }
+ else {
+ double factor = ( si.totalswap == 0 ) ? 0.1 : 0.2;
+ limit = int(( factor * si.totalram * si.mem_unit ) / Mbyte );
+ }
+ }
+ if ( limit < 20 )
+ limit = 20;
+ else
+ limit = int ( limit * 1.5 );
+ MESSAGE ( "SMDS_Mesh::CheckMemory() memory limit = " << limit << " MB" );
+ }
+
+ // compute separately to avoid overflow
+ int freeMb =
+ ( si.freeram * si.mem_unit ) / Mbyte +
+ ( si.freeswap * si.mem_unit ) / Mbyte;
+
+ if ( freeMb > limit )
+ return freeMb - limit;
+
+ if ( doNotRaise )
+ return 0;
+
+ MESSAGE ("SMDS_Mesh::CheckMemory() throws as free memory too low: " << freeMb <<" MB" );
+ throw std::bad_alloc();
+#else
+ return -1;
+#endif
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Create a new mesh object
+///////////////////////////////////////////////////////////////////////////////
+SMDS_Mesh::SMDS_Mesh():
+ myNodeFactory( new SMDS_NodeFactory( this )),
+ myCellFactory( new SMDS_ElementFactory( this )),
+ myParent(NULL),
+ myModified(false), myModifTime(0), myCompactTime(0),
+ xmin(0), xmax(0), ymin(0), ymax(0), zmin(0), zmax(0)
+{
+ myGrid = SMDS_UnstructuredGrid::New();
+ myGrid->setSMDS_mesh(this);
+ myGrid->Initialize();
+ myGrid->Allocate();
+ vtkPoints* points = vtkPoints::New();
+ // bug "21125: EDF 1233 SMESH: Degrardation of precision in a test case for quadratic conversion"
+ // Use double type for storing coordinates of nodes instead of float.
+ points->SetDataType(VTK_DOUBLE);
+ points->SetNumberOfPoints( 0 );
+ myGrid->SetPoints( points );
+ points->Delete();
+ this->Modified();
+
+ // initialize static maps in SMDS_MeshCell, to be thread-safe
+ SMDS_MeshCell::InitStaticMembers();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Create a new child mesh
+/// Note that the tree structure of SMDS_Mesh seems to be unused in this version
+/// (2003-09-08) of SMESH
+///////////////////////////////////////////////////////////////////////////////
+SMDS_Mesh::SMDS_Mesh(SMDS_Mesh * parent):
+ myNodeFactory( new SMDS_NodeFactory( this )),
+ myCellFactory( new SMDS_ElementFactory( this )),
+ myParent(parent)
+{
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///Create a submesh and add it to the current mesh
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_Mesh *SMDS_Mesh::AddSubMesh()
+{
+ SMDS_Mesh *submesh = new SMDS_Mesh(this);
+ myChildren.insert(myChildren.end(), submesh);
+ return submesh;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///create a MeshNode and add it to the current Mesh
+///An ID is automatically assigned to the node.
+///@return : The created node
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_MeshNode * SMDS_Mesh::AddNode(double x, double y, double z)
+{
+ return SMDS_Mesh::AddNodeWithID( x,y,z, myNodeFactory->GetFreeID() );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///create a MeshNode and add it to the current Mesh
+///@param ID : The ID of the MeshNode to create
+///@return : The created node or NULL if a node with this ID already exists
+///////////////////////////////////////////////////////////////////////////////
+SMDS_MeshNode * SMDS_Mesh::AddNodeWithID( double x, double y, double z, int ID )
+{
+ // find the MeshNode corresponding to ID
+ SMDS_MeshNode *node = myNodeFactory->NewNode( ID );
+ if ( node )
+ {
+ node->init( x, y, z );
+ myInfo.myNbNodes++;
+ myModified = true;
+ this->adjustBoundingBox(x, y, z);
+ }
+ return node;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// create a Mesh0DElement and add it to the current Mesh
+/// @return : The created Mesh0DElement
+///////////////////////////////////////////////////////////////////////////////
+SMDS_Mesh0DElement* SMDS_Mesh::Add0DElementWithID(int idnode, int ID)
+{
+ const SMDS_MeshNode * node = myNodeFactory->FindNode(idnode);
+ if (!node) return NULL;
+ return SMDS_Mesh::Add0DElementWithID(node, ID);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// create a Mesh0DElement and add it to the current Mesh
+/// @return : The created Mesh0DElement
+///////////////////////////////////////////////////////////////////////////////
+SMDS_Mesh0DElement* SMDS_Mesh::Add0DElement(const SMDS_MeshNode * node)
+{
+ return SMDS_Mesh::Add0DElementWithID( node, myCellFactory->GetFreeID() );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Create a new Mesh0DElement and at it to the mesh
+/// @param idnode ID of the node
+/// @param ID ID of the 0D element to create
+/// @return The created 0D element or NULL if an element with this
+/// ID already exists or if input node is not found.
+///////////////////////////////////////////////////////////////////////////////
+SMDS_Mesh0DElement* SMDS_Mesh::Add0DElementWithID(const SMDS_MeshNode * n, int ID)
+{
+ if (!n) return 0;
+
+ if (Nb0DElements() % CHECKMEMORY_INTERVAL == 0) CheckMemory();
+
+ if ( SMDS_MeshCell * cell = myCellFactory->NewCell( ID ))
+ {
+ cell->init( SMDSEntity_0D, /*nbNodes=*/1, n );
+ myInfo.myNb0DElements++;
+ return static_cast< SMDS_Mesh0DElement*> ( cell );
+ }
+
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// create a Ball and add it to the current Mesh
+/// @return : The created Ball
+///////////////////////////////////////////////////////////////////////////////
+SMDS_BallElement* SMDS_Mesh::AddBallWithID( int idnode, double diameter, int ID )
+{
+ const SMDS_MeshNode * node = myNodeFactory->FindNode( idnode );
+ if (!node) return NULL;
+ return SMDS_Mesh::AddBallWithID( node, diameter, ID );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// create a Ball and add it to the current Mesh
+/// @return : The created Ball
+///////////////////////////////////////////////////////////////////////////////
+SMDS_BallElement* SMDS_Mesh::AddBall(const SMDS_MeshNode * node, double diameter)
+{
+ return SMDS_Mesh::AddBallWithID(node, diameter, myCellFactory->GetFreeID());
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Create a new Ball and at it to the mesh
+/// @param idnode ID of the node
+// @param diameter ball diameter
+/// @param ID ID of the 0D element to create
+/// @return The created 0D element or NULL if an element with this
+/// ID already exists or if input node is not found.
+///////////////////////////////////////////////////////////////////////////////
+SMDS_BallElement* SMDS_Mesh::AddBallWithID(const SMDS_MeshNode * n, double diameter, int ID)
+{
+ if (!n) return 0;
+
+ if (NbBalls() % CHECKMEMORY_INTERVAL == 0) CheckMemory();
+
+ SMDS_BallElement* ball = static_cast< SMDS_BallElement*>( myCellFactory->NewElement( ID ));
+ if ( ball )
+ {
+ ball->init( n, diameter );
+ myInfo.myNbBalls++;
+ }
+ return ball;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// create a MeshEdge and add it to the current Mesh
+/// @return : The created MeshEdge
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_MeshEdge* SMDS_Mesh::AddEdgeWithID(int idnode1, int idnode2, int ID)
+{
+ const SMDS_MeshNode * node1 = myNodeFactory->FindNode(idnode1);
+ const SMDS_MeshNode * node2 = myNodeFactory->FindNode(idnode2);
+ if(!node1 || !node2) return NULL;
+ return SMDS_Mesh::AddEdgeWithID(node1, node2, ID);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// create a MeshEdge and add it to the current Mesh
+/// @return : The created MeshEdge
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_MeshEdge* SMDS_Mesh::AddEdge(const SMDS_MeshNode * node1,
+ const SMDS_MeshNode * node2)
+{
+ return SMDS_Mesh::AddEdgeWithID(node1, node2, myCellFactory->GetFreeID());
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Create a new edge and at it to the mesh
+/// @param idnode1 ID of the first node
+/// @param idnode2 ID of the second node
+/// @param ID ID of the edge to create
+/// @return The created edge or NULL if an element with this ID already exists or
+/// if input nodes are not found.
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_MeshEdge* SMDS_Mesh::AddEdgeWithID(const SMDS_MeshNode * n1,
+ const SMDS_MeshNode * n2,
+ int ID)
+{
+ if ( !n1 || !n2 ) return 0;
+
+ if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
+ {
+ cell->init( SMDSEntity_Edge, /*nbNodes=*/2, n1, n2 );
+ myInfo.myNbEdges++;
+ return static_cast<SMDS_MeshEdge*>( cell );
+ }
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Add a triangle defined by its nodes. An ID is automatically affected to the
+/// Created face
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
+ const SMDS_MeshNode * n2,
+ const SMDS_MeshNode * n3)
+{
+ return SMDS_Mesh::AddFaceWithID(n1,n2,n3, myCellFactory->GetFreeID());
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Add a triangle defined by its nodes IDs
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int idnode1, int idnode2, int idnode3, int ID)
+{
+ const SMDS_MeshNode * node1 = myNodeFactory->FindNode(idnode1);
+ const SMDS_MeshNode * node2 = myNodeFactory->FindNode(idnode2);
+ const SMDS_MeshNode * node3 = myNodeFactory->FindNode(idnode3);
+ if(!node1 || !node2 || !node3) return NULL;
+ return SMDS_Mesh::AddFaceWithID(node1, node2, node3, ID);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Add a triangle defined by its nodes
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
+ const SMDS_MeshNode * n2,
+ const SMDS_MeshNode * n3,
+ int ID)
+{
+ if ( !n1 || !n2 || !n3 ) return 0;
+ if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+
+ if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
+ {
+ cell->init( SMDSEntity_Triangle, /*nbNodes=*/3, n1, n2, n3 );
+ myInfo.myNbTriangles++;
+ return static_cast<SMDS_MeshFace*>( cell );
+ }
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Add a quadrangle defined by its nodes. An ID is automatically affected to the
+/// created face
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
+ const SMDS_MeshNode * n2,
+ const SMDS_MeshNode * n3,
+ const SMDS_MeshNode * n4)
+{
+ return SMDS_Mesh::AddFaceWithID(n1,n2,n3, n4, myCellFactory->GetFreeID());
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Add a quadrangle defined by its nodes IDs
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int idnode1,
+ int idnode2,
+ int idnode3,
+ int idnode4,
+ int ID)
+{
+ const SMDS_MeshNode *node1, *node2, *node3, *node4;
+ node1 = myNodeFactory->FindNode(idnode1);
+ node2 = myNodeFactory->FindNode(idnode2);
+ node3 = myNodeFactory->FindNode(idnode3);
+ node4 = myNodeFactory->FindNode(idnode4);
+ if ( !node1 || !node2 || !node3 || !node4 ) return NULL;
+ return SMDS_Mesh::AddFaceWithID(node1, node2, node3, node4, ID);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Add a quadrangle defined by its nodes
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
+ const SMDS_MeshNode * n2,
+ const SMDS_MeshNode * n3,
+ const SMDS_MeshNode * n4,
+ int ID)
+{
+ if ( !n1 || !n2 || !n3 || !n4 ) return 0;
+ if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+
+ if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
+ {
+ cell->init( SMDSEntity_Quadrangle, /*nbNodes=*/4, n1, n2, n3, n4 );
+ myInfo.myNbQuadrangles++;
+ return static_cast<SMDS_MeshFace*>( cell );
+ }
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///Create a new tetrahedron and add it to the mesh.
+///@return The created tetrahedron
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
+ const SMDS_MeshNode * n2,
+ const SMDS_MeshNode * n3,
+ const SMDS_MeshNode * n4)
+{
+ return SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, myCellFactory->GetFreeID() );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///Create a new tetrahedron and add it to the mesh.
+///@param ID The ID of the new volume
+///@return The created tetrahedron or NULL if an element with this ID already exists
+///or if input nodes are not found.
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_MeshVolume * SMDS_Mesh::AddVolumeWithID(int idnode1,
+ int idnode2,
+ int idnode3,
+ int idnode4,
+ int ID)
+{
+ const SMDS_MeshNode *node1, *node2, *node3, *node4;
+ node1 = myNodeFactory->FindNode(idnode1);
+ node2 = myNodeFactory->FindNode(idnode2);
+ node3 = myNodeFactory->FindNode(idnode3);
+ node4 = myNodeFactory->FindNode(idnode4);
+ if(!node1 || !node2 || !node3 || !node4) return NULL;
+ return SMDS_Mesh::AddVolumeWithID(node1, node2, node3, node4, ID);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///Create a new tetrahedron and add it to the mesh.
+///@param ID The ID of the new volume
+///@return The created tetrahedron
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
+ const SMDS_MeshNode * n2,
+ const SMDS_MeshNode * n3,
+ const SMDS_MeshNode * n4,
+ int ID)
+{
+ if ( !n1 || !n2 || !n3 || !n4 ) return 0;
+ if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+
+ if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
+ {
+ cell->init( SMDSEntity_Tetra, /*nbNodes=*/4, n1, n2, n3, n4 );
+ myInfo.myNbTetras++;
+ return static_cast<SMDS_MeshVolume*>( cell );
+ }
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///Create a new pyramid and add it to the mesh.
+///Nodes 1,2,3 and 4 define the base of the pyramid
+///@return The created pyramid
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
+ const SMDS_MeshNode * n2,
+ const SMDS_MeshNode * n3,
+ const SMDS_MeshNode * n4,
+ const SMDS_MeshNode * n5)
+{
+ return SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, myCellFactory->GetFreeID() );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///Create a new pyramid and add it to the mesh.
+///Nodes 1,2,3 and 4 define the base of the pyramid
+///@param ID The ID of the new volume
+///@return The created pyramid or NULL if an element with this ID already exists
+///or if input nodes are not found.
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_MeshVolume * SMDS_Mesh::AddVolumeWithID(int idnode1,
+ int idnode2,
+ int idnode3,
+ int idnode4,
+ int idnode5,
+ int ID)
+{
+ const SMDS_MeshNode *node1, *node2, *node3, *node4, *node5;
+ node1 = myNodeFactory->FindNode(idnode1);
+ node2 = myNodeFactory->FindNode(idnode2);
+ node3 = myNodeFactory->FindNode(idnode3);
+ node4 = myNodeFactory->FindNode(idnode4);
+ node5 = myNodeFactory->FindNode(idnode5);
+ if(!node1 || !node2 || !node3 || !node4 || !node5) return NULL;
+ return SMDS_Mesh::AddVolumeWithID(node1, node2, node3, node4, node5, ID);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///Create a new pyramid and add it to the mesh.
+///Nodes 1,2,3 and 4 define the base of the pyramid
+///@param ID The ID of the new volume
+///@return The created pyramid
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
+ const SMDS_MeshNode * n2,
+ const SMDS_MeshNode * n3,
+ const SMDS_MeshNode * n4,
+ const SMDS_MeshNode * n5,
+ int ID)
+{
+ if ( !n1 || !n2 || !n3 || !n4 || !n5 ) return 0;
+ if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+
+ if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
+ {
+ cell->init( SMDSEntity_Pyramid, /*nbNodes=*/5, n1, n2, n3, n4, n5 );
+ myInfo.myNbPyramids++;
+ return static_cast<SMDS_MeshVolume*>( cell );
+ }
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///Create a new prism and add it to the mesh.
+///Nodes 1,2,3 is a triangle and 1,2,5,4 a quadrangle.
+///@return The created prism
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
+ const SMDS_MeshNode * n2,
+ const SMDS_MeshNode * n3,
+ const SMDS_MeshNode * n4,
+ const SMDS_MeshNode * n5,
+ const SMDS_MeshNode * n6)
+{
+ int ID = myCellFactory->GetFreeID();
+ return SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6, ID);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///Create a new prism and add it to the mesh.
+///Nodes 1,2,3 is a triangle and 1,2,5,4 a quadrangle.
+///@param ID The ID of the new volume
+///@return The created prism or NULL if an element with this ID already exists
+///or if input nodes are not found.
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_MeshVolume * SMDS_Mesh::AddVolumeWithID(int idnode1,
+ int idnode2,
+ int idnode3,
+ int idnode4,
+ int idnode5,
+ int idnode6,
+ int ID)
+{
+ const SMDS_MeshNode *node1, *node2, *node3, *node4, *node5, *node6;
+ node1 = myNodeFactory->FindNode(idnode1);
+ node2 = myNodeFactory->FindNode(idnode2);
+ node3 = myNodeFactory->FindNode(idnode3);
+ node4 = myNodeFactory->FindNode(idnode4);
+ node5 = myNodeFactory->FindNode(idnode5);
+ node6 = myNodeFactory->FindNode(idnode6);
+ return SMDS_Mesh::AddVolumeWithID(node1, node2, node3, node4, node5, node6, ID);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///Create a new prism and add it to the mesh.
+///Nodes 1,2,3 is a triangle and 1,2,5,4 a quadrangle.
+///@param ID The ID of the new volume
+///@return The created prism
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
+ const SMDS_MeshNode * n2,
+ const SMDS_MeshNode * n3,
+ const SMDS_MeshNode * n4,
+ const SMDS_MeshNode * n5,
+ const SMDS_MeshNode * n6,
+ int ID)
+{
+ if ( !n1 || !n2 || !n3 || !n4 || !n5 || !n6 ) return 0;
+ if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+
+ if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
+ {
+ cell->init( SMDSEntity_Penta, /*nbNodes=*/6, n1, n2, n3, n4, n5, n6 );
+ myInfo.myNbPrisms++;
+ return static_cast<SMDS_MeshVolume*>( cell );
+ }
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///Create a new hexagonal prism and add it to the mesh.
+///@return The created prism
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
+ const SMDS_MeshNode * n2,
+ const SMDS_MeshNode * n3,
+ const SMDS_MeshNode * n4,
+ const SMDS_MeshNode * n5,
+ const SMDS_MeshNode * n6,
+ const SMDS_MeshNode * n7,
+ const SMDS_MeshNode * n8,
+ const SMDS_MeshNode * n9,
+ const SMDS_MeshNode * n10,
+ const SMDS_MeshNode * n11,
+ const SMDS_MeshNode * n12)
+{
+ return SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6,
+ n7, n8, n9, n10, n11, n12,
+ myCellFactory->GetFreeID() );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///Create a new hexagonal prism and add it to the mesh.
+///@param ID The ID of the new volume
+///@return The created prism or NULL if an element with this ID already exists
+///or if input nodes are not found.
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_MeshVolume * SMDS_Mesh::AddVolumeWithID(int idnode1,
+ int idnode2,
+ int idnode3,
+ int idnode4,
+ int idnode5,
+ int idnode6,
+ int idnode7,
+ int idnode8,
+ int idnode9,
+ int idnode10,
+ int idnode11,
+ int idnode12,
+ int ID)
+{
+ const SMDS_MeshNode *node1 = myNodeFactory->FindNode(idnode1);
+ const SMDS_MeshNode *node2 = myNodeFactory->FindNode(idnode2);
+ const SMDS_MeshNode *node3 = myNodeFactory->FindNode(idnode3);
+ const SMDS_MeshNode *node4 = myNodeFactory->FindNode(idnode4);
+ const SMDS_MeshNode *node5 = myNodeFactory->FindNode(idnode5);
+ const SMDS_MeshNode *node6 = myNodeFactory->FindNode(idnode6);
+ const SMDS_MeshNode *node7 = myNodeFactory->FindNode(idnode7);
+ const SMDS_MeshNode *node8 = myNodeFactory->FindNode(idnode8);
+ const SMDS_MeshNode *node9 = myNodeFactory->FindNode(idnode9);
+ const SMDS_MeshNode *node10 = myNodeFactory->FindNode(idnode10);
+ const SMDS_MeshNode *node11 = myNodeFactory->FindNode(idnode11);
+ const SMDS_MeshNode *node12 = myNodeFactory->FindNode(idnode12);
+ return SMDS_Mesh::AddVolumeWithID(node1, node2, node3, node4, node5, node6,
+ node7, node8, node9, node10, node11, node12,
+ ID);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///Create a new hexagonal prism and add it to the mesh.
+///@param ID The ID of the new volume
+///@return The created prism
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
+ const SMDS_MeshNode * n2,
+ const SMDS_MeshNode * n3,
+ const SMDS_MeshNode * n4,
+ const SMDS_MeshNode * n5,
+ const SMDS_MeshNode * n6,
+ const SMDS_MeshNode * n7,
+ const SMDS_MeshNode * n8,
+ const SMDS_MeshNode * n9,
+ const SMDS_MeshNode * n10,
+ const SMDS_MeshNode * n11,
+ const SMDS_MeshNode * n12,
+ int ID)
+{
+ SMDS_MeshVolume* volume = 0;
+ if(!n1 || !n2 || !n3 || !n4 || !n5 || !n6 ||
+ !n7 || !n8 || !n9 || !n10 || !n11 || !n12 )
+ return volume;
+ if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+
+ if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
+ {
+ cell->init( SMDSEntity_Hexagonal_Prism,
+ /*nbNodes=*/12, n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12 );
+ myInfo.myNbHexPrism++;
+ return static_cast<SMDS_MeshVolume*>( cell );
+ }
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///Create a new hexahedron and add it to the mesh.
+///Nodes 1,2,3,4 and 5,6,7,8 are quadrangle and 5,1 and 7,3 are an edges.
+///@return The created hexahedron
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
+ const SMDS_MeshNode * n2,
+ const SMDS_MeshNode * n3,
+ const SMDS_MeshNode * n4,
+ const SMDS_MeshNode * n5,
+ const SMDS_MeshNode * n6,
+ const SMDS_MeshNode * n7,
+ const SMDS_MeshNode * n8)
+{
+ int ID = myCellFactory->GetFreeID();
+ return SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6, n7, n8, ID);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///Create a new hexahedron and add it to the mesh.
+///Nodes 1,2,3,4 and 5,6,7,8 are quadrangle and 5,1 and 7,3 are an edges.
+///@param ID The ID of the new volume
+///@return The created hexahedron or NULL if an element with this ID already
+///exists or if input nodes are not found.
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_MeshVolume * SMDS_Mesh::AddVolumeWithID(int idnode1,
+ int idnode2,
+ int idnode3,
+ int idnode4,
+ int idnode5,
+ int idnode6,
+ int idnode7,
+ int idnode8,
+ int ID)
+{
+ const SMDS_MeshNode *node1, *node2, *node3, *node4, *node5, *node6, *node7, *node8;
+ node1 = myNodeFactory->FindNode(idnode1);
+ node2 = myNodeFactory->FindNode(idnode2);
+ node3 = myNodeFactory->FindNode(idnode3);
+ node4 = myNodeFactory->FindNode(idnode4);
+ node5 = myNodeFactory->FindNode(idnode5);
+ node6 = myNodeFactory->FindNode(idnode6);
+ node7 = myNodeFactory->FindNode(idnode7);
+ node8 = myNodeFactory->FindNode(idnode8);
+ return SMDS_Mesh::AddVolumeWithID(node1, node2, node3, node4, node5, node6,
+ node7, node8, ID);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///Create a new hexahedron and add it to the mesh.
+///Nodes 1,2,3,4 and 5,6,7,8 are quadrangle and 5,1 and 7,3 are an edges.
+///@param ID The ID of the new volume
+///@return The created prism or NULL if an element with this ID already exists
+///or if input nodes are not found.
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
+ const SMDS_MeshNode * n2,
+ const SMDS_MeshNode * n3,
+ const SMDS_MeshNode * n4,
+ const SMDS_MeshNode * n5,
+ const SMDS_MeshNode * n6,
+ const SMDS_MeshNode * n7,
+ const SMDS_MeshNode * n8,
+ int ID)
+{
+ SMDS_MeshVolume* volume = 0;
+ if ( !n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n7 || !n8) return volume;
+ if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+
+ if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
+ {
+ cell->init( SMDSEntity_Hexa,
+ /*nbNodes=*/8, n1, n2, n3, n4, n5, n6, n7, n8 );
+ myInfo.myNbHexas++;
+ return static_cast<SMDS_MeshVolume*>( cell );
+ }
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Add a polygon defined by its nodes IDs
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_MeshFace* SMDS_Mesh::AddPolygonalFaceWithID (const std::vector<int> & nodes_ids,
+ const int ID)
+{
+ int nbNodes = nodes_ids.size();
+ std::vector<const SMDS_MeshNode*> nodes (nbNodes);
+ for (int i = 0; i < nbNodes; i++) {
+ nodes[i] = myNodeFactory->FindNode( nodes_ids[i] );
+ if (!nodes[i]) return NULL;
+ }
+ return SMDS_Mesh::AddPolygonalFaceWithID(nodes, ID);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Add a polygon defined by its nodes
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_MeshFace*
+SMDS_Mesh::AddPolygonalFaceWithID (const std::vector<const SMDS_MeshNode*> & nodes,
+ const int ID)
+{
+ if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+
+ if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
+ {
+ cell->init( SMDSEntity_Polygon, nodes );
+ myInfo.myNbPolygons++;
+ return static_cast<SMDS_MeshFace*>( cell );
+ }
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Add a polygon defined by its nodes.
+/// An ID is automatically affected to the created face.
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_MeshFace* SMDS_Mesh::AddPolygonalFace (const std::vector<const SMDS_MeshNode*> & nodes)
+{
+ return SMDS_Mesh::AddPolygonalFaceWithID(nodes, myCellFactory->GetFreeID());
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Add a quadratic polygon defined by its nodes IDs
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_MeshFace* SMDS_Mesh::AddQuadPolygonalFaceWithID (const std::vector<int> & nodes_ids,
+ const int ID)
+{
+ std::vector<const SMDS_MeshNode*> nodes( nodes_ids.size() );
+ for ( size_t i = 0; i < nodes.size(); i++) {
+ nodes[i] = myNodeFactory->FindNode(nodes_ids[i]);
+ if (!nodes[i]) return NULL;
+ }
+ return SMDS_Mesh::AddQuadPolygonalFaceWithID(nodes, ID);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Add a quadratic polygon defined by its nodes
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_MeshFace*
+SMDS_Mesh::AddQuadPolygonalFaceWithID (const std::vector<const SMDS_MeshNode*> & nodes,
+ const int ID)
+{
+ if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+ if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
+ {
+ cell->init( SMDSEntity_Quad_Polygon, nodes );
+ myInfo.myNbQuadPolygons++;
+ return static_cast<SMDS_MeshFace*>( cell );
+ }
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Add a quadratic polygon defined by its nodes.
+/// An ID is automatically affected to the created face.
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_MeshFace* SMDS_Mesh::AddQuadPolygonalFace (const std::vector<const SMDS_MeshNode*> & nodes)
+{
+ return SMDS_Mesh::AddQuadPolygonalFaceWithID(nodes, myCellFactory->GetFreeID());
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Create a new polyhedral volume and add it to the mesh.
+/// @param ID The ID of the new volume
+/// @return The created volume or NULL if an element with this ID already exists
+/// or if input nodes are not found.
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_MeshVolume * SMDS_Mesh::AddPolyhedralVolumeWithID (const std::vector<int> & nodes_ids,
+ const std::vector<int> & quantities,
+ const int ID)
+{
+ int nbNodes = nodes_ids.size();
+ std::vector<const SMDS_MeshNode*> nodes (nbNodes);
+ for (int i = 0; i < nbNodes; i++) {
+ nodes[i] = myNodeFactory->FindNode(nodes_ids[i]);
+ if (!nodes[i]) return NULL;
+ }
+ return SMDS_Mesh::AddPolyhedralVolumeWithID(nodes, quantities, ID);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Create a new polyhedral volume and add it to the mesh.
+/// @param ID The ID of the new volume
+/// @return The created volume
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_MeshVolume*
+SMDS_Mesh::AddPolyhedralVolumeWithID (const std::vector<const SMDS_MeshNode*>& nodes,
+ const std::vector<int> & quantities,
+ const int ID)
+{
+ if ( nodes.empty() || quantities.empty() )
+ return NULL;
+ if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+
+ if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
+ {
+ SMDS_MeshVolume* volume = static_cast<SMDS_MeshVolume*>( cell );
+ volume->init( nodes, quantities );
+ myInfo.myNbPolyhedrons++;
+ return volume;
+ }
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Create a new polyhedral volume and add it to the mesh.
+/// @return The created volume
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_MeshVolume* SMDS_Mesh::AddPolyhedralVolume
+(const std::vector<const SMDS_MeshNode*> & nodes,
+ const std::vector<int> & quantities)
+{
+ int ID = myCellFactory->GetFreeID();
+ return SMDS_Mesh::AddPolyhedralVolumeWithID(nodes, quantities, ID);
+}
+
+SMDS_MeshVolume* SMDS_Mesh::AddVolumeFromVtkIds(const std::vector<vtkIdType>& vtkNodeIds)
+{
+ SMDS_MeshCell* cell = myCellFactory->NewCell( myCellFactory->GetFreeID() );
+ SMDS_MeshVolume * vol = static_cast<SMDS_MeshVolume*>( cell );
+ vol->init( vtkNodeIds );
+ myInfo.add( cell );
+ return vol;
+}
+
+SMDS_MeshFace* SMDS_Mesh::AddFaceFromVtkIds(const std::vector<vtkIdType>& vtkNodeIds)
+{
+ SMDS_MeshCell* cell = myCellFactory->NewCell( myCellFactory->GetFreeID() );
+ SMDS_MeshFace * f = static_cast<SMDS_MeshFace*>( cell );
+ f->init( vtkNodeIds );
+ myInfo.add( cell );
+ return f;
+}
+
+//=======================================================================
+//function : MoveNode
+//purpose :
+//=======================================================================
+
+void SMDS_Mesh::MoveNode(const SMDS_MeshNode *n, double x, double y, double z)
+{
+ SMDS_MeshNode * node=const_cast<SMDS_MeshNode*>(n);
+ node->setXYZ(x,y,z);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Return the node whose SMDS ID is 'ID'.
+///////////////////////////////////////////////////////////////////////////////
+const SMDS_MeshNode * SMDS_Mesh::FindNode(int ID) const
+{
+ return myNodeFactory->FindNode( ID );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Return the node whose VTK ID is 'vtkId'.
+///////////////////////////////////////////////////////////////////////////////
+const SMDS_MeshNode * SMDS_Mesh::FindNodeVtk(int vtkId) const
+{
+ return myNodeFactory->FindNode( vtkId + 1 );
+}
+
+const SMDS_MeshElement * SMDS_Mesh::FindElementVtk(int IDelem) const
+{
+ return myCellFactory->FindElement( FromVtkToSmds( IDelem ));
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Remove a node and all the elements which own this node
+///////////////////////////////////////////////////////////////////////////////
+
+void SMDS_Mesh::RemoveNode(const SMDS_MeshNode * node)
+{
+ RemoveElement(node, 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;
+
+ std::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 element
+ std::set<const SMDS_MeshNode*> oldNodes( element->begin_nodes(), element->end_nodes() );
+
+ // change nodes
+ bool Ok = false;
+ if ( SMDS_MeshCell* cell = dynamic_cast<SMDS_MeshCell*>((SMDS_MeshElement*) element))
+ Ok = cell->ChangeNodes(nodes, nbnodes);
+
+ if ( Ok )
+ setMyModified();
+
+ if ( Ok && GetGrid()->HasLinks() ) // update InverseElements
+ {
+ std::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( element );
+ 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( element );
+ }
+ }
+
+ return Ok;
+}
+
+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;
+}
+
+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;
+}
+
+const SMDS_MeshEdge* SMDS_Mesh::FindEdge(const SMDS_MeshNode * node1,
+ const SMDS_MeshNode * node2)
+{
+ if ( !node1 ) return 0;
+ const SMDS_MeshEdge * toReturn=NULL;
+ SMDS_ElemIteratorPtr it1=node1->GetInverseElementIterator(SMDSAbs_Edge);
+ 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;
+ }
+ }
+ return toReturn;
+}
+
+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(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;
+}
+
+//=======================================================================
+//function : FindFace
+//purpose :
+//=======================================================================
+
+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;
+}
+
+//=======================================================================
+//function : FindFace
+//purpose :quadratic triangle
+//=======================================================================
+
+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(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
+{
+ return myCellFactory->FindElement( IDelem );
+}
+
+//=======================================================================
+//function : FindFace
+//purpose : find polygon
+//=======================================================================
+
+
+const SMDS_MeshFace* SMDS_Mesh::FindFace (const std::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 std::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;
+}
+
+//================================================================================
+/*!
+ * \brief Return elements including all given nodes
+ * \param [in] nodes - nodes to find elements around
+ * \param [out] foundElems - the found elements
+ * \param [in] type - type of elements to find
+ * \return int - a number of found elements
+ */
+//================================================================================
+
+int SMDS_Mesh::GetElementsByNodes(const std::vector<const SMDS_MeshNode *>& nodes,
+ std::vector<const SMDS_MeshElement *>& foundElems,
+ const SMDSAbs_ElementType type)
+{
+ // chose a node with minimal number of inverse elements
+ const SMDS_MeshNode* n0 = nodes[0];
+ int minNbInverse = n0 ? n0->NbInverseElements( type ) : 1000;
+ for ( size_t i = 1; i < nodes.size(); ++i )
+ if ( nodes[i] && nodes[i]->NbInverseElements( type ) < minNbInverse )
+ {
+ n0 = nodes[i];
+ minNbInverse = n0->NbInverseElements( type );
+ }
+
+ foundElems.clear();
+ if ( n0 )
+ {
+ foundElems.reserve( minNbInverse );
+ SMDS_ElemIteratorPtr eIt = n0->GetInverseElementIterator( type );
+ while ( eIt->more() )
+ {
+ const SMDS_MeshElement* e = eIt->next();
+ bool includeAll = true;
+ for ( size_t i = 0; i < nodes.size() && includeAll; ++i )
+ if ( nodes[i] != n0 && e->GetNodeIndex( nodes[i] ) < 0 )
+ includeAll = false;
+ if ( includeAll )
+ foundElems.push_back( e );
+ }
+ }
+ return foundElems.size();
+}