/*!
* 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
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 :
ID += deltaID;
}
}
-
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;
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();
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;
}
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;
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 );
}
}
}
+
+ // save links to update adjacent faces in MakeMesh() method
+ myLinks = indGroups;
}
//=======================================================================
// 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 )
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 );
}
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
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;
};
else\r
myPicture2d->hide();\r
}\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
};\r
\r
#endif\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
// 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++ )
{
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();
mySelBtn [ Vertex2 ]->hide();
mySelEdit[ Vertex2 ]->hide();
myReverseChk->show();
+ myCreatePolyChk->show();
myPicture2d->show();
myPicture3d->hide();
mySelLbl[ Object ]->setText( tr( "FACE" ) );
mySelBtn [ Vertex2 ]->show();
mySelEdit[ Vertex2 ]->show();
myReverseChk->hide();
+ myCreatePolyChk->hide();
myPicture2d->hide();
myPicture3d->show();
mySelLbl[ Object ]->setText( tr( "3D_BLOCK" ) );
{
return second ? myNode2->value() - 1 : myNode1->value() - 1;
}
-
QPushButton* myNewBtn;
QCheckBox* myReverseChk;
+ QCheckBox* myCreatePolyChk;
SMESHGUI_PatternWidget* myPicture2d;
QFrame* myPicture3d;
QLabel* myPreview3d;
};
#endif
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
#include <vtkCell3D.h>
#include <vtkQuad.h>
#include <vtkTriangle.h>
+#include <vtkPolygon.h>
+#include <vtkConvexPointSet.h>
#include <vtkIdList.h>
#include <vtkIntArray.h>
#include <vtkCellArray.h>
{
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 );
//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 );
}
//=======================================================================
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();