smds_memimp_joints

This commit is contained in:
prascle 2010-07-25 08:13:16 +00:00
parent 0c16e57723
commit 4eb3d62127
25 changed files with 674 additions and 55 deletions

View File

@ -869,6 +869,19 @@ module SMESH
*/
boolean Make2DMeshFrom3D();
/*!
* \brief Double nodes on shared faces between groups of volumes and create flat elements on demand.
* The list of groups must describe a partition of the mesh volumes.
* The nodes of the internal faces at the boundaries of the groups are doubled.
* In option, the internal faces are replaced by flat elements.
* Triangles are transformed in prisms, and quadrangles in hexahedrons.
* \param theDomains - list of groups of volumes
* \param createJointElems - if TRUE, create the elements
* \return TRUE if operation has been completed successfully, FALSE otherwise
*/
boolean DoubleNodesOnGroupBoundaries( in ListOfGroups theDomains,
in boolean createJointElems );
};
};

View File

@ -265,6 +265,12 @@ const unsigned char* SMDS_Down1D::getUpTypes(int cellId)
return &_upCellTypes[_upCellIndex[cellId]];
}
void SMDS_Down1D::getNodeIds(int cellId, std::set<int>& nodeSet)
{
for (int i = 0; i < _nbDownCells; i++)
nodeSet.insert(_cellIds[_nbDownCells * cellId + i]);
}
int SMDS_Down1D::getNodeSet(int cellId, int* nodeSet)
{
for (int i = 0; i < _nbDownCells; i++)
@ -481,6 +487,16 @@ const unsigned char* SMDS_Down2D::getUpTypes(int cellId)
return &_upCellTypes[2 * cellId];
}
void SMDS_Down2D::getNodeIds(int cellId, std::set<int>& nodeSet)
{
for (int i = 0; i < _nbDownCells; i++)
{
int downCellId = _cellIds[_nbDownCells * cellId + i];
unsigned char cellType = _cellTypes[i];
this->_grid->getDownArray(cellType)->getNodeIds(downCellId, nodeSet);
}
}
/*! Find in vtkUnstructuredGrid the volumes containing a face already stored in vtkUnstructuredGrid.
* Search the volumes containing a face, to store the info in SMDS_Down2D for later uses
* with SMDS_Down2D::getUpCells and SMDS_Down2D::getUpTypes.
@ -753,6 +769,16 @@ const unsigned char* SMDS_Down3D::getUpTypes(int cellId)
return 0;
}
void SMDS_Down3D::getNodeIds(int cellId, std::set<int>& nodeSet)
{
int vtkId = this->_vtkCellIds[cellId];
vtkIdType npts = 0;
vtkIdType *nodes; // will refer to the point id's of the volume
_grid->GetCellPoints(vtkId, npts, nodes);
for (int i = 0; i < npts; i++)
nodeSet.insert(nodes[i]);
}
int SMDS_Down3D::FindFaceByNodes(int cellId, ElemByNodesType& faceByNodes)
{
int *faces = &_cellIds[_nbDownCells * cellId];
@ -1074,6 +1100,37 @@ SMDS_DownTetra::~SMDS_DownTetra()
{
}
void SMDS_DownTetra::getOrderedNodesOfFace(int cellId, std::vector<int>& orderedNodes)
{
set<int> setNodes;
setNodes.clear();
for (int i = 0; i < orderedNodes.size(); i++)
setNodes.insert(orderedNodes[i]);
//MESSAGE("cellId = " << cellId);
vtkIdType npts = 0;
vtkIdType *nodes; // will refer to the point id's of the volume
_grid->GetCellPoints(this->_vtkCellIds[cellId], npts, nodes);
set<int> tofind;
int ids[12] = { 0, 1, 2, 0, 1, 3, 0, 2, 3, 1, 2, 3 };
for (int k = 0; k < 4; k++)
{
tofind.clear();
for (int i = 0; i < 3; i++)
tofind.insert(nodes[ids[3 * k + i]]);
if (setNodes == tofind)
{
for (int i = 0; i < 3; i++)
orderedNodes[i] = nodes[ids[3 * k + i]];
return;
}
}
MESSAGE("=== Problem volume " << _vtkCellIds[cellId] << " " << _grid->_mesh->fromVtkToSmds(_vtkCellIds[cellId]));
MESSAGE(orderedNodes[0] << " " << orderedNodes[1] << " " << orderedNodes[2]);
MESSAGE(nodes[0] << " " << nodes[1] << " " << nodes[2] << " " << nodes[3]);
}
void SMDS_DownTetra::addDownCell(int cellId, int lowCellId, unsigned char aType)
{
//ASSERT((cellId >=0)&& (cellId < _maxId));
@ -1150,6 +1207,11 @@ SMDS_DownQuadTetra::~SMDS_DownQuadTetra()
{
}
void SMDS_DownQuadTetra::getOrderedNodesOfFace(int cellId, std::vector<int>& orderedNodes)
{
// TODO
}
void SMDS_DownQuadTetra::addDownCell(int cellId, int lowCellId, unsigned char aType)
{
//ASSERT((cellId >=0)&& (cellId < _maxId));
@ -1241,6 +1303,11 @@ SMDS_DownPyramid::~SMDS_DownPyramid()
{
}
void SMDS_DownPyramid::getOrderedNodesOfFace(int cellId, std::vector<int>& orderedNodes)
{
// TODO
}
void SMDS_DownPyramid::addDownCell(int cellId, int lowCellId, unsigned char aType)
{
//ASSERT((cellId >=0) && (cellId < _maxId));
@ -1340,6 +1407,11 @@ SMDS_DownQuadPyramid::~SMDS_DownQuadPyramid()
{
}
void SMDS_DownQuadPyramid::getOrderedNodesOfFace(int cellId, std::vector<int>& orderedNodes)
{
// TODO
}
void SMDS_DownQuadPyramid::addDownCell(int cellId, int lowCellId, unsigned char aType)
{
//ASSERT((cellId >=0) && (cellId < _maxId));
@ -1456,6 +1528,11 @@ SMDS_DownPenta::~SMDS_DownPenta()
{
}
void SMDS_DownPenta::getOrderedNodesOfFace(int cellId, std::vector<int>& orderedNodes)
{
// TODO
}
void SMDS_DownPenta::addDownCell(int cellId, int lowCellId, unsigned char aType)
{
//ASSERT((cellId >=0) && (cellId < _maxId));
@ -1559,6 +1636,11 @@ SMDS_DownQuadPenta::~SMDS_DownQuadPenta()
{
}
void SMDS_DownQuadPenta::getOrderedNodesOfFace(int cellId, std::vector<int>& orderedNodes)
{
// TODO
}
void SMDS_DownQuadPenta::addDownCell(int cellId, int lowCellId, unsigned char aType)
{
//ASSERT((cellId >=0) && (cellId < _maxId));
@ -1682,6 +1764,11 @@ SMDS_DownHexa::~SMDS_DownHexa()
{
}
void SMDS_DownHexa::getOrderedNodesOfFace(int cellId, std::vector<int>& orderedNodes)
{
// TODO
}
void SMDS_DownHexa::addDownCell(int cellId, int lowCellId, unsigned char aType)
{
//ASSERT((cellId >=0)&& (cellId < _maxId));
@ -1780,6 +1867,11 @@ SMDS_DownQuadHexa::~SMDS_DownQuadHexa()
{
}
void SMDS_DownQuadHexa::getOrderedNodesOfFace(int cellId, std::vector<int>& orderedNodes)
{
// TODO
}
void SMDS_DownQuadHexa::addDownCell(int cellId, int lowCellId, unsigned char aType)
{
//ASSERT((cellId >=0)&& (cellId < _maxId));

View File

@ -26,6 +26,28 @@ typedef struct
int nbElems;
} ListElemByNodesType; // TODO resize for polyhedrons
class DownIdType
{
public:
DownIdType(int a, unsigned char b) :
cellId(a), cellType(b)
{
}
int cellId;
unsigned char cellType;
};
struct DownIdCompare
{
bool operator ()(const DownIdType e1, const DownIdType e2) const
{
if (e1.cellId == e2.cellId)
return (e1.cellType < e2.cellType);
else
return (e1.cellId < e2.cellId);
}
};
class SMDS_Downward
{
friend class SMDS_UnstructuredGrid;
@ -38,6 +60,7 @@ public:
virtual int getNumberOfUpCells(int cellId) = 0;
virtual const int* getUpCells(int cellId) = 0;
virtual const unsigned char* getUpTypes(int cellId) = 0;
virtual void getNodeIds(int cellId, std::set<int>& nodeSet) = 0;
int getVtkCellId(int cellId)
{
return _vtkCellIds[cellId];
@ -75,6 +98,7 @@ public:
virtual int getNumberOfUpCells(int cellId);
virtual const int* getUpCells(int cellId);
virtual const unsigned char* getUpTypes(int cellId);
virtual void getNodeIds(int cellId, std::set<int>& nodeSet);
protected:
SMDS_Down1D(SMDS_UnstructuredGrid *grid, int nbDownCells);
~SMDS_Down1D();
@ -105,6 +129,7 @@ public:
virtual int getNumberOfUpCells(int cellId);
virtual const int* getUpCells(int cellId);
virtual const unsigned char* getUpTypes(int cellId);
virtual void getNodeIds(int cellId, std::set<int>& nodeSet);
protected:
SMDS_Down2D(SMDS_UnstructuredGrid *grid, int nbDownCells);
~SMDS_Down2D();
@ -134,6 +159,8 @@ public:
virtual int getNumberOfUpCells(int cellId);
virtual const int* getUpCells(int cellId);
virtual const unsigned char* getUpTypes(int cellId);
virtual void getNodeIds(int cellId, std::set<int>& nodeSet);
virtual void getOrderedNodesOfFace(int cellId, std::vector<int>& orderedNodes) = 0;
protected:
SMDS_Down3D(SMDS_UnstructuredGrid *grid, int nbDownCells);
~SMDS_Down3D();
@ -225,6 +252,7 @@ class SMDS_DownTetra: public SMDS_Down3D
{
friend class SMDS_UnstructuredGrid;
public:
virtual void getOrderedNodesOfFace(int cellId, std::vector<int>& orderedNodes);
protected:
SMDS_DownTetra(SMDS_UnstructuredGrid *grid);
~SMDS_DownTetra();
@ -236,6 +264,7 @@ class SMDS_DownQuadTetra: public SMDS_Down3D
{
friend class SMDS_UnstructuredGrid;
public:
virtual void getOrderedNodesOfFace(int cellId, std::vector<int>& orderedNodes);
protected:
SMDS_DownQuadTetra(SMDS_UnstructuredGrid *grid);
~SMDS_DownQuadTetra();
@ -247,6 +276,7 @@ class SMDS_DownPyramid: public SMDS_Down3D
{
friend class SMDS_UnstructuredGrid;
public:
virtual void getOrderedNodesOfFace(int cellId, std::vector<int>& orderedNodes);
protected:
SMDS_DownPyramid(SMDS_UnstructuredGrid *grid);
~SMDS_DownPyramid();
@ -258,6 +288,7 @@ class SMDS_DownQuadPyramid: public SMDS_Down3D
{
friend class SMDS_UnstructuredGrid;
public:
virtual void getOrderedNodesOfFace(int cellId, std::vector<int>& orderedNodes);
protected:
SMDS_DownQuadPyramid(SMDS_UnstructuredGrid *grid);
~SMDS_DownQuadPyramid();
@ -267,18 +298,21 @@ protected:
class SMDS_DownPenta: public SMDS_Down3D
{
friend class SMDS_UnstructuredGrid;
public:
virtual void getOrderedNodesOfFace(int cellId, std::vector<int>& orderedNodes);
protected:
SMDS_DownPenta(SMDS_UnstructuredGrid *grid);
~SMDS_DownPenta();
virtual void addDownCell(int cellId, int lowCellId, unsigned char aType);
virtual void computeFacesWithNodes(int cellId, ListElemByNodesType& facesWithNodes);
protected:
};
class SMDS_DownQuadPenta: public SMDS_Down3D
{
friend class SMDS_UnstructuredGrid;
public:
virtual void getOrderedNodesOfFace(int cellId, std::vector<int>& orderedNodes);
protected:
SMDS_DownQuadPenta(SMDS_UnstructuredGrid *grid);
~SMDS_DownQuadPenta();
@ -290,6 +324,7 @@ class SMDS_DownHexa: public SMDS_Down3D
{
friend class SMDS_UnstructuredGrid;
public:
virtual void getOrderedNodesOfFace(int cellId, std::vector<int>& orderedNodes);
protected:
SMDS_DownHexa(SMDS_UnstructuredGrid *grid);
~SMDS_DownHexa();
@ -301,6 +336,7 @@ class SMDS_DownQuadHexa: public SMDS_Down3D
{
friend class SMDS_UnstructuredGrid;
public:
virtual void getOrderedNodesOfFace(int cellId, std::vector<int>& orderedNodes);
protected:
SMDS_DownQuadHexa(SMDS_UnstructuredGrid *grid);
~SMDS_DownQuadHexa();

View File

@ -20,7 +20,7 @@
// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
//
// SMESH SMDS : implementaion of Salome mesh data structure
// SMESH SMDS : implementation of Salome mesh data structure
//
#ifndef _SMDS_FaceOfEdges_HeaderFile
#define _SMDS_FaceOfEdges_HeaderFile
@ -48,6 +48,7 @@ class SMDS_EXPORT SMDS_FaceOfEdges:public SMDS_MeshFace
SMDSAbs_ElementType GetType() const;
virtual SMDSAbs_EntityType GetEntityType() const;
virtual bool ChangeNodes(const SMDS_MeshNode* nodes[], const int nbNodes) {return false;};
int NbNodes() const;
int NbEdges() const;
int NbFaces() const;

View File

@ -43,6 +43,10 @@ public:
{
return SMDSEntity_Edge;
}
virtual bool ChangeNodes(const SMDS_MeshNode* nodes[], const int nbNodes)
{
return false;
}
int NbNodes() const;
int NbEdges() const;
friend bool operator<(const SMDS_LinearEdge& e1, const SMDS_LinearEdge& e2);

View File

@ -209,6 +209,7 @@ SMDS_MeshNode * SMDS_Mesh::AddNodeWithID(double x, double y, double z, int ID)
if(!node){
//if ( myNodes.Extent() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
//SMDS_MeshNode * node=new SMDS_MeshNode(ID, myMeshId, -1, x, y, z);
myNodeIDFactory->adjustMaxId(ID);
SMDS_MeshNode * node = myNodePool->getNew();
node->init(ID, myMeshId, -1, x, y, z);
if (ID >= myNodes.size())
@ -1453,6 +1454,7 @@ bool SMDS_Mesh::ChangeElementNodes(const SMDS_MeshElement * element,
const SMDS_MeshNode * nodes[],
const int nbnodes)
{
// TODO use polymorphism, check number of nodes and type are unchanged.
MYASSERT(0); // REVOIR LES TYPES
// keep current nodes of elem
set<const SMDS_MeshElement*> oldNodes;
@ -1465,47 +1467,51 @@ bool SMDS_Mesh::ChangeElementNodes(const SMDS_MeshElement * element,
// change nodes
bool Ok = false;
SMDS_MeshElement* elem = const_cast<SMDS_MeshElement*>(element);
switch ( elem->GetType() )
{
case SMDSAbs_0DElement: {
if ( SMDS_Mesh0DElement* elem0d = dynamic_cast<SMDS_Mesh0DElement*>( elem ))
Ok = elem0d->ChangeNode( nodes[0] );
break;
}
case SMDSAbs_Edge: {
if ( nbnodes == 2 ) {
if ( SMDS_VtkEdge* edge = dynamic_cast<SMDS_VtkEdge*>( elem ))
Ok = edge->ChangeNodes( nodes[0], nodes[1] );
}
else if ( nbnodes == 3 ) {
if ( SMDS_QuadraticEdge* edge = dynamic_cast<SMDS_QuadraticEdge*>( elem ))
Ok = edge->ChangeNodes( nodes[0], nodes[1], nodes[2] );
}
break;
}
case SMDSAbs_Face: {
if ( SMDS_FaceOfNodes* face = dynamic_cast<SMDS_FaceOfNodes*>( elem ))
Ok = face->ChangeNodes( nodes, nbnodes );
else
if ( SMDS_QuadraticFaceOfNodes* QF = dynamic_cast<SMDS_QuadraticFaceOfNodes*>( elem ))
Ok = QF->ChangeNodes( nodes, nbnodes );
else
if (SMDS_PolygonalFaceOfNodes* face = dynamic_cast<SMDS_PolygonalFaceOfNodes*>(elem))
Ok = face->ChangeNodes(nodes, nbnodes);
break;
}
case SMDSAbs_Volume: {
if ( SMDS_VolumeOfNodes* vol = dynamic_cast<SMDS_VolumeOfNodes*>( elem ))
Ok = vol->ChangeNodes( nodes, nbnodes );
else
if ( SMDS_QuadraticVolumeOfNodes* QV = dynamic_cast<SMDS_QuadraticVolumeOfNodes*>( elem ))
Ok = QV->ChangeNodes( nodes, nbnodes );
break;
}
default:
MESSAGE ( "WRONG ELEM TYPE");
}
SMDS_MeshCell* cell = dynamic_cast<SMDS_MeshCell*>((SMDS_MeshElement*) element);
if (cell)
Ok = cell->ChangeNodes(nodes, nbnodes);
// SMDS_MeshElement* elem = const_cast<SMDS_MeshElement*>(element);
// switch ( elem->GetType() )
// {
// case SMDSAbs_0DElement: {
// if ( SMDS_Mesh0DElement* elem0d = dynamic_cast<SMDS_Mesh0DElement*>( elem ))
// Ok = elem0d->ChangeNode( nodes[0] );
// break;
// }
// case SMDSAbs_Edge: {
// if ( nbnodes == 2 ) {
// if ( SMDS_VtkEdge* edge = dynamic_cast<SMDS_VtkEdge*>( elem ))
// Ok = edge->ChangeNodes( nodes[0], nodes[1] );
// }
// else if ( nbnodes == 3 ) {
// if ( SMDS_QuadraticEdge* edge = dynamic_cast<SMDS_QuadraticEdge*>( elem ))
// Ok = edge->ChangeNodes( nodes[0], nodes[1], nodes[2] );
// }
// break;
// }
// case SMDSAbs_Face: {
// if ( SMDS_FaceOfNodes* face = dynamic_cast<SMDS_FaceOfNodes*>( elem ))
// Ok = face->ChangeNodes( nodes, nbnodes );
// else
// if ( SMDS_QuadraticFaceOfNodes* QF = dynamic_cast<SMDS_QuadraticFaceOfNodes*>( elem ))
// Ok = QF->ChangeNodes( nodes, nbnodes );
// else
// if (SMDS_PolygonalFaceOfNodes* face = dynamic_cast<SMDS_PolygonalFaceOfNodes*>(elem))
// Ok = face->ChangeNodes(nodes, nbnodes);
// break;
// }
// case SMDSAbs_Volume: {
// if ( SMDS_VolumeOfNodes* vol = dynamic_cast<SMDS_VolumeOfNodes*>( elem ))
// Ok = vol->ChangeNodes( nodes, nbnodes );
// else
// if ( SMDS_QuadraticVolumeOfNodes* QV = dynamic_cast<SMDS_QuadraticVolumeOfNodes*>( elem ))
// Ok = QV->ChangeNodes( nodes, nbnodes );
// break;
// }
// default:
// MESSAGE ( "WRONG ELEM TYPE");
// }
if ( Ok ) { // update InverseElements
@ -1516,7 +1522,7 @@ bool SMDS_Mesh::ChangeElementNodes(const SMDS_MeshElement * element,
it = oldNodes.find( nodes[i] );
if ( it == oldNodes.end() )
// new node
const_cast<SMDS_MeshNode*>( nodes[i] )->AddInverseElement( elem );
const_cast<SMDS_MeshNode*>( nodes[i] )->AddInverseElement( cell );
else
// remove from oldNodes a node that remains in elem
oldNodes.erase( it );
@ -1526,7 +1532,7 @@ bool SMDS_Mesh::ChangeElementNodes(const SMDS_MeshElement * element,
{
SMDS_MeshNode * n = static_cast<SMDS_MeshNode *>
(const_cast<SMDS_MeshElement *>( *it ));
n->RemoveInverseElement( elem );
n->RemoveInverseElement( cell );
}
}

View File

@ -66,7 +66,7 @@ public:
static std::vector<SMDS_Mesh*> _meshList;
//! actual nodes coordinates, cells definition and reverse connectivity are stored in a vtkUnstructuredGrid
inline vtkUnstructuredGrid* getGrid() {return myGrid; };
inline SMDS_UnstructuredGrid* getGrid() {return myGrid; };
inline int getMeshId() {return myMeshId; };
SMDS_NodeIteratorPtr nodesIterator(bool idInceasingOrder=false) const;
@ -573,7 +573,6 @@ public:
void incrementCellsCapacity(int nbCells);
void adjustStructure();
void dumpGrid(string ficdump="dumpGrid");
static int chunkSize;
protected:
@ -608,8 +607,9 @@ protected:
inline void adjustmyCellsCapacity(int ID)
{
assert(ID >= 0);
myElementIDFactory->adjustMaxId(ID);
if (ID >= myCells.size())
myCells.resize(ID+SMDS_Mesh::chunkSize,0);
myCells.resize(ID+SMDS_Mesh::chunkSize,0);
};
// Fields PRIVATE

View File

@ -35,6 +35,7 @@ class SMDS_EXPORT SMDS_Mesh0DElement: public SMDS_MeshCell
public:
SMDS_Mesh0DElement (const SMDS_MeshNode * node);
bool ChangeNode (const SMDS_MeshNode * node);
virtual bool ChangeNodes(const SMDS_MeshNode* nodes[], const int nbNodes) {return false;};
void Print (std::ostream & OS) const;
SMDSAbs_ElementType GetType() const;

View File

@ -12,6 +12,9 @@ class SMDS_EXPORT SMDS_MeshCell: public SMDS_MeshElement
public:
SMDS_MeshCell();
virtual ~SMDS_MeshCell();
virtual bool ChangeNodes(const SMDS_MeshNode* nodes[], const int nbNodes)= 0;
inline void setVtkId(int vtkId)
{
myVtkID = vtkId;

View File

@ -111,3 +111,4 @@ void SMDS_MeshIDFactory::emptyPool(int maxId)
myMaxID = maxId-1;
myPoolOfID.clear();
}

View File

@ -45,6 +45,7 @@ public:
SMDS_Mesh* GetMesh();
inline bool isPoolIdEmpty() { return myPoolOfID.empty(); };
void emptyPool(int maxId);
inline void adjustMaxId(int ID) { if (ID > myMaxID) myMaxID = ID;};
protected:
SMDS_MeshIDFactory();
int myMaxID;

View File

@ -303,9 +303,10 @@ void SMDS_UnstructuredGrid::setCellIdToDownId(int vtkCellId, int downId)
* Downward connectivity is no more valid if vtkUnstructuredGrid is modified.
*
*/
void SMDS_UnstructuredGrid::BuildDownwardConnectivity()
void SMDS_UnstructuredGrid::BuildDownwardConnectivity(bool withEdges)
{
MESSAGE("SMDS_UnstructuredGrid::BuildDownwardConnectivity");CHRONO(2);
// TODO calcul partiel sans edges
// --- erase previous data if any
@ -665,3 +666,107 @@ void SMDS_UnstructuredGrid::BuildDownwardConnectivity()
}CHRONOSTOP(24);CHRONOSTOP(2);
_counters->stats();
}
/*! Get the neighbors of a cell.
* Only the neighbors having the dimension of the cell are taken into account
* (neighbors of a volume are the volumes sharing a face with this volume,
* neighbors of a face are the faces sharing an edge with this face...).
* @param neighborsVtkIds vector of neighbors vtk id's to fill (reserve enough space).
* @param downIds downward id's of cells of dimension n-1, to fill (reserve enough space).
* @param downTypes vtk types of cells of dimension n-1, to fill (reserve enough space).
* @param vtkId the vtk id of the cell
* @return number of neighbors
*/
int SMDS_UnstructuredGrid::GetNeighbors(int* neighborsVtkIds, int* downIds, unsigned char* downTypes, int vtkId)
{
int vtkType = this->GetCellType(vtkId);
int cellDim = SMDS_Downward::getCellDimension(vtkType);
if (cellDim != 3)
return 0; // TODO voisins des faces ou edges
int cellId = this->_cellIdToDownId[vtkId];
int nbCells = _downArray[vtkType]->getNumberOfDownCells(cellId);
const int *downCells = _downArray[vtkType]->getDownCells(cellId);
const unsigned char* downTyp = _downArray[vtkType]->getDownTypes(cellId);
// --- iteration on faces of the 3D cell.
int nb = 0;
for (int i = 0; i < nbCells; i++)
{
int downId = downCells[i];
int cellType = downTyp[i];
int nbUp = _downArray[cellType]->getNumberOfUpCells(downId);
const int *upCells = _downArray[cellType]->getUpCells(downId);
const unsigned char* upTypes = _downArray[cellType]->getUpTypes(downId);
// --- max 2 upCells, one is this cell, the other is a neighbor
for (int j = 0; j < nbUp; j++)
{
if ((upCells[j] == cellId) && (upTypes[j] == vtkType))
continue;
int vtkNeighbor = _downArray[upTypes[j]]->getVtkCellId(upCells[j]);
neighborsVtkIds[nb] = vtkNeighbor;
downIds[nb] = downId;
downTypes[nb] = cellType;
nb++;
}
if (nb >= NBMAXNEIGHBORS)
assert(0);
}
return nb;
}
/*! get the node id's of a cell.
* The cell is defined by it's downward connectivity id and type.
* @param nodeSet set of of vtk node id's to fill.
* @param downId downward connectivity id of the cell.
* @param downType type of cell.
*/
void SMDS_UnstructuredGrid::GetNodeIds(std::set<int>& nodeSet, int downId, unsigned char downType)
{
_downArray[downType]->getNodeIds(downId, nodeSet);
}
/*! change some nodes in cell without modifying type or internal connectivity.
* Nodes inverse connectivity is maintained up to date.
* @param vtkVolId vtk id of the cell
* @param localClonedNodeIds map old node id to new node id.
*/
void SMDS_UnstructuredGrid::ModifyCellNodes(int vtkVolId, std::map<int, int> localClonedNodeIds)
{
vtkIdType npts = 0;
vtkIdType *pts; // will refer to the point id's of the face
this->GetCellPoints(vtkVolId, npts, pts);
for (int i = 0; i < npts; i++)
{
if (localClonedNodeIds.count(pts[i]))
{
vtkIdType oldpt = pts[i];
pts[i] = localClonedNodeIds[oldpt];
//MESSAGE(oldpt << " --> " << pts[i]);
//this->RemoveReferenceToCell(oldpt, vtkVolId);
//this->AddReferenceToCell(pts[i], vtkVolId);
}
}
}
/*! Create a volume (prism or hexahedron) by duplication of a face.
* the nodes of the new face are already created.
* @param vtkVolId vtk id of a volume containing the face, to get an orientation for the face.
* @param localClonedNodeIds map old node id to new node id.
* @return vtk id of the new volume.
*/
int SMDS_UnstructuredGrid::getOrderedNodesOfFace(int vtkVolId, std::vector<int>& orderedNodes)
{
int vtkType = this->GetCellType(vtkVolId);
int cellDim = SMDS_Downward::getCellDimension(vtkType);
if (cellDim != 3)
return 0;
SMDS_Down3D *downvol = static_cast<SMDS_Down3D*> (_downArray[vtkType]);
int downVolId = this->_cellIdToDownId[vtkVolId];
downvol->getOrderedNodesOfFace(downVolId, orderedNodes);
return orderedNodes.size();
}

