*/
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 );
+
};
};
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++)
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.
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];
{
}
+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));
{
}
+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));
{
}
+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));
{
}
+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));
{
}
+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));
{
}
+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));
{
}
+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));
{
}
+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));
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;
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];
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();
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();
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();
{
friend class SMDS_UnstructuredGrid;
public:
+ virtual void getOrderedNodesOfFace(int cellId, std::vector<int>& orderedNodes);
protected:
SMDS_DownTetra(SMDS_UnstructuredGrid *grid);
~SMDS_DownTetra();
{
friend class SMDS_UnstructuredGrid;
public:
+ virtual void getOrderedNodesOfFace(int cellId, std::vector<int>& orderedNodes);
protected:
SMDS_DownQuadTetra(SMDS_UnstructuredGrid *grid);
~SMDS_DownQuadTetra();
{
friend class SMDS_UnstructuredGrid;
public:
+ virtual void getOrderedNodesOfFace(int cellId, std::vector<int>& orderedNodes);
protected:
SMDS_DownPyramid(SMDS_UnstructuredGrid *grid);
~SMDS_DownPyramid();
{
friend class SMDS_UnstructuredGrid;
public:
+ virtual void getOrderedNodesOfFace(int cellId, std::vector<int>& orderedNodes);
protected:
SMDS_DownQuadPyramid(SMDS_UnstructuredGrid *grid);
~SMDS_DownQuadPyramid();
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();
{
friend class SMDS_UnstructuredGrid;
public:
+ virtual void getOrderedNodesOfFace(int cellId, std::vector<int>& orderedNodes);
protected:
SMDS_DownHexa(SMDS_UnstructuredGrid *grid);
~SMDS_DownHexa();
{
friend class SMDS_UnstructuredGrid;
public:
+ virtual void getOrderedNodesOfFace(int cellId, std::vector<int>& orderedNodes);
protected:
SMDS_DownQuadHexa(SMDS_UnstructuredGrid *grid);
~SMDS_DownQuadHexa();
// 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
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;
{
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);
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())
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;
// 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
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 );
{
SMDS_MeshNode * n = static_cast<SMDS_MeshNode *>
(const_cast<SMDS_MeshElement *>( *it ));
- n->RemoveInverseElement( elem );
+ n->RemoveInverseElement( cell );
}
}
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;
void incrementCellsCapacity(int nbCells);
void adjustStructure();
void dumpGrid(string ficdump="dumpGrid");
-
static int chunkSize;
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
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;
public:
SMDS_MeshCell();
virtual ~SMDS_MeshCell();
+
+ virtual bool ChangeNodes(const SMDS_MeshNode* nodes[], const int nbNodes)= 0;
+
inline void setVtkId(int vtkId)
{
myVtkID = vtkId;
myMaxID = maxId-1;
myPoolOfID.clear();
}
+
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;
* 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
}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();
+}
+
#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;
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;
return _downArray[vtkType];
}
static SMDS_UnstructuredGrid* New();
+ SMDS_Mesh *_mesh;
protected:
SMDS_UnstructuredGrid();
~SMDS_UnstructuredGrid();
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;
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;
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;
}
~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;
bool SMDS_VtkFace::ChangeNodes(const SMDS_MeshNode* nodes[], const int nbNodes)
{
+ // TODO
return true;
}
bool SMDS_VtkVolume::ChangeNodes(const SMDS_MeshNode* nodes[],
const int nbNodes)
{
- // utilise dans SMDS_Mesh
+ // TODO utilise dans SMDS_Mesh
return true;
}
#include "SMDS_QuadraticFaceOfNodes.hxx"
#include "SMDS_MeshGroup.hxx"
#include "SMDS_LinearEdge.hxx"
+#include "SMDS_Downward.hxx"
#include "SMESHDS_Group.hxx"
#include "SMESHDS_Mesh.hxx"
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 );
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 );
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] );
}
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
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] );
}
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 )
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);
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 );
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 );
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 );
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;
}
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;
}
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 );
}
}
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 );
}
}
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 );
}
}
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
// 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 );
}
}
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
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
#include "SMDS_EdgePosition.hxx"
#include "SMDS_FacePosition.hxx"
#include "SMDS_SpacePosition.hxx"
+#include "SMDS_Downward.hxx"
#include "SMESHDS_GroupOnGeom.hxx"
#include <Standard_ErrorHandler.hxx>
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();
}
+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;
+}
#include "SMESHDS_DataMapOfShape.hxx"
class SMESHDS_GroupBase;
+class DownIdType;
class SMESHDS_EXPORT SMESHDS_Mesh:public SMDS_Mesh{
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);
bool IsGroupOfSubShapes (const TopoDS_Shape& aSubShape) const;
void compactMesh();
+ void BuildDownWardConnectivity(bool withEdges);
~SMESHDS_Mesh();
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;
+}
*/
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(); }
# @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.
#