mirror of
https://git.salome-platform.org/gitpub/modules/smesh.git
synced 2024-12-26 17:30:35 +05:00
Pattern mapping: replace adjacent faces with polygons to obtain conform mesh. Improve polygons and polyhedral volumes processing.
This commit is contained in:
parent
0482db55d3
commit
ed0ea97e94
@ -103,9 +103,12 @@ module SMESH
|
||||
|
||||
/*!
|
||||
* Create nodes and elements in <theMesh> using nodes
|
||||
* coordinates computed by either of Apply...() methods
|
||||
* coordinates computed by either of Apply...() methods.
|
||||
* If CreatePoly is TRUE, replace adjacent faces by polygons,
|
||||
* inserting new nodes in common links.
|
||||
*/
|
||||
boolean MakeMesh(in SMESH_Mesh theMesh);
|
||||
boolean MakeMesh (in SMESH_Mesh theMesh,
|
||||
in boolean CreatePoly);
|
||||
|
||||
/*!
|
||||
* Return the loaded pattern in the string form to be saved in file
|
||||
|
@ -1385,6 +1385,55 @@ const SMDS_MeshElement* SMDS_Mesh::FindElement(int IDelem) const
|
||||
return myElementIDFactory->MeshElement(IDelem);
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : FindFace
|
||||
//purpose : find polygon
|
||||
//=======================================================================
|
||||
|
||||
const SMDS_MeshFace* SMDS_Mesh::FindFace (std::vector<int> nodes_ids) const
|
||||
{
|
||||
int nbnodes = nodes_ids.size();
|
||||
std::vector<const SMDS_MeshNode *> poly_nodes (nbnodes);
|
||||
for (int inode = 0; inode < nbnodes; inode++) {
|
||||
const SMDS_MeshNode * node = FindNode(nodes_ids[inode]);
|
||||
if (node == NULL) return NULL;
|
||||
}
|
||||
return FindFace(poly_nodes);
|
||||
}
|
||||
|
||||
const SMDS_MeshFace* SMDS_Mesh::FindFace (std::vector<const SMDS_MeshNode *> nodes)
|
||||
{
|
||||
int nbNodes = nodes.size();
|
||||
if (nbNodes < 1) return NULL;
|
||||
|
||||
bool isFound = true;
|
||||
const SMDS_MeshFace * face;
|
||||
set<const SMDS_MeshFace *> faces;
|
||||
|
||||
for (int inode = 0; inode < nbNodes && isFound; inode++) {
|
||||
set<const SMDS_MeshFace *> new_faces;
|
||||
|
||||
SMDS_ElemIteratorPtr itF = nodes[inode]->facesIterator();
|
||||
while (itF->more()) {
|
||||
face = static_cast<const SMDS_MeshFace *>(itF->next());
|
||||
if (face->NbNodes() == nbNodes) {
|
||||
if (inode == 0 || faces.find(face) != faces.end()) {
|
||||
new_faces.insert(face);
|
||||
}
|
||||
}
|
||||
}
|
||||
faces = new_faces;
|
||||
if (new_faces.size() == 0) {
|
||||
isFound = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (isFound)
|
||||
return face;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : DumpNodes
|
||||
//purpose :
|
||||
@ -2129,4 +2178,3 @@ void SMDS_Mesh::Renumber (const bool isNodes, const int startID, const int del
|
||||
ID += deltaID;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -260,6 +260,10 @@ public:
|
||||
const SMDS_MeshNode *n2,
|
||||
const SMDS_MeshNode *n3,
|
||||
const SMDS_MeshNode *n4);
|
||||
|
||||
const SMDS_MeshFace *FindFace(std::vector<int> nodes_ids) const;
|
||||
static const SMDS_MeshFace* FindFace(std::vector<const SMDS_MeshNode *> nodes);
|
||||
|
||||
int MaxNodeID() const;
|
||||
int MinNodeID() const;
|
||||
int MaxElementID() const;
|
||||
|
@ -1274,6 +1274,8 @@ void laplacianSmooth(SMESHDS_Mesh * theMesh,
|
||||
if ( theElems.find( elem ) == theElems.end() )
|
||||
continue;
|
||||
|
||||
if (elem->IsPoly())
|
||||
continue;
|
||||
int i = 0, iNode = 0;
|
||||
const SMDS_MeshNode* aNodes [4];
|
||||
SMDS_ElemIteratorPtr itN = elem->nodesIterator();
|
||||
@ -1858,7 +1860,8 @@ static void makeWalls (SMESHDS_Mesh* aMesh,
|
||||
for (int inode = 0; inode < nbPolygonNodes; inode++) {
|
||||
polygon_nodes[inode] = nodes[inode];
|
||||
}
|
||||
aMesh->AddPolygonalFace(polygon_nodes);
|
||||
if (!hasFreeLinks || !aMesh->FindFace(polygon_nodes))
|
||||
aMesh->AddPolygonalFace(polygon_nodes);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -2691,6 +2694,92 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes)
|
||||
int nbUniqueNodes = nodeSet.size();
|
||||
if ( nbNodes != nbUniqueNodes ) // some nodes stick
|
||||
{
|
||||
// Polygons and Polyhedral volumes
|
||||
if (elem->IsPoly()) {
|
||||
|
||||
if (elem->GetType() == SMDSAbs_Face) {
|
||||
// Polygon
|
||||
if (nbUniqueNodes < 3) {
|
||||
isOk = false;
|
||||
} else {
|
||||
// get simple seq of nodes
|
||||
const SMDS_MeshNode* simpleNodes[ nbNodes ];
|
||||
int iSimple = 0;
|
||||
|
||||
simpleNodes[iSimple++] = curNodes[0];
|
||||
for (iCur = 1; iCur < nbNodes; iCur++) {
|
||||
if (curNodes[iCur] != simpleNodes[iSimple - 1]) {
|
||||
simpleNodes[iSimple++] = curNodes[iCur];
|
||||
}
|
||||
}
|
||||
int nbSimple = iSimple;
|
||||
if (simpleNodes[nbSimple - 1] == simpleNodes[0]) {
|
||||
nbSimple--;
|
||||
}
|
||||
|
||||
// separate cycles
|
||||
bool foundCycle = (nbSimple > nbUniqueNodes);
|
||||
while (foundCycle) {
|
||||
foundCycle = false;
|
||||
set<const SMDS_MeshNode*> cycleSet;
|
||||
for (iSimple = 0; iSimple < nbSimple && !foundCycle; iSimple++) {
|
||||
const SMDS_MeshNode* n = simpleNodes[iSimple];
|
||||
if (!cycleSet.insert( n ).second) {
|
||||
foundCycle = true;
|
||||
|
||||
// separate cycle
|
||||
int iC = 0, curLast = iSimple;
|
||||
for (; iC < curLast; iC++) {
|
||||
if (simpleNodes[iC] == n) break;
|
||||
}
|
||||
int cycleLen = curLast - iC;
|
||||
if (cycleLen > 2) {
|
||||
// create sub-element
|
||||
vector<const SMDS_MeshNode *> poly_nodes (cycleLen);
|
||||
for (int ii = 0; iC < curLast; iC++) {
|
||||
poly_nodes[ii++] = simpleNodes[iC];
|
||||
}
|
||||
SMDS_MeshElement* newElem = aMesh->AddPolygonalFace(poly_nodes);
|
||||
if (aShapeId)
|
||||
aMesh->SetMeshElementOnShape(newElem, aShapeId);
|
||||
}
|
||||
// put the rest nodes from the first cycle position
|
||||
for (iC = curLast + 1; iC < nbSimple; iC++) {
|
||||
simpleNodes[iC - cycleLen] = simpleNodes[iC];
|
||||
}
|
||||
nbSimple -= cycleLen;
|
||||
}
|
||||
} // for (iSimple = 0; iSimple < nbSimple; iSimple++)
|
||||
} // while (foundCycle)
|
||||
|
||||
if (iSimple > 2) {
|
||||
aMesh->ChangeElementNodes(elem, simpleNodes, nbSimple);
|
||||
} else {
|
||||
isOk = false;
|
||||
}
|
||||
}
|
||||
|
||||
} else if (elem->GetType() == SMDSAbs_Volume) {
|
||||
// Polyhedral volume
|
||||
if (nbUniqueNodes < 4) {
|
||||
isOk = false;
|
||||
} else {
|
||||
// each face has to be analized in order to check volume validity
|
||||
//aMesh->ChangeElementNodes(elem, uniqueNodes, nbUniqueNodes);
|
||||
isOk = false;
|
||||
}
|
||||
|
||||
} else {
|
||||
isOk = false;
|
||||
}
|
||||
|
||||
if (!isOk)
|
||||
rmElemIds.push_back(elem->GetID());
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Regular elements
|
||||
switch ( nbNodes ) {
|
||||
case 2: ///////////////////////////////////// EDGE
|
||||
isOk = false; break;
|
||||
@ -3930,17 +4019,31 @@ SMESH_MeshEditor::Sew_Error
|
||||
bool isNewFace = setOfFaceNodeSet.insert( faceNodeSet ).second;
|
||||
if ( isNewFace ) {
|
||||
// no such a face is given but it still can exist, check it
|
||||
if ( nbNodes == 3 )
|
||||
if ( nbNodes == 3 ) {
|
||||
aFreeFace = aMesh->FindFace( fNodes[0],fNodes[1],fNodes[2] );
|
||||
else
|
||||
} else if ( nbNodes == 4 ) {
|
||||
aFreeFace = aMesh->FindFace( fNodes[0],fNodes[1],fNodes[2],fNodes[3] );
|
||||
} else {
|
||||
vector<const SMDS_MeshNode *> poly_nodes (nbNodes);
|
||||
for (int inode = 0; inode < nbNodes; inode++) {
|
||||
poly_nodes[inode] = fNodes[inode];
|
||||
}
|
||||
aFreeFace = aMesh->FindFace(poly_nodes);
|
||||
}
|
||||
}
|
||||
if ( !aFreeFace ) {
|
||||
// create a temporary face
|
||||
if ( nbNodes == 3 )
|
||||
if ( nbNodes == 3 ) {
|
||||
aFreeFace = aTmpFacesMesh.AddFace( fNodes[0],fNodes[1],fNodes[2] );
|
||||
else
|
||||
} else if ( nbNodes == 4 ) {
|
||||
aFreeFace = aTmpFacesMesh.AddFace( fNodes[0],fNodes[1],fNodes[2],fNodes[3] );
|
||||
} else {
|
||||
vector<const SMDS_MeshNode *> poly_nodes (nbNodes);
|
||||
for (int inode = 0; inode < nbNodes; inode++) {
|
||||
poly_nodes[inode] = fNodes[inode];
|
||||
}
|
||||
aFreeFace = aTmpFacesMesh.AddPolygonalFace(poly_nodes);
|
||||
}
|
||||
}
|
||||
if ( aFreeFace )
|
||||
freeFaceList.push_back( aFreeFace );
|
||||
|
@ -2681,6 +2681,9 @@ void SMESH_Pattern::mergePoints (map<TNodeSet, list<list<int> > >& indGroups,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// save links to update adjacent faces in MakeMesh() method
|
||||
myLinks = indGroups;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
@ -3135,7 +3138,7 @@ bool SMESH_Pattern::Apply (const SMDS_MeshVolume* theVolume,
|
||||
// coordinates computed by either of Apply...() methods
|
||||
//=======================================================================
|
||||
|
||||
bool SMESH_Pattern::MakeMesh(SMESH_Mesh* theMesh)
|
||||
bool SMESH_Pattern::MakeMesh (SMESH_Mesh* theMesh, bool toCreatePoly)
|
||||
{
|
||||
MESSAGE(" ::MakeMesh() " );
|
||||
if ( !myIsComputed )
|
||||
@ -3368,6 +3371,46 @@ bool SMESH_Pattern::MakeMesh(SMESH_Mesh* theMesh)
|
||||
editor.Remove( elemIDs, false );
|
||||
}
|
||||
|
||||
if (toCreatePoly && myIs2D) {
|
||||
// replace adjacent faces by polygons, inserting nodes in common link
|
||||
|
||||
map< TNodeSet, list< list<int> > >::iterator linksIt;
|
||||
for (linksIt = myLinks.begin(); linksIt != myLinks.end(); linksIt++) {
|
||||
// end nodes of link
|
||||
set<const SMDS_MeshNode*> ends = linksIt->first;
|
||||
set<const SMDS_MeshNode*>::iterator endsIt = ends.begin();
|
||||
const SMDS_MeshNode* n1 = *endsIt;
|
||||
endsIt++;
|
||||
const SMDS_MeshNode* n2 = *endsIt;
|
||||
|
||||
// middle nodes of link (to be inserted in adjacent faces)
|
||||
list<const SMDS_MeshNode*> link_nodes;
|
||||
|
||||
list< list<int> > coincident_links = linksIt->second;
|
||||
list<int>& link = coincident_links.front();
|
||||
list<int>::iterator linkIt = link.begin();
|
||||
for (; linkIt != link.end(); linkIt++) {
|
||||
if (onMeshElements)
|
||||
link_nodes.push_back(nodesVector[ *linkIt ]);
|
||||
else
|
||||
link_nodes.push_back(pointNodeMap[ & myPoints[ *linkIt ]]);
|
||||
}
|
||||
|
||||
// update all adjacent faces
|
||||
set<const SMDS_MeshElement*> elemSet, avoidSet;
|
||||
while (true) {
|
||||
const SMDS_MeshElement* adjElem =
|
||||
SMESH_MeshEditor::FindFaceInSet(n1, n2, elemSet, avoidSet);
|
||||
if (adjElem) {
|
||||
SMESH_MeshEditor editor (theMesh);
|
||||
editor.InsertNodesIntoLink(adjElem, n1, n2, link_nodes, toCreatePoly);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return setErrorCode( ERR_OK );
|
||||
}
|
||||
|
||||
|
@ -128,7 +128,7 @@ class SMESH_Pattern {
|
||||
bool GetMappedPoints ( std::list<const gp_XYZ *> & thePoints ) const;
|
||||
// Return nodes coordinates computed by Apply() method
|
||||
|
||||
bool MakeMesh(SMESH_Mesh* theMesh);
|
||||
bool MakeMesh (SMESH_Mesh* theMesh, bool toCreatePoly = false);
|
||||
// Create nodes and elements in <theMesh> using nodes
|
||||
// coordinates computed by either of Apply...() methods
|
||||
|
||||
@ -306,6 +306,8 @@ class SMESH_Pattern {
|
||||
std::map< int, const SMDS_MeshNode*> myXYZIdToNodeMap; // map id to node of a refined element
|
||||
std::vector<const SMDS_MeshElement*> myElements; // refined elements
|
||||
std::vector<const SMDS_MeshNode*> myOrderedNodes;
|
||||
|
||||
std::map< TNodeSet, std::list< std::list<int> > > myLinks;
|
||||
};
|
||||
|
||||
|
||||
|
@ -774,24 +774,3 @@ void SMESHGUI_CreatePatternDlg::onTypeChanged( int theType )
|
||||
else
|
||||
myPicture2d->hide();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -139,20 +139,3 @@ private:
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -206,6 +206,9 @@ QFrame* SMESHGUI_MeshPatternDlg::createMainFrame( QWidget* theParent )
|
||||
// reverse check box
|
||||
myReverseChk = new QCheckBox( tr( "REVERSE" ), aPatGrp );
|
||||
|
||||
// CreatePoly check box
|
||||
myCreatePolyChk = new QCheckBox( tr( "CREATE_POLYGONS_NEAR_BOUNDARY" ), aPatGrp );
|
||||
|
||||
// Pictures 2d and 3d
|
||||
for ( int i = 0; i < 2; i++ )
|
||||
{
|
||||
@ -389,7 +392,9 @@ bool SMESHGUI_MeshPatternDlg::onApply()
|
||||
myGeomObj[ Object ], myGeomObj[ Vertex1 ], myGeomObj[ Vertex2 ] );
|
||||
}
|
||||
|
||||
if ( myPattern->MakeMesh( myMesh ) )
|
||||
bool toCreatePoly = (myCreatePolyChk->isChecked() && (myType == Type_2d));
|
||||
|
||||
if ( myPattern->MakeMesh( myMesh, toCreatePoly ) )
|
||||
{
|
||||
mySelection->ClearIObjects();
|
||||
SMESHGUI* aCompGUI = SMESHGUI::GetSMESHGUI();
|
||||
@ -1121,6 +1126,7 @@ void SMESHGUI_MeshPatternDlg::onTypeChanged( int theType )
|
||||
mySelBtn [ Vertex2 ]->hide();
|
||||
mySelEdit[ Vertex2 ]->hide();
|
||||
myReverseChk->show();
|
||||
myCreatePolyChk->show();
|
||||
myPicture2d->show();
|
||||
myPicture3d->hide();
|
||||
mySelLbl[ Object ]->setText( tr( "FACE" ) );
|
||||
@ -1137,6 +1143,7 @@ void SMESHGUI_MeshPatternDlg::onTypeChanged( int theType )
|
||||
mySelBtn [ Vertex2 ]->show();
|
||||
mySelEdit[ Vertex2 ]->show();
|
||||
myReverseChk->hide();
|
||||
myCreatePolyChk->hide();
|
||||
myPicture2d->hide();
|
||||
myPicture3d->show();
|
||||
mySelLbl[ Object ]->setText( tr( "3D_BLOCK" ) );
|
||||
@ -1386,4 +1393,3 @@ int SMESHGUI_MeshPatternDlg::getNode( bool second ) const
|
||||
{
|
||||
return second ? myNode2->value() - 1 : myNode1->value() - 1;
|
||||
}
|
||||
|
||||
|
@ -145,6 +145,7 @@ private:
|
||||
QPushButton* myNewBtn;
|
||||
|
||||
QCheckBox* myReverseChk;
|
||||
QCheckBox* myCreatePolyChk;
|
||||
SMESHGUI_PatternWidget* myPicture2d;
|
||||
QFrame* myPicture3d;
|
||||
QLabel* myPreview3d;
|
||||
@ -168,20 +169,3 @@ private:
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -50,6 +50,8 @@
|
||||
#include <vtkCell3D.h>
|
||||
#include <vtkQuad.h>
|
||||
#include <vtkTriangle.h>
|
||||
#include <vtkPolygon.h>
|
||||
#include <vtkConvexPointSet.h>
|
||||
#include <vtkIdList.h>
|
||||
#include <vtkIntArray.h>
|
||||
#include <vtkCellArray.h>
|
||||
@ -332,12 +334,15 @@ SMESH::long_array_var SMESHGUI_MultiEditDlg::getIds()
|
||||
{
|
||||
vtkTriangle* aTri = vtkTriangle::SafeDownCast(aCell);
|
||||
vtkQuad* aQua = vtkQuad::SafeDownCast(aCell);
|
||||
vtkCell3D* a3d = vtkCell3D::SafeDownCast(aCell);
|
||||
vtkPolygon* aPG = vtkPolygon::SafeDownCast(aCell);
|
||||
|
||||
vtkCell3D* a3d = vtkCell3D::SafeDownCast(aCell);
|
||||
vtkConvexPointSet* aPH = vtkConvexPointSet::SafeDownCast(aCell);
|
||||
|
||||
if ( aTri && myFilterType == SMESHGUI_TriaFilter ||
|
||||
aQua && myFilterType == SMESHGUI_QuadFilter ||
|
||||
( aTri || aQua ) && myFilterType == SMESHGUI_FaceFilter ||
|
||||
a3d && myFilterType == SMESHGUI_VolumeFilter )
|
||||
( aTri || aQua || aPG ) && myFilterType == SMESHGUI_FaceFilter ||
|
||||
( a3d || aPH ) && myFilterType == SMESHGUI_VolumeFilter )
|
||||
{
|
||||
int anObjId = aVisualObj->GetElemObjId( i );
|
||||
myIds.Add( anObjId );
|
||||
|
@ -296,13 +296,14 @@ SMESH::point_array*
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
|
||||
CORBA::Boolean SMESH_Pattern_i::MakeMesh(SMESH::SMESH_Mesh_ptr theMesh)
|
||||
CORBA::Boolean SMESH_Pattern_i::MakeMesh (SMESH::SMESH_Mesh_ptr theMesh,
|
||||
const CORBA::Boolean CreatePoly)
|
||||
{
|
||||
::SMESH_Mesh* aMesh = getMesh( theMesh );
|
||||
if ( !aMesh )
|
||||
return false;
|
||||
|
||||
return myPattern.MakeMesh( aMesh );
|
||||
return myPattern.MakeMesh( aMesh, CreatePoly );
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
|
@ -75,7 +75,8 @@ class SMESH_Pattern_i:
|
||||
CORBA::Long theNode000Index,
|
||||
CORBA::Long theNode001Index);
|
||||
|
||||
CORBA::Boolean MakeMesh(SMESH::SMESH_Mesh_ptr theMesh);
|
||||
CORBA::Boolean MakeMesh (SMESH::SMESH_Mesh_ptr theMesh,
|
||||
const CORBA::Boolean CreatePoly);
|
||||
|
||||
SMESH::SMESH_Pattern::ErrorCode GetErrorCode();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user