View File

@ -9,10 +9,14 @@
#define _SMDS_UNSTRUCTUREDGRID_HXX
#include <vector>
#include <set>
#include <map>
#include <vtkUnstructuredGrid.h>
#include "chrono.hxx"
#define NBMAXNEIGHBORS 10
class SMDS_Downward;
class SMDS_Mesh;
@ -29,7 +33,11 @@ public:
int CellIdToDownId(int vtkCellId);
void setCellIdToDownId(int vtkCellId, int downId);
void BuildDownwardConnectivity();
void BuildDownwardConnectivity(bool withEdges);
int GetNeighbors(int* neighborsVtkIds, int* downIds, unsigned char* downTypes, int vtkId);
void GetNodeIds(std::set<int>& nodeSet, int downId, unsigned char downType);
void ModifyCellNodes(int vtkVolId, std::map<int, int> localClonedNodeIds);
int getOrderedNodesOfFace(int vtkVolId, std::vector<int>& orderedNodes);
vtkCellLinks* GetLinks()
{
return Links;
@ -39,6 +47,7 @@ public:
return _downArray[vtkType];
}
static SMDS_UnstructuredGrid* New();
SMDS_Mesh *_mesh;
protected:
SMDS_UnstructuredGrid();
~SMDS_UnstructuredGrid();
@ -47,7 +56,6 @@ protected:
vtkCellArray* newConnectivity, vtkIdTypeArray* newLocations, vtkIdType* pointsCell, int& alreadyCopied,
int start, int end);
SMDS_Mesh *_mesh;
std::vector<int> _cellIdToDownId; //!< convert vtk Id to downward[vtkType] id, initialized with -1
std::vector<unsigned char> _downTypes;
std::vector<SMDS_Downward*> _downArray;

