Pattern mapping: replace adjacent faces with polygons to obtain conform mesh. Improve polygons and polyhedral volumes processing.

This commit is contained in:
jfa 2005-03-05 11:30:59 +00:00
parent 0482db55d3
commit ed0ea97e94
13 changed files with 235 additions and 73 deletions

View File

@ -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

View 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;
}
}

View File

@ -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;

View File

@ -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,6 +1860,7 @@ static void makeWalls (SMESHDS_Mesh* aMesh,
for (int inode = 0; inode < nbPolygonNodes; inode++) {
polygon_nodes[inode] = nodes[inode];
}
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 );

View File

@ -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 );
}

View File

@ -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;
};

View File

@ -774,24 +774,3 @@ void SMESHGUI_CreatePatternDlg::onTypeChanged( int theType )
else
myPicture2d->hide();
}

View File

@ -139,20 +139,3 @@ private:
};
#endif

View File

@ -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;
}

View File

@ -145,6 +145,7 @@ private:
QPushButton* myNewBtn;
QCheckBox* myReverseChk;
QCheckBox* myCreatePolyChk;
SMESHGUI_PatternWidget* myPicture2d;
QFrame* myPicture3d;
QLabel* myPreview3d;
@ -168,20 +169,3 @@ private:
};
#endif

View File

@ -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);
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 );

View File

@ -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 );
}
//=======================================================================

View File

@ -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();