#include "SMESH_subMesh.hxx"
#include "SMESH_ControlsDef.hxx"
#include "SMESH_MesherHelper.hxx"
+#include "SMESH_OctreeNode.hxx"
#include "utilities.h"
#include <map>
#include <set>
+#define cast2Node(elem) static_cast<const SMDS_MeshNode*>( elem )
+
using namespace std;
using namespace SMESH::Controls;
typedef map<const SMDS_MeshElement*, vector<TNodeOfNodeListMapItr> > TElemOfVecOfNnlmiMap;
//typedef map<const SMDS_MeshElement*, vector<TNodeOfNodeVecMapItr> > TElemOfVecOfMapNodesMap;
+struct TNodeXYZ : public gp_XYZ {
+ TNodeXYZ( const SMDS_MeshNode* n ):gp_XYZ( n->X(), n->Y(), n->Z() ) {}
+};
+
typedef pair< const SMDS_MeshNode*, const SMDS_MeshNode* > NLink;
+/*!
+ * \brief A sorted pair of nodes
+ */
+struct TLink: public NLink
+{
+ TLink(const SMDS_MeshNode* n1, const SMDS_MeshNode* n2 ):NLink( n1, n2 )
+ { if ( n1->GetID() < n2->GetID() ) std::swap( first, second ); }
+ TLink(const NLink& link ):NLink( link )
+ { if ( first->GetID() < second->GetID() ) std::swap( first, second ); }
+};
+
//=======================================================================
//function : SMESH_MeshEditor
//purpose :
{
}
+//=======================================================================
+/*!
+ * \brief Add element
+ */
+//=======================================================================
+
+SMDS_MeshElement*
+SMESH_MeshEditor::AddElement(const vector<const SMDS_MeshNode*> & node,
+ const SMDSAbs_ElementType type,
+ const bool isPoly,
+ const int ID)
+{
+ SMDS_MeshElement* e = 0;
+ int nbnode = node.size();
+ SMESHDS_Mesh* mesh = GetMeshDS();
+ switch ( type ) {
+ case SMDSAbs_Edge:
+ if ( nbnode == 2 )
+ if ( ID ) e = mesh->AddEdgeWithID(node[0], node[1], ID);
+ else e = mesh->AddEdge (node[0], node[1] );
+ else if ( nbnode == 3 )
+ if ( ID ) e = mesh->AddEdgeWithID(node[0], node[1], node[2], ID);
+ else e = mesh->AddEdge (node[0], node[1], node[2] );
+ break;
+ case SMDSAbs_Face:
+ if ( !isPoly ) {
+ if (nbnode == 3)
+ if ( ID ) e = mesh->AddFaceWithID(node[0], node[1], node[2], ID);
+ else e = mesh->AddFace (node[0], node[1], node[2] );
+ else if (nbnode == 4)
+ if ( ID ) e = mesh->AddFaceWithID(node[0], node[1], node[2], node[3], ID);
+ else e = mesh->AddFace (node[0], node[1], node[2], node[3] );
+ else if (nbnode == 6)
+ if ( ID ) e = mesh->AddFaceWithID(node[0], node[1], node[2], node[3],
+ node[4], node[5], ID);
+ else e = mesh->AddFace (node[0], node[1], node[2], node[3],
+ node[4], node[5] );
+ else if (nbnode == 8)
+ if ( ID ) e = mesh->AddFaceWithID(node[0], node[1], node[2], node[3],
+ node[4], node[5], node[6], node[7], ID);
+ else e = mesh->AddFace (node[0], node[1], node[2], node[3],
+ node[4], node[5], node[6], node[7] );
+ } else {
+ if ( ID ) e = mesh->AddPolygonalFaceWithID(node, ID);
+ else e = mesh->AddPolygonalFace (node );
+ }
+ break;
+ case SMDSAbs_Volume:
+ if ( !isPoly ) {
+ if (nbnode == 4)
+ if ( ID ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3], ID);
+ else e = mesh->AddVolume (node[0], node[1], node[2], node[3] );
+ else if (nbnode == 5)
+ if ( ID ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3],
+ node[4], ID);
+ else e = mesh->AddVolume (node[0], node[1], node[2], node[3],
+ node[4] );
+ else if (nbnode == 6)
+ if ( ID ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3],
+ node[4], node[5], ID);
+ else e = mesh->AddVolume (node[0], node[1], node[2], node[3],
+ node[4], node[5] );
+ else if (nbnode == 8)
+ if ( ID ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3],
+ node[4], node[5], node[6], node[7], ID);
+ else e = mesh->AddVolume (node[0], node[1], node[2], node[3],
+ node[4], node[5], node[6], node[7] );
+ else if (nbnode == 10)
+ if ( ID ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3],
+ node[4], node[5], node[6], node[7],
+ node[8], node[9], ID);
+ else e = mesh->AddVolume (node[0], node[1], node[2], node[3],
+ node[4], node[5], node[6], node[7],
+ node[8], node[9] );
+ else if (nbnode == 13)
+ if ( ID ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3],
+ node[4], node[5], node[6], node[7],
+ node[8], node[9], node[10],node[11],
+ node[12],ID);
+ else e = mesh->AddVolume (node[0], node[1], node[2], node[3],
+ node[4], node[5], node[6], node[7],
+ node[8], node[9], node[10],node[11],
+ node[12] );
+ else if (nbnode == 15)
+ if ( ID ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3],
+ node[4], node[5], node[6], node[7],
+ node[8], node[9], node[10],node[11],
+ node[12],node[13],node[14],ID);
+ else e = mesh->AddVolume (node[0], node[1], node[2], node[3],
+ node[4], node[5], node[6], node[7],
+ node[8], node[9], node[10],node[11],
+ node[12],node[13],node[14] );
+ else if (nbnode == 20)
+ if ( ID ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3],
+ node[4], node[5], node[6], node[7],
+ node[8], node[9], node[10],node[11],
+ node[12],node[13],node[14],node[15],
+ node[16],node[17],node[18],node[19],ID);
+ else e = mesh->AddVolume (node[0], node[1], node[2], node[3],
+ node[4], node[5], node[6], node[7],
+ node[8], node[9], node[10],node[11],
+ node[12],node[13],node[14],node[15],
+ node[16],node[17],node[18],node[19] );
+ }
+ }
+ return e;
+}
+
+//=======================================================================
+/*!
+ * \brief Add element
+ */
+//=======================================================================
+
+SMDS_MeshElement* SMESH_MeshEditor::AddElement(const vector<int> & nodeIDs,
+ const SMDSAbs_ElementType type,
+ const bool isPoly,
+ const int ID)
+{
+ vector<const SMDS_MeshNode*> nodes;
+ nodes.reserve( nodeIDs.size() );
+ vector<int>::const_iterator id = nodeIDs.begin();
+ while ( id != nodeIDs.end() ) {
+ if ( const SMDS_MeshNode* node = GetMeshDS()->FindNode( *id++ ))
+ nodes.push_back( node );
+ else
+ return 0;
+ }
+ return AddElement( nodes, type, isPoly, ID );
+}
+
//=======================================================================
//function : Remove
//purpose : Remove a node or an element.
//=======================================================================
//function : IsMedium
-//purpose :
+//purpose :
//=======================================================================
bool SMESH_MeshEditor::IsMedium(const SMDS_MeshNode* node,
const SMDSAbs_ElementType typeToCheck)
{
bool isMedium = false;
- SMDS_ElemIteratorPtr it = node->GetInverseElementIterator();
- while (it->more()) {
+ SMDS_ElemIteratorPtr it = node->GetInverseElementIterator(typeToCheck);
+ while (it->more() && !isMedium ) {
const SMDS_MeshElement* elem = it->next();
isMedium = elem->IsMediumNode(node);
- if ( typeToCheck == SMDSAbs_All || elem->GetType() == typeToCheck )
- break;
}
return isMedium;
}
ShiftNodesQuadTria(N2);
}
// now we receive following N1 and N2 (using numeration as above image)
- // tria1 : (1 2 4 5 9 7) and tria2 : (3 4 2 8 9 6)
+ // tria1 : (1 2 4 5 9 7) and tria2 : (3 4 2 8 9 6)
// i.e. first nodes from both arrays determ new diagonal
return true;
}
SMDS_ElemIteratorPtr it = theTria1->nodesIterator();
while ( it->more() ) {
aNodes[ i ] = static_cast<const SMDS_MeshNode*>( it->next() );
-
+
if ( i > 2 ) // theTria2
// find same node of theTria1
for ( int j = 0; j < 3; j++ )
if ( i == 6 && it->more() )
return false; // theTria2 is not a triangle
}
-
+
// find indices of 1,2 and of A,B in theTria1
int iA = 0, iB = 0, i1 = 0, i2 = 0;
for ( i = 0; i < 6; i++ ) {
aNodes[ sameInd[ iB ]] = aNodes[ i1 ];
//MESSAGE( theTria1 << theTria2 );
-
+
GetMeshDS()->ChangeElementNodes( theTria1, aNodes, 3 );
GetMeshDS()->ChangeElementNodes( theTria2, &aNodes[ 3 ], 3 );
-
+
//MESSAGE( theTria1 << theTria2 );
return true;
-
+
} // end if(F1 && F2)
// check case of quadratic faces
// 5
// 1 +--+--+ 2 theTria1: (1 2 4 5 9 7) or (2 4 1 9 7 5) or (4 1 2 7 5 9)
// | /| theTria2: (2 3 4 6 8 9) or (3 4 2 8 9 6) or (4 2 3 9 6 8)
- // | / |
+ // | / |
// 7 + + + 6
// | /9 |
// |/ |
- // 4 +--+--+ 3
+ // 4 +--+--+ 3
// 8
-
+
const SMDS_MeshNode* N1 [6];
const SMDS_MeshNode* N2 [6];
if(!GetNodesFromTwoTria(theTria1,theTria2,N1,N2))
return false;
// now we receive following N1 and N2 (using numeration as above image)
- // tria1 : (1 2 4 5 9 7) and tria2 : (3 4 2 8 9 6)
+ // tria1 : (1 2 4 5 9 7) and tria2 : (3 4 2 8 9 6)
// i.e. first nodes from both arrays determ new diagonal
const SMDS_MeshNode* N1new [6];
else if ( aNodes2[ i ] != theNode1 )
i2 = i; // node 2
}
-
+
// nodes 1 and 2 should not be the same
if ( aNodes1[ i1 ] == aNodes2[ i2 ] )
return false;
GetMeshDS()->ChangeElementNodes( tr2, aNodes2, 3 );
//MESSAGE( tr1 << tr2 );
-
+
return true;
}
const SMDS_MeshNode* n4 = 0;
SMDS_ElemIteratorPtr it = tr2->nodesIterator();
int i=0;
- //while ( !n4 && it->more() ) {
while ( !n4 && i<3 ) {
- const SMDS_MeshNode * n = static_cast<const SMDS_MeshNode*>( it->next() );
+ const SMDS_MeshNode * n = cast2Node( it->next() );
i++;
bool isDiag = ( n == theNode1 || n == theNode2 );
if ( !isDiag )
int iNode = 0, iFirstDiag = -1;
it = tr1->nodesIterator();
i=0;
- //while ( it->more() ) {
while ( i<3 ) {
- const SMDS_MeshNode * n = static_cast<const SMDS_MeshNode*>( it->next() );
+ const SMDS_MeshNode * n = cast2Node( it->next() );
i++;
bool isDiag = ( n == theNode1 || n == theNode2 );
if ( isDiag ) {
// 5
// 1 +--+--+ 2 tr1: (1 2 4 5 9 7) or (2 4 1 9 7 5) or (4 1 2 7 5 9)
// | /| tr2: (2 3 4 6 8 9) or (3 4 2 8 9 6) or (4 2 3 9 6 8)
- // | / |
+ // | / |
// 7 + + + 6
// | /9 |
// |/ |
- // 4 +--+--+ 3
+ // 4 +--+--+ 3
// 8
-
+
const SMDS_MeshNode* N1 [6];
const SMDS_MeshNode* N2 [6];
if(!GetNodesFromTwoTria(tr1,tr2,N1,N2))
return false;
// now we receive following N1 and N2 (using numeration as above image)
- // tria1 : (1 2 4 5 9 7) and tria2 : (3 4 2 8 9 6)
+ // tria1 : (1 2 4 5 9 7) and tria2 : (3 4 2 8 9 6)
// i.e. first nodes from both arrays determ new diagonal
const SMDS_MeshNode* aNodes[8];
for (int iface = 1; iface <= nbFaces; iface++) {
int inode, nbFaceNodes = aPolyedre->NbFaceNodes(iface);
quantities[iface - 1] = nbFaceNodes;
-
+
for (inode = nbFaceNodes; inode >= 1; inode--) {
const SMDS_MeshNode* curNode = aPolyedre->GetFaceNode(iface, inode);
poly_nodes.push_back(curNode);
}
}
-
+
return GetMeshDS()->ChangePolyhedronNodes( theElem, poly_nodes, quantities );
}
aNodes[ i-1 ]->GetPosition()->GetTypeOfPosition() == SMDS_TOP_FACE )
{
inFaceNode = aNodes[ i-1 ];
- }
+ }
}
// find middle point for (0,1,2,3)
// and create a node in this point;
SMESHDS_Mesh * aMesh)
{
const set<SMESHDS_GroupBase*>& groups = aMesh->GetGroups();
- if (!groups.empty())
+ if (!groups.empty())
{
set<SMESHDS_GroupBase*>::const_iterator GrIt = groups.begin();
- for (; GrIt != groups.end(); GrIt++)
+ for (; GrIt != groups.end(); GrIt++)
{
SMESHDS_Group* grp = dynamic_cast<SMESHDS_Group*>(*GrIt);
if (!grp || grp->IsEmpty()) continue;
aNodes[ i-1 ]->GetPosition()->GetTypeOfPosition() == SMDS_TOP_FACE )
{
inFaceNode = aNodes[ i-1 ];
- }
+ }
}
// find middle point for (0,1,2,3)
return false;
SMESHDS_Mesh * aMesh = GetMeshDS();
- //LinkID_Gen aLinkID_Gen( aMesh );
// Prepare data for algo: build
// 1. map of elements with their linkIDs
// 2. map of linkIDs with their elements
- //map< long, list< const SMDS_MeshElement* > > mapLi_listEl;
- //map< long, list< const SMDS_MeshElement* > >::iterator itLE;
- //map< const SMDS_MeshElement*, set< long > > mapEl_setLi;
- //map< const SMDS_MeshElement*, set< long > >::iterator itEL;
-
- map< NLink, list< const SMDS_MeshElement* > > mapLi_listEl;
- map< NLink, list< const SMDS_MeshElement* > >::iterator itLE;
- map< const SMDS_MeshElement*, set< NLink > > mapEl_setLi;
- map< const SMDS_MeshElement*, set< NLink > >::iterator itEL;
+ map< TLink, list< const SMDS_MeshElement* > > mapLi_listEl;
+ map< TLink, list< const SMDS_MeshElement* > >::iterator itLE;
+ map< const SMDS_MeshElement*, set< TLink > > mapEl_setLi;
+ map< const SMDS_MeshElement*, set< TLink > >::iterator itEL;
TIDSortedElemSet::iterator itElem;
for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ ) {
const SMDS_MeshElement* elem = *itElem;
- //if ( !elem || elem->NbNodes() != 3 )
- // continue;
if(!elem || elem->GetType() != SMDSAbs_Face ) continue;
bool IsTria = elem->NbNodes()==3 || (elem->NbNodes()==6 && elem->IsQuadratic());
if(!IsTria) continue;
const SMDS_MeshNode* aNodes [4];
SMDS_ElemIteratorPtr itN = elem->nodesIterator();
int i = 0;
- //while ( itN->more() )
while ( i<3 )
- aNodes[ i++ ] = static_cast<const SMDS_MeshNode*>( itN->next() );
- ASSERT( i == 3 );
+ aNodes[ i++ ] = cast2Node( itN->next() );
aNodes[ 3 ] = aNodes[ 0 ];
// fill maps
for ( i = 0; i < 3; i++ ) {
- //long linkID = aLinkID_Gen.GetLinkID( aNodes[ i ], aNodes[ i+1 ] );
- NLink link(( aNodes[i] < aNodes[i+1] ? aNodes[i] : aNodes[i+1] ),
- ( aNodes[i] < aNodes[i+1] ? aNodes[i+1] : aNodes[i] ));
+ TLink link( aNodes[i], aNodes[i+1] );
// check if elements sharing a link can be fused
- //itLE = mapLi_listEl.find( linkID );
itLE = mapLi_listEl.find( link );
if ( itLE != mapLi_listEl.end() ) {
if ((*itLE).second.size() > 1 ) // consider only 2 elems adjacent by a link
(*itLE).second.push_back( elem );
}
else {
- //mapLi_listEl[ linkID ].push_back( elem );
mapLi_listEl[ link ].push_back( elem );
}
- //mapEl_setLi [ elem ].insert( linkID );
mapEl_setLi [ elem ].insert( link );
}
}
int nbElems = (*itLE).second.size();
if ( nbElems < 2 ) {
const SMDS_MeshElement* elem = (*itLE).second.front();
- //long link = (*itLE).first;
- NLink link = (*itLE).first;
+ TLink link = (*itLE).first;
mapEl_setLi[ elem ].erase( link );
if ( mapEl_setLi[ elem ].empty() )
mapEl_setLi.erase( elem );
while ( ! mapEl_setLi.empty() ) {
// Look for the start element:
// the element having the least nb of shared links
-
const SMDS_MeshElement* startElem = 0;
int minNbLinks = 4;
for ( itEL = mapEl_setLi.begin(); itEL != mapEl_setLi.end(); itEL++ ) {
// search elements to fuse starting from startElem or links of elements
// fused earlyer - startLinks
- //list< long > startLinks;
- list< NLink > startLinks;
+ list< TLink > startLinks;
while ( startElem || !startLinks.empty() ) {
while ( !startElem && !startLinks.empty() ) {
// Get an element to start, by a link
- //long linkId = startLinks.front();
- NLink linkId = startLinks.front();
+ TLink linkId = startLinks.front();
startLinks.pop_front();
itLE = mapLi_listEl.find( linkId );
if ( itLE != mapLi_listEl.end() ) {
if ( startElem ) {
// Get candidates to be fused
const SMDS_MeshElement *tr1 = startElem, *tr2 = 0, *tr3 = 0;
- //long link12, link13;
- NLink link12, link13;
+ const TLink *link12, *link13;
startElem = 0;
ASSERT( mapEl_setLi.find( tr1 ) != mapEl_setLi.end() );
- //set< long >& setLi = mapEl_setLi[ tr1 ];
- set< NLink >& setLi = mapEl_setLi[ tr1 ];
+ set< TLink >& setLi = mapEl_setLi[ tr1 ];
ASSERT( !setLi.empty() );
- //set< long >::iterator itLi;
- set< NLink >::iterator itLi;
- for ( itLi = setLi.begin(); itLi != setLi.end(); itLi++ ) {
- //long linkID = (*itLi);
- NLink linkID = (*itLi);
- itLE = mapLi_listEl.find( linkID );
+ set< TLink >::iterator itLi;
+ for ( itLi = setLi.begin(); itLi != setLi.end(); itLi++ )
+ {
+ const TLink & link = (*itLi);
+ itLE = mapLi_listEl.find( link );
if ( itLE == mapLi_listEl.end() )
continue;
continue;
if ( tr2 ) {
tr3 = elem;
- link13 = linkID;
+ link13 = &link;
}
else {
tr2 = elem;
- link12 = linkID;
+ link12 = &link;
}
// add other links of elem to list of links to re-start from
- //set< long >& links = mapEl_setLi[ elem ];
- //set< long >::iterator it;
- set< NLink >& links = mapEl_setLi[ elem ];
- set< NLink >::iterator it;
+ set< TLink >& links = mapEl_setLi[ elem ];
+ set< TLink >::iterator it;
for ( it = links.begin(); it != links.end(); it++ ) {
- //long linkID2 = (*it);
- NLink linkID2 = (*it);
- if ( linkID2 != linkID )
- startLinks.push_back( linkID2 );
+ const TLink& link2 = (*it);
+ if ( link2 != link )
+ startLinks.push_back( link2 );
}
}
// Get nodes of possible quadrangles
const SMDS_MeshNode *n12 [4], *n13 [4];
bool Ok12 = false, Ok13 = false;
- //const SMDS_MeshNode *linkNode1, *linkNode2;
const SMDS_MeshNode *linkNode1, *linkNode2;
if(tr2) {
- //const SMDS_MeshNode *linkNode1 = link12.first;
- //const SMDS_MeshNode *linkNode2 = link12.second;
- linkNode1 = link12.first;
- linkNode2 = link12.second;
- //if ( tr2 &&
- // aLinkID_Gen.GetNodes( link12, linkNode1, linkNode2 ) &&
- // getQuadrangleNodes( n12, linkNode1, linkNode2, tr1, tr2 ))
- // Ok12 = true;
+ linkNode1 = link12->first;
+ linkNode2 = link12->second;
if ( tr2 && getQuadrangleNodes( n12, linkNode1, linkNode2, tr1, tr2 ))
Ok12 = true;
}
if(tr3) {
- linkNode1 = link13.first;
- linkNode2 = link13.second;
- //if ( tr3 &&
- // aLinkID_Gen.GetNodes( link13, linkNode1, linkNode2 ) &&
- // getQuadrangleNodes( n13, linkNode1, linkNode2, tr1, tr3 ))
- // Ok13 = true;
+ linkNode1 = link13->first;
+ linkNode2 = link13->second;
if ( tr3 && getQuadrangleNodes( n13, linkNode1, linkNode2, tr1, tr3 ))
Ok13 = true;
}
mapEl_setLi.erase( tr1 );
if ( Ok12 ) {
mapEl_setLi.erase( tr2 );
- mapLi_listEl.erase( link12 );
+ mapLi_listEl.erase( *link12 );
if(tr1->NbNodes()==3) {
if( tr1->GetID() < tr2->GetID() ) {
aMesh->ChangeElementNodes( tr1, n12, 4 );
const SMDS_MeshNode* N2 [6];
GetNodesFromTwoTria(tr1,tr2,N1,N2);
// now we receive following N1 and N2 (using numeration as above image)
- // tria1 : (1 2 4 5 9 7) and tria2 : (3 4 2 8 9 6)
+ // tria1 : (1 2 4 5 9 7) and tria2 : (3 4 2 8 9 6)
// i.e. first nodes from both arrays determ new diagonal
const SMDS_MeshNode* aNodes[8];
aNodes[0] = N1[0];
}
else if ( Ok13 ) {
mapEl_setLi.erase( tr3 );
- mapLi_listEl.erase( link13 );
+ mapLi_listEl.erase( *link13 );
if(tr1->NbNodes()==3) {
if( tr1->GetID() < tr2->GetID() ) {
aMesh->ChangeElementNodes( tr1, n13, 4 );
const SMDS_MeshNode* N2 [6];
GetNodesFromTwoTria(tr1,tr3,N1,N2);
// now we receive following N1 and N2 (using numeration as above image)
- // tria1 : (1 2 4 5 9 7) and tria2 : (3 4 2 8 9 6)
+ // tria1 : (1 2 4 5 9 7) and tria2 : (3 4 2 8 9 6)
// i.e. first nodes from both arrays determ new diagonal
const SMDS_MeshNode* aNodes[8];
aNodes[0] = N1[0];
return true;
}*/
+//================================================================================
+/*!
+ * \brief Return nodes linked to the given one
+ * \param theNode - the node
+ * \param linkedNodes - the found nodes
+ * \param type - the type of elements to check
+ *
+ * Medium nodes are ignored
+ */
+//================================================================================
+
+void SMESH_MeshEditor::GetLinkedNodes( const SMDS_MeshNode* theNode,
+ TIDSortedElemSet & linkedNodes,
+ SMDSAbs_ElementType type )
+{
+ SMDS_ElemIteratorPtr elemIt = theNode->GetInverseElementIterator(type);
+ while ( elemIt->more() )
+ {
+ const SMDS_MeshElement* elem = elemIt->next();
+ SMDS_ElemIteratorPtr nodeIt = elem->nodesIterator();
+ if ( elem->GetType() == SMDSAbs_Volume )
+ {
+ SMDS_VolumeTool vol( elem );
+ while ( nodeIt->more() ) {
+ const SMDS_MeshNode* n = cast2Node( nodeIt->next() );
+ if ( theNode != n && vol.IsLinked( theNode, n ))
+ linkedNodes.insert( n );
+ }
+ }
+ else
+ {
+ for ( int i = 0; nodeIt->more(); ++i ) {
+ const SMDS_MeshNode* n = cast2Node( nodeIt->next() );
+ if ( n == theNode ) {
+ int iBefore = i - 1;
+ int iAfter = i + 1;
+ if ( elem->IsQuadratic() ) {
+ int nb = elem->NbNodes() / 2;
+ iAfter = SMESH_MesherHelper::WrapIndex( iAfter, nb );
+ iBefore = SMESH_MesherHelper::WrapIndex( iBefore, nb );
+ }
+ linkedNodes.insert( elem->GetNode( iAfter ));
+ linkedNodes.insert( elem->GetNode( iBefore ));
+ }
+ }
+ }
+ }
+}
+
//=======================================================================
//function : laplacianSmooth
//purpose : pulls theNode toward the center of surrounding nodes directly
{
// find surrounding nodes
- set< const SMDS_MeshNode* > nodeSet;
- SMDS_ElemIteratorPtr elemIt = theNode->GetInverseElementIterator(SMDSAbs_Face);
- while ( elemIt->more() )
- {
- const SMDS_MeshElement* elem = elemIt->next();
-
- for ( int i = 0; i < elem->NbNodes(); ++i ) {
- if ( elem->GetNode( i ) == theNode ) {
- // add linked nodes
- int iBefore = i - 1;
- int iAfter = i + 1;
- if ( elem->IsQuadratic() ) {
- int nbCorners = elem->NbNodes() / 2;
- if ( iAfter >= nbCorners )
- iAfter = 0; // elem->GetNode() wraps index
- if ( iBefore == -1 )
- iBefore = nbCorners - 1;
- }
- nodeSet.insert( elem->GetNode( iAfter ));
- nodeSet.insert( elem->GetNode( iBefore ));
- break;
- }
- }
- }
+ TIDSortedElemSet nodeSet;
+ SMESH_MeshEditor::GetLinkedNodes( theNode, nodeSet, SMDSAbs_Face );
// compute new coodrs
double coord[] = { 0., 0., 0. };
- set< const SMDS_MeshNode* >::iterator nodeSetIt = nodeSet.begin();
+ TIDSortedElemSet::iterator nodeSetIt = nodeSet.begin();
for ( ; nodeSetIt != nodeSet.end(); nodeSetIt++ ) {
- const SMDS_MeshNode* node = (*nodeSetIt);
+ const SMDS_MeshNode* node = cast2Node(*nodeSetIt);
if ( theSurface.IsNull() ) { // smooth in 3D
coord[0] += node->X();
coord[1] += node->Y();
gp_XY uv2 = helper.GetNodeUV( face, Ns[i+2], Ns[i] );
gp_XY uv = ( uv1 + uv2 ) / 2.;
gp_Pnt xyz = surface->Value( uv.X(), uv.Y() );
- x = xyz.X(); y = xyz.Y(); z = xyz.Z();
+ x = xyz.X(); y = xyz.Y(); z = xyz.Z();
}
else {
x = (Ns[i]->X() + Ns[i+2]->X())/2;
}
}
}
-
+
} // loop on face ids
}
// Loop on elem nodes:
// find new nodes and detect same nodes indices
int nbNodes = elem->NbNodes();
- list<const SMDS_MeshNode*>::const_iterator itNN[ nbNodes ];
+ //---PR
+ //list<const SMDS_MeshNode*>::const_iterator itNN[ nbNodes ];
+ vector < list< const SMDS_MeshNode* >::const_iterator > itNN;
+ itNN.reserve(nbNodes);
+ //---PR
const SMDS_MeshNode* prevNod[ nbNodes ], *nextNod[ nbNodes ], *midlNod[ nbNodes ];
int iNode, nbSame = 0, iNotSameNode = 0, iSameNode = 0;
vector<int> sames(nbNodes);
if ( nbSame == 0 ) // --- hexahedron
aNewElem = aMesh->AddVolume (prevNod[ i0 ], prevNod[ 1 ], prevNod[ i2 ], prevNod[ 3 ],
nextNod[ i0 ], nextNod[ 1 ], nextNod[ i2 ], nextNod[ 3 ]);
-
+
else if ( nbSame == 1 ) { // --- pyramid + pentahedron
aNewElem = aMesh->AddVolume (prevNod[ iBeforeSame ], prevNod[ iAfterSame ],
nextNod[ iAfterSame ], nextNod[ iBeforeSame ],
// realized for extrusion only
//vector<const SMDS_MeshNode*> polyedre_nodes (nbNodes*2 + 4*nbNodes);
//vector<int> quantities (nbNodes + 2);
-
+
//quantities[0] = nbNodes; // bottom of prism
//for (int inode = 0; inode < nbNodes; inode++) {
// polyedre_nodes[inode] = prevNod[inode];
//for (int inode = 0; inode < nbNodes; inode++) {
// polyedre_nodes[nbNodes + inode] = nextNod[inode];
//}
-
+
//for (int iface = 0; iface < nbNodes; iface++) {
// quantities[iface + 2] = 4;
// int inextface = (iface == nbNodes - 1) ? 0 : iface + 1;
const gp_Ax1& theAxis,
const double theAngle,
const int theNbSteps,
- const double theTol)
+ const double theTol,
+ const bool theMakeWalls)
{
myLastCreatedElems.Clear();
myLastCreatedNodes.Clear();
sweepElement( aMesh, elem, newNodesItVec, newElemsMap[elem], theNbSteps, myLastCreatedElems );
}
- makeWalls( aMesh, mapNewNodes, newElemsMap, mapElemNewNodes, theElems, theNbSteps, myLastCreatedElems );
-
+ if ( theMakeWalls )
+ makeWalls( aMesh, mapNewNodes, newElemsMap, mapElemNewNodes,
+ theElems, theNbSteps, myLastCreatedElems );
}
//=======================================================================
//function : CreateNode
-//purpose :
+//purpose :
//=======================================================================
const SMDS_MeshNode* SMESH_MeshEditor::CreateNode(const double x,
const double y,
gp_Pnt P2(aN->X(),aN->Y(),aN->Z());
if(P1.Distance(P2)<tolnode)
return aN;
- }
+ }
}
// create new node and return it
if ( !theCopy && needReverse ) {
SMDS_ElemIteratorPtr invElemIt = node->GetInverseElementIterator();
while ( invElemIt->more() ) {
- const SMDS_MeshElement* iel = invElemIt->next();
+ const SMDS_MeshElement* iel = invElemIt->next();
inverseElemSet.insert( iel );
}
}
}
// find transformed nodes
- const SMDS_MeshNode* nodes[8];
+ vector<const SMDS_MeshNode*> nodes(nbNodes);
int iNode = 0;
SMDS_ElemIteratorPtr itN = elem->nodesIterator();
while ( itN->more() ) {
continue; // not all nodes transformed
if ( theCopy ) {
- // add a new element
- switch ( elemType ) {
- case SMDSAbs_Edge:
- if ( nbNodes == 2 )
- myLastCreatedElems.Append(aMesh->AddEdge( nodes[ 0 ], nodes[ 1 ] ));
- else
- myLastCreatedElems.Append(aMesh->AddEdge( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ] ));
- break;
- case SMDSAbs_Face:
- if ( nbNodes == 3 )
- myLastCreatedElems.Append(aMesh->AddFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ] ));
- else if(nbNodes==4)
- myLastCreatedElems.Append(aMesh->AddFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ] , nodes[ 3 ]));
- else if(nbNodes==6)
- myLastCreatedElems.Append(aMesh->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
- nodes[4], nodes[5]));
- else // nbNodes==8
- myLastCreatedElems.Append(aMesh->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
- nodes[4], nodes[5], nodes[6], nodes[7]));
- break;
- case SMDSAbs_Volume:
- if ( nbNodes == 4 )
- myLastCreatedElems.Append(aMesh->AddVolume( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ] , nodes[ 3 ] ));
- else if ( nbNodes == 8 )
- myLastCreatedElems.Append(aMesh->AddVolume( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ] , nodes[ 3 ],
- nodes[ 4 ], nodes[ 5 ], nodes[ 6 ] , nodes[ 7 ]));
- else if ( nbNodes == 6 )
- myLastCreatedElems.Append(aMesh->AddVolume( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ] , nodes[ 3 ],
- nodes[ 4 ], nodes[ 5 ]));
- else if ( nbNodes == 5 )
- myLastCreatedElems.Append(aMesh->AddVolume( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ] , nodes[ 3 ],
- nodes[ 4 ]));
- else if(nbNodes==10)
- myLastCreatedElems.Append(aMesh->AddVolume(nodes[0], nodes[1], nodes[2], nodes[3], nodes[4],
- nodes[5], nodes[6], nodes[7], nodes[8], nodes[9]));
- else if(nbNodes==13)
- myLastCreatedElems.Append(aMesh->AddVolume(nodes[0], nodes[1], nodes[2], nodes[3], nodes[4],
- nodes[5], nodes[6], nodes[7], nodes[8], nodes[9],
- nodes[10], nodes[11], nodes[12]));
- else if(nbNodes==15)
- myLastCreatedElems.Append(aMesh->AddVolume(nodes[0], nodes[1], nodes[2], nodes[3], nodes[4],
- nodes[5], nodes[6], nodes[7], nodes[8], nodes[9],
- nodes[10], nodes[11], nodes[12], nodes[13], nodes[14]));
- else // nbNodes==20
- myLastCreatedElems.Append(aMesh->AddVolume(nodes[0], nodes[1], nodes[2], nodes[3], nodes[4],
- nodes[5], nodes[6], nodes[7], nodes[8], nodes[9],
- nodes[10], nodes[11], nodes[12], nodes[13], nodes[14],
- nodes[15], nodes[16], nodes[17], nodes[18], nodes[19]));
- break;
- default:;
- }
+ if ( SMDS_MeshElement* copy = AddElement( nodes, elem->GetType(), elem->IsPoly() ))
+ myLastCreatedElems.Append( copy );
}
else
{
// reverse element as it was reversed by transformation
if ( nbNodes > 2 )
- aMesh->ChangeElementNodes( elem, nodes, nbNodes );
+ aMesh->ChangeElementNodes( elem, &nodes[0], nbNodes );
}
}
}
//=======================================================================
//function : FindCoincidentNodes
//purpose : Return list of group of nodes close to each other within theTolerance
-// Search among theNodes or in the whole mesh if theNodes is empty.
+// Search among theNodes or in the whole mesh if theNodes is empty using
+// an Octree algorithm
//=======================================================================
void SMESH_MeshEditor::FindCoincidentNodes (set<const SMDS_MeshNode*> & theNodes,
myLastCreatedElems.Clear();
myLastCreatedNodes.Clear();
- double tol2 = theTolerance * theTolerance;
-
- list<const SMDS_MeshNode*> nodes;
+ set<const SMDS_MeshNode*> nodes;
if ( theNodes.empty() )
{ // get all nodes in the mesh
SMDS_NodeIteratorPtr nIt = GetMeshDS()->nodesIterator();
while ( nIt->more() )
- nodes.push_back( nIt->next() );
+ nodes.insert( nodes.end(),nIt->next());
}
else
+ nodes=theNodes;
+ SMESH_OctreeNode::FindCoincidentNodes ( nodes, &theGroupsOfNodes, theTolerance);
+
+}
+
+//=======================================================================
+/*!
+ * \brief Implementation of search for the node closest to point
+ */
+//=======================================================================
+
+struct SMESH_NodeSearcherImpl: public SMESH_NodeSearcher
+{
+ /*!
+ * \brief Constructor
+ */
+ SMESH_NodeSearcherImpl( const SMESHDS_Mesh* theMesh )
{
- nodes.insert( nodes.end(), theNodes.begin(), theNodes.end() );
+ set<const SMDS_MeshNode*> nodes;
+ if ( theMesh ) {
+ SMDS_NodeIteratorPtr nIt = theMesh->nodesIterator();
+ while ( nIt->more() )
+ nodes.insert( nodes.end(), nIt->next() );
+ }
+ myOctreeNode = new SMESH_OctreeNode(nodes) ;
}
-
- list<const SMDS_MeshNode*>::iterator it2, it1 = nodes.begin();
- for ( ; it1 != nodes.end(); it1++ )
+ /*!
+ * \brief Do it's job
+ */
+ const SMDS_MeshNode* FindClosestTo( const gp_Pnt& thePnt )
{
- const SMDS_MeshNode* n1 = *it1;
- gp_Pnt p1( n1->X(), n1->Y(), n1->Z() );
-
- list<const SMDS_MeshNode*> * groupPtr = 0;
- it2 = it1;
- for ( it2++; it2 != nodes.end(); it2++ )
+ SMDS_MeshNode tgtNode( thePnt.X(), thePnt.Y(), thePnt.Z() );
+ list<const SMDS_MeshNode*> nodes;
+ const double precision = 1e-6;
+ myOctreeNode->NodesAround( &tgtNode, &nodes, precision );
+
+ double minSqDist = DBL_MAX;
+ Bnd_B3d box;
+ if ( nodes.empty() ) // get all nodes of OctreeNode's closest to thePnt
{
- const SMDS_MeshNode* n2 = *it2;
- gp_Pnt p2( n2->X(), n2->Y(), n2->Z() );
- if ( p1.SquareDistance( p2 ) <= tol2 )
+ // sort leafs by their distance from thePnt
+ typedef map< double, SMESH_OctreeNode* > TDistTreeMap;
+ TDistTreeMap treeMap;
+ list< SMESH_OctreeNode* > treeList;
+ list< SMESH_OctreeNode* >::iterator trIt;
+ treeList.push_back( myOctreeNode );
+ for ( trIt = treeList.begin(); trIt != treeList.end(); ++trIt)
{
- if ( !groupPtr ) {
- theGroupsOfNodes.push_back( list<const SMDS_MeshNode*>() );
- groupPtr = & theGroupsOfNodes.back();
- groupPtr->push_back( n1 );
+ SMESH_OctreeNode* tree = *trIt;
+ if ( !tree->isLeaf() ) { // put children to the queue
+ SMESH_OctreeNodeIteratorPtr cIt = tree->GetChildrenIterator();
+ while ( cIt->more() )
+ treeList.push_back( cIt->next() );
}
- if(groupPtr->front()>n2)
- groupPtr->push_front( n2 );
- else
- groupPtr->push_back( n2 );
- it2 = nodes.erase( it2 );
- it2--;
+ else if ( tree->NbNodes() ) { // put tree to treeMap
+ tree->getBox( box );
+ double sqDist = thePnt.SquareDistance( 0.5 * ( box.CornerMin() + box.CornerMax() ));
+ pair<TDistTreeMap::iterator,bool> it_in = treeMap.insert( make_pair( sqDist, tree ));
+ if ( !it_in.second ) // not unique distance to box center
+ treeMap.insert( it_in.first, make_pair( sqDist - 1e-13*treeMap.size(), tree ));
+ }
+ }
+ // find distance after which there is no sense to check tree's
+ double sqLimit = DBL_MAX;
+ TDistTreeMap::iterator sqDist_tree = treeMap.begin();
+ if ( treeMap.size() > 5 ) {
+ SMESH_OctreeNode* closestTree = sqDist_tree->second;
+ closestTree->getBox( box );
+ double limit = sqrt( sqDist_tree->first ) + sqrt ( box.SquareExtent() );
+ sqLimit = limit * limit;
+ }
+ // get all nodes from trees
+ for ( ; sqDist_tree != treeMap.end(); ++sqDist_tree) {
+ if ( sqDist_tree->first > sqLimit )
+ break;
+ SMESH_OctreeNode* tree = sqDist_tree->second;
+ tree->NodesAround( tree->GetNodeIterator()->next(), &nodes );
+ }
+ }
+ // find closest among nodes
+ minSqDist = DBL_MAX;
+ const SMDS_MeshNode* closestNode = 0;
+ list<const SMDS_MeshNode*>::iterator nIt = nodes.begin();
+ for ( ; nIt != nodes.end(); ++nIt ) {
+ double sqDist = thePnt.SquareDistance( TNodeXYZ( *nIt ) );
+ if ( minSqDist > sqDist ) {
+ closestNode = *nIt;
+ minSqDist = sqDist;
}
}
+ return closestNode;
}
+ /*!
+ * \brief Destructor
+ */
+ ~SMESH_NodeSearcherImpl() { delete myOctreeNode; }
+private:
+ SMESH_OctreeNode* myOctreeNode;
+};
+
+//=======================================================================
+/*!
+ * \brief Return SMESH_NodeSearcher
+ */
+//=======================================================================
+
+SMESH_NodeSearcher* SMESH_MeshEditor::GetNodeSearcher()
+{
+ return new SMESH_NodeSearcherImpl( GetMeshDS() );
}
//=======================================================================
else
isOk = false;
break;
- case 8: {
+ case 8: {
if(elem->IsQuadratic()) { // Quadratic quadrangle
// 1 5 2
// +---+---+
}
-// =================================================
+// ========================================================
// class : SortableElement
-// purpose : auxilary
-// =================================================
+// purpose : allow sorting elements basing on their nodes
+// ========================================================
class SortableElement : public set <const SMDS_MeshElement*>
{
public:
SortableElement( const SMDS_MeshElement* theElem )
{
- myID = theElem->GetID();
+ myElem = theElem;
SMDS_ElemIteratorPtr nodeIt = theElem->nodesIterator();
while ( nodeIt->more() )
this->insert( nodeIt->next() );
}
- const long GetID() const
- { return myID; }
+ const SMDS_MeshElement* Get() const
+ { return myElem; }
- void SetID(const long anID) const
- { myID = anID; }
+ void Set(const SMDS_MeshElement* e) const
+ { myElem = e; }
private:
- mutable long myID;
+ mutable const SMDS_MeshElement* myElem;
};
+//=======================================================================
+//function : FindEqualElements
+//purpose :
+//=======================================================================
+void SMESH_MeshEditor::FindEqualElements(set<const SMDS_MeshElement*> & theElements,
+ TListOfListOfElementsID & theGroupsOfElementsID)
+{
+ myLastCreatedElems.Clear();
+ myLastCreatedNodes.Clear();
+
+ typedef set<const SMDS_MeshElement*> TElemsSet;
+ typedef map< SortableElement, int > TMapOfNodeSet;
+ typedef list<int> TGroupOfElems;
+
+ TElemsSet elems;
+ if ( theElements.empty() )
+ { // get all elements in the mesh
+ SMDS_ElemIteratorPtr eIt = GetMeshDS()->elementsIterator();
+ while ( eIt->more() )
+ elems.insert( elems.end(), eIt->next());
+ }
+ else
+ elems = theElements;
+
+ vector< TGroupOfElems > arrayOfGroups;
+ TGroupOfElems groupOfElems;
+ TMapOfNodeSet mapOfNodeSet;
+
+ TElemsSet::iterator elemIt = elems.begin();
+ for ( int i = 0, j=0; elemIt != elems.end(); ++elemIt, ++j ) {
+ const SMDS_MeshElement* curElem = *elemIt;
+ SortableElement SE(curElem);
+ int ind = -1;
+ // check uniqueness
+ pair< TMapOfNodeSet::iterator, bool> pp = mapOfNodeSet.insert(make_pair(SE, i));
+ if( !(pp.second) ) {
+ TMapOfNodeSet::iterator& itSE = pp.first;
+ ind = (*itSE).second;
+ arrayOfGroups[ind].push_back(curElem->GetID());
+ }
+ else {
+ groupOfElems.clear();
+ groupOfElems.push_back(curElem->GetID());
+ arrayOfGroups.push_back(groupOfElems);
+ i++;
+ }
+ }
+
+ vector< TGroupOfElems >::iterator groupIt = arrayOfGroups.begin();
+ for ( ; groupIt != arrayOfGroups.end(); ++groupIt ) {
+ groupOfElems = *groupIt;
+ if ( groupOfElems.size() > 1 ) {
+ groupOfElems.sort();
+ theGroupsOfElementsID.push_back(groupOfElems);
+ }
+ }
+}
//=======================================================================
//function : MergeEqualElements
//purpose : Remove all but one of elements built on the same nodes.
//=======================================================================
-void SMESH_MeshEditor::MergeEqualElements()
+void SMESH_MeshEditor::MergeEqualElements(TListOfListOfElementsID & theGroupsOfElementsID)
{
myLastCreatedElems.Clear();
myLastCreatedNodes.Clear();
+ typedef list<int> TListOfIDs;
+ TListOfIDs rmElemIds; // IDs of elems to remove
+
SMESHDS_Mesh* aMesh = GetMeshDS();
- SMDS_EdgeIteratorPtr eIt = aMesh->edgesIterator();
- SMDS_FaceIteratorPtr fIt = aMesh->facesIterator();
- SMDS_VolumeIteratorPtr vIt = aMesh->volumesIterator();
-
- list< int > rmElemIds; // IDs of elems to remove
-
- for ( int iDim = 1; iDim <= 3; iDim++ ) {
-
- set< SortableElement > setOfNodeSet;
- while ( 1 ) {
- // get next element
- const SMDS_MeshElement* elem = 0;
- if ( iDim == 1 ) {
- if ( eIt->more() ) elem = eIt->next();
- } else if ( iDim == 2 ) {
- if ( fIt->more() ) elem = fIt->next();
- } else {
- if ( vIt->more() ) elem = vIt->next();
- }
- if ( !elem ) break;
-
- SortableElement SE(elem);
-
- // check uniqueness
- pair< set<SortableElement>::iterator, bool> pp = setOfNodeSet.insert(SE);
- if( !(pp.second) ) {
- set<SortableElement>::iterator itSE = pp.first;
- SortableElement SEold = *itSE;
- if( SEold.GetID() > SE.GetID() ) {
- rmElemIds.push_back( SEold.GetID() );
- (*itSE).SetID(SE.GetID());
- }
- else {
- rmElemIds.push_back( SE.GetID() );
- }
- }
+ TListOfListOfElementsID::iterator groupsIt = theGroupsOfElementsID.begin();
+ while ( groupsIt != theGroupsOfElementsID.end() ) {
+ TListOfIDs& aGroupOfElemID = *groupsIt;
+ aGroupOfElemID.sort();
+ int elemIDToKeep = aGroupOfElemID.front();
+ const SMDS_MeshElement* elemToKeep = aMesh->FindElement(elemIDToKeep);
+ aGroupOfElemID.pop_front();
+ TListOfIDs::iterator idIt = aGroupOfElemID.begin();
+ while ( idIt != aGroupOfElemID.end() ) {
+ int elemIDToRemove = *idIt;
+ const SMDS_MeshElement* elemToRemove = aMesh->FindElement(elemIDToRemove);
+ // add the kept element in groups of removed one (PAL15188)
+ AddToSameGroups( elemToKeep, elemToRemove, aMesh );
+ rmElemIds.push_back( elemIDToRemove );
+ ++idIt;
}
+ ++groupsIt;
}
Remove( rmElemIds, false );
}
}
}
-
+
// create new elements
SMESHDS_Mesh *aMesh = GetMeshDS();
int aShapeId = FindShape( theFace );
-
+
i1 = 0; i2 = 1;
for ( iSplit = 0; iSplit < nbSplits - 1; iSplit++ ) {
SMDS_MeshElement* newElem = 0;
if ( aShapeId && newElem )
aMesh->SetMeshElementOnShape( newElem, aShapeId );
}
-
+
// change nodes of theFace
const SMDS_MeshNode* newNodes[ 4 ];
newNodes[ 0 ] = linkNodes[ i1 ];
il1 = il1 - nbshift;
// now have to insert nodes between n0 and n1 or n1 and n2 (see below)
// n0 n1 n2 n0 n1 n2
- // +-----+-----+ +-----+-----+
+ // +-----+-----+ +-----+-----+
// \ / | |
// \ / | |
// n5+ +n3 n7+ +n3
//function : ConvertElemToQuadratic
//purpose :
//=======================================================================
-void SMESH_MeshEditor::ConvertElemToQuadratic(SMESHDS_SubMesh *theSm,
- SMESH_MesherHelper* theHelper,
- const bool theForce3d)
+void SMESH_MeshEditor::ConvertElemToQuadratic(SMESHDS_SubMesh * theSm,
+ SMESH_MesherHelper& theHelper,
+ const bool theForce3d)
{
if( !theSm ) return;
SMESHDS_Mesh* meshDS = GetMeshDS();
while(ElemItr->more())
{
const SMDS_MeshElement* elem = ElemItr->next();
- if( !elem ) continue;
+ if( !elem || elem->IsQuadratic() ) continue;
int id = elem->GetID();
int nbNodes = elem->NbNodes();
vector<const SMDS_MeshNode *> aNds (nbNodes);
-
+
for(int i = 0; i < nbNodes; i++)
{
aNds[i] = elem->GetNode(i);
}
-
SMDSAbs_ElementType aType = elem->GetType();
+
+ theSm->RemoveElement(elem);
+ meshDS->SMDS_Mesh::RemoveFreeElement(elem);
+
const SMDS_MeshElement* NewElem = 0;
switch( aType )
{
case SMDSAbs_Edge :
{
- meshDS->RemoveFreeElement(elem, theSm);
- NewElem = theHelper->AddQuadraticEdge(aNds[0], aNds[1], id, theForce3d);
+ NewElem = theHelper.AddEdge(aNds[0], aNds[1], id, theForce3d);
break;
}
case SMDSAbs_Face :
{
- if(elem->IsQuadratic()) continue;
-
- meshDS->RemoveFreeElement(elem, theSm);
switch(nbNodes)
{
case 3:
- NewElem = theHelper->AddFace(aNds[0], aNds[1], aNds[2], id, theForce3d);
+ NewElem = theHelper.AddFace(aNds[0], aNds[1], aNds[2], id, theForce3d);
break;
case 4:
- NewElem = theHelper->AddFace(aNds[0], aNds[1], aNds[2], aNds[3], id, theForce3d);
+ NewElem = theHelper.AddFace(aNds[0], aNds[1], aNds[2], aNds[3], id, theForce3d);
break;
default:
continue;
}
- break;
+ break;
}
case SMDSAbs_Volume :
{
- if( elem->IsQuadratic() ) continue;
-
- meshDS->RemoveFreeElement(elem, theSm);
switch(nbNodes)
{
case 4:
- NewElem = theHelper->AddVolume(aNds[0], aNds[1], aNds[2], aNds[3], id, true);
+ NewElem = theHelper.AddVolume(aNds[0], aNds[1], aNds[2], aNds[3], id, true);
break;
case 6:
- NewElem = theHelper->AddVolume(aNds[0], aNds[1], aNds[2], aNds[3], aNds[4], aNds[5], id, true);
+ NewElem = theHelper.AddVolume(aNds[0], aNds[1], aNds[2], aNds[3], aNds[4], aNds[5], id, true);
break;
case 8:
- NewElem = theHelper->AddVolume(aNds[0], aNds[1], aNds[2], aNds[3],
- aNds[4], aNds[5], aNds[6], aNds[7], id, true);
+ NewElem = theHelper.AddVolume(aNds[0], aNds[1], aNds[2], aNds[3],
+ aNds[4], aNds[5], aNds[6], aNds[7], id, true);
break;
default:
continue;
}
- break;
+ break;
}
default :
continue;
AddToSameGroups( NewElem, elem, meshDS);
theSm->AddElement( NewElem );
}
+ if ( NewElem != elem )
+ RemoveElemFromGroups (elem, meshDS);
}
}
{
SMESHDS_Mesh* meshDS = GetMeshDS();
- SMESH_MesherHelper* aHelper = new SMESH_MesherHelper(*myMesh);
- aHelper->SetKeyIsQuadratic( true );
+ SMESH_MesherHelper aHelper(*myMesh);
+ aHelper.SetIsQuadratic( true );
const TopoDS_Shape& aShape = meshDS->ShapeToMesh();
if ( !aShape.IsNull() && GetMesh()->GetSubMeshContaining(aShape) )
{
SMESH_subMesh *aSubMesh = GetMesh()->GetSubMeshContaining(aShape);
-
+
const map < int, SMESH_subMesh * >& aMapSM = aSubMesh->DependsOn();
map < int, SMESH_subMesh * >::const_iterator itsub;
for (itsub = aMapSM.begin(); itsub != aMapSM.end(); itsub++)
{
SMESHDS_SubMesh *sm = ((*itsub).second)->GetSubMeshDS();
- aHelper->SetSubShape( (*itsub).second->GetSubShape() );
+ aHelper.SetSubShape( (*itsub).second->GetSubShape() );
ConvertElemToQuadratic(sm, aHelper, theForce3d);
}
- aHelper->SetSubShape( aSubMesh->GetSubShape() );
+ aHelper.SetSubShape( aSubMesh->GetSubShape() );
ConvertElemToQuadratic(aSubMesh->GetSubMeshDS(), aHelper, theForce3d);
}
else
while(aEdgeItr->more())
{
const SMDS_MeshEdge* edge = aEdgeItr->next();
- if(edge)
+ if(edge && !edge->IsQuadratic())
{
int id = edge->GetID();
const SMDS_MeshNode* n1 = edge->GetNode(0);
const SMDS_MeshNode* n2 = edge->GetNode(1);
- RemoveElemFromGroups (edge, meshDS);
meshDS->SMDS_Mesh::RemoveFreeElement(edge);
- const SMDS_QuadraticEdge* NewEdge = aHelper->AddQuadraticEdge(n1, n2, id, theForce3d);
- AddToSameGroups(NewEdge, edge, meshDS);
+ const SMDS_MeshEdge* NewEdge = aHelper.AddEdge(n1, n2, id, theForce3d);
+ if ( NewEdge )
+ AddToSameGroups(NewEdge, edge, meshDS);
+ if ( NewEdge != edge )
+ RemoveElemFromGroups (edge, meshDS);
}
}
SMDS_FaceIteratorPtr aFaceItr = meshDS->facesIterator();
{
const SMDS_MeshFace* face = aFaceItr->next();
if(!face || face->IsQuadratic() ) continue;
-
+
int id = face->GetID();
int nbNodes = face->NbNodes();
vector<const SMDS_MeshNode *> aNds (nbNodes);
aNds[i] = face->GetNode(i);
}
- RemoveElemFromGroups (face, meshDS);
meshDS->SMDS_Mesh::RemoveFreeElement(face);
SMDS_MeshFace * NewFace = 0;
switch(nbNodes)
{
case 3:
- NewFace = aHelper->AddFace(aNds[0], aNds[1], aNds[2], id, theForce3d);
+ NewFace = aHelper.AddFace(aNds[0], aNds[1], aNds[2], id, theForce3d);
break;
case 4:
- NewFace = aHelper->AddFace(aNds[0], aNds[1], aNds[2], aNds[3], id, theForce3d);
+ NewFace = aHelper.AddFace(aNds[0], aNds[1], aNds[2], aNds[3], id, theForce3d);
break;
default:
continue;
}
- AddToSameGroups(NewFace, face, meshDS);
+ if ( NewFace )
+ AddToSameGroups(NewFace, face, meshDS);
+ if ( NewFace != face )
+ RemoveElemFromGroups (face, meshDS);
}
SMDS_VolumeIteratorPtr aVolumeItr = meshDS->volumesIterator();
while(aVolumeItr->more())
{
const SMDS_MeshVolume* volume = aVolumeItr->next();
if(!volume || volume->IsQuadratic() ) continue;
-
+
int id = volume->GetID();
int nbNodes = volume->NbNodes();
vector<const SMDS_MeshNode *> aNds (nbNodes);
aNds[i] = volume->GetNode(i);
}
- RemoveElemFromGroups (volume, meshDS);
meshDS->SMDS_Mesh::RemoveFreeElement(volume);
SMDS_MeshVolume * NewVolume = 0;
switch(nbNodes)
{
case 4:
- NewVolume = aHelper->AddVolume(aNds[0], aNds[1], aNds[2],
- aNds[3], id, true );
+ NewVolume = aHelper.AddVolume(aNds[0], aNds[1], aNds[2],
+ aNds[3], id, true );
break;
case 6:
- NewVolume = aHelper->AddVolume(aNds[0], aNds[1], aNds[2],
- aNds[3], aNds[4], aNds[5], id, true);
+ NewVolume = aHelper.AddVolume(aNds[0], aNds[1], aNds[2],
+ aNds[3], aNds[4], aNds[5], id, true);
break;
case 8:
- NewVolume = aHelper->AddVolume(aNds[0], aNds[1], aNds[2], aNds[3],
- aNds[4], aNds[5], aNds[6], aNds[7], id, true);
+ NewVolume = aHelper.AddVolume(aNds[0], aNds[1], aNds[2], aNds[3],
+ aNds[4], aNds[5], aNds[6], aNds[7], id, true);
break;
default:
continue;
}
- AddToSameGroups(NewVolume, volume, meshDS);
+ if ( NewVolume )
+ AddToSameGroups(NewVolume, volume, meshDS);
+ if ( NewVolume != volume )
+ RemoveElemFromGroups (volume, meshDS);
}
}
- delete aHelper;
}
//=======================================================================
//function : RemoveQuadElem
//purpose :
//=======================================================================
-void SMESH_MeshEditor::RemoveQuadElem(SMESHDS_SubMesh *theSm,
+void SMESH_MeshEditor::RemoveQuadElem(SMESHDS_SubMesh * theSm,
SMDS_ElemIteratorPtr theItr,
- RemoveQuadNodeMap& theRemoveNodeMap)
+ const int theShapeID)
{
SMESHDS_Mesh* meshDS = GetMeshDS();
while( theItr->more() )
{
const SMDS_MeshElement* elem = theItr->next();
- if( elem )
+ if( elem && elem->IsQuadratic())
{
- if( !elem->IsQuadratic() )
- continue;
-
int id = elem->GetID();
-
- int nbNodes = elem->NbNodes(), idx = 0;
- vector<const SMDS_MeshNode *> aNds;
+ int nbNodes = elem->NbNodes();
+ vector<const SMDS_MeshNode *> aNds, mediumNodes;
+ aNds.reserve( nbNodes );
+ mediumNodes.reserve( nbNodes );
for(int i = 0; i < nbNodes; i++)
{
const SMDS_MeshNode* n = elem->GetNode(i);
if( elem->IsMediumNode( n ) )
- {
- ItRemoveQuadNodeMap itRNM = theRemoveNodeMap.find( n );
- if( itRNM == theRemoveNodeMap.end() )
- {
- theRemoveNodeMap.insert(RemoveQuadNodeMap::value_type( n,theSm ));
- }
- }
- else
+ mediumNodes.push_back( n );
+ else
aNds.push_back( n );
}
-
- idx = aNds.size();
- if( !idx ) continue;
- SMDSAbs_ElementType aType = elem->GetType();
+ if( aNds.empty() ) continue;
+ SMDSAbs_ElementType aType = elem->GetType();
//remove old quadratic elements
- meshDS->RemoveFreeElement( elem, theSm );
-
- SMDS_MeshElement * NewElem = 0;
- switch(aType)
- {
- case SMDSAbs_Edge:
- NewElem = meshDS->AddEdgeWithID( aNds[0], aNds[1] ,id );
- break;
- case SMDSAbs_Face:
- if( idx==3 ) NewElem = meshDS->AddFaceWithID( aNds[0],
- aNds[1], aNds[2], id );
- if( idx==4 ) NewElem = meshDS->AddFaceWithID( aNds[0],
- aNds[1], aNds[2], aNds[3],id );
- break;
- case SMDSAbs_Volume:
- if( idx==4 ) NewElem = meshDS->AddVolumeWithID( aNds[0],
- aNds[1], aNds[2], aNds[3], id );
- if( idx==6 ) NewElem = meshDS->AddVolumeWithID( aNds[0],
- aNds[1], aNds[2], aNds[3],
- aNds[4], aNds[5], id );
- if( idx==8 ) NewElem = meshDS->AddVolumeWithID(aNds[0],
- aNds[1], aNds[2], aNds[3],
- aNds[4], aNds[5], aNds[6],
- aNds[7] ,id );
- break;
- default:
- break;
- }
-
- AddToSameGroups(NewElem, elem, meshDS);
- if( theSm )
+ meshDS->SMDS_Mesh::RemoveFreeElement( elem );
+ if ( theSm )
+ theSm->RemoveElement( elem );
+
+ SMDS_MeshElement * NewElem = AddElement( aNds, aType, false, id );
+ if ( NewElem )
+ AddToSameGroups(NewElem, elem, meshDS);
+ if ( NewElem != elem )
+ RemoveElemFromGroups (elem, meshDS);
+ if( theSm && NewElem )
theSm->AddElement( NewElem );
+
+ // remove medium nodes
+ vector<const SMDS_MeshNode*>::iterator nIt = mediumNodes.begin();
+ for ( ; nIt != mediumNodes.end(); ++nIt ) {
+ const SMDS_MeshNode* n = *nIt;
+ if ( n->NbInverseNodes() == 0 ) {
+ if ( n->GetPosition()->GetShapeId() != theShapeID )
+ meshDS->RemoveFreeNode( n, meshDS->MeshElements
+ ( n->GetPosition()->GetShapeId() ));
+ else
+ meshDS->RemoveFreeNode( n, theSm );
+ }
+ }
}
}
}
+
//=======================================================================
//function : ConvertFromQuadratic
//purpose :
bool SMESH_MeshEditor::ConvertFromQuadratic()
{
SMESHDS_Mesh* meshDS = GetMeshDS();
- RemoveQuadNodeMap aRemoveNodeMap;
-
const TopoDS_Shape& aShape = meshDS->ShapeToMesh();
if ( !aShape.IsNull() && GetMesh()->GetSubMeshContaining(aShape) )
{
SMESH_subMesh *aSubMesh = GetMesh()->GetSubMeshContaining(aShape);
-
+
const map < int, SMESH_subMesh * >& aMapSM = aSubMesh->DependsOn();
map < int, SMESH_subMesh * >::const_iterator itsub;
for (itsub = aMapSM.begin(); itsub != aMapSM.end(); itsub++)
{
SMESHDS_SubMesh *sm = ((*itsub).second)->GetSubMeshDS();
if( sm )
- RemoveQuadElem( sm, sm->GetElements(), aRemoveNodeMap );
+ RemoveQuadElem( sm, sm->GetElements(), itsub->second->GetId() );
}
SMESHDS_SubMesh *Sm = aSubMesh->GetSubMeshDS();
if( Sm )
- RemoveQuadElem( Sm, Sm->GetElements(), aRemoveNodeMap );
+ RemoveQuadElem( Sm, Sm->GetElements(), aSubMesh->GetId() );
}
else
{
SMESHDS_SubMesh *aSM = 0;
- RemoveQuadElem( aSM, meshDS->elementsIterator(), aRemoveNodeMap );
- }
-
- //remove all quadratic nodes
- ItRemoveQuadNodeMap itRNM = aRemoveNodeMap.begin();
- for ( ; itRNM != aRemoveNodeMap.end(); itRNM++ )
- {
- meshDS->RemoveFreeNode( (*itRNM).first, (*itRNM).second );
+ RemoveQuadElem( aSM, meshDS->elementsIterator(), 0 );
}
return true;
return aResult;
}
-/*!
- * \brief A sorted pair of nodes
- */
-struct TLink: public NLink
-{
- TLink(const SMDS_MeshNode* n1, const SMDS_MeshNode* n2 ):NLink( n1, n2 )
- { if ( n1 < n2 ) std::swap( first, second ); }
- TLink(const NLink& link ):NLink( link )
- { if ( first < second ) std::swap( first, second ); }
-};
-
//================================================================================
/*!
- * \brief Find corresponding nodes in two sets of faces
+ * \brief Find corresponding nodes in two sets of faces
* \param theSide1 - first face set
* \param theSide2 - second first face
* \param theFirstNode1 - a boundary node of set 1