View File

@ -56,6 +56,7 @@ class SMDS_EXPORT SMDS_VolumeOfFaces:public SMDS_MeshVolume
const SMDS_MeshFace * face6);
virtual SMDSAbs_EntityType GetEntityType() const;
virtual bool ChangeNodes(const SMDS_MeshNode* nodes[], const int nbNodes) {return false;};
void Print(std::ostream & OS) const;
int NbFaces() const;

View File

@ -37,6 +37,13 @@ void SMDS_VtkEdge::init(std::vector<vtkIdType> nodeIds, SMDS_Mesh* mesh)
bool SMDS_VtkEdge::ChangeNodes(const SMDS_MeshNode * node1,
const SMDS_MeshNode * node2)
{
// TODO remove
return true;
}
bool SMDS_VtkEdge::ChangeNodes(const SMDS_MeshNode* nodes[], const int nbNodes)
{
// TODO
return true;
}

View File

@ -16,6 +16,7 @@ public:
~SMDS_VtkEdge();
void init(std::vector<vtkIdType> nodeIds, SMDS_Mesh* mesh);
bool ChangeNodes(const SMDS_MeshNode * node1, const SMDS_MeshNode * node2);
virtual bool ChangeNodes(const SMDS_MeshNode* nodes[], const int nbNodes);
void Print(std::ostream & OS) const;
int NbNodes() const;

