PR: tools for crack meshing : detection of elements affected by node duplication, identification of elements near a geom shape, to create a hole, creation of the skin of the future hole

This commit is contained in:
prascle 2012-09-04 13:54:50 +00:00
parent c63113a9ae
commit 7446d65dcb
5 changed files with 850 additions and 37 deletions

View File

@ -10894,6 +10894,70 @@ namespace {
};
}
//================================================================================
/*!
\brief Identify the elements that will be affected by node duplication (actual duplication is not performed.
This method is the first step of DoubleNodeElemGroupsInRegion.
\param theElems - list of groups of elements (edges or faces) to be replicated
\param theNodesNot - list of groups of nodes not to replicated
\param theShape - shape to detect affected elements (element which geometric center
located on or inside shape).
The replicated nodes should be associated to affected elements.
\return groups of affected elements
\sa DoubleNodeElemGroupsInRegion()
*/
//================================================================================
bool SMESH_MeshEditor::AffectedElemGroupsInRegion( const TIDSortedElemSet& theElems,
const TIDSortedElemSet& theNodesNot,
const TopoDS_Shape& theShape,
TIDSortedElemSet& theAffectedElems)
{
if ( theShape.IsNull() )
return false;
const double aTol = Precision::Confusion();
auto_ptr< BRepClass3d_SolidClassifier> bsc3d;
auto_ptr<_FaceClassifier> aFaceClassifier;
if ( theShape.ShapeType() == TopAbs_SOLID )
{
bsc3d.reset( new BRepClass3d_SolidClassifier(theShape));;
bsc3d->PerformInfinitePoint(aTol);
}
else if (theShape.ShapeType() == TopAbs_FACE )
{
aFaceClassifier.reset( new _FaceClassifier(TopoDS::Face(theShape)));
}
// iterates on indicated elements and get elements by back references from their nodes
TIDSortedElemSet::const_iterator elemItr = theElems.begin();
for ( ; elemItr != theElems.end(); ++elemItr )
{
SMDS_MeshElement* anElem = (SMDS_MeshElement*)*elemItr;
if (!anElem)
continue;
SMDS_ElemIteratorPtr nodeItr = anElem->nodesIterator();
while ( nodeItr->more() )
{
const SMDS_MeshNode* aNode = cast2Node(nodeItr->next());
if ( !aNode || theNodesNot.find(aNode) != theNodesNot.end() )
continue;
SMDS_ElemIteratorPtr backElemItr = aNode->GetInverseElementIterator();
while ( backElemItr->more() )
{
const SMDS_MeshElement* curElem = backElemItr->next();
if ( curElem && theElems.find(curElem) == theElems.end() &&
( bsc3d.get() ?
isInside( curElem, *bsc3d, aTol ) :
isInside( curElem, *aFaceClassifier, aTol )))
theAffectedElems.insert( curElem );
}
}
}
return true;
}
//================================================================================
/*!
\brief Creates a hole in a mesh by doubling the nodes of some particular elements
@ -11651,6 +11715,532 @@ bool SMESH_MeshEditor::CreateFlatElementsOnFacesGroups(const std::vector<TIDSort
return true;
}
/*!
* \brief identify all the elements around a geom shape, get the faces delimiting the hole
* Build groups of volume to remove, groups of faces to replace on the skin of the object,
* groups of faces to remove inside the object, (idem edges).
* Build ordered list of nodes at the border of each group of faces to replace (to be used to build a geom subshape)
*/
void SMESH_MeshEditor::CreateHoleSkin(double radius,
const TopoDS_Shape& theShape,
SMESH_NodeSearcher* theNodeSearcher,
const char* groupName,
std::vector<double>& nodesCoords,
std::vector<std::vector<int> >& listOfListOfNodes)
{
MESSAGE("--------------------------------");
MESSAGE("SMESH_MeshEditor::CreateHoleSkin");
MESSAGE("--------------------------------");
// --- zone of volumes to remove is given :
// 1 either by a geom shape (one or more vertices) and a radius,
// 2 either by a group of nodes (representative of the shape)to use with the radius,
// 3 either by a group of nodes where all the elements build on one of this nodes are to remove,
// In the case 2, the group of nodes is an external group of nodes from another mesh,
// In the case 3, the group of nodes is an internal group of the mesh (obtained for instance by a filter),
// defined by it's name.
SMESHDS_GroupBase* groupDS = 0;
SMESH_Mesh::GroupIteratorPtr groupIt = this->myMesh->GetGroups();
while ( groupIt->more() )
{
groupDS = 0;
SMESH_Group * group = groupIt->next();
if ( !group ) continue;
groupDS = group->GetGroupDS();
if ( !groupDS || groupDS->IsEmpty() ) continue;
std::string grpName = group->GetName();
if (grpName == groupName)
break;
}
bool isNodeGroup = false;
bool isNodeCoords = false;
if (groupDS)
{
if (groupDS->GetType() != SMDSAbs_Node)
return;
isNodeGroup = true; // a group of nodes exists and it is in this mesh
}
if (nodesCoords.size() > 0)
isNodeCoords = true; // a list o nodes given by their coordinates
// --- define groups to build
int idg; // --- group of SMDS volumes
string grpvName = groupName;
grpvName += "_vol";
SMESH_Group *grp = this->myMesh->AddGroup(SMDSAbs_Volume, grpvName.c_str(), idg);
if (!grp)
{
MESSAGE("group not created " << grpvName);
return;
}
SMESHDS_Group *sgrp = dynamic_cast<SMESHDS_Group*>(grp->GetGroupDS());
int idgs; // --- group of SMDS faces on the skin
string grpsName = groupName;
grpsName += "_skin";
SMESH_Group *grps = this->myMesh->AddGroup(SMDSAbs_Face, grpsName.c_str(), idgs);
if (!grps)
{
MESSAGE("group not created " << grpsName);
return;
}
SMESHDS_Group *sgrps = dynamic_cast<SMESHDS_Group*>(grps->GetGroupDS());
int idgi; // --- group of SMDS faces internal (several shapes)
string grpiName = groupName;
grpiName += "_internalFaces";
SMESH_Group *grpi = this->myMesh->AddGroup(SMDSAbs_Face, grpiName.c_str(), idgi);
if (!grpi)
{
MESSAGE("group not created " << grpiName);
return;
}
SMESHDS_Group *sgrpi = dynamic_cast<SMESHDS_Group*>(grpi->GetGroupDS());
int idgei; // --- group of SMDS faces internal (several shapes)
string grpeiName = groupName;
grpeiName += "_internalEdges";
SMESH_Group *grpei = this->myMesh->AddGroup(SMDSAbs_Edge, grpeiName.c_str(), idgei);
if (!grpei)
{
MESSAGE("group not created " << grpeiName);
return;
}
SMESHDS_Group *sgrpei = dynamic_cast<SMESHDS_Group*>(grpei->GetGroupDS());
// --- build downward connectivity
SMESHDS_Mesh *meshDS = this->myMesh->GetMeshDS();
meshDS->BuildDownWardConnectivity(true);
SMDS_UnstructuredGrid* grid = meshDS->getGrid();
// --- set of volumes detected inside
std::set<int> setOfInsideVol;
std::set<int> setOfVolToCheck;
std::vector<gp_Pnt> gpnts;
gpnts.clear();
if (isNodeGroup) // --- a group of nodes is provided : find all the volumes using one or more of this nodes
{
MESSAGE("group of nodes provided");
SMDS_ElemIteratorPtr elemIt = groupDS->GetElements();
while ( elemIt->more() )
{
const SMDS_MeshElement* elem = elemIt->next();
if (!elem)
continue;
const SMDS_MeshNode* node = dynamic_cast<const SMDS_MeshNode*>(elem);
if (!node)
continue;
SMDS_MeshElement* vol = 0;
SMDS_ElemIteratorPtr volItr = node->GetInverseElementIterator(SMDSAbs_Volume);
while (volItr->more())
{
vol = (SMDS_MeshElement*)volItr->next();
setOfInsideVol.insert(vol->getVtkId());
sgrp->Add(vol->GetID());
}
}
}
else if (isNodeCoords)
{
MESSAGE("list of nodes coordinates provided");
int i = 0;
int k = 0;
while (i < nodesCoords.size()-2)
{
double x = nodesCoords[i++];
double y = nodesCoords[i++];
double z = nodesCoords[i++];
gp_Pnt p = gp_Pnt(x, y ,z);
gpnts.push_back(p);
MESSAGE("TopoDS_Vertex " << k++ << " " << p.X() << " " << p.Y() << " " << p.Z());
}
}
else // --- no group, no coordinates : use the vertices of the geom shape provided, and radius
{
MESSAGE("no group of nodes provided, using vertices from geom shape, and radius");
TopTools_IndexedMapOfShape vertexMap;
TopExp::MapShapes( theShape, TopAbs_VERTEX, vertexMap );
gp_Pnt p = gp_Pnt(0,0,0);
if (vertexMap.Extent() < 1)
return;
for ( int i = 1; i <= vertexMap.Extent(); ++i )
{
const TopoDS_Vertex& vertex = TopoDS::Vertex( vertexMap( i ));
p = BRep_Tool::Pnt(vertex);
gpnts.push_back(p);
MESSAGE("TopoDS_Vertex " << i << " " << p.X() << " " << p.Y() << " " << p.Z());
}
}
if (gpnts.size() > 0)
{
int nodeId = 0;
const SMDS_MeshNode* startNode = theNodeSearcher->FindClosestTo(gpnts[0]);
if (startNode)
nodeId = startNode->GetID();
MESSAGE("nodeId " << nodeId);
double radius2 = radius*radius;
MESSAGE("radius2 " << radius2);
// --- volumes on start node
setOfVolToCheck.clear();
SMDS_MeshElement* startVol = 0;
SMDS_ElemIteratorPtr volItr = startNode->GetInverseElementIterator(SMDSAbs_Volume);
while (volItr->more())
{
startVol = (SMDS_MeshElement*)volItr->next();
setOfVolToCheck.insert(startVol->getVtkId());
}
if (setOfVolToCheck.empty())
{
MESSAGE("No volumes found");
return;
}
// --- starting with central volumes then their neighbors, check if they are inside
// or outside the domain, until no more new neighbor volume is inside.
// Fill the group of inside volumes
std::map<int, double> mapOfNodeDistance2;
mapOfNodeDistance2.clear();
std::set<int> setOfOutsideVol;
while (!setOfVolToCheck.empty())
{
std::set<int>::iterator it = setOfVolToCheck.begin();
int vtkId = *it;
MESSAGE("volume to check, vtkId " << vtkId << " smdsId " << meshDS->fromVtkToSmds(vtkId));
bool volInside = false;
vtkIdType npts = 0;
vtkIdType* pts = 0;
grid->GetCellPoints(vtkId, npts, pts);
for (int i=0; i<npts; i++)
{
double distance2 = 0;
if (mapOfNodeDistance2.count(pts[i]))
{
distance2 = mapOfNodeDistance2[pts[i]];
MESSAGE("point " << pts[i] << " distance2 " << distance2);
}
else
{
double *coords = grid->GetPoint(pts[i]);
gp_Pnt aPoint = gp_Pnt(coords[0], coords[1], coords[2]);
distance2 = 1.E40;
for (int j=0; j<gpnts.size(); j++)
{
double d2 = aPoint.SquareDistance(gpnts[j]);
if (d2 < distance2)
{
distance2 = d2;
if (distance2 < radius2)
break;
}
}
mapOfNodeDistance2[pts[i]] = distance2;
MESSAGE(" point " << pts[i] << " distance2 " << distance2 << " coords " << coords[0] << " " << coords[1] << " " << coords[2]);
}
if (distance2 < radius2)
{
volInside = true; // one or more nodes inside the domain
sgrp->Add(meshDS->fromVtkToSmds(vtkId));
break;
}
}
if (volInside)
{
setOfInsideVol.insert(vtkId);
MESSAGE(" volume inside, vtkId " << vtkId << " smdsId " << meshDS->fromVtkToSmds(vtkId));
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++)
if (!setOfInsideVol.count(neighborsVtkIds[n]) ||setOfOutsideVol.count(neighborsVtkIds[n]))
setOfVolToCheck.insert(neighborsVtkIds[n]);
}
else
{
setOfOutsideVol.insert(vtkId);
MESSAGE(" volume outside, vtkId " << vtkId << " smdsId " << meshDS->fromVtkToSmds(vtkId));
}
setOfVolToCheck.erase(vtkId);
}
}
// --- for outside hexahedrons, check if they have more than one neighbor volume inside
// If yes, add the volume to the inside set
bool addedInside = true;
std::set<int> setOfVolToReCheck;
while (addedInside)
{
MESSAGE(" --------------------------- re check");
addedInside = false;
std::set<int>::iterator itv = setOfInsideVol.begin();
for (; itv != setOfInsideVol.end(); ++itv)
{
int vtkId = *itv;
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++)
if (!setOfInsideVol.count(neighborsVtkIds[n]))
setOfVolToReCheck.insert(neighborsVtkIds[n]);
}
setOfVolToCheck = setOfVolToReCheck;
setOfVolToReCheck.clear();
while (!setOfVolToCheck.empty())
{
std::set<int>::iterator it = setOfVolToCheck.begin();
int vtkId = *it;
if (grid->GetCellType(vtkId) == VTK_HEXAHEDRON)
{
MESSAGE("volume to recheck, vtkId " << vtkId << " smdsId " << meshDS->fromVtkToSmds(vtkId));
int countInside = 0;
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++)
if (setOfInsideVol.count(neighborsVtkIds[n]))
countInside++;
MESSAGE("countInside " << countInside);
if (countInside > 1)
{
MESSAGE(" volume inside, vtkId " << vtkId << " smdsId " << meshDS->fromVtkToSmds(vtkId));
setOfInsideVol.insert(vtkId);
sgrp->Add(meshDS->fromVtkToSmds(vtkId));
addedInside = true;
}
else
setOfVolToReCheck.insert(vtkId);
}
setOfVolToCheck.erase(vtkId);
}
}
// --- map of Downward faces at the boundary, inside the global volume
// map of Downward faces on the skin of the global volume (equivalent to SMDS faces on the skin)
// fill group of SMDS faces inside the volume (when several volume shapes)
// fill group of SMDS faces on the skin of the global volume (if skin)
std::map<DownIdType, int, DownIdCompare> boundaryFaces; // boundary faces inside the volume --> corresponding cell
std::map<DownIdType, int, DownIdCompare> skinFaces; // faces on the skin of the global volume --> corresponding cell
std::set<int>::iterator it = setOfInsideVol.begin();
for (; it != setOfInsideVol.end(); ++it)
{
int vtkId = *it;
//MESSAGE(" vtkId " << vtkId << " smdsId " << meshDS->fromVtkToSmds(vtkId));
int neighborsVtkIds[NBMAXNEIGHBORS];
int downIds[NBMAXNEIGHBORS];
unsigned char downTypes[NBMAXNEIGHBORS];
int nbNeighbors = grid->GetNeighbors(neighborsVtkIds, downIds, downTypes, vtkId, true);
for (int n = 0; n < nbNeighbors; n++)
{
int neighborDim = SMDS_Downward::getCellDimension(grid->GetCellType(neighborsVtkIds[n]));
if (neighborDim == 3)
{
if (! setOfInsideVol.count(neighborsVtkIds[n])) // neighbor volume is not inside : face is boundary
{
DownIdType face(downIds[n], downTypes[n]);
boundaryFaces[face] = vtkId;
}
// if the face between to volumes is in the mesh, get it (internal face between shapes)
int vtkFaceId = grid->getDownArray(downTypes[n])->getVtkCellId(downIds[n]);
if (vtkFaceId >= 0)
{
sgrpi->Add(meshDS->fromVtkToSmds(vtkFaceId));
// find also the smds edges on this face
int nbEdges = grid->getDownArray(downTypes[n])->getNumberOfDownCells(downIds[n]);
const int* dEdges = grid->getDownArray(downTypes[n])->getDownCells(downIds[n]);
const unsigned char* dTypes = grid->getDownArray(downTypes[n])->getDownTypes(downIds[n]);
for (int i = 0; i < nbEdges; i++)
{
int vtkEdgeId = grid->getDownArray(dTypes[i])->getVtkCellId(dEdges[i]);
if (vtkEdgeId >= 0)
sgrpei->Add(meshDS->fromVtkToSmds(vtkEdgeId));
}
}
}
else if (neighborDim == 2) // skin of the volume
{
DownIdType face(downIds[n], downTypes[n]);
skinFaces[face] = vtkId;
int vtkFaceId = grid->getDownArray(downTypes[n])->getVtkCellId(downIds[n]);
if (vtkFaceId >= 0)
sgrps->Add(meshDS->fromVtkToSmds(vtkFaceId));
}
}
}
// --- identify the edges constituting the wire of each subshape on the skin
// define polylines with the nodes of edges, equivalent to wires
// project polylines on subshapes, and partition, to get geom faces
std::map<int, std::set<int> > shapeIdToVtkIdSet; // shapeId --> set of vtkId on skin
std::set<int> emptySet;
emptySet.clear();
std::set<int> shapeIds;
SMDS_ElemIteratorPtr itelem = sgrps->GetElements();
while (itelem->more())
{
const SMDS_MeshElement *elem = itelem->next();
int shapeId = elem->getshapeId();
int vtkId = elem->getVtkId();
if (!shapeIdToVtkIdSet.count(shapeId))
{
shapeIdToVtkIdSet[shapeId] = emptySet;
shapeIds.insert(shapeId);
}
shapeIdToVtkIdSet[shapeId].insert(vtkId);
}
std::map<int, std::set<DownIdType, DownIdCompare> > shapeIdToEdges; // shapeId --> set of downward edges
std::set<DownIdType, DownIdCompare> emptyEdges;
emptyEdges.clear();
std::map<int, std::set<int> >::iterator itShape = shapeIdToVtkIdSet.begin();
for (; itShape != shapeIdToVtkIdSet.end(); ++itShape)
{
int shapeId = itShape->first;
MESSAGE(" --- Shape ID --- "<< shapeId);
shapeIdToEdges[shapeId] = emptyEdges;
std::vector<int> nodesEdges;
std::set<int>::iterator its = itShape->second.begin();
for (; its != itShape->second.end(); ++its)
{
int vtkId = *its;
MESSAGE(" " << vtkId);
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++)
{
if (neighborsVtkIds[n]<0) // only smds faces are considered as neighbors here
continue;
int smdsId = meshDS->fromVtkToSmds(neighborsVtkIds[n]);
const SMDS_MeshElement* elem = meshDS->FindElement(smdsId);
if ( shapeIds.count(elem->getshapeId()) && !sgrps->Contains(elem)) // edge : neighbor in the set of shape, not in the group
{
DownIdType edge(downIds[n], downTypes[n]);
if (!shapeIdToEdges[shapeId].count(edge))
{
shapeIdToEdges[shapeId].insert(edge);
int vtkNodeId[3];
int nbNodes = grid->getDownArray(downTypes[n])->getNodes(downIds[n],vtkNodeId);
nodesEdges.push_back(vtkNodeId[0]);
nodesEdges.push_back(vtkNodeId[nbNodes-1]);
MESSAGE(" --- nodes " << vtkNodeId[0]+1 << " " << vtkNodeId[nbNodes-1]+1);
}
}
}
}
std::list<int> order;
order.clear();
if (nodesEdges.size() > 0)
{
order.push_back(nodesEdges[0]); MESSAGE(" --- back " << order.back()+1); // SMDS id = VTK id + 1;
nodesEdges[0] = -1;
order.push_back(nodesEdges[1]); MESSAGE(" --- back " << order.back()+1);
nodesEdges[1] = -1; // do not reuse this edge
bool found = true;
while (found)
{
int nodeTofind = order.back(); // try first to push back
int i = 0;
for (i = 0; i<nodesEdges.size(); i++)
if (nodesEdges[i] == nodeTofind)
break;
if (i == nodesEdges.size())
found = false; // no follower found on back
else
{
if (i%2) // odd ==> use the previous one
if (nodesEdges[i-1] < 0)
found = false;
else
{
order.push_back(nodesEdges[i-1]); MESSAGE(" --- back " << order.back()+1);
nodesEdges[i-1] = -1;
}
else // even ==> use the next one
if (nodesEdges[i+1] < 0)
found = false;
else
{
order.push_back(nodesEdges[i+1]); MESSAGE(" --- back " << order.back()+1);
nodesEdges[i+1] = -1;
}
}
if (found)
continue;
// try to push front
found = true;
nodeTofind = order.front(); // try to push front
for (i = 0; i<nodesEdges.size(); i++)
if (nodesEdges[i] == nodeTofind)
break;
if (i == nodesEdges.size())
{
found = false; // no predecessor found on front
continue;
}
if (i%2) // odd ==> use the previous one
if (nodesEdges[i-1] < 0)
found = false;
else
{
order.push_front(nodesEdges[i-1]); MESSAGE(" --- front " << order.front()+1);
nodesEdges[i-1] = -1;
}
else // even ==> use the next one
if (nodesEdges[i+1] < 0)
found = false;
else
{
order.push_front(nodesEdges[i+1]); MESSAGE(" --- front " << order.front()+1);
nodesEdges[i+1] = -1;
}
}
}
std::vector<int> nodes;
nodes.push_back(shapeId);
std::list<int>::iterator itl = order.begin();
for (; itl != order.end(); itl++)
{
nodes.push_back((*itl) + 1); // SMDS id = VTK id + 1;
MESSAGE(" ordered node " << nodes[nodes.size()-1]);
}
listOfListOfNodes.push_back(nodes);
}
// partition geom faces with blocFissure
// mesh blocFissure and geom faces of the skin (external wires given, triangle algo to choose)
// mesh volume around blocFissure (skin triangles and quadrangle given, tetra algo to choose)
return;
}
//================================================================================
/*!
* \brief Generates skin mesh (containing 2D cells) from 3D mesh

View File

@ -576,6 +576,11 @@ public:
const TIDSortedElemSet& theNodesNot,
const TIDSortedElemSet& theAffectedElems );
bool AffectedElemGroupsInRegion( const TIDSortedElemSet& theElems,
const TIDSortedElemSet& theNodesNot,
const TopoDS_Shape& theShape,
TIDSortedElemSet& theAffectedElems);
bool DoubleNodesInRegion( const TIDSortedElemSet& theElems,
const TIDSortedElemSet& theNodesNot,
const TopoDS_Shape& theShape );
@ -587,6 +592,13 @@ public:
bool CreateFlatElementsOnFacesGroups( const std::vector<TIDSortedElemSet>& theElems );
void CreateHoleSkin(double radius,
const TopoDS_Shape& theShape,
SMESH_NodeSearcher* theNodeSearcher,
const char* groupName,
std::vector<double>& nodesCoords,
std::vector<std::vector<int> >& listOfListOfNodes);
/*!
* \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

@ -5941,6 +5941,124 @@ SMESH_MeshEditor_i::DoubleNodeElemGroupsInRegion(const SMESH::ListOfGroups& theE
return aResult;
}
//================================================================================
/*!
\brief Identify the elements that will be affected by node duplication (actual duplication is not performed.
This method is the first step of DoubleNodeElemGroupsInRegion.
\param theElems - list of groups of elements (edges or faces) to be replicated
\param theNodesNot - list of groups of nodes not to replicated
\param theShape - shape to detect affected elements (element which geometric center
located on or inside shape).
The replicated nodes should be associated to affected elements.
\return groups of affected elements
\sa DoubleNodeElemGroupsInRegion()
*/
//================================================================================
SMESH::ListOfGroups*
SMESH_MeshEditor_i::AffectedElemGroupsInRegion( const SMESH::ListOfGroups& theElems,
const SMESH::ListOfGroups& theNodesNot,
GEOM::GEOM_Object_ptr theShape )
{
MESSAGE("AffectedElemGroupsInRegion");
SMESH::ListOfGroups_var aListOfGroups = new SMESH::ListOfGroups();
bool isEdgeGroup = false;
bool isFaceGroup = false;
bool isVolumeGroup = false;
SMESH::SMESH_Group_var aNewEdgeGroup = myMesh_i->CreateGroup(SMESH::EDGE, "affectedEdges");
SMESH::SMESH_Group_var aNewFaceGroup = myMesh_i->CreateGroup(SMESH::FACE, "affectedFaces");
SMESH::SMESH_Group_var aNewVolumeGroup = myMesh_i->CreateGroup(SMESH::VOLUME, "affectedVolumes");
initData();
::SMESH_MeshEditor aMeshEditor(myMesh);
SMESHDS_Mesh* aMeshDS = GetMeshDS();
TIDSortedElemSet anElems, aNodes;
listOfGroupToSet(theElems, aMeshDS, anElems, false);
listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true);
TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape(theShape);
TIDSortedElemSet anAffected;
bool aResult = aMeshEditor.AffectedElemGroupsInRegion(anElems, aNodes, aShape, anAffected);
storeResult(aMeshEditor);
myMesh->GetMeshDS()->Modified();
TPythonDump pyDump;
if (aResult)
{
myMesh->SetIsModified(true);
int lg = anAffected.size();
MESSAGE("lg="<< lg);
SMESH::long_array_var volumeIds = new SMESH::long_array;
volumeIds->length(lg);
SMESH::long_array_var faceIds = new SMESH::long_array;
faceIds->length(lg);
SMESH::long_array_var edgeIds = new SMESH::long_array;
edgeIds->length(lg);
int ivol = 0;
int iface = 0;
int iedge = 0;
TIDSortedElemSet::const_iterator eIt = anAffected.begin();
for (; eIt != anAffected.end(); ++eIt)
{
const SMDS_MeshElement* anElem = *eIt;
if (!anElem)
continue;
int elemId = anElem->GetID();
if (myMesh->GetElementType(elemId, true) == SMDSAbs_Volume)
volumeIds[ivol++] = elemId;
else if (myMesh->GetElementType(elemId, true) == SMDSAbs_Face)
faceIds[iface++] = elemId;
else if (myMesh->GetElementType(elemId, true) == SMDSAbs_Edge)
edgeIds[iedge++] = elemId;
}
volumeIds->length(ivol);
faceIds->length(iface);
edgeIds->length(iedge);
aNewVolumeGroup->Add(volumeIds);
aNewFaceGroup->Add(faceIds);
aNewEdgeGroup->Add(edgeIds);
isVolumeGroup = (aNewVolumeGroup->Size() > 0);
isFaceGroup = (aNewFaceGroup->Size() > 0);
isEdgeGroup = (aNewEdgeGroup->Size() > 0);
}
int nbGroups = 0;
if (isEdgeGroup)
nbGroups++;
if (isFaceGroup)
nbGroups++;
if (isVolumeGroup)
nbGroups++;
aListOfGroups->length(nbGroups);
int i = 0;
if (isEdgeGroup)
aListOfGroups[i++] = aNewEdgeGroup._retn();
if (isFaceGroup)
aListOfGroups[i++] = aNewFaceGroup._retn();
if (isVolumeGroup)
aListOfGroups[i++] = aNewVolumeGroup._retn();
// Update Python script
pyDump << "[ ";
if (isEdgeGroup)
pyDump << aNewEdgeGroup << ", ";
if (isFaceGroup)
pyDump << aNewFaceGroup << ", ";
if (isVolumeGroup)
pyDump << aNewVolumeGroup << ", ";
pyDump << "] = ";
pyDump << this << ".AffectedElemGroupsInRegion( " << &theElems << ", " << &theNodesNot << ", " << theShape << " )";
return aListOfGroups._retn();
}
//================================================================================
/*!
\brief Generated skin mesh (containing 2D cells) from 3D mesh
@ -6059,6 +6177,53 @@ CORBA::Boolean SMESH_MeshEditor_i::CreateFlatElementsOnFacesGroups( const SMESH:
return aResult;
}
/*!
* \brief identify all the elements around a geom shape, get the faces delimiting the hole
* Build groups of volume to remove, groups of faces to replace on the skin of the object,
* groups of faces to remove inside the object, (idem edges).
* Build ordered list of nodes at the border of each group of faces to replace (to be used to build a geom subshape)
*/
void SMESH_MeshEditor_i::CreateHoleSkin(CORBA::Double radius,
GEOM::GEOM_Object_ptr theShape,
const char* groupName,
const SMESH::double_array& theNodesCoords,
SMESH::array_of_long_array_out GroupsOfNodes)
throw (SALOME::SALOME_Exception)
{
initData();
std::vector<std::vector<int> > aListOfListOfNodes;
::SMESH_MeshEditor aMeshEditor( myMesh );
theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
if ( !theNodeSearcher )
theNodeSearcher = aMeshEditor.GetNodeSearcher();
vector<double> nodesCoords;
for (int i = 0; i < theNodesCoords.length(); i++)
{
nodesCoords.push_back( theNodesCoords[i] );
}
TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
aMeshEditor.CreateHoleSkin(radius, aShape, theNodeSearcher, groupName, nodesCoords, aListOfListOfNodes);
GroupsOfNodes = new SMESH::array_of_long_array;
GroupsOfNodes->length( aListOfListOfNodes.size() );
std::vector<std::vector<int> >::iterator llIt = aListOfListOfNodes.begin();
for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
{
vector<int>& aListOfNodes = *llIt;
vector<int>::iterator lIt = aListOfNodes.begin();;
SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
aGroup.length( aListOfNodes.size() );
for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
aGroup[ j ] = (*lIt);
}
TPythonDump() << "lists_nodes = " << this << ".CreateHoleSkin( "
<< radius << ", " << theShape << ", " << ", " << groupName << ", " << theNodesCoords << " )";
}
// issue 20749 ===================================================================
/*!
* \brief Creates missing boundary elements

View File

@ -743,6 +743,22 @@ public:
CORBA::Boolean DoubleNodeElemGroupsInRegion( const SMESH::ListOfGroups& theElems,
const SMESH::ListOfGroups& theNodesNot,
GEOM::GEOM_Object_ptr theShape );
/*!
* \brief Identify the elements that will be affected by node duplication (actual duplication is not performed.
* This method is the first step of DoubleNodeElemGroupsInRegion.
* \param theElems - list of groups of elements (edges or faces) to be replicated
* \param theNodesNot - list of groups of nodes not to replicated
* \param theShape - shape to detect affected elements (element which geometric center
* located on or inside shape).
* The replicated nodes should be associated to affected elements.
* \return groups of affected elements
* \sa DoubleNodeElemGroupsInRegion()
*/
SMESH::ListOfGroups* AffectedElemGroupsInRegion( const SMESH::ListOfGroups& theElems,
const SMESH::ListOfGroups& theNodesNot,
GEOM::GEOM_Object_ptr theShape );
/*!
* \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.
@ -767,6 +783,19 @@ public:
*/
CORBA::Boolean CreateFlatElementsOnFacesGroups( const SMESH::ListOfGroups& theGroupsOfFaces );
/*!
* \brief identify all the elements around a geom shape, get the faces delimiting the hole
* Build groups of volume to remove, groups of faces to replace on the skin of the object,
* groups of faces to remove insidethe object, (idem edges).
* Build ordered list of nodes at the border of each group of faces to replace (to be used to build a geom subshape)
*/
void CreateHoleSkin(CORBA::Double radius,
GEOM::GEOM_Object_ptr theShape,
const char* groupName,
const SMESH::double_array& theNodesCoords,
SMESH::array_of_long_array_out GroupsOfNodes)
throw (SALOME::SALOME_Exception);
/*!
* \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

@ -3976,6 +3976,18 @@ class Mesh:
def DoubleNodeElemGroupsInRegion(self, theElems, theNodesNot, theShape):
return self.editor.DoubleNodeElemGroupsInRegion(theElems, theNodesNot, theShape)
## Identify the elements that will be affected by node duplication (actual duplication is not performed.
# This method is the first step of DoubleNodeElemGroupsInRegion.
# @param theElems - list of groups of elements (edges or faces) to be replicated
# @param theNodesNot - list of groups of nodes not to replicated
# @param theShape - shape to detect affected elements (element which geometric center
# located on or inside shape).
# The replicated nodes should be associated to affected elements.
# @return groups of affected elements
# @ingroup l2_modif_edit
def AffectedElemGroupsInRegion(self, theElems, theNodesNot, theShape):
return self.editor.AffectedElemGroupsInRegion(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.
@ -3997,6 +4009,11 @@ class Mesh:
def CreateFlatElementsOnFacesGroups(self, theGroupsOfFaces ):
return self.editor.CreateFlatElementsOnFacesGroups( theGroupsOfFaces )
## identify all the elements around a geom shape, get the faces delimiting the hole
#
def CreateHoleSkin(self, radius, theShape, groupName, theNodesCoords):
return self.editor.CreateHoleSkin( radius, theShape, groupName, theNodesCoords )
def _valueFromFunctor(self, funcType, elemId):
fn = self.smeshpyD.GetFunctor(funcType)
fn.SetMesh(self.mesh)