View File

@ -51,6 +51,7 @@ void SMDS_VtkFace::init(std::vector<vtkIdType> nodeIds, SMDS_Mesh* mesh)
bool SMDS_VtkFace::ChangeNodes(const SMDS_MeshNode* nodes[], const int nbNodes)
{
// TODO
return true;
}

View File

@ -61,7 +61,7 @@ void SMDS_VtkVolume::init(std::vector<vtkIdType> nodeIds, SMDS_Mesh* mesh)
bool SMDS_VtkVolume::ChangeNodes(const SMDS_MeshNode* nodes[],
const int nbNodes)
{
// utilise dans SMDS_Mesh
// TODO utilise dans SMDS_Mesh
return true;
}

View File

@ -36,6 +36,7 @@
#include "SMDS_QuadraticFaceOfNodes.hxx"
#include "SMDS_MeshGroup.hxx"
#include "SMDS_LinearEdge.hxx"
#include "SMDS_Downward.hxx"
#include "SMESHDS_Group.hxx"
#include "SMESHDS_Mesh.hxx"
@ -798,7 +799,7 @@ bool SMESH_MeshEditor::DeleteDiag (const SMDS_MeshNode * theNode1,
return false;
//MESSAGE( endl << tr1 << tr2 );
// TODO problem ChangeElementNodes : not the same number of nodes, not the same type
GetMeshDS()->ChangeElementNodes( tr1, aNodes, 4 );
myLastCreatedElems.Append(tr1);
GetMeshDS()->RemoveElement( tr2 );
@ -844,6 +845,7 @@ bool SMESH_MeshEditor::DeleteDiag (const SMDS_MeshNode * theNode1,
aNodes[6] = N2[3];
aNodes[7] = N1[5];
// TODO problem ChangeElementNodes : not the same number of nodes, not the same type
GetMeshDS()->ChangeElementNodes( tr1, aNodes, 8 );
myLastCreatedElems.Append(tr1);
GetMeshDS()->RemoveElement( tr2 );
@ -1017,11 +1019,13 @@ bool SMESH_MeshEditor::QuadToTri (TIDSortedElemSet & theElems,
if ( aBadRate1 <= aBadRate2 ) {
// tr1 + tr2 is better
// TODO problem ChangeElementNodes : not the same number of nodes, not the same type
aMesh->ChangeElementNodes( elem, aNodes, 3 );
newElem = aMesh->AddFace( aNodes[2], aNodes[3], aNodes[0] );
}
else {
// tr3 + tr4 is better
// TODO problem ChangeElementNodes : not the same number of nodes, not the same type
aMesh->ChangeElementNodes( elem, &aNodes[1], 3 );
newElem = aMesh->AddFace( aNodes[3], aNodes[0], aNodes[1] );
}
@ -1097,6 +1101,7 @@ bool SMESH_MeshEditor::QuadToTri (TIDSortedElemSet & theElems,
newElem = aMesh->AddFace(aNodes[3], aNodes[0], aNodes[1],
aNodes[7], aNodes[4], newN );
}
// TODO problem ChangeElementNodes : not the same number of nodes, not the same type
aMesh->ChangeElementNodes( elem, N, 6 );
} // quadratic case
@ -1729,10 +1734,12 @@ bool SMESH_MeshEditor::QuadToTri (TIDSortedElemSet & theElems,
int aShapeId = FindShape( elem );
const SMDS_MeshElement* newElem = 0;
if ( the13Diag ) {
// TODO problem ChangeElementNodes : not the same number of nodes, not the same type
aMesh->ChangeElementNodes( elem, aNodes, 3 );
newElem = aMesh->AddFace( aNodes[2], aNodes[3], aNodes[0] );
}
else {
// TODO problem ChangeElementNodes : not the same number of nodes, not the same type
aMesh->ChangeElementNodes( elem, &aNodes[1], 3 );
newElem = aMesh->AddFace( aNodes[3], aNodes[0], aNodes[1] );
}
@ -1818,6 +1825,7 @@ bool SMESH_MeshEditor::QuadToTri (TIDSortedElemSet & theElems,
aNodes[7], aNodes[4], newN );
}
myLastCreatedElems.Append(newElem);
// TODO problem ChangeElementNodes : not the same number of nodes, not the same type
aMesh->ChangeElementNodes( elem, N, 6 );
// put a new triangle on the same shape and add to the same groups
if ( aShapeId )
@ -2119,11 +2127,13 @@ bool SMESH_MeshEditor::TriToQuad (TIDSortedElemSet & theElems,
mapLi_listEl.erase( *link12 );
if(tr1->NbNodes()==3) {
if( tr1->GetID() < tr2->GetID() ) {
// TODO problem ChangeElementNodes : not the same number of nodes, not the same type
aMesh->ChangeElementNodes( tr1, n12, 4 );
myLastCreatedElems.Append(tr1);
aMesh->RemoveElement( tr2 );
}
else {
// TODO problem ChangeElementNodes : not the same number of nodes, not the same type
aMesh->ChangeElementNodes( tr2, n12, 4 );
myLastCreatedElems.Append(tr2);
aMesh->RemoveElement( tr1);
@ -2146,11 +2156,13 @@ bool SMESH_MeshEditor::TriToQuad (TIDSortedElemSet & theElems,
aNodes[6] = N2[3];
aNodes[7] = N1[5];
if( tr1->GetID() < tr2->GetID() ) {
// TODO problem ChangeElementNodes : not the same number of nodes, not the same type
GetMeshDS()->ChangeElementNodes( tr1, aNodes, 8 );
myLastCreatedElems.Append(tr1);
GetMeshDS()->RemoveElement( tr2 );
}
else {
// TODO problem ChangeElementNodes : not the same number of nodes, not the same type
GetMeshDS()->ChangeElementNodes( tr2, aNodes, 8 );
myLastCreatedElems.Append(tr2);
GetMeshDS()->RemoveElement( tr1 );
@ -2164,11 +2176,13 @@ bool SMESH_MeshEditor::TriToQuad (TIDSortedElemSet & theElems,
mapLi_listEl.erase( *link13 );
if(tr1->NbNodes()==3) {
if( tr1->GetID() < tr2->GetID() ) {
// TODO problem ChangeElementNodes : not the same number of nodes, not the same type
aMesh->ChangeElementNodes( tr1, n13, 4 );
myLastCreatedElems.Append(tr1);
aMesh->RemoveElement( tr3 );
}
else {
// TODO problem ChangeElementNodes : not the same number of nodes, not the same type
aMesh->ChangeElementNodes( tr3, n13, 4 );
myLastCreatedElems.Append(tr3);
aMesh->RemoveElement( tr1 );
@ -2191,11 +2205,13 @@ bool SMESH_MeshEditor::TriToQuad (TIDSortedElemSet & theElems,
aNodes[6] = N2[3];
aNodes[7] = N1[5];
if( tr1->GetID() < tr2->GetID() ) {
// TODO problem ChangeElementNodes : not the same number of nodes, not the same type
GetMeshDS()->ChangeElementNodes( tr1, aNodes, 8 );
myLastCreatedElems.Append(tr1);
GetMeshDS()->RemoveElement( tr3 );
}
else {
// TODO problem ChangeElementNodes : not the same number of nodes, not the same type
GetMeshDS()->ChangeElementNodes( tr3, aNodes, 8 );
myLastCreatedElems.Append(tr3);
GetMeshDS()->RemoveElement( tr1 );
@ -3872,6 +3888,7 @@ void SMESH_MeshEditor::makeWalls (TNodeOfNodeListMap & mapNewNodes,
if ( !f )
myLastCreatedElems.Append(aMesh->AddFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ] ));
else if ( nodes[ 1 ] != f->GetNodeWrap( f->GetNodeIndex( nodes[ 0 ] ) + 1 ))
// TODO problem ChangeElementNodes : not the same number of nodes, not the same type
aMesh->ChangeElementNodes( f, nodes, nbn );
break;
}
@ -3880,6 +3897,7 @@ void SMESH_MeshEditor::makeWalls (TNodeOfNodeListMap & mapNewNodes,
if ( !f )
myLastCreatedElems.Append(aMesh->AddFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ], nodes[ 3 ] ));
else if ( nodes[ 1 ] != f->GetNodeWrap( f->GetNodeIndex( nodes[ 0 ] ) + 1 ))
// TODO problem ChangeElementNodes : not the same number of nodes, not the same type
aMesh->ChangeElementNodes( f, nodes, nbn );
break;
}
@ -3900,6 +3918,7 @@ void SMESH_MeshEditor::makeWalls (TNodeOfNodeListMap & mapNewNodes,
tmpnodes[3] = nodes[1];
tmpnodes[4] = nodes[3];
tmpnodes[5] = nodes[5];
// TODO problem ChangeElementNodes : not the same number of nodes, not the same type
aMesh->ChangeElementNodes( f, tmpnodes, nbn );
}
}
@ -3920,6 +3939,7 @@ void SMESH_MeshEditor::makeWalls (TNodeOfNodeListMap & mapNewNodes,
tmpnodes[5] = nodes[3];
tmpnodes[6] = nodes[5];
tmpnodes[7] = nodes[7];
// TODO problem ChangeElementNodes : not the same number of nodes, not the same type
aMesh->ChangeElementNodes( f, tmpnodes, nbn );
}
}
@ -3930,6 +3950,7 @@ void SMESH_MeshEditor::makeWalls (TNodeOfNodeListMap & mapNewNodes,
if ( !f )
myLastCreatedElems.Append(aMesh->AddPolygonalFace(polygon_nodes));
else if ( nodes[ 1 ] != f->GetNodeWrap( f->GetNodeIndex( nodes[ 0 ] ) + 1 ))
// TODO problem ChangeElementNodes : not the same number of nodes, not the same type
aMesh->ChangeElementNodes( f, nodes, nbn );
}
}
@ -8645,6 +8666,7 @@ void SMESH_MeshEditor::InsertNodesIntoLink(const SMDS_MeshElement* theFace,
newNodes[ 1 ] = linkNodes[ i2 ];
newNodes[ 2 ] = nodes[ iSplit >= iBestQuad ? i3 : i4 ];
newNodes[ 3 ] = nodes[ i4 ];
// TODO problem ChangeElementNodes : not the same number of nodes, not the same type
aMesh->ChangeElementNodes( theFace, newNodes, iSplit == iBestQuad ? 4 : 3 );
} // end if(!theFace->IsQuadratic())
else { // theFace is quadratic
@ -9740,6 +9762,7 @@ SMESH_MeshEditor::SewSideElements (TIDSortedElemSet& theSide1,
// elemIDsToRemove.push_back( e->GetID() );
// else
if ( nbReplaced )
// TODO problem ChangeElementNodes : not the same number of nodes, not the same type
aMesh->ChangeElementNodes( e, & nodes[0], nbNodes );
}
}
@ -10234,6 +10257,192 @@ bool SMESH_MeshEditor::DoubleNodesInRegion( const TIDSortedElemSet& theElems,
return DoubleNodes( theElems, theNodesNot, anAffected );
}
/*!
* \brief Double nodes on shared faces between groups of volumes and create flat elements on demand.
* The list of groups must describe a partition of the mesh volumes.
* The nodes of the internal faces at the boundaries of the groups are doubled.
* In option, the internal faces are replaced by flat elements.
* Triangles are transformed in prisms, and quadrangles in hexahedrons.
* @param theElems - list of groups of volumes, where a group of volume is a set of
* SMDS_MeshElements sorted by Id.
* @param createJointElems - if TRUE, create the elements
* @return TRUE if operation has been completed successfully, FALSE otherwise
*/
bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSortedElemSet>& theElems,
bool createJointElems)
{
MESSAGE("------------------------------------------------------");
MESSAGE("SMESH_MeshEditor::CreateJointElementsOnGroupBoundaries");
MESSAGE("------------------------------------------------------");
SMESHDS_Mesh *meshDS = this->myMesh->GetMeshDS();
meshDS->BuildDownWardConnectivity(false);
SMDS_UnstructuredGrid *grid = meshDS->getGrid();
// --- build the list of faces shared by 2 domains (group of elements), with their domain and volume indexes
// build the list of nodes shared by 2 or more domains, with their domain indexes
std::map<DownIdType, std::map<int,int>, DownIdCompare> faceDomains; // 2x(id domain --> id volume)
std::map<int, std::map<int,int> > nodeDomains; //oldId -> (domainId -> newId)
faceDomains.clear();
nodeDomains.clear();
std::map<int,int> emptyMap;
emptyMap.clear();
for (int idom = 0; idom < theElems.size(); idom++)
{
// --- build a map (face to duplicate --> volume to modify)
// with all the faces shared by 2 domains (group of elements)
// and corresponding volume of this domain, for each shared face.
// a volume has a face shared by 2 domains if it has a neighbor which is not in is domain.
const TIDSortedElemSet& domain = theElems[idom];
TIDSortedElemSet::const_iterator elemItr = domain.begin();
for (; elemItr != domain.end(); ++elemItr)
{
SMDS_MeshElement* anElem = (SMDS_MeshElement*) *elemItr;
if (!anElem)
continue;
int vtkId = meshDS->fromSmdsToVtk(anElem->getId());
int neighborsVtkIds[NBMAXNEIGHBORS];
int downIds[NBMAXNEIGHBORS];
unsigned char downTypes[NBMAXNEIGHBORS];
int nbNeighbors = grid->GetNeighbors(neighborsVtkIds, downIds, downTypes, vtkId);
for (int n = 0; n < nbNeighbors; n++)
{
int smdsId = meshDS->fromVtkToSmds(neighborsVtkIds[n]);
const SMDS_MeshElement* elem = meshDS->FindElement(smdsId);
if (! domain.count(elem)) // neighbor is in another domain : face is shared
{
DownIdType face(downIds[n], downTypes[n]);
if (!faceDomains.count(face))
faceDomains[face] = emptyMap; // create an empty entry for face
if (!faceDomains[face].count(idom))
{
faceDomains[face][idom] = vtkId; // volume associated to face in this domain
}
}
}
}
}
MESSAGE("Number of shared faces " << faceDomains.size());
// --- for each shared face, get the nodes
// for each node, for each domain of the face, create a clone of the node
std::map<DownIdType, std::map<int,int>, DownIdCompare>::iterator itface = faceDomains.begin();
for( ; itface != faceDomains.end();++itface )
{
DownIdType face = itface->first;
std::map<int,int> domvol = itface->second;
std::set<int> oldNodes;
oldNodes.clear();
grid->GetNodeIds(oldNodes, face.cellId, face.cellType);
std::set<int>::iterator itn = oldNodes.begin();
for (;itn != oldNodes.end(); ++itn)
{
int oldId = *itn;
if (!nodeDomains.count(oldId))
nodeDomains[oldId] = emptyMap; // create an empty entry for node
std::map<int,int>::iterator itdom = domvol.begin();
for(; itdom != domvol.end(); ++itdom)
{
int idom = itdom->first;
if ( nodeDomains[oldId].empty() )
nodeDomains[oldId][idom] = oldId; // keep the old node in the first domain
else
{
double *coords = grid->GetPoint(oldId);
SMDS_MeshNode *newNode = meshDS->AddNode(coords[0], coords[1], coords[2]);
int newId = newNode->GetID();
nodeDomains[oldId][idom] = newId; // cloned node for other domains
}
}
}
}
// --- iterate on shared faces (volumes to modify, face to extrude)
// get node id's of the face (id SMDS = id VTK)
// create flat element with old and new nodes if requested
if (createJointElems)
{
itface = faceDomains.begin();
for( ; itface != faceDomains.end();++itface )
{
DownIdType face = itface->first;
std::set<int> oldNodes;
std::set<int>::iterator itn;
oldNodes.clear();
grid->GetNodeIds(oldNodes, face.cellId, face.cellType);
std::map<int,int> localClonedNodeIds;
std::map<int,int> domvol = itface->second;
std::map<int,int>::iterator itdom = domvol.begin();
int dom1 = itdom->first;
int vtkVolId = itdom->second;
itdom++;
int dom2 = itdom->first;
localClonedNodeIds.clear();
for (itn = oldNodes.begin(); itn != oldNodes.end(); ++itn)
{
int oldId = *itn;
int refid = oldId;
if (nodeDomains[oldId].count(dom1))
refid = nodeDomains[oldId][dom1];
else
MESSAGE("--- problem domain node " << dom1 << " " << oldId);
int newid = oldId;
if (nodeDomains[oldId].count(dom2))
newid = nodeDomains[oldId][dom2];
else
MESSAGE("--- problem domain node " << dom2 << " " << oldId);
localClonedNodeIds[oldId] = newid;
}
int smdsId = meshDS->fromVtkToSmds(vtkVolId);
meshDS->extrudeVolumeFromFace(smdsId, localClonedNodeIds);
}
}
// --- iterate on shared faces (volumes to modify, face to extrude)
// get node id's of the face (id SMDS = id VTK)
// replace old nodes by new nodes in volumes, and update inverse connectivity
itface = faceDomains.begin();
for( ; itface != faceDomains.end();++itface )
{
DownIdType face = itface->first;
std::set<int> oldNodes;
std::set<int>::iterator itn;
oldNodes.clear();
grid->GetNodeIds(oldNodes, face.cellId, face.cellType);
std::map<int,int> localClonedNodeIds;
std::map<int,int> domvol = itface->second;
std::map<int,int>::iterator itdom = domvol.begin();
for(; itdom != domvol.end(); ++itdom)
{
int idom = itdom->first;
int vtkVolId = itdom->second;
localClonedNodeIds.clear();
for (itn = oldNodes.begin(); itn != oldNodes.end(); ++itn)
{
int oldId = *itn;
if (nodeDomains[oldId].count(idom))
localClonedNodeIds[oldId] = nodeDomains[oldId][idom];
}
int smdsId = meshDS->fromVtkToSmds(vtkVolId);
meshDS->ModifyCellNodes(smdsId, localClonedNodeIds);
}
}
grid->BuildLinks();
// TODO replace also old nodes by new nodes in faces and edges
}
//================================================================================
/*!
* \brief Generated skin mesh (containing 2D cells) from 3D mesh

View File

@ -627,6 +627,9 @@ public:
const TIDSortedElemSet& theNodesNot,
const TopoDS_Shape& theShape );
bool DoubleNodesOnGroupBoundaries( const std::vector<TIDSortedElemSet>& theElems,
bool createJointElems);
/*!
* \brief Generated skin mesh (containing 2D cells) from 3D mesh
* The created 2D mesh elements based on nodes of free faces of boundary volumes

View File

@ -33,6 +33,7 @@
#include "SMDS_EdgePosition.hxx"
#include "SMDS_FacePosition.hxx"
#include "SMDS_SpacePosition.hxx"
#include "SMDS_Downward.hxx"
#include "SMESHDS_GroupOnGeom.hxx"
#include <Standard_ErrorHandler.hxx>
@ -1914,8 +1915,6 @@ void SMESHDS_Mesh::compactMesh()
myVtkIndex.swap(newVtkToSmds);
MESSAGE("myCells.size()=" << myCells.size() << " myIDElements.size()=" << myIDElements.size() << " myVtkIndex.size()=" << myVtkIndex.size() );
myGrid->BuildDownwardConnectivity();
// ---TODO: myNodes, myElements in submeshes
// map<int,SMESHDS_SubMesh*>::iterator it = myShapeIndexToSubMesh.begin();
@ -1926,3 +1925,53 @@ void SMESHDS_Mesh::compactMesh()
}
void SMESHDS_Mesh::BuildDownWardConnectivity(bool withEdges)
{
myGrid->BuildDownwardConnectivity(withEdges);
}
/*! change some nodes in cell without modifying type or internal connectivity.
* Nodes inverse connectivity is maintained up to date.
* @param smdsVolId smds id of the cell.
* @param localClonedNodeIds map old node id to new node id.
* @return ok if success.
*/
bool SMESHDS_Mesh::ModifyCellNodes(int smdsVolId, std::map<int,int> localClonedNodeIds)
{
int vtkVolId = this->fromSmdsToVtk(smdsVolId);
myGrid->ModifyCellNodes(vtkVolId, localClonedNodeIds);
return true;
}
/*! Create a volume (prism or hexahedron) by duplication of a face.
* the nodes of the new face are already created.
* @param vtkVolId vtk id of a volume containing the face, to get an orientation for the face.
* @param localClonedNodeIds map old node id to new node id. The old nodes define the face in the volume.
* @return ok if success.
*/
bool SMESHDS_Mesh::extrudeVolumeFromFace(int smdsVolId, std::map<int,int> localClonedNodeIds)
{
int vtkVolId = this->fromSmdsToVtk(smdsVolId);
//MESSAGE(smdsVolId << " " << vtkVolId);
vector<int> orderedNodes;
orderedNodes.clear();
map<int, int>::iterator it = localClonedNodeIds.begin();
for (; it != localClonedNodeIds.end(); ++it)
orderedNodes.push_back(it->first);
int nbNodes = myGrid->getOrderedNodesOfFace(vtkVolId, orderedNodes);
if (nbNodes == 3)
{
int newVtkVolId =myElementIDFactory->GetFreeID();
SMDS_MeshVolume *vol = this->AddVolumeWithID(orderedNodes[0],
orderedNodes[1],
orderedNodes[2],
localClonedNodeIds[orderedNodes[0]],
localClonedNodeIds[orderedNodes[1]],
localClonedNodeIds[orderedNodes[2]],
newVtkVolId);
}
// TODO update subshape list of elements and nodes
return true;
}

View File

@ -56,6 +56,7 @@
#include "SMESHDS_DataMapOfShape.hxx"
class SMESHDS_GroupBase;
class DownIdType;
class SMESHDS_EXPORT SMESHDS_Mesh:public SMDS_Mesh{
public:
@ -397,6 +398,8 @@ public:
bool ChangePolyhedronNodes(const SMDS_MeshElement * elem,
std::vector<const SMDS_MeshNode*> nodes,
std::vector<int> quantities);
bool ModifyCellNodes(int smdsVolId, std::map<int,int> localClonedNodeIds);
bool extrudeVolumeFromFace(int smdsVolId, std::map<int,int> localClonedNodeIds);
void Renumber (const bool isNodes, const int startID=1, const int deltaID=1);
void SetNodeInVolume(SMDS_MeshNode * aNode, const TopoDS_Shell & S);
@ -440,6 +443,7 @@ public:
bool IsGroupOfSubShapes (const TopoDS_Shape& aSubShape) const;
void compactMesh();
void BuildDownWardConnectivity(bool withEdges);
~SMESHDS_Mesh();

View File

@ -4766,3 +4766,51 @@ CORBA::Boolean SMESH_MeshEditor_i::Make2DMeshFrom3D()
TPythonDump() << "isDone = " << this << ".Make2DMeshFrom3D()";
return aResult;
}
//================================================================================
/*!
* \brief Double nodes on shared faces between groups of volumes and create flat elements on demand.
* The list of groups must describe a partition of the mesh volumes.
* The nodes of the internal faces at the boundaries of the groups are doubled.
* In option, the internal faces are replaced by flat elements.
* Triangles are transformed in prisms, and quadrangles in hexahedrons.
* @param theDomains - list of groups of volumes
* @param createJointElems - if TRUE, create the elements
* @return TRUE if operation has been completed successfully, FALSE otherwise
*/
//================================================================================
CORBA::Boolean SMESH_MeshEditor_i::DoubleNodesOnGroupBoundaries( const SMESH::ListOfGroups& theDomains,
CORBA::Boolean createJointElems )
{
initData();
::SMESH_MeshEditor aMeshEditor( myMesh );
SMESHDS_Mesh* aMeshDS = GetMeshDS();
vector<TIDSortedElemSet> domains;
domains.clear();
for ( int i = 0, n = theDomains.length(); i < n; i++ )
{
SMESH::SMESH_GroupBase_var aGrp = theDomains[ i ];
if ( !CORBA::is_nil( aGrp ) && ( aGrp->GetType() != SMESH::NODE ) )
{
TIDSortedElemSet domain;
domain.clear();
domains.push_back(domain);
SMESH::long_array_var anIDs = aGrp->GetIDs();
arrayToSet( anIDs, aMeshDS, domains[ i ], SMDSAbs_All );
}
}
bool aResult = aMeshEditor.DoubleNodesOnGroupBoundaries( domains, createJointElems );
storeResult( aMeshEditor) ;
// Update Python script
TPythonDump() << "isDone = " << this << ".DoubleNodesOnGroupBoundaries( " << &theDomains
<< ", " << createJointElems << " )";
return aResult;
}

View File

@ -647,6 +647,20 @@ public:
*/
CORBA::Boolean Make2DMeshFrom3D();
/*!
* \brief Double nodes on shared faces between groups of volumes and create flat elements on demand.
* The list of groups must describe a partition of the mesh volumes.
* The nodes of the internal faces at the boundaries of the groups are doubled.
* In option, the internal faces are replaced by flat elements.
* Triangles are transformed in prisms, and quadrangles in hexahedrons.
* @param theDomains - list of groups of volumes
* @param createJointElems - if TRUE, create the elements
* @return TRUE if operation has been completed successfully, FALSE otherwise
*/
CORBA::Boolean DoubleNodesOnGroupBoundaries( const SMESH::ListOfGroups& theDomains,
CORBA::Boolean createJointElems );
private: //!< private methods
SMESHDS_Mesh * GetMeshDS() { return myMesh->GetMeshDS(); }

View File

@ -3719,6 +3719,17 @@ class Mesh:
# @ingroup l2_modif_edit
def DoubleNodeElemGroupsInRegion(self, theElems, theNodesNot, theShape):
return self.editor.DoubleNodeElemGroupsInRegion(theElems, theNodesNot, theShape)
## Double nodes on shared faces between groups of volumes and create flat elements on demand.
# The list of groups must describe a partition of the mesh volumes.
# The nodes of the internal faces at the boundaries of the groups are doubled.
# In option, the internal faces are replaced by flat elements.
# Triangles are transformed in prisms, and quadrangles in hexahedrons.
# @param theDomains - list of groups of volumes
# @param createJointElems - if TRUE, create the elements
# @return TRUE if operation has been completed successfully, FALSE otherwise
def DoubleNodesOnGroupBoundaries(self, theDomains, createJointElems ):
return self.editor.DoubleNodesOnGroupBoundaries( theDomains, createJointElems )
## The mother class to define algorithm, it is not recommended to use it directly.
#