// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
-// See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
//
//
//
#include "SMDS_PolyhedralVolumeOfNodes.hxx"
#include "SMDS_FacePosition.hxx"
#include "SMDS_SpacePosition.hxx"
+#include "SMDS_QuadraticFaceOfNodes.hxx"
#include "SMESHDS_Group.hxx"
#include "SMESHDS_Mesh.hxx"
#include "SMESH_subMesh.hxx"
#include "SMESH_ControlsDef.hxx"
+#include "SMESH_MesherHelper.hxx"
+#include "SMESH_OctreeNode.hxx"
#include "utilities.h"
#include <GeomAdaptor_Surface.hxx>
#include <ElCLib.hxx>
#include <TColStd_ListOfInteger.hxx>
+#include <TopoDS_Face.hxx>
#include <map>
+#include <set>
using namespace std;
using namespace SMESH::Controls;
-typedef map<const SMDS_MeshNode*, const SMDS_MeshNode*> TNodeNodeMap;
typedef map<const SMDS_MeshElement*, list<const SMDS_MeshNode*> > TElemOfNodeListMap;
typedef map<const SMDS_MeshElement*, list<const SMDS_MeshElement*> > TElemOfElemListMap;
typedef map<const SMDS_MeshNode*, list<const SMDS_MeshNode*> > TNodeOfNodeListMap;
typedef TNodeOfNodeListMap::iterator TNodeOfNodeListMapItr;
+//typedef map<const SMDS_MeshNode*, vector<const SMDS_MeshNode*> > TNodeOfNodeVecMap;
+//typedef TNodeOfNodeVecMap::iterator TNodeOfNodeVecMapItr;
typedef map<const SMDS_MeshElement*, vector<TNodeOfNodeListMapItr> > TElemOfVecOfNnlmiMap;
+//typedef map<const SMDS_MeshElement*, vector<TNodeOfNodeVecMapItr> > TElemOfVecOfMapNodesMap;
+
+typedef pair< const SMDS_MeshNode*, const SMDS_MeshNode* > NLink;
//=======================================================================
//function : SMESH_MeshEditor
bool SMESH_MeshEditor::Remove (const list< int >& theIDs,
const bool isNodes )
{
+ myLastCreatedElems.Clear();
+ myLastCreatedNodes.Clear();
SMESHDS_Mesh* aMesh = GetMeshDS();
set< SMESH_subMesh *> smmap;
list<int>::const_iterator it = theIDs.begin();
- for ( ; it != theIDs.end(); it++ )
- {
+ for ( ; it != theIDs.end(); it++ ) {
const SMDS_MeshElement * elem;
if ( isNodes )
elem = aMesh->FindNode( *it );
// Find sub-meshes to notify about modification
SMDS_ElemIteratorPtr nodeIt = elem->nodesIterator();
- while ( nodeIt->more() )
- {
+ while ( nodeIt->more() ) {
const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
const SMDS_PositionPtr& aPosition = node->GetPosition();
if ( aPosition.get() ) {
- int aShapeID = aPosition->GetShapeId();
- if ( aShapeID ) {
- TopoDS_Shape aShape = aMesh->IndexToShape( aShapeID );
- SMESH_subMesh * sm = GetMesh()->GetSubMeshContaining( aShape );
- if ( sm )
+ if ( int aShapeID = aPosition->GetShapeId() ) {
+ if ( SMESH_subMesh * sm = GetMesh()->GetSubMeshContaining( aShapeID ) )
smmap.insert( sm );
}
}
for ( smIt = smmap.begin(); smIt != smmap.end(); smIt++ )
(*smIt)->ComputeStateEngine( SMESH_subMesh::MESH_ENTITY_REMOVED );
}
+
+ // Check if the whole mesh becomes empty
+ if ( SMESH_subMesh * sm = GetMesh()->GetSubMeshContaining( 1 ) )
+ sm->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE );
+
return true;
}
int SMESH_MeshEditor::FindShape (const SMDS_MeshElement * theElem)
{
+ myLastCreatedElems.Clear();
+ myLastCreatedNodes.Clear();
+
SMESHDS_Mesh * aMesh = GetMeshDS();
if ( aMesh->ShapeToMesh().IsNull() )
return 0;
- if ( theElem->GetType() == SMDSAbs_Node )
- {
+ if ( theElem->GetType() == SMDSAbs_Node ) {
const SMDS_PositionPtr& aPosition =
static_cast<const SMDS_MeshNode*>( theElem )->GetPosition();
if ( aPosition.get() )
TopoDS_Shape aShape; // the shape a node is on
SMDS_ElemIteratorPtr nodeIt = theElem->nodesIterator();
- while ( nodeIt->more() )
- {
+ while ( nodeIt->more() ) {
const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
const SMDS_PositionPtr& aPosition = node->GetPosition();
if ( aPosition.get() ) {
- int aShapeID = aPosition->GetShapeId();
- SMESHDS_SubMesh * sm = aMesh->MeshElements( aShapeID );
- if ( sm )
- {
- if ( sm->Contains( theElem ))
- return aShapeID;
- if ( aShape.IsNull() )
- aShape = aMesh->IndexToShape( aShapeID );
- }
- else
- {
- //MESSAGE ( "::FindShape() No SubShape for aShapeID " << aShapeID );
- }
+ int aShapeID = aPosition->GetShapeId();
+ SMESHDS_SubMesh * sm = aMesh->MeshElements( aShapeID );
+ if ( sm ) {
+ if ( sm->Contains( theElem ))
+ return aShapeID;
+ if ( aShape.IsNull() )
+ aShape = aMesh->IndexToShape( aShapeID );
+ }
+ else {
+ //MESSAGE ( "::FindShape() No SubShape for aShapeID " << aShapeID );
}
+ }
}
// None of nodes is on a proper shape,
return 0;
}
TopTools_ListIteratorOfListOfShape ancIt( GetMesh()->GetAncestors( aShape ));
- for ( ; ancIt.More(); ancIt.Next() )
- {
- SMESHDS_SubMesh * sm = aMesh->MeshElements( ancIt.Value() );
- if ( sm && sm->Contains( theElem ))
- return aMesh->ShapeToIndex( ancIt.Value() );
+ for ( ; ancIt.More(); ancIt.Next() ) {
+ SMESHDS_SubMesh * sm = aMesh->MeshElements( ancIt.Value() );
+ if ( sm && sm->Contains( theElem ))
+ return aMesh->ShapeToIndex( ancIt.Value() );
}
//MESSAGE ("::FindShape() - SHAPE NOT FOUND")
return 0;
}
+//=======================================================================
+//function : IsMedium
+//purpose :
+//=======================================================================
+
+bool SMESH_MeshEditor::IsMedium(const SMDS_MeshNode* node,
+ const SMDSAbs_ElementType typeToCheck)
+{
+ bool isMedium = false;
+ SMDS_ElemIteratorPtr it = node->GetInverseElementIterator();
+ while (it->more()) {
+ const SMDS_MeshElement* elem = it->next();
+ isMedium = elem->IsMediumNode(node);
+ if ( typeToCheck == SMDSAbs_All || elem->GetType() == typeToCheck )
+ break;
+ }
+ return isMedium;
+}
+
+//=======================================================================
+//function : ShiftNodesQuadTria
+//purpose : auxilary
+// Shift nodes in the array corresponded to quadratic triangle
+// example: (0,1,2,3,4,5) -> (1,2,0,4,5,3)
+//=======================================================================
+static void ShiftNodesQuadTria(const SMDS_MeshNode* aNodes[])
+{
+ const SMDS_MeshNode* nd1 = aNodes[0];
+ aNodes[0] = aNodes[1];
+ aNodes[1] = aNodes[2];
+ aNodes[2] = nd1;
+ const SMDS_MeshNode* nd2 = aNodes[3];
+ aNodes[3] = aNodes[4];
+ aNodes[4] = aNodes[5];
+ aNodes[5] = nd2;
+}
+
+//=======================================================================
+//function : GetNodesFromTwoTria
+//purpose : auxilary
+// Shift nodes in the array corresponded to quadratic triangle
+// example: (0,1,2,3,4,5) -> (1,2,0,4,5,3)
+//=======================================================================
+static bool GetNodesFromTwoTria(const SMDS_MeshElement * theTria1,
+ const SMDS_MeshElement * theTria2,
+ const SMDS_MeshNode* N1[],
+ const SMDS_MeshNode* N2[])
+{
+ SMDS_ElemIteratorPtr it = theTria1->nodesIterator();
+ int i=0;
+ while(i<6) {
+ N1[i] = static_cast<const SMDS_MeshNode*>( it->next() );
+ i++;
+ }
+ if(it->more()) return false;
+ it = theTria2->nodesIterator();
+ i=0;
+ while(i<6) {
+ N2[i] = static_cast<const SMDS_MeshNode*>( it->next() );
+ i++;
+ }
+ if(it->more()) return false;
+
+ int sames[3] = {-1,-1,-1};
+ int nbsames = 0;
+ int j;
+ for(i=0; i<3; i++) {
+ for(j=0; j<3; j++) {
+ if(N1[i]==N2[j]) {
+ sames[i] = j;
+ nbsames++;
+ break;
+ }
+ }
+ }
+ if(nbsames!=2) return false;
+ if(sames[0]>-1) {
+ ShiftNodesQuadTria(N1);
+ if(sames[1]>-1) {
+ ShiftNodesQuadTria(N1);
+ }
+ }
+ i = sames[0] + sames[1] + sames[2];
+ for(; i<2; i++) {
+ 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)
+ // i.e. first nodes from both arrays determ new diagonal
+ return true;
+}
+
//=======================================================================
//function : InverseDiag
//purpose : Replace two neighbour triangles with ones built on the same 4 nodes
bool SMESH_MeshEditor::InverseDiag (const SMDS_MeshElement * theTria1,
const SMDS_MeshElement * theTria2 )
{
+ myLastCreatedElems.Clear();
+ myLastCreatedNodes.Clear();
+
if (!theTria1 || !theTria2)
return false;
+
const SMDS_FaceOfNodes* F1 = dynamic_cast<const SMDS_FaceOfNodes*>( theTria1 );
- if (!F1) return false;
const SMDS_FaceOfNodes* F2 = dynamic_cast<const SMDS_FaceOfNodes*>( theTria2 );
- if (!F2) return false;
+ if (F1 && F2) {
- // 1 +--+ A theTria1: ( 1 A B ) A->2 ( 1 2 B ) 1 +--+ A
- // | /| theTria2: ( B A 2 ) B->1 ( 1 A 2 ) |\ |
- // |/ | | \|
- // B +--+ 2 B +--+ 2
+ // 1 +--+ A theTria1: ( 1 A B ) A->2 ( 1 2 B ) 1 +--+ A
+ // | /| theTria2: ( B A 2 ) B->1 ( 1 A 2 ) |\ |
+ // |/ | | \|
+ // B +--+ 2 B +--+ 2
- // put nodes in array and find out indices of the same ones
- const SMDS_MeshNode* aNodes [6];
- int sameInd [] = { 0, 0, 0, 0, 0, 0 };
- int i = 0;
- 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 ( aNodes[ i ] == aNodes[ j ]) {
- sameInd[ j ] = i;
- sameInd[ i ] = j;
- break;
- }
- // next
- i++;
- if ( i == 3 ) {
- if ( it->more() )
- return false; // theTria1 is not a triangle
- it = theTria2->nodesIterator();
+ // put nodes in array and find out indices of the same ones
+ const SMDS_MeshNode* aNodes [6];
+ int sameInd [] = { 0, 0, 0, 0, 0, 0 };
+ int i = 0;
+ 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 ( aNodes[ i ] == aNodes[ j ]) {
+ sameInd[ j ] = i;
+ sameInd[ i ] = j;
+ break;
+ }
+ // next
+ i++;
+ if ( i == 3 ) {
+ if ( it->more() )
+ return false; // theTria1 is not a triangle
+ it = theTria2->nodesIterator();
+ }
+ if ( i == 6 && it->more() )
+ return false; // theTria2 is not a triangle
}
- 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++ )
- {
- if ( sameInd [ i ] == 0 )
- if ( i < 3 ) i1 = i;
- else i2 = i;
- else if (i < 3)
- if ( iA ) iB = i;
- else iA = i;
- }
- // nodes 1 and 2 should not be the same
- if ( aNodes[ i1 ] == aNodes[ i2 ] )
- return false;
+ // 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++ ) {
+ if ( sameInd [ i ] == 0 )
+ if ( i < 3 ) i1 = i;
+ else i2 = i;
+ else if (i < 3)
+ if ( iA ) iB = i;
+ else iA = i;
+ }
+ // nodes 1 and 2 should not be the same
+ if ( aNodes[ i1 ] == aNodes[ i2 ] )
+ return false;
+ // theTria1: A->2
+ aNodes[ iA ] = aNodes[ i2 ];
+ // theTria2: B->1
+ aNodes[ sameInd[ iB ]] = aNodes[ i1 ];
- // theTria1: A->2
- aNodes[ iA ] = aNodes[ i2 ];
- // theTria2: B->1
- aNodes[ sameInd[ iB ]] = aNodes[ i1 ];
+ //MESSAGE( theTria1 << theTria2 );
- //MESSAGE( theTria1 << theTria2 );
+ GetMeshDS()->ChangeElementNodes( theTria1, aNodes, 3 );
+ GetMeshDS()->ChangeElementNodes( theTria2, &aNodes[ 3 ], 3 );
- GetMeshDS()->ChangeElementNodes( theTria1, aNodes, 3 );
- GetMeshDS()->ChangeElementNodes( theTria2, &aNodes[ 3 ], 3 );
+ //MESSAGE( theTria1 << theTria2 );
+
+ return true;
- //MESSAGE( theTria1 << theTria2 );
+ } // end if(F1 && F2)
+
+ // check case of quadratic faces
+ const SMDS_QuadraticFaceOfNodes* QF1 =
+ dynamic_cast<const SMDS_QuadraticFaceOfNodes*> (theTria1);
+ if(!QF1) return false;
+ const SMDS_QuadraticFaceOfNodes* QF2 =
+ dynamic_cast<const SMDS_QuadraticFaceOfNodes*> (theTria2);
+ if(!QF2) return false;
+
+ // 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
+ // 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)
+ // i.e. first nodes from both arrays determ new diagonal
+
+ const SMDS_MeshNode* N1new [6];
+ const SMDS_MeshNode* N2new [6];
+ N1new[0] = N1[0];
+ N1new[1] = N2[0];
+ N1new[2] = N2[1];
+ N1new[3] = N1[4];
+ N1new[4] = N2[3];
+ N1new[5] = N1[5];
+ N2new[0] = N1[0];
+ N2new[1] = N1[1];
+ N2new[2] = N2[0];
+ N2new[3] = N1[3];
+ N2new[4] = N2[5];
+ N2new[5] = N1[4];
+ // replaces nodes in faces
+ GetMeshDS()->ChangeElementNodes( theTria1, N1new, 6 );
+ GetMeshDS()->ChangeElementNodes( theTria2, N2new, 6 );
return true;
}
theTria1 = theTria2 = 0;
set< const SMDS_MeshElement* > emap;
- SMDS_ElemIteratorPtr it = theNode1->GetInverseElementIterator();
+ SMDS_ElemIteratorPtr it = theNode1->GetInverseElementIterator(SMDSAbs_Face);
while (it->more()) {
const SMDS_MeshElement* elem = it->next();
- if ( elem->GetType() == SMDSAbs_Face && elem->NbNodes() == 3 )
+ if ( elem->NbNodes() == 3 )
emap.insert( elem );
}
- it = theNode2->GetInverseElementIterator();
+ it = theNode2->GetInverseElementIterator(SMDSAbs_Face);
while (it->more()) {
const SMDS_MeshElement* elem = it->next();
- if ( elem->GetType() == SMDSAbs_Face &&
- emap.find( elem ) != emap.end() )
+ if ( emap.find( elem ) != emap.end() )
if ( theTria1 ) {
- theTria2 = elem;
+ // theTria1 must be element with minimum ID
+ if( theTria1->GetID() < elem->GetID() ) {
+ theTria2 = elem;
+ }
+ else {
+ theTria2 = theTria1;
+ theTria1 = elem;
+ }
break;
- } else {
+ }
+ else {
theTria1 = elem;
}
}
bool SMESH_MeshEditor::InverseDiag (const SMDS_MeshNode * theNode1,
const SMDS_MeshNode * theNode2)
{
+ myLastCreatedElems.Clear();
+ myLastCreatedNodes.Clear();
+
MESSAGE( "::InverseDiag()" );
const SMDS_MeshElement *tr1, *tr2;
return false;
const SMDS_FaceOfNodes* F1 = dynamic_cast<const SMDS_FaceOfNodes*>( tr1 );
- if (!F1) return false;
+ //if (!F1) return false;
const SMDS_FaceOfNodes* F2 = dynamic_cast<const SMDS_FaceOfNodes*>( tr2 );
- if (!F2) return false;
-
- // 1 +--+ A tr1: ( 1 A B ) A->2 ( 1 2 B ) 1 +--+ A
- // | /| tr2: ( B A 2 ) B->1 ( 1 A 2 ) |\ |
- // |/ | | \|
- // B +--+ 2 B +--+ 2
-
- // put nodes in array
- // and find indices of 1,2 and of A in tr1 and of B in tr2
- int i, iA1 = 0, i1 = 0;
- const SMDS_MeshNode* aNodes1 [3];
- SMDS_ElemIteratorPtr it;
- for (i = 0, it = tr1->nodesIterator(); it->more(); i++ ) {
- aNodes1[ i ] = static_cast<const SMDS_MeshNode*>( it->next() );
- if ( aNodes1[ i ] == theNode1 )
- iA1 = i; // node A in tr1
- else if ( aNodes1[ i ] != theNode2 )
- i1 = i; // node 1
- }
- int iB2 = 0, i2 = 0;
- const SMDS_MeshNode* aNodes2 [3];
- for (i = 0, it = tr2->nodesIterator(); it->more(); i++ ) {
- aNodes2[ i ] = static_cast<const SMDS_MeshNode*>( it->next() );
- if ( aNodes2[ i ] == theNode2 )
- iB2 = i; // node B in tr2
- else if ( aNodes2[ i ] != theNode1 )
- i2 = i; // node 2
- }
+ //if (!F2) return false;
+ if (F1 && F2) {
+
+ // 1 +--+ A tr1: ( 1 A B ) A->2 ( 1 2 B ) 1 +--+ A
+ // | /| tr2: ( B A 2 ) B->1 ( 1 A 2 ) |\ |
+ // |/ | | \|
+ // B +--+ 2 B +--+ 2
+
+ // put nodes in array
+ // and find indices of 1,2 and of A in tr1 and of B in tr2
+ int i, iA1 = 0, i1 = 0;
+ const SMDS_MeshNode* aNodes1 [3];
+ SMDS_ElemIteratorPtr it;
+ for (i = 0, it = tr1->nodesIterator(); it->more(); i++ ) {
+ aNodes1[ i ] = static_cast<const SMDS_MeshNode*>( it->next() );
+ if ( aNodes1[ i ] == theNode1 )
+ iA1 = i; // node A in tr1
+ else if ( aNodes1[ i ] != theNode2 )
+ i1 = i; // node 1
+ }
+ int iB2 = 0, i2 = 0;
+ const SMDS_MeshNode* aNodes2 [3];
+ for (i = 0, it = tr2->nodesIterator(); it->more(); i++ ) {
+ aNodes2[ i ] = static_cast<const SMDS_MeshNode*>( it->next() );
+ if ( aNodes2[ i ] == theNode2 )
+ iB2 = i; // node B in tr2
+ 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;
+ // nodes 1 and 2 should not be the same
+ if ( aNodes1[ i1 ] == aNodes2[ i2 ] )
+ return false;
- // tr1: A->2
- aNodes1[ iA1 ] = aNodes2[ i2 ];
- // tr2: B->1
- aNodes2[ iB2 ] = aNodes1[ i1 ];
+ // tr1: A->2
+ aNodes1[ iA1 ] = aNodes2[ i2 ];
+ // tr2: B->1
+ aNodes2[ iB2 ] = aNodes1[ i1 ];
- //MESSAGE( tr1 << tr2 );
+ //MESSAGE( tr1 << tr2 );
- GetMeshDS()->ChangeElementNodes( tr1, aNodes1, 3 );
- GetMeshDS()->ChangeElementNodes( tr2, aNodes2, 3 );
+ GetMeshDS()->ChangeElementNodes( tr1, aNodes1, 3 );
+ GetMeshDS()->ChangeElementNodes( tr2, aNodes2, 3 );
- //MESSAGE( tr1 << tr2 );
+ //MESSAGE( tr1 << tr2 );
- return true;
+ return true;
+ }
+ // check case of quadratic faces
+ const SMDS_QuadraticFaceOfNodes* QF1 =
+ dynamic_cast<const SMDS_QuadraticFaceOfNodes*> (tr1);
+ if(!QF1) return false;
+ const SMDS_QuadraticFaceOfNodes* QF2 =
+ dynamic_cast<const SMDS_QuadraticFaceOfNodes*> (tr2);
+ if(!QF2) return false;
+ return InverseDiag(tr1,tr2);
}
//=======================================================================
const SMDS_MeshElement * tr1,
const SMDS_MeshElement * tr2 )
{
+ if( tr1->NbNodes() != tr2->NbNodes() )
+ return false;
// find the 4-th node to insert into tr1
const SMDS_MeshNode* n4 = 0;
SMDS_ElemIteratorPtr it = tr2->nodesIterator();
- while ( !n4 && it->more() )
- {
+ int i=0;
+ //while ( !n4 && it->more() ) {
+ while ( !n4 && i<3 ) {
const SMDS_MeshNode * n = static_cast<const SMDS_MeshNode*>( it->next() );
+ i++;
bool isDiag = ( n == theNode1 || n == theNode2 );
if ( !isDiag )
n4 = n;
// Make an array of nodes to be in a quadrangle
int iNode = 0, iFirstDiag = -1;
it = tr1->nodesIterator();
- while ( it->more() )
- {
+ i=0;
+ //while ( it->more() ) {
+ while ( i<3 ) {
const SMDS_MeshNode * n = static_cast<const SMDS_MeshNode*>( it->next() );
+ i++;
bool isDiag = ( n == theNode1 || n == theNode2 );
- if ( isDiag )
- {
+ if ( isDiag ) {
if ( iFirstDiag < 0 )
iFirstDiag = iNode;
else if ( iNode - iFirstDiag == 1 )
theQuadNodes[ iNode++ ] = n4; // insert the 4-th node between diagonal nodes
}
- else if ( n == n4 )
- {
+ else if ( n == n4 ) {
return false; // tr1 and tr2 should not have all the same nodes
}
theQuadNodes[ iNode++ ] = n;
bool SMESH_MeshEditor::DeleteDiag (const SMDS_MeshNode * theNode1,
const SMDS_MeshNode * theNode2)
{
+ myLastCreatedElems.Clear();
+ myLastCreatedNodes.Clear();
+
MESSAGE( "::DeleteDiag()" );
const SMDS_MeshElement *tr1, *tr2;
return false;
const SMDS_FaceOfNodes* F1 = dynamic_cast<const SMDS_FaceOfNodes*>( tr1 );
- if (!F1) return false;
+ //if (!F1) return false;
const SMDS_FaceOfNodes* F2 = dynamic_cast<const SMDS_FaceOfNodes*>( tr2 );
- if (!F2) return false;
+ //if (!F2) return false;
+ if (F1 && F2) {
- const SMDS_MeshNode* aNodes [ 4 ];
- if ( ! getQuadrangleNodes( aNodes, theNode1, theNode2, tr1, tr2 ))
- return false;
+ const SMDS_MeshNode* aNodes [ 4 ];
+ if ( ! getQuadrangleNodes( aNodes, theNode1, theNode2, tr1, tr2 ))
+ return false;
+
+ //MESSAGE( endl << tr1 << tr2 );
+
+ GetMeshDS()->ChangeElementNodes( tr1, aNodes, 4 );
+ myLastCreatedElems.Append(tr1);
+ GetMeshDS()->RemoveElement( tr2 );
+
+ //MESSAGE( endl << tr1 );
- //MESSAGE( endl << tr1 << tr2 );
+ return true;
+ }
- GetMeshDS()->ChangeElementNodes( tr1, aNodes, 4 );
+ // check case of quadratic faces
+ const SMDS_QuadraticFaceOfNodes* QF1 =
+ dynamic_cast<const SMDS_QuadraticFaceOfNodes*> (tr1);
+ if(!QF1) return false;
+ const SMDS_QuadraticFaceOfNodes* QF2 =
+ dynamic_cast<const SMDS_QuadraticFaceOfNodes*> (tr2);
+ if(!QF2) return false;
+
+ // 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
+ // 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)
+ // i.e. first nodes from both arrays determ new diagonal
+
+ const SMDS_MeshNode* aNodes[8];
+ aNodes[0] = N1[0];
+ aNodes[1] = N1[1];
+ aNodes[2] = N2[0];
+ aNodes[3] = N2[1];
+ aNodes[4] = N1[3];
+ aNodes[5] = N2[5];
+ aNodes[6] = N2[3];
+ aNodes[7] = N1[5];
+
+ GetMeshDS()->ChangeElementNodes( tr1, aNodes, 8 );
+ myLastCreatedElems.Append(tr1);
GetMeshDS()->RemoveElement( tr2 );
- //MESSAGE( endl << tr1 );
+ // remove middle node (9)
+ GetMeshDS()->RemoveNode( N1[4] );
return true;
}
bool SMESH_MeshEditor::Reorient (const SMDS_MeshElement * theElem)
{
+ myLastCreatedElems.Clear();
+ myLastCreatedNodes.Clear();
+
if (!theElem)
return false;
SMDS_ElemIteratorPtr it = theElem->nodesIterator();
switch ( theElem->GetType() ) {
case SMDSAbs_Edge:
- case SMDSAbs_Face:
- {
- int i = theElem->NbNodes();
- vector<const SMDS_MeshNode*> aNodes( i );
- while ( it->more() )
- aNodes[ --i ]= static_cast<const SMDS_MeshNode*>( it->next() );
- return GetMeshDS()->ChangeElementNodes( theElem, &aNodes[0], theElem->NbNodes() );
+ case SMDSAbs_Face: {
+ if(!theElem->IsQuadratic()) {
+ int i = theElem->NbNodes();
+ vector<const SMDS_MeshNode*> aNodes( i );
+ while ( it->more() )
+ aNodes[ --i ]= static_cast<const SMDS_MeshNode*>( it->next() );
+ return GetMeshDS()->ChangeElementNodes( theElem, &aNodes[0], theElem->NbNodes() );
+ }
+ else {
+ // quadratic elements
+ if(theElem->GetType()==SMDSAbs_Edge) {
+ vector<const SMDS_MeshNode*> aNodes(3);
+ aNodes[1]= static_cast<const SMDS_MeshNode*>( it->next() );
+ aNodes[0]= static_cast<const SMDS_MeshNode*>( it->next() );
+ aNodes[2]= static_cast<const SMDS_MeshNode*>( it->next() );
+ return GetMeshDS()->ChangeElementNodes( theElem, &aNodes[0], 3 );
+ }
+ else {
+ int nbn = theElem->NbNodes();
+ vector<const SMDS_MeshNode*> aNodes(nbn);
+ aNodes[0]= static_cast<const SMDS_MeshNode*>( it->next() );
+ int i=1;
+ for(; i<nbn/2; i++) {
+ aNodes[nbn/2-i]= static_cast<const SMDS_MeshNode*>( it->next() );
+ }
+ for(i=0; i<nbn/2; i++) {
+ aNodes[nbn-i-1]= static_cast<const SMDS_MeshNode*>( it->next() );
+ }
+ return GetMeshDS()->ChangeElementNodes( theElem, &aNodes[0], nbn );
+ }
+ }
}
- case SMDSAbs_Volume:
- {
+ case SMDSAbs_Volume: {
if (theElem->IsPoly()) {
const SMDS_PolyhedralVolumeOfNodes* aPolyedre =
static_cast<const SMDS_PolyhedralVolumeOfNodes*>( theElem );
return GetMeshDS()->ChangePolyhedronNodes( theElem, poly_nodes, quantities );
- } else {
+ }
+ else {
SMDS_VolumeTool vTool;
if ( !vTool.Set( theElem ))
return false;
// theCrit is used to select a diagonal to cut
//=======================================================================
-bool SMESH_MeshEditor::QuadToTri (set<const SMDS_MeshElement*> & theElems,
+bool SMESH_MeshEditor::QuadToTri (TIDSortedElemSet & theElems,
SMESH::Controls::NumericalFunctorPtr theCrit)
{
+ myLastCreatedElems.Clear();
+ myLastCreatedNodes.Clear();
+
MESSAGE( "::QuadToTri()" );
if ( !theCrit.get() )
SMESHDS_Mesh * aMesh = GetMeshDS();
- set< const SMDS_MeshElement * >::iterator itElem;
- for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ )
- {
- const SMDS_MeshElement* elem = (*itElem);
- if ( !elem || elem->GetType() != SMDSAbs_Face || elem->NbNodes() != 4 )
+ Handle(Geom_Surface) surface;
+ SMESH_MesherHelper helper( *GetMesh() );
+
+ TIDSortedElemSet::iterator itElem;
+ for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ ) {
+ const SMDS_MeshElement* elem = *itElem;
+ if ( !elem || elem->GetType() != SMDSAbs_Face )
+ continue;
+ if ( elem->NbNodes() != ( elem->IsQuadratic() ? 8 : 4 ))
continue;
// retrieve element nodes
- const SMDS_MeshNode* aNodes [4];
+ const SMDS_MeshNode* aNodes [8];
SMDS_ElemIteratorPtr itN = elem->nodesIterator();
int i = 0;
while ( itN->more() )
aBadRate2 = getBadRate( &tr3, theCrit ) + getBadRate( &tr4, theCrit );
int aShapeId = FindShape( elem );
- //MESSAGE( "aBadRate1 = " << aBadRate1 << "; aBadRate2 = " << aBadRate2
- // << " ShapeID = " << aShapeId << endl << elem );
+ const SMDS_MeshElement* newElem = 0;
- if ( aBadRate1 <= aBadRate2 ) {
- // tr1 + tr2 is better
- aMesh->ChangeElementNodes( elem, aNodes, 3 );
- //MESSAGE( endl << elem );
+ if( !elem->IsQuadratic() ) {
- elem = aMesh->AddFace( aNodes[2], aNodes[3], aNodes[0] );
+ // split liner quadrangle
+
+ if ( aBadRate1 <= aBadRate2 ) {
+ // tr1 + tr2 is better
+ aMesh->ChangeElementNodes( elem, aNodes, 3 );
+ newElem = aMesh->AddFace( aNodes[2], aNodes[3], aNodes[0] );
+ }
+ else {
+ // tr3 + tr4 is better
+ aMesh->ChangeElementNodes( elem, &aNodes[1], 3 );
+ newElem = aMesh->AddFace( aNodes[3], aNodes[0], aNodes[1] );
+ }
}
else {
- // tr3 + tr4 is better
- aMesh->ChangeElementNodes( elem, &aNodes[1], 3 );
- //MESSAGE( endl << elem );
- elem = aMesh->AddFace( aNodes[3], aNodes[0], aNodes[1] );
- }
- //MESSAGE( endl << elem );
+ // split quadratic quadrangle
+
+ // get surface elem is on
+ if ( aShapeId != helper.GetSubShapeID() ) {
+ surface.Nullify();
+ TopoDS_Shape shape;
+ if ( aShapeId > 0 )
+ shape = aMesh->IndexToShape( aShapeId );
+ if ( !shape.IsNull() && shape.ShapeType() == TopAbs_FACE ) {
+ TopoDS_Face face = TopoDS::Face( shape );
+ surface = BRep_Tool::Surface( face );
+ if ( !surface.IsNull() )
+ helper.SetSubShape( shape );
+ }
+ }
+ // get elem nodes
+ const SMDS_MeshNode* aNodes [8];
+ const SMDS_MeshNode* inFaceNode = 0;
+ SMDS_ElemIteratorPtr itN = elem->nodesIterator();
+ int i = 0;
+ while ( itN->more() ) {
+ aNodes[ i++ ] = static_cast<const SMDS_MeshNode*>( itN->next() );
+ if ( !inFaceNode && helper.GetNodeUVneedInFaceNode() &&
+ 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;
+ gp_XYZ p( 0,0,0 );
+ if ( surface.IsNull() ) {
+ for(i=0; i<4; i++)
+ p += gp_XYZ(aNodes[i]->X(), aNodes[i]->Y(), aNodes[i]->Z() );
+ p /= 4;
+ }
+ else {
+ TopoDS_Face face = TopoDS::Face( helper.GetSubShape() );
+ gp_XY uv( 0,0 );
+ for(i=0; i<4; i++)
+ uv += helper.GetNodeUV( face, aNodes[i], inFaceNode );
+ uv /= 4.;
+ p = surface->Value( uv.X(), uv.Y() ).XYZ();
+ }
+ const SMDS_MeshNode* newN = aMesh->AddNode( p.X(), p.Y(), p.Z() );
+ myLastCreatedNodes.Append(newN);
+
+ // create a new element
+ const SMDS_MeshNode* N[6];
+ if ( aBadRate1 <= aBadRate2 ) {
+ N[0] = aNodes[0];
+ N[1] = aNodes[1];
+ N[2] = aNodes[2];
+ N[3] = aNodes[4];
+ N[4] = aNodes[5];
+ N[5] = newN;
+ newElem = aMesh->AddFace(aNodes[2], aNodes[3], aNodes[0],
+ aNodes[6], aNodes[7], newN );
+ }
+ else {
+ N[0] = aNodes[1];
+ N[1] = aNodes[2];
+ N[2] = aNodes[3];
+ N[3] = aNodes[5];
+ N[4] = aNodes[6];
+ N[5] = newN;
+ newElem = aMesh->AddFace(aNodes[3], aNodes[0], aNodes[1],
+ aNodes[7], aNodes[4], newN );
+ }
+ aMesh->ChangeElementNodes( elem, N, 6 );
+
+ } // quadratic case
+
+ // care of a new element
+
+ myLastCreatedElems.Append(newElem);
+ AddToSameGroups( newElem, elem, aMesh );
// put a new triangle on the same shape
if ( aShapeId )
- aMesh->SetMeshElementOnShape( elem, aShapeId );
+ aMesh->SetMeshElementOnShape( newElem, aShapeId );
}
-
return true;
}
int SMESH_MeshEditor::BestSplit (const SMDS_MeshElement* theQuad,
SMESH::Controls::NumericalFunctorPtr theCrit)
{
+ myLastCreatedElems.Clear();
+ myLastCreatedNodes.Clear();
+
if (!theCrit.get())
return -1;
- if (!theQuad || theQuad->GetType() != SMDSAbs_Face || theQuad->NbNodes() != 4)
+ if (!theQuad || theQuad->GetType() != SMDSAbs_Face )
return -1;
- // retrieve element nodes
- const SMDS_MeshNode* aNodes [4];
- SMDS_ElemIteratorPtr itN = theQuad->nodesIterator();
- int i = 0;
- while (itN->more())
- aNodes[ i++ ] = static_cast<const SMDS_MeshNode*>( itN->next() );
+ if( theQuad->NbNodes()==4 ||
+ (theQuad->NbNodes()==8 && theQuad->IsQuadratic()) ) {
- // compare two sets of possible triangles
- double aBadRate1, aBadRate2; // to what extent a set is bad
- SMDS_FaceOfNodes tr1 ( aNodes[0], aNodes[1], aNodes[2] );
- SMDS_FaceOfNodes tr2 ( aNodes[2], aNodes[3], aNodes[0] );
- aBadRate1 = getBadRate( &tr1, theCrit ) + getBadRate( &tr2, theCrit );
+ // retrieve element nodes
+ const SMDS_MeshNode* aNodes [4];
+ SMDS_ElemIteratorPtr itN = theQuad->nodesIterator();
+ int i = 0;
+ //while (itN->more())
+ while (i<4) {
+ aNodes[ i++ ] = static_cast<const SMDS_MeshNode*>( itN->next() );
+ }
+ // compare two sets of possible triangles
+ double aBadRate1, aBadRate2; // to what extent a set is bad
+ SMDS_FaceOfNodes tr1 ( aNodes[0], aNodes[1], aNodes[2] );
+ SMDS_FaceOfNodes tr2 ( aNodes[2], aNodes[3], aNodes[0] );
+ aBadRate1 = getBadRate( &tr1, theCrit ) + getBadRate( &tr2, theCrit );
- SMDS_FaceOfNodes tr3 ( aNodes[1], aNodes[2], aNodes[3] );
- SMDS_FaceOfNodes tr4 ( aNodes[3], aNodes[0], aNodes[1] );
- aBadRate2 = getBadRate( &tr3, theCrit ) + getBadRate( &tr4, theCrit );
+ SMDS_FaceOfNodes tr3 ( aNodes[1], aNodes[2], aNodes[3] );
+ SMDS_FaceOfNodes tr4 ( aNodes[3], aNodes[0], aNodes[1] );
+ aBadRate2 = getBadRate( &tr3, theCrit ) + getBadRate( &tr4, theCrit );
- if (aBadRate1 <= aBadRate2) // tr1 + tr2 is better
- return 1; // diagonal 1-3
+ if (aBadRate1 <= aBadRate2) // tr1 + tr2 is better
+ return 1; // diagonal 1-3
- return 2; // diagonal 2-4
+ return 2; // diagonal 2-4
+ }
+ return -1;
}
//=======================================================================
}
}
+
+//=======================================================================
+//function : RemoveElemFromGroups
+//purpose : Remove removeelem to the groups the elemInGroups belongs to
+//=======================================================================
+void SMESH_MeshEditor::RemoveElemFromGroups (const SMDS_MeshElement* removeelem,
+ SMESHDS_Mesh * aMesh)
+{
+ const set<SMESHDS_GroupBase*>& groups = aMesh->GetGroups();
+ if (!groups.empty())
+ {
+ set<SMESHDS_GroupBase*>::const_iterator GrIt = groups.begin();
+ for (; GrIt != groups.end(); GrIt++)
+ {
+ SMESHDS_Group* grp = dynamic_cast<SMESHDS_Group*>(*GrIt);
+ if (!grp || grp->IsEmpty()) continue;
+ grp->SMDSGroup().Remove(removeelem);
+ }
+ }
+}
+
+
//=======================================================================
//function : QuadToTri
//purpose : Cut quadrangles into triangles.
// theCrit is used to select a diagonal to cut
//=======================================================================
-bool SMESH_MeshEditor::QuadToTri (std::set<const SMDS_MeshElement*> & theElems,
- const bool the13Diag)
+bool SMESH_MeshEditor::QuadToTri (TIDSortedElemSet & theElems,
+ const bool the13Diag)
{
+ myLastCreatedElems.Clear();
+ myLastCreatedNodes.Clear();
+
MESSAGE( "::QuadToTri()" );
SMESHDS_Mesh * aMesh = GetMeshDS();
- set< const SMDS_MeshElement * >::iterator itElem;
- for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ )
- {
- const SMDS_MeshElement* elem = (*itElem);
- if ( !elem || elem->GetType() != SMDSAbs_Face || elem->NbNodes() != 4 )
+ Handle(Geom_Surface) surface;
+ SMESH_MesherHelper helper( *GetMesh() );
+
+ TIDSortedElemSet::iterator itElem;
+ for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ ) {
+ const SMDS_MeshElement* elem = *itElem;
+ if ( !elem || elem->GetType() != SMDSAbs_Face )
continue;
+ bool isquad = elem->NbNodes()==4 || elem->NbNodes()==8;
+ if(!isquad) continue;
- // retrieve element nodes
- const SMDS_MeshNode* aNodes [4];
- SMDS_ElemIteratorPtr itN = elem->nodesIterator();
- int i = 0;
- while ( itN->more() )
- aNodes[ i++ ] = static_cast<const SMDS_MeshNode*>( itN->next() );
+ if(elem->NbNodes()==4) {
+ // retrieve element nodes
+ const SMDS_MeshNode* aNodes [4];
+ SMDS_ElemIteratorPtr itN = elem->nodesIterator();
+ int i = 0;
+ while ( itN->more() )
+ aNodes[ i++ ] = static_cast<const SMDS_MeshNode*>( itN->next() );
- int aShapeId = FindShape( elem );
- const SMDS_MeshElement* newElem = 0;
- if ( the13Diag )
- {
- aMesh->ChangeElementNodes( elem, aNodes, 3 );
- newElem = aMesh->AddFace( aNodes[2], aNodes[3], aNodes[0] );
- }
- else
- {
- aMesh->ChangeElementNodes( elem, &aNodes[1], 3 );
- newElem = aMesh->AddFace( aNodes[3], aNodes[0], aNodes[1] );
+ int aShapeId = FindShape( elem );
+ const SMDS_MeshElement* newElem = 0;
+ if ( the13Diag ) {
+ aMesh->ChangeElementNodes( elem, aNodes, 3 );
+ newElem = aMesh->AddFace( aNodes[2], aNodes[3], aNodes[0] );
+ }
+ else {
+ aMesh->ChangeElementNodes( elem, &aNodes[1], 3 );
+ newElem = aMesh->AddFace( aNodes[3], aNodes[0], aNodes[1] );
+ }
+ myLastCreatedElems.Append(newElem);
+ // put a new triangle on the same shape and add to the same groups
+ if ( aShapeId )
+ aMesh->SetMeshElementOnShape( newElem, aShapeId );
+ AddToSameGroups( newElem, elem, aMesh );
}
- // put a new triangle on the same shape and add to the same groups
+ // Quadratic quadrangle
- if ( aShapeId )
- aMesh->SetMeshElementOnShape( newElem, aShapeId );
+ if( elem->NbNodes()==8 && elem->IsQuadratic() ) {
- AddToSameGroups( newElem, elem, aMesh );
+ // get surface elem is on
+ int aShapeId = FindShape( elem );
+ if ( aShapeId != helper.GetSubShapeID() ) {
+ surface.Nullify();
+ TopoDS_Shape shape;
+ if ( aShapeId > 0 )
+ shape = aMesh->IndexToShape( aShapeId );
+ if ( !shape.IsNull() && shape.ShapeType() == TopAbs_FACE ) {
+ TopoDS_Face face = TopoDS::Face( shape );
+ surface = BRep_Tool::Surface( face );
+ if ( !surface.IsNull() )
+ helper.SetSubShape( shape );
+ }
+ }
+
+ const SMDS_MeshNode* aNodes [8];
+ const SMDS_MeshNode* inFaceNode = 0;
+ SMDS_ElemIteratorPtr itN = elem->nodesIterator();
+ int i = 0;
+ while ( itN->more() ) {
+ aNodes[ i++ ] = static_cast<const SMDS_MeshNode*>( itN->next() );
+ if ( !inFaceNode && helper.GetNodeUVneedInFaceNode() &&
+ 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;
+ gp_XYZ p( 0,0,0 );
+ if ( surface.IsNull() ) {
+ for(i=0; i<4; i++)
+ p += gp_XYZ(aNodes[i]->X(), aNodes[i]->Y(), aNodes[i]->Z() );
+ p /= 4;
+ }
+ else {
+ TopoDS_Face geomFace = TopoDS::Face( helper.GetSubShape() );
+ gp_XY uv( 0,0 );
+ for(i=0; i<4; i++)
+ uv += helper.GetNodeUV( geomFace, aNodes[i], inFaceNode );
+ uv /= 4.;
+ p = surface->Value( uv.X(), uv.Y() ).XYZ();
+ }
+ const SMDS_MeshNode* newN = aMesh->AddNode( p.X(), p.Y(), p.Z() );
+ myLastCreatedNodes.Append(newN);
+
+ // create a new element
+ const SMDS_MeshElement* newElem = 0;
+ const SMDS_MeshNode* N[6];
+ if ( the13Diag ) {
+ N[0] = aNodes[0];
+ N[1] = aNodes[1];
+ N[2] = aNodes[2];
+ N[3] = aNodes[4];
+ N[4] = aNodes[5];
+ N[5] = newN;
+ newElem = aMesh->AddFace(aNodes[2], aNodes[3], aNodes[0],
+ aNodes[6], aNodes[7], newN );
+ }
+ else {
+ N[0] = aNodes[1];
+ N[1] = aNodes[2];
+ N[2] = aNodes[3];
+ N[3] = aNodes[5];
+ N[4] = aNodes[6];
+ N[5] = newN;
+ newElem = aMesh->AddFace(aNodes[3], aNodes[0], aNodes[1],
+ aNodes[7], aNodes[4], newN );
+ }
+ myLastCreatedElems.Append(newElem);
+ aMesh->ChangeElementNodes( elem, N, 6 );
+ // put a new triangle on the same shape and add to the same groups
+ if ( aShapeId )
+ aMesh->SetMeshElementOnShape( newElem, aShapeId );
+ AddToSameGroups( newElem, elem, aMesh );
+ }
}
return true;
if ( !SMESH::Controls::NumericalFunctor::GetPoints( tr1, P1 ) ||
!SMESH::Controls::NumericalFunctor::GetPoints( tr2, P2 ))
return angle;
- gp_Vec N1 = gp_Vec( P1(2) - P1(1) ) ^ gp_Vec( P1(3) - P1(1) );
+ gp_Vec N1,N2;
+ if(!tr1->IsQuadratic())
+ N1 = gp_Vec( P1(2) - P1(1) ) ^ gp_Vec( P1(3) - P1(1) );
+ else
+ N1 = gp_Vec( P1(3) - P1(1) ) ^ gp_Vec( P1(5) - P1(1) );
if ( N1.SquareMagnitude() <= gp::Resolution() )
return angle;
- gp_Vec N2 = gp_Vec( P2(2) - P2(1) ) ^ gp_Vec( P2(3) - P2(1) );
+ if(!tr2->IsQuadratic())
+ N2 = gp_Vec( P2(2) - P2(1) ) ^ gp_Vec( P2(3) - P2(1) );
+ else
+ N2 = gp_Vec( P2(3) - P2(1) ) ^ gp_Vec( P2(5) - P2(1) );
if ( N2.SquareMagnitude() <= gp::Resolution() )
return angle;
// find the first diagonal node n1 in the triangles:
// take in account a diagonal link orientation
const SMDS_MeshElement *nFirst[2], *tr[] = { tr1, tr2 };
- for ( int t = 0; t < 2; t++ )
- {
+ for ( int t = 0; t < 2; t++ ) {
SMDS_ElemIteratorPtr it = tr[ t ]->nodesIterator();
int i = 0, iDiag = -1;
while ( it->more()) {
// class generating a unique ID for a pair of nodes
// and able to return nodes by that ID
// =================================================
-
class LinkID_Gen {
public:
long myMaxID;
};
+
//=======================================================================
//function : TriToQuad
//purpose : Fuse neighbour triangles into quadrangles.
// fusion is still performed.
//=======================================================================
-bool SMESH_MeshEditor::TriToQuad (set<const SMDS_MeshElement*> & theElems,
+bool SMESH_MeshEditor::TriToQuad (TIDSortedElemSet & theElems,
SMESH::Controls::NumericalFunctorPtr theCrit,
const double theMaxAngle)
{
+ myLastCreatedElems.Clear();
+ myLastCreatedNodes.Clear();
+
MESSAGE( "::TriToQuad()" );
if ( !theCrit.get() )
return false;
SMESHDS_Mesh * aMesh = GetMeshDS();
- LinkID_Gen aLinkID_Gen( aMesh );
-
+ //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;
-
- set<const SMDS_MeshElement*>::iterator itElem;
- for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ )
- {
- const SMDS_MeshElement* elem = (*itElem);
- if ( !elem || elem->NbNodes() != 3 )
- continue;
+ //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;
+
+ 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;
// retrieve element nodes
const SMDS_MeshNode* aNodes [4];
SMDS_ElemIteratorPtr itN = elem->nodesIterator();
int i = 0;
- while ( itN->more() )
+ //while ( itN->more() )
+ while ( i<3 )
aNodes[ i++ ] = static_cast<const SMDS_MeshNode*>( itN->next() );
ASSERT( i == 3 );
aNodes[ 3 ] = aNodes[ 0 ];
// fill maps
- for ( i = 0; i < 3; i++ )
- {
- long linkID = aLinkID_Gen.GetLinkID( aNodes[ i ], aNodes[ i+1 ] );
+ 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] ));
// check if elements sharing a link can be fused
- itLE = mapLi_listEl.find( linkID );
- if ( itLE != mapLi_listEl.end() )
- {
+ //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
continue;
const SMDS_MeshElement* elem2 = (*itLE).second.front();
-// if ( FindShape( elem ) != FindShape( elem2 ))
-// continue; // do not fuse triangles laying on different shapes
+ //if ( FindShape( elem ) != FindShape( elem2 ))
+ // continue; // do not fuse triangles laying on different shapes
if ( getAngle( elem, elem2, aNodes[i], aNodes[i+1] ) > theMaxAngle )
continue; // avoid making badly shaped quads
(*itLE).second.push_back( elem );
}
- else
- mapLi_listEl[ linkID ].push_back( elem );
- mapEl_setLi [ elem ].insert( linkID );
+ else {
+ //mapLi_listEl[ linkID ].push_back( elem );
+ mapLi_listEl[ link ].push_back( elem );
+ }
+ //mapEl_setLi [ elem ].insert( linkID );
+ mapEl_setLi [ elem ].insert( link );
}
}
// Clean the maps from the links shared by a sole element, ie
// links to which only one element is bound in mapLi_listEl
- for ( itLE = mapLi_listEl.begin(); itLE != mapLi_listEl.end(); itLE++ )
- {
+ for ( itLE = mapLi_listEl.begin(); itLE != mapLi_listEl.end(); itLE++ ) {
int nbElems = (*itLE).second.size();
if ( nbElems < 2 ) {
const SMDS_MeshElement* elem = (*itLE).second.front();
- long link = (*itLE).first;
+ //long link = (*itLE).first;
+ NLink link = (*itLE).first;
mapEl_setLi[ elem ].erase( link );
if ( mapEl_setLi[ elem ].empty() )
mapEl_setLi.erase( elem );
// Algo: fuse triangles into quadrangles
- while ( ! mapEl_setLi.empty() )
- {
+ 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++ )
- {
+ for ( itEL = mapEl_setLi.begin(); itEL != mapEl_setLi.end(); itEL++ ) {
int nbLinks = (*itEL).second.size();
- if ( nbLinks < minNbLinks )
- {
+ if ( nbLinks < minNbLinks ) {
startElem = (*itEL).first;
minNbLinks = nbLinks;
if ( minNbLinks == 1 )
// search elements to fuse starting from startElem or links of elements
// fused earlyer - startLinks
- list< long > startLinks;
- while ( startElem || !startLinks.empty() )
- {
- while ( !startElem && !startLinks.empty() )
- {
+ //list< long > startLinks;
+ list< NLink > startLinks;
+ while ( startElem || !startLinks.empty() ) {
+ while ( !startElem && !startLinks.empty() ) {
// Get an element to start, by a link
- long linkId = startLinks.front();
+ //long linkId = startLinks.front();
+ NLink linkId = startLinks.front();
startLinks.pop_front();
itLE = mapLi_listEl.find( linkId );
- if ( itLE != mapLi_listEl.end() )
- {
+ if ( itLE != mapLi_listEl.end() ) {
list< const SMDS_MeshElement* > & listElem = (*itLE).second;
list< const SMDS_MeshElement* >::iterator itE = listElem.begin();
for ( ; itE != listElem.end() ; itE++ )
}
}
- if ( startElem )
- {
+ if ( startElem ) {
// Get candidates to be fused
-
const SMDS_MeshElement *tr1 = startElem, *tr2 = 0, *tr3 = 0;
- long link12, link13;
+ //long link12, link13;
+ NLink link12, link13;
startElem = 0;
ASSERT( mapEl_setLi.find( tr1 ) != mapEl_setLi.end() );
- set< long >& setLi = mapEl_setLi[ tr1 ];
+ //set< long >& setLi = mapEl_setLi[ tr1 ];
+ set< NLink >& setLi = mapEl_setLi[ tr1 ];
ASSERT( !setLi.empty() );
- set< long >::iterator itLi;
- for ( itLi = setLi.begin(); itLi != setLi.end(); itLi++ )
- {
- long linkID = (*itLi);
+ //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 );
if ( itLE == mapLi_listEl.end() )
continue;
+
const SMDS_MeshElement* elem = (*itLE).second.front();
if ( elem == tr1 )
elem = (*itLE).second.back();
mapLi_listEl.erase( itLE );
if ( mapEl_setLi.find( elem ) == mapEl_setLi.end())
continue;
- if ( tr2 )
- {
+ if ( tr2 ) {
tr3 = elem;
link13 = linkID;
}
- else
- {
+ else {
tr2 = elem;
link12 = linkID;
}
// add other links of elem to list of links to re-start from
- set< long >& links = mapEl_setLi[ elem ];
- set< long >::iterator it;
- for ( it = links.begin(); it != links.end(); it++ )
- {
- long linkID2 = (*it);
+ //set< long >& links = mapEl_setLi[ elem ];
+ //set< long >::iterator it;
+ set< NLink >& links = mapEl_setLi[ elem ];
+ set< NLink >::iterator it;
+ for ( it = links.begin(); it != links.end(); it++ ) {
+ //long linkID2 = (*it);
+ NLink linkID2 = (*it);
if ( linkID2 != linkID )
startLinks.push_back( linkID2 );
}
}
// 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 &&
- aLinkID_Gen.GetNodes( link12, linkNode1, linkNode2 ) &&
- getQuadrangleNodes( n12, linkNode1, linkNode2, tr1, tr2 ))
- Ok12 = true;
- if ( tr3 &&
- aLinkID_Gen.GetNodes( link13, linkNode1, linkNode2 ) &&
- getQuadrangleNodes( n13, linkNode1, linkNode2, tr1, tr3 ))
- Ok13 = true;
+ 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;
+ 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;
+ if ( tr3 && getQuadrangleNodes( n13, linkNode1, linkNode2, tr1, tr3 ))
+ Ok13 = true;
+ }
// Choose a pair to fuse
-
- if ( Ok12 && Ok13 )
- {
+ if ( Ok12 && Ok13 ) {
SMDS_FaceOfNodes quad12 ( n12[ 0 ], n12[ 1 ], n12[ 2 ], n12[ 3 ] );
SMDS_FaceOfNodes quad13 ( n13[ 0 ], n13[ 1 ], n13[ 2 ], n13[ 3 ] );
double aBadRate12 = getBadRate( &quad12, theCrit );
Ok13 = false;
}
-
// Make quadrangles
// and remove fused elems and removed links from the maps
-
mapEl_setLi.erase( tr1 );
- if ( Ok12 )
- {
+ if ( Ok12 ) {
mapEl_setLi.erase( tr2 );
mapLi_listEl.erase( link12 );
- aMesh->ChangeElementNodes( tr1, n12, 4 );
- aMesh->RemoveElement( tr2 );
+ if(tr1->NbNodes()==3) {
+ if( tr1->GetID() < tr2->GetID() ) {
+ aMesh->ChangeElementNodes( tr1, n12, 4 );
+ myLastCreatedElems.Append(tr1);
+ aMesh->RemoveElement( tr2 );
+ }
+ else {
+ aMesh->ChangeElementNodes( tr2, n12, 4 );
+ myLastCreatedElems.Append(tr2);
+ aMesh->RemoveElement( tr1);
+ }
+ }
+ else {
+ const SMDS_MeshNode* N1 [6];
+ 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)
+ // i.e. first nodes from both arrays determ new diagonal
+ const SMDS_MeshNode* aNodes[8];
+ aNodes[0] = N1[0];
+ aNodes[1] = N1[1];
+ aNodes[2] = N2[0];
+ aNodes[3] = N2[1];
+ aNodes[4] = N1[3];
+ aNodes[5] = N2[5];
+ aNodes[6] = N2[3];
+ aNodes[7] = N1[5];
+ if( tr1->GetID() < tr2->GetID() ) {
+ GetMeshDS()->ChangeElementNodes( tr1, aNodes, 8 );
+ myLastCreatedElems.Append(tr1);
+ GetMeshDS()->RemoveElement( tr2 );
+ }
+ else {
+ GetMeshDS()->ChangeElementNodes( tr2, aNodes, 8 );
+ myLastCreatedElems.Append(tr2);
+ GetMeshDS()->RemoveElement( tr1 );
+ }
+ // remove middle node (9)
+ GetMeshDS()->RemoveNode( N1[4] );
+ }
}
- else if ( Ok13 )
- {
+ else if ( Ok13 ) {
mapEl_setLi.erase( tr3 );
mapLi_listEl.erase( link13 );
- aMesh->ChangeElementNodes( tr1, n13, 4 );
- aMesh->RemoveElement( tr3 );
+ if(tr1->NbNodes()==3) {
+ if( tr1->GetID() < tr2->GetID() ) {
+ aMesh->ChangeElementNodes( tr1, n13, 4 );
+ myLastCreatedElems.Append(tr1);
+ aMesh->RemoveElement( tr3 );
+ }
+ else {
+ aMesh->ChangeElementNodes( tr3, n13, 4 );
+ myLastCreatedElems.Append(tr3);
+ aMesh->RemoveElement( tr1 );
+ }
+ }
+ else {
+ const SMDS_MeshNode* N1 [6];
+ 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)
+ // i.e. first nodes from both arrays determ new diagonal
+ const SMDS_MeshNode* aNodes[8];
+ aNodes[0] = N1[0];
+ aNodes[1] = N1[1];
+ aNodes[2] = N2[0];
+ aNodes[3] = N2[1];
+ aNodes[4] = N1[3];
+ aNodes[5] = N2[5];
+ aNodes[6] = N2[3];
+ aNodes[7] = N1[5];
+ if( tr1->GetID() < tr2->GetID() ) {
+ GetMeshDS()->ChangeElementNodes( tr1, aNodes, 8 );
+ myLastCreatedElems.Append(tr1);
+ GetMeshDS()->RemoveElement( tr3 );
+ }
+ else {
+ GetMeshDS()->ChangeElementNodes( tr3, aNodes, 8 );
+ myLastCreatedElems.Append(tr3);
+ GetMeshDS()->RemoveElement( tr1 );
+ }
+ // remove middle node (9)
+ GetMeshDS()->RemoveNode( N1[4] );
+ }
}
// Next element to fuse: the rejected one
// find surrounding nodes
set< const SMDS_MeshNode* > nodeSet;
- SMDS_ElemIteratorPtr elemIt = theNode->GetInverseElementIterator();
+ SMDS_ElemIteratorPtr elemIt = theNode->GetInverseElementIterator(SMDSAbs_Face);
while ( elemIt->more() )
{
const SMDS_MeshElement* elem = elemIt->next();
- if ( elem->GetType() != SMDSAbs_Face )
- continue;
- // put all nodes in array
- int nbNodes = 0, iNode = 0;
- vector< const SMDS_MeshNode*> aNodes( elem->NbNodes() );
- SMDS_ElemIteratorPtr itN = elem->nodesIterator();
- while ( itN->more() )
- {
- aNodes[ nbNodes ] = static_cast<const SMDS_MeshNode*>( itN->next() );
- if ( aNodes[ nbNodes ] == theNode )
- iNode = nbNodes; // index of theNode within aNodes
- nbNodes++;
+ 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;
+ }
}
- // add linked nodes
- int iAfter = ( iNode + 1 == nbNodes ) ? 0 : iNode + 1;
- nodeSet.insert( aNodes[ iAfter ]);
- int iBefore = ( iNode == 0 ) ? nbNodes - 1 : iNode - 1;
- nodeSet.insert( aNodes[ iBefore ]);
}
// compute new coodrs
// compute new XYZ
- SMDS_ElemIteratorPtr elemIt = theNode->GetInverseElementIterator();
+ SMDS_ElemIteratorPtr elemIt = theNode->GetInverseElementIterator(SMDSAbs_Face);
while ( elemIt->more() )
{
const SMDS_MeshElement* elem = elemIt->next();
- if ( elem->GetType() != SMDSAbs_Face )
- continue;
nbElems++;
gp_XYZ elemCenter(0.,0.,0.);
SMESH::Controls::TSequenceOfXYZ aNodePoints;
SMDS_ElemIteratorPtr itN = elem->nodesIterator();
- while ( itN->more() )
- {
+ int nn = elem->NbNodes();
+ if(elem->IsQuadratic()) nn = nn/2;
+ int i=0;
+ //while ( itN->more() ) {
+ while ( i<nn ) {
const SMDS_MeshNode* aNode = static_cast<const SMDS_MeshNode*>( itN->next() );
+ i++;
gp_XYZ aP( aNode->X(), aNode->Y(), aNode->Z() );
aNodePoints.push_back( aP );
if ( !theSurface.IsNull() ) { // smooth in 2D
}
double elemArea = anAreaFunc.GetValue( aNodePoints );
totalArea += elemArea;
- elemCenter /= elem->NbNodes();
+ elemCenter /= nn;
aNewXYZ += elemCenter * elemArea;
}
aNewXYZ /= totalArea;
if ( !theSurface.IsNull() ) {
- ASSERT( theUVMap.find( theNode ) != theUVMap.end() );
theUVMap[ theNode ]->SetCoord( aNewXYZ.X(), aNewXYZ.Y() );
aNewXYZ = theSurface->Value( aNewXYZ.X(), aNewXYZ.Y() ).XYZ();
}
// on edges and boundary nodes are always fixed.
//=======================================================================
-void SMESH_MeshEditor::Smooth (set<const SMDS_MeshElement*> & theElems,
- set<const SMDS_MeshNode*> & theFixedNodes,
- const SmoothMethod theSmoothMethod,
- const int theNbIterations,
- double theTgtAspectRatio,
- const bool the2D)
+void SMESH_MeshEditor::Smooth (TIDSortedElemSet & theElems,
+ set<const SMDS_MeshNode*> & theFixedNodes,
+ const SmoothMethod theSmoothMethod,
+ const int theNbIterations,
+ double theTgtAspectRatio,
+ const bool the2D)
{
+ myLastCreatedElems.Clear();
+ myLastCreatedNodes.Clear();
+
MESSAGE((theSmoothMethod==LAPLACIAN ? "LAPLACIAN" : "CENTROIDAL") << "--::Smooth()");
if ( theTgtAspectRatio < 1.0 )
theTgtAspectRatio = 1.0;
+ const double disttol = 1.e-16;
+
SMESH::Controls::AspectRatio aQualityFunc;
SMESHDS_Mesh* aMesh = GetMeshDS();
if ( theElems.empty() ) {
// add all faces to theElems
SMDS_FaceIteratorPtr fIt = aMesh->facesIterator();
- while ( fIt->more() )
- theElems.insert( fIt->next() );
+ while ( fIt->more() ) {
+ const SMDS_MeshElement* face = fIt->next();
+ theElems.insert( face );
+ }
}
// get all face ids theElems are on
set< int > faceIdSet;
- set< const SMDS_MeshElement* >::iterator itElem;
+ TIDSortedElemSet::iterator itElem;
if ( the2D )
for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ ) {
int fId = FindShape( *itElem );
// ===============================================
set< int >::reverse_iterator fId = faceIdSet.rbegin(); // treate 0 fId at the end
- for ( ; fId != faceIdSet.rend(); ++fId )
- {
+ for ( ; fId != faceIdSet.rend(); ++fId ) {
// get face surface and submesh
Handle(Geom_Surface) surface;
SMESHDS_SubMesh* faceSubMesh = 0;
// compute UV for them
// ---------------------------------------------------------
bool checkBoundaryNodes = false;
+ bool isQuadratic = false;
set<const SMDS_MeshNode*> setMovableNodes;
map< const SMDS_MeshNode*, gp_XY* > uvMap, uvMap2;
list< gp_XY > listUV; // uvs the 2 uvMaps refer to
int nbElemOnFace = 0;
itElem = theElems.begin();
// loop on not yet smoothed elements: look for elems on a face
- while ( itElem != theElems.end() )
- {
+ while ( itElem != theElems.end() ) {
if ( faceSubMesh && nbElemOnFace == faceSubMesh->NbElements() )
break; // all elements found
- const SMDS_MeshElement* elem = (*itElem);
+ const SMDS_MeshElement* elem = *itElem;
if ( !elem || elem->GetType() != SMDSAbs_Face || elem->NbNodes() < 3 ||
( faceSubMesh && !faceSubMesh->Contains( elem ))) {
++itElem;
theElems.erase( itElem++ );
nbElemOnFace++;
+ if ( !isQuadratic )
+ isQuadratic = elem->IsQuadratic();
+
// get movable nodes of elem
const SMDS_MeshNode* node;
SMDS_TypeOfPosition posType;
SMDS_ElemIteratorPtr itN = elem->nodesIterator();
- while ( itN->more() ) {
+ int nn = 0, nbn = elem->NbNodes();
+ if(elem->IsQuadratic())
+ nbn = nbn/2;
+ while ( nn++ < nbn ) {
node = static_cast<const SMDS_MeshNode*>( itN->next() );
const SMDS_PositionPtr& pos = node->GetPosition();
posType = pos.get() ? pos->GetTypeOfPosition() : SMDS_TOP_3DSPACE;
{
// check if all faces around the node are on faceSubMesh
// because a node on edge may be bound to face
- SMDS_ElemIteratorPtr eIt = node->GetInverseElementIterator();
+ SMDS_ElemIteratorPtr eIt = node->GetInverseElementIterator(SMDSAbs_Face);
bool all = true;
if ( faceSubMesh ) {
while ( eIt->more() && all ) {
const SMDS_MeshElement* e = eIt->next();
- if ( e->GetType() == SMDSAbs_Face )
- all = faceSubMesh->Contains( e );
+ all = faceSubMesh->Contains( e );
}
}
if ( all )
// get nodes to check UV
list< const SMDS_MeshNode* > uvCheckNodes;
itN = elem->nodesIterator();
- while ( itN->more() ) {
+ nn = 0; nbn = elem->NbNodes();
+ if(elem->IsQuadratic())
+ nbn = nbn/2;
+ while ( nn++ < nbn ) {
node = static_cast<const SMDS_MeshNode*>( itN->next() );
if ( uvMap.find( node ) == uvMap.end() )
uvCheckNodes.push_back( node );
// add nodes of elems sharing node
-// SMDS_ElemIteratorPtr eIt = node->GetInverseElementIterator();
+// SMDS_ElemIteratorPtr eIt = node->GetInverseElementIterator(SMDSAbs_Face);
// while ( eIt->more() ) {
// const SMDS_MeshElement* e = eIt->next();
-// if ( e != elem && e->GetType() == SMDSAbs_Face ) {
+// if ( e != elem ) {
// SMDS_ElemIteratorPtr nIt = e->nodesIterator();
// while ( nIt->more() ) {
// const SMDS_MeshNode* n =
}
// check UV on face
list< const SMDS_MeshNode* >::iterator n = uvCheckNodes.begin();
- for ( ; n != uvCheckNodes.end(); ++n )
- {
+ for ( ; n != uvCheckNodes.end(); ++n ) {
node = *n;
gp_XY uv( 0, 0 );
const SMDS_PositionPtr& pos = node->GetPosition();
// fix nodes on mesh boundary
- if ( checkBoundaryNodes )
- {
+ if ( checkBoundaryNodes ) {
typedef pair<const SMDS_MeshNode*, const SMDS_MeshNode*> TLink;
map< TLink, int > linkNbMap; // how many times a link encounters in elemsOnFace
map< TLink, int >::iterator link_nb;
// put all elements links to linkNbMap
list< const SMDS_MeshElement* >::iterator elemIt = elemsOnFace.begin();
- for ( ; elemIt != elemsOnFace.end(); ++elemIt )
- {
- // put elem nodes in array
- vector< const SMDS_MeshNode* > nodes;
- nodes.reserve( (*elemIt)->NbNodes() + 1 );
- SMDS_ElemIteratorPtr itN = (*elemIt)->nodesIterator();
- while ( itN->more() )
- nodes.push_back( static_cast<const SMDS_MeshNode*>( itN->next() ));
- nodes.push_back( nodes.front() );
+ for ( ; elemIt != elemsOnFace.end(); ++elemIt ) {
+ const SMDS_MeshElement* elem = (*elemIt);
+ int nbn = elem->NbNodes();
+ if(elem->IsQuadratic())
+ nbn = nbn/2;
// loop on elem links: insert them in linkNbMap
- for ( int iN = 1; iN < nodes.size(); ++iN ) {
+ const SMDS_MeshNode* curNode, *prevNode = elem->GetNode( nbn );
+ for ( int iN = 0; iN < nbn; ++iN ) {
+ curNode = elem->GetNode( iN );
TLink link;
- if ( nodes[ iN-1 ]->GetID() < nodes[ iN ]->GetID() )
- link = make_pair( nodes[ iN-1 ], nodes[ iN ] );
- else
- link = make_pair( nodes[ iN ], nodes[ iN-1 ] );
+ if ( curNode < prevNode ) link = make_pair( curNode , prevNode );
+ else link = make_pair( prevNode , curNode );
+ prevNode = curNode;
link_nb = linkNbMap.find( link );
if ( link_nb == linkNbMap.end() )
linkNbMap.insert( make_pair ( link, 1 ));
// -----------------------------------------------------
set<const SMDS_MeshNode*> nodesNearSeam; // to smooth using uvMap2
- if ( !surface.IsNull() )
- {
+ if ( !surface.IsNull() ) {
TopExp_Explorer eExp( face, TopAbs_EDGE );
- for ( ; eExp.More(); eExp.Next() )
- {
+ for ( ; eExp.More(); eExp.Next() ) {
TopoDS_Edge edge = TopoDS::Edge( eExp.Current() );
if ( !BRep_Tool::IsClosed( edge, face ))
continue;
// get nodes on seam and its vertices
list< const SMDS_MeshNode* > seamNodes;
SMDS_NodeIteratorPtr nSeamIt = sm->GetNodes();
- while ( nSeamIt->more() )
- seamNodes.push_back( nSeamIt->next() );
+ while ( nSeamIt->more() ) {
+ const SMDS_MeshNode* node = nSeamIt->next();
+ if ( !isQuadratic || !IsMedium( node ))
+ seamNodes.push_back( node );
+ }
TopExp_Explorer vExp( edge, TopAbs_VERTEX );
for ( ; vExp.More(); vExp.Next() ) {
sm = aMesh->MeshElements( vExp.Current() );
}
// loop on nodes on seam
list< const SMDS_MeshNode* >::iterator noSeIt = seamNodes.begin();
- for ( ; noSeIt != seamNodes.end(); ++noSeIt )
- {
+ for ( ; noSeIt != seamNodes.end(); ++noSeIt ) {
const SMDS_MeshNode* nSeam = *noSeIt;
map< const SMDS_MeshNode*, gp_XY* >::iterator n_uv = uvMap.find( nSeam );
if ( n_uv == uvMap.end() )
uvMap2[ nSeam ] = &listUV.back();
// collect movable nodes linked to ones on seam in nodesNearSeam
- SMDS_ElemIteratorPtr eIt = nSeam->GetInverseElementIterator();
- while ( eIt->more() )
- {
+ SMDS_ElemIteratorPtr eIt = nSeam->GetInverseElementIterator(SMDSAbs_Face);
+ while ( eIt->more() ) {
const SMDS_MeshElement* e = eIt->next();
- if ( e->GetType() != SMDSAbs_Face )
- continue;
int nbUseMap1 = 0, nbUseMap2 = 0;
SMDS_ElemIteratorPtr nIt = e->nodesIterator();
- while ( nIt->more() )
+ int nn = 0, nbn = e->NbNodes();
+ if(e->IsQuadratic()) nbn = nbn/2;
+ while ( nn++ < nbn )
{
const SMDS_MeshNode* n =
static_cast<const SMDS_MeshNode*>( nIt->next() );
}
// for centroidalSmooth all element nodes must
// be on one side of a seam
- if ( theSmoothMethod == CENTROIDAL && nbUseMap1 && nbUseMap2 )
- {
+ if ( theSmoothMethod == CENTROIDAL && nbUseMap1 && nbUseMap2 ) {
SMDS_ElemIteratorPtr nIt = e->nodesIterator();
- while ( nIt->more() ) {
+ nn = 0;
+ while ( nn++ < nbn ) {
const SMDS_MeshNode* n =
static_cast<const SMDS_MeshNode*>( nIt->next() );
setMovableNodes.erase( n );
int it = -1;
double maxRatio = -1., maxDisplacement = -1.;
set<const SMDS_MeshNode*>::iterator nodeToMove;
- for ( it = 0; it < theNbIterations; it++ )
- {
+ for ( it = 0; it < theNbIterations; it++ ) {
maxDisplacement = 0.;
nodeToMove = setMovableNodes.begin();
- for ( ; nodeToMove != setMovableNodes.end(); nodeToMove++ )
- {
+ for ( ; nodeToMove != setMovableNodes.end(); nodeToMove++ ) {
const SMDS_MeshNode* node = (*nodeToMove);
gp_XYZ aPrevPos ( node->X(), node->Y(), node->Z() );
maxDisplacement = aDispl;
}
// no node movement => exit
- if ( maxDisplacement < 1.e-16 ) {
+ //if ( maxDisplacement < 1.e-16 ) {
+ if ( maxDisplacement < disttol ) {
MESSAGE("-- no node movement --");
break;
}
// check elements quality
maxRatio = 0;
list< const SMDS_MeshElement* >::iterator elemIt = elemsOnFace.begin();
- for ( ; elemIt != elemsOnFace.end(); ++elemIt )
- {
+ for ( ; elemIt != elemsOnFace.end(); ++elemIt ) {
const SMDS_MeshElement* elem = (*elemIt);
if ( !elem || elem->GetType() != SMDSAbs_Face )
continue;
// new nodes positions are computed,
// record movement in DS and set new UV
// ---------------------------------------
-
nodeToMove = setMovableNodes.begin();
- for ( ; nodeToMove != setMovableNodes.end(); nodeToMove++ )
- {
+ for ( ; nodeToMove != setMovableNodes.end(); nodeToMove++ ) {
SMDS_MeshNode* node = const_cast< SMDS_MeshNode* > (*nodeToMove);
aMesh->MoveNode( node, node->X(), node->Y(), node->Z() );
map< const SMDS_MeshNode*, gp_XY* >::iterator node_uv = uvMap.find( node );
}
}
+ // move medium nodes of quadratic elements
+ if ( isQuadratic )
+ {
+ SMESH_MesherHelper helper( *GetMesh() );
+ if ( !face.IsNull() )
+ helper.SetSubShape( face );
+ list< const SMDS_MeshElement* >::iterator elemIt = elemsOnFace.begin();
+ for ( ; elemIt != elemsOnFace.end(); ++elemIt ) {
+ const SMDS_QuadraticFaceOfNodes* QF =
+ dynamic_cast<const SMDS_QuadraticFaceOfNodes*> (*elemIt);
+ if(QF) {
+ vector<const SMDS_MeshNode*> Ns;
+ Ns.reserve(QF->NbNodes()+1);
+ SMDS_NodeIteratorPtr anIter = QF->interlacedNodesIterator();
+ while ( anIter->more() )
+ Ns.push_back( anIter->next() );
+ Ns.push_back( Ns[0] );
+ double x, y, z;
+ for(int i=0; i<QF->NbNodes(); i=i+2) {
+ if ( !surface.IsNull() ) {
+ gp_XY uv1 = helper.GetNodeUV( face, Ns[i], Ns[i+2] );
+ 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();
+ }
+ else {
+ x = (Ns[i]->X() + Ns[i+2]->X())/2;
+ y = (Ns[i]->Y() + Ns[i+2]->Y())/2;
+ z = (Ns[i]->Z() + Ns[i+2]->Z())/2;
+ }
+ if( fabs( Ns[i+1]->X() - x ) > disttol ||
+ fabs( Ns[i+1]->Y() - y ) > disttol ||
+ fabs( Ns[i+1]->Z() - z ) > disttol ) {
+ // we have to move i+1 node
+ aMesh->MoveNode( Ns[i+1], x, y, z );
+ }
+ }
+ }
+ }
+ }
+
} // loop on face ids
+
}
//=======================================================================
static void sweepElement(SMESHDS_Mesh* aMesh,
const SMDS_MeshElement* elem,
const vector<TNodeOfNodeListMapItr> & newNodesItVec,
- list<const SMDS_MeshElement*>& newElems)
+ list<const SMDS_MeshElement*>& newElems,
+ const int nbSteps,
+ SMESH_SequenceOfElemPtr& myLastCreatedElems)
{
// Loop on elem nodes:
// find new nodes and detect same nodes indices
int nbNodes = elem->NbNodes();
list<const SMDS_MeshNode*>::const_iterator itNN[ nbNodes ];
- const SMDS_MeshNode* prevNod[ nbNodes ], *nextNod[ nbNodes ];
+ const SMDS_MeshNode* prevNod[ nbNodes ], *nextNod[ nbNodes ], *midlNod[ nbNodes ];
int iNode, nbSame = 0, iNotSameNode = 0, iSameNode = 0;
+ vector<int> sames(nbNodes);
- for ( iNode = 0; iNode < nbNodes; iNode++ )
- {
+ bool issimple[nbNodes];
+
+ for ( iNode = 0; iNode < nbNodes; iNode++ ) {
TNodeOfNodeListMapItr nnIt = newNodesItVec[ iNode ];
const SMDS_MeshNode* node = nnIt->first;
const list< const SMDS_MeshNode* > & listNewNodes = nnIt->second;
if ( listNewNodes.empty() )
return;
+ if(listNewNodes.size()==nbSteps) {
+ issimple[iNode] = true;
+ }
+ else {
+ issimple[iNode] = false;
+ }
+
itNN[ iNode ] = listNewNodes.begin();
prevNod[ iNode ] = node;
nextNod[ iNode ] = listNewNodes.front();
+//cout<<"iNode="<<iNode<<endl;
+//cout<<" prevNod[iNode]="<< prevNod[iNode]<<" nextNod[iNode]="<< nextNod[iNode]<<endl;
if ( prevNod[ iNode ] != nextNod [ iNode ])
iNotSameNode = iNode;
else {
iSameNode = iNode;
- nbSame++;
+ //nbSame++;
+ sames[nbSame++] = iNode;
}
}
+//cout<<"1 nbSame="<<nbSame<<endl;
if ( nbSame == nbNodes || nbSame > 2) {
MESSAGE( " Too many same nodes of element " << elem->GetID() );
return;
}
+// if( elem->IsQuadratic() && nbSame>0 ) {
+// MESSAGE( "Can not rotate quadratic element " << elem->GetID() );
+// return;
+// }
+
int iBeforeSame = 0, iAfterSame = 0, iOpposSame = 0;
if ( nbSame > 0 ) {
iBeforeSame = ( iSameNode == 0 ? nbNodes - 1 : iSameNode - 1 );
iOpposSame = ( iSameNode - 2 < 0 ? iSameNode + 2 : iSameNode - 2 );
}
+//if(nbNodes==8)
+//cout<<" prevNod[0]="<< prevNod[0]<<" prevNod[1]="<< prevNod[1]
+// <<" prevNod[2]="<< prevNod[2]<<" prevNod[3]="<< prevNod[4]
+// <<" prevNod[4]="<< prevNod[4]<<" prevNod[5]="<< prevNod[5]
+// <<" prevNod[6]="<< prevNod[6]<<" prevNod[7]="<< prevNod[7]<<endl;
+
// check element orientation
int i0 = 0, i2 = 2;
if ( nbNodes > 2 && !isReverse( prevNod, nextNod, nbNodes, iNotSameNode )) {
}
// make new elements
- int iStep, nbSteps = newNodesItVec[ 0 ]->second.size();
- for (iStep = 0; iStep < nbSteps; iStep++ )
- {
+ int iStep;//, nbSteps = newNodesItVec[ 0 ]->second.size();
+ for (iStep = 0; iStep < nbSteps; iStep++ ) {
// get next nodes
for ( iNode = 0; iNode < nbNodes; iNode++ ) {
- nextNod[ iNode ] = *itNN[ iNode ];
- itNN[ iNode ]++;
+ if(issimple[iNode]) {
+ nextNod[ iNode ] = *itNN[ iNode ];
+ itNN[ iNode ]++;
+ }
+ else {
+ if( elem->GetType()==SMDSAbs_Node ) {
+ // we have to use two nodes
+ midlNod[ iNode ] = *itNN[ iNode ];
+ itNN[ iNode ]++;
+ nextNod[ iNode ] = *itNN[ iNode ];
+ itNN[ iNode ]++;
+ }
+ else if(!elem->IsQuadratic() ||
+ elem->IsQuadratic() && elem->IsMediumNode(prevNod[iNode]) ) {
+ // we have to use each second node
+ itNN[ iNode ]++;
+ nextNod[ iNode ] = *itNN[ iNode ];
+ itNN[ iNode ]++;
+ }
+ else {
+ // we have to use two nodes
+ midlNod[ iNode ] = *itNN[ iNode ];
+ itNN[ iNode ]++;
+ nextNod[ iNode ] = *itNN[ iNode ];
+ itNN[ iNode ]++;
+ }
+ }
}
SMDS_MeshElement* aNewElem = 0;
- switch ( nbNodes )
- {
- case 0:
- return;
- case 1: { // NODE
- if ( nbSame == 0 )
- aNewElem = aMesh->AddEdge( prevNod[ 0 ], nextNod[ 0 ] );
- break;
- }
- case 2: { // EDGE
-
- if ( nbSame == 0 )
- aNewElem = aMesh->AddFace(prevNod[ 0 ], prevNod[ 1 ],
- nextNod[ 1 ], nextNod[ 0 ] );
- else
- aNewElem = aMesh->AddFace(prevNod[ 0 ], prevNod[ 1 ],
- nextNod[ iNotSameNode ] );
- break;
- }
- case 3: { // TRIANGLE
-
- if ( nbSame == 0 ) // --- pentahedron
- aNewElem = aMesh->AddVolume (prevNod[ i0 ], prevNod[ 1 ], prevNod[ i2 ],
- nextNod[ i0 ], nextNod[ 1 ], nextNod[ i2 ] );
+ if(!elem->IsPoly()) {
+ switch ( nbNodes ) {
+ case 0:
+ return;
+ case 1: { // NODE
+ if ( nbSame == 0 ) {
+ if(issimple[0])
+ aNewElem = aMesh->AddEdge( prevNod[ 0 ], nextNod[ 0 ] );
+ else
+ aNewElem = aMesh->AddEdge( prevNod[ 0 ], nextNod[ 0 ], midlNod[ 0 ] );
+ }
+ break;
+ }
+ case 2: { // EDGE
+ if ( nbSame == 0 )
+ aNewElem = aMesh->AddFace(prevNod[ 0 ], prevNod[ 1 ],
+ nextNod[ 1 ], nextNod[ 0 ] );
+ else
+ aNewElem = aMesh->AddFace(prevNod[ 0 ], prevNod[ 1 ],
+ nextNod[ iNotSameNode ] );
+ break;
+ }
- else if ( nbSame == 1 ) // --- pyramid
- aNewElem = aMesh->AddVolume (prevNod[ iBeforeSame ], prevNod[ iAfterSame ],
- nextNod[ iAfterSame ], nextNod[ iBeforeSame ],
- nextNod[ iSameNode ]);
+ case 3: { // TRIANGLE or quadratic edge
+ if(elem->GetType() == SMDSAbs_Face) { // TRIANGLE
- else // 2 same nodes: --- tetrahedron
- aNewElem = aMesh->AddVolume (prevNod[ i0 ], prevNod[ 1 ], prevNod[ i2 ],
- nextNod[ iNotSameNode ]);
- break;
- }
- case 4: { // QUADRANGLE
+ if ( nbSame == 0 ) // --- pentahedron
+ aNewElem = aMesh->AddVolume (prevNod[ i0 ], prevNod[ 1 ], prevNod[ i2 ],
+ nextNod[ i0 ], nextNod[ 1 ], nextNod[ i2 ] );
- 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
+ aNewElem = aMesh->AddVolume (prevNod[ iBeforeSame ], prevNod[ iAfterSame ],
+ nextNod[ iAfterSame ], nextNod[ iBeforeSame ],
+ nextNod[ iSameNode ]);
- else if ( nbSame == 1 ) // --- pyramid + pentahedron
- {
- aNewElem = aMesh->AddVolume (prevNod[ iBeforeSame ], prevNod[ iAfterSame ],
- nextNod[ iAfterSame ], nextNod[ iBeforeSame ],
- nextNod[ iSameNode ]);
- newElems.push_back( aNewElem );
- aNewElem = aMesh->AddVolume (prevNod[ iAfterSame ], prevNod[ iOpposSame ],
- prevNod[ iBeforeSame ], nextNod[ iAfterSame ],
- nextNod[ iOpposSame ], nextNod[ iBeforeSame ] );
- }
- else if ( nbSame == 2 ) // pentahedron
- {
- if ( prevNod[ iBeforeSame ] == nextNod[ iBeforeSame ] )
- // iBeforeSame is same too
- aNewElem = aMesh->AddVolume (prevNod[ iBeforeSame ], prevNod[ iOpposSame ],
- nextNod[ iOpposSame ], prevNod[ iSameNode ],
- prevNod[ iAfterSame ], nextNod[ iAfterSame ]);
- else
- // iAfterSame is same too
- aNewElem = aMesh->AddVolume (prevNod[ iSameNode ], prevNod[ iBeforeSame ],
- nextNod[ iBeforeSame ], prevNod[ iAfterSame ],
- prevNod[ iOpposSame ], nextNod[ iOpposSame ]);
+ else // 2 same nodes: --- tetrahedron
+ aNewElem = aMesh->AddVolume (prevNod[ i0 ], prevNod[ 1 ], prevNod[ i2 ],
+ nextNod[ iNotSameNode ]);
+ }
+ else { // quadratic edge
+ if(nbSame==0) { // quadratic quadrangle
+ aNewElem = aMesh->AddFace(prevNod[0], nextNod[0], nextNod[1], prevNod[1],
+ midlNod[0], nextNod[2], midlNod[1], prevNod[2]);
+ }
+ else if(nbSame==1) { // quadratic triangle
+ if(sames[0]==2)
+ return; // medium node on axis
+ else if(sames[0]==0) {
+ aNewElem = aMesh->AddFace(prevNod[0], nextNod[1], prevNod[1],
+ nextNod[2], midlNod[1], prevNod[2]);
+ }
+ else { // sames[0]==1
+ aNewElem = aMesh->AddFace(prevNod[0], nextNod[0], prevNod[1],
+ midlNod[0], nextNod[2], prevNod[2]);
+ }
+ }
+ else
+ return;
+ }
+ break;
+ }
+ case 4: { // QUADRANGLE
+
+ 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 ],
+ nextNod[ iSameNode ]);
+ newElems.push_back( aNewElem );
+ aNewElem = aMesh->AddVolume (prevNod[ iAfterSame ], prevNod[ iOpposSame ],
+ prevNod[ iBeforeSame ], nextNod[ iAfterSame ],
+ nextNod[ iOpposSame ], nextNod[ iBeforeSame ] );
+ }
+ else if ( nbSame == 2 ) { // pentahedron
+ if ( prevNod[ iBeforeSame ] == nextNod[ iBeforeSame ] )
+ // iBeforeSame is same too
+ aNewElem = aMesh->AddVolume (prevNod[ iBeforeSame ], prevNod[ iOpposSame ],
+ nextNod[ iOpposSame ], prevNod[ iSameNode ],
+ prevNod[ iAfterSame ], nextNod[ iAfterSame ]);
+ else
+ // iAfterSame is same too
+ aNewElem = aMesh->AddVolume (prevNod[ iSameNode ], prevNod[ iBeforeSame ],
+ nextNod[ iBeforeSame ], prevNod[ iAfterSame ],
+ prevNod[ iOpposSame ], nextNod[ iOpposSame ]);
+ }
+ break;
+ }
+ case 6: { // quadratic triangle
+ // create pentahedron with 15 nodes
+ if(i0>0) { // reversed case
+ aNewElem = aMesh->AddVolume (prevNod[0], prevNod[2], prevNod[1],
+ nextNod[0], nextNod[2], nextNod[1],
+ prevNod[5], prevNod[4], prevNod[3],
+ nextNod[5], nextNod[4], nextNod[3],
+ midlNod[0], midlNod[2], midlNod[1]);
+ }
+ else { // not reversed case
+ aNewElem = aMesh->AddVolume (prevNod[0], prevNod[1], prevNod[2],
+ nextNod[0], nextNod[1], nextNod[2],
+ prevNod[3], prevNod[4], prevNod[5],
+ nextNod[3], nextNod[4], nextNod[5],
+ midlNod[0], midlNod[1], midlNod[2]);
+ }
+ break;
+ }
+ case 8: { // quadratic quadrangle
+ // create hexahedron with 20 nodes
+ if(i0>0) { // reversed case
+ aNewElem = aMesh->AddVolume (prevNod[0], prevNod[3], prevNod[2], prevNod[1],
+ nextNod[0], nextNod[3], nextNod[2], nextNod[1],
+ prevNod[7], prevNod[6], prevNod[5], prevNod[4],
+ nextNod[7], nextNod[6], nextNod[5], nextNod[4],
+ midlNod[0], midlNod[3], midlNod[2], midlNod[1]);
+ }
+ else { // not reversed case
+ aNewElem = aMesh->AddVolume (prevNod[0], prevNod[1], prevNod[2], prevNod[3],
+ nextNod[0], nextNod[1], nextNod[2], nextNod[3],
+ prevNod[4], prevNod[5], prevNod[6], prevNod[7],
+ nextNod[4], nextNod[5], nextNod[6], nextNod[7],
+ midlNod[0], midlNod[1], midlNod[2], midlNod[3]);
+ }
+ break;
+ }
+ default: {
+ // 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];
+ //}
+
+ //quantities[1] = nbNodes; // top of prism
+ //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;
+ // polyedre_nodes[2*nbNodes + 4*iface + 0] = prevNod[iface];
+ // polyedre_nodes[2*nbNodes + 4*iface + 1] = prevNod[inextface];
+ // polyedre_nodes[2*nbNodes + 4*iface + 2] = nextNod[inextface];
+ // polyedre_nodes[2*nbNodes + 4*iface + 3] = nextNod[iface];
+ //}
+ //aNewElem = aMesh->AddPolyhedralVolume (polyedre_nodes, quantities);
+ break;
+ }
}
- break;
}
- default: {
+
+ if(!aNewElem) {
// realized for extrusion only
vector<const SMDS_MeshNode*> polyedre_nodes (nbNodes*2 + 4*nbNodes);
vector<int> quantities (nbNodes + 2);
}
aNewElem = aMesh->AddPolyhedralVolume (polyedre_nodes, quantities);
}
- }
- if ( aNewElem )
+
+ if ( aNewElem ) {
newElems.push_back( aNewElem );
+ myLastCreatedElems.Append(aNewElem);
+ }
// set new prev nodes
for ( iNode = 0; iNode < nbNodes; iNode++ )
//purpose : create 1D and 2D elements around swept elements
//=======================================================================
-static void makeWalls (SMESHDS_Mesh* aMesh,
- TNodeOfNodeListMap & mapNewNodes,
- TElemOfElemListMap & newElemsMap,
- TElemOfVecOfNnlmiMap & elemNewNodesMap,
- set<const SMDS_MeshElement*>& elemSet)
+static void makeWalls (SMESHDS_Mesh* aMesh,
+ TNodeOfNodeListMap & mapNewNodes,
+ TElemOfElemListMap & newElemsMap,
+ TElemOfVecOfNnlmiMap & elemNewNodesMap,
+ TIDSortedElemSet& elemSet,
+ const int nbSteps,
+ SMESH_SequenceOfElemPtr& myLastCreatedElems)
{
ASSERT( newElemsMap.size() == elemNewNodesMap.size() );
// Find nodes belonging to only one initial element - sweep them to get edges.
TNodeOfNodeListMapItr nList = mapNewNodes.begin();
- for ( ; nList != mapNewNodes.end(); nList++ )
- {
+ for ( ; nList != mapNewNodes.end(); nList++ ) {
const SMDS_MeshNode* node =
static_cast<const SMDS_MeshNode*>( nList->first );
SMDS_ElemIteratorPtr eIt = node->GetInverseElementIterator();
int nbInitElems = 0;
- while ( eIt->more() && nbInitElems < 2 )
- if ( elemSet.find( eIt->next() ) != elemSet.end() )
+ const SMDS_MeshElement* el = 0;
+ SMDSAbs_ElementType highType = SMDSAbs_Edge; // count most complex elements only
+ while ( eIt->more() && nbInitElems < 2 ) {
+ el = eIt->next();
+ SMDSAbs_ElementType type = el->GetType();
+ if ( type == SMDSAbs_Volume || type < highType ) continue;
+ if ( type > highType ) {
+ nbInitElems = 0;
+ highType = type;
+ }
+ if ( elemSet.find(el) != elemSet.end() )
nbInitElems++;
+ }
if ( nbInitElems < 2 ) {
- vector<TNodeOfNodeListMapItr> newNodesItVec( 1, nList );
- list<const SMDS_MeshElement*> newEdges;
- sweepElement( aMesh, node, newNodesItVec, newEdges );
+ bool NotCreateEdge = el && el->IsQuadratic() && el->IsMediumNode(node);
+ if(!NotCreateEdge) {
+ vector<TNodeOfNodeListMapItr> newNodesItVec( 1, nList );
+ list<const SMDS_MeshElement*> newEdges;
+ sweepElement( aMesh, node, newNodesItVec, newEdges, nbSteps, myLastCreatedElems );
+ }
}
}
TElemOfElemListMap::iterator itElem = newElemsMap.begin();
TElemOfVecOfNnlmiMap::iterator itElemNodes = elemNewNodesMap.begin();
- for ( ; itElem != newElemsMap.end(); itElem++, itElemNodes++ )
- {
+ for ( ; itElem != newElemsMap.end(); itElem++, itElemNodes++ ) {
const SMDS_MeshElement* elem = itElem->first;
vector<TNodeOfNodeListMapItr>& vecNewNodes = itElemNodes->second;
- if ( elem->GetType() == SMDSAbs_Edge )
- {
+ if ( elem->GetType() == SMDSAbs_Edge ) {
// create a ceiling edge
- aMesh->AddEdge(vecNewNodes[ 0 ]->second.back(),
- vecNewNodes[ 1 ]->second.back() );
+ if (!elem->IsQuadratic()) {
+ if ( !aMesh->FindEdge( vecNewNodes[ 0 ]->second.back(),
+ vecNewNodes[ 1 ]->second.back()))
+ myLastCreatedElems.Append(aMesh->AddEdge(vecNewNodes[ 0 ]->second.back(),
+ vecNewNodes[ 1 ]->second.back()));
+ }
+ else {
+ if ( !aMesh->FindEdge( vecNewNodes[ 0 ]->second.back(),
+ vecNewNodes[ 1 ]->second.back(),
+ vecNewNodes[ 2 ]->second.back()))
+ myLastCreatedElems.Append(aMesh->AddEdge(vecNewNodes[ 0 ]->second.back(),
+ vecNewNodes[ 1 ]->second.back(),
+ vecNewNodes[ 2 ]->second.back()));
+ }
}
if ( elem->GetType() != SMDSAbs_Face )
continue;
+ if(itElem->second.size()==0) continue;
+
bool hasFreeLinks = false;
- set<const SMDS_MeshElement*> avoidSet;
+ TIDSortedElemSet avoidSet;
avoidSet.insert( elem );
- // loop on a face nodes
set<const SMDS_MeshNode*> aFaceLastNodes;
int iNode, nbNodes = vecNewNodes.size();
- for ( iNode = 0; iNode < nbNodes; iNode++ )
- {
- aFaceLastNodes.insert( vecNewNodes[ iNode ]->second.back() );
- // look for free links of a face
- int iNext = ( iNode + 1 == nbNodes ) ? 0 : iNode + 1;
- const SMDS_MeshNode* n1 = vecNewNodes[ iNode ]->first;
- const SMDS_MeshNode* n2 = vecNewNodes[ iNext ]->first;
- // check if a link is free
- if ( ! SMESH_MeshEditor::FindFaceInSet ( n1, n2, elemSet, avoidSet ))
- {
- hasFreeLinks = true;
- // make an edge and a ceiling for a new edge
- if ( !aMesh->FindEdge( n1, n2 ))
- aMesh->AddEdge( n1, n2 );
- n1 = vecNewNodes[ iNode ]->second.back();
- n2 = vecNewNodes[ iNext ]->second.back();
- if ( !aMesh->FindEdge( n1, n2 ))
- aMesh->AddEdge( n1, n2 );
+ if(!elem->IsQuadratic()) {
+ // loop on the face nodes
+ for ( iNode = 0; iNode < nbNodes; iNode++ ) {
+ aFaceLastNodes.insert( vecNewNodes[ iNode ]->second.back() );
+ // look for free links of the face
+ int iNext = ( iNode + 1 == nbNodes ) ? 0 : iNode + 1;
+ const SMDS_MeshNode* n1 = vecNewNodes[ iNode ]->first;
+ const SMDS_MeshNode* n2 = vecNewNodes[ iNext ]->first;
+ // check if a link is free
+ if ( ! SMESH_MeshEditor::FindFaceInSet ( n1, n2, elemSet, avoidSet )) {
+ hasFreeLinks = true;
+ // make an edge and a ceiling for a new edge
+ if ( !aMesh->FindEdge( n1, n2 )) {
+ myLastCreatedElems.Append(aMesh->AddEdge( n1, n2 ));
+ }
+ n1 = vecNewNodes[ iNode ]->second.back();
+ n2 = vecNewNodes[ iNext ]->second.back();
+ if ( !aMesh->FindEdge( n1, n2 )) {
+ myLastCreatedElems.Append(aMesh->AddEdge( n1, n2 ));
+ }
+ }
+ }
+ }
+ else { // elem is quadratic face
+ int nbn = nbNodes/2;
+ for ( iNode = 0; iNode < nbn; iNode++ ) {
+ aFaceLastNodes.insert( vecNewNodes[ iNode ]->second.back() );
+ int iNext = ( iNode + 1 == nbn ) ? 0 : iNode + 1;
+ const SMDS_MeshNode* n1 = vecNewNodes[ iNode ]->first;
+ const SMDS_MeshNode* n2 = vecNewNodes[ iNext ]->first;
+ // check if a link is free
+ if ( ! SMESH_MeshEditor::FindFaceInSet ( n1, n2, elemSet, avoidSet )) {
+ hasFreeLinks = true;
+ // make an edge and a ceiling for a new edge
+ // find medium node
+ const SMDS_MeshNode* n3 = vecNewNodes[ iNode+nbn ]->first;
+ if ( !aMesh->FindEdge( n1, n2, n3 )) {
+ myLastCreatedElems.Append(aMesh->AddEdge( n1, n2, n3 ));
+ }
+ n1 = vecNewNodes[ iNode ]->second.back();
+ n2 = vecNewNodes[ iNext ]->second.back();
+ n3 = vecNewNodes[ iNode+nbn ]->second.back();
+ if ( !aMesh->FindEdge( n1, n2, n3 )) {
+ myLastCreatedElems.Append(aMesh->AddEdge( n1, n2, n3 ));
+ }
+ }
+ }
+ for ( iNode = nbn; iNode < 2*nbn; iNode++ ) {
+ aFaceLastNodes.insert( vecNewNodes[ iNode ]->second.back() );
}
}
+
// sweep free links into faces
- if ( hasFreeLinks )
- {
+ if ( hasFreeLinks ) {
list<const SMDS_MeshElement*> & newVolumes = itElem->second;
- int iStep, nbSteps = vecNewNodes[0]->second.size();
+ int iStep; //, nbSteps = vecNewNodes[0]->second.size();
int iVol, volNb, nbVolumesByStep = newVolumes.size() / nbSteps;
set<const SMDS_MeshNode*> initNodeSet, faceNodeSet;
for ( iNode = 0; iNode < nbNodes; iNode++ )
initNodeSet.insert( vecNewNodes[ iNode ]->first );
- for ( volNb = 0; volNb < nbVolumesByStep; volNb++ )
- {
+ for ( volNb = 0; volNb < nbVolumesByStep; volNb++ ) {
list<const SMDS_MeshElement*>::iterator v = newVolumes.begin();
iVol = 0;
while ( iVol++ < volNb ) v++;
list< int > fInd;
SMDS_VolumeTool vTool( *v );
int iF, nbF = vTool.NbFaces();
- for ( iF = 0; iF < nbF; iF ++ )
+ for ( iF = 0; iF < nbF; iF ++ ) {
if (vTool.IsFreeFace( iF ) &&
vTool.GetFaceNodes( iF, faceNodeSet ) &&
initNodeSet != faceNodeSet) // except an initial face
fInd.push_back( iF );
+ }
if ( fInd.empty() )
continue;
// create faces for all steps
- for ( iStep = 0; iStep < nbSteps; iStep++ )
- {
+ // if such a face has been already created by sweep of edge, assure that its orientation is OK
+ for ( iStep = 0; iStep < nbSteps; iStep++ ) {
vTool.Set( *v );
vTool.SetExternalNormal();
list< int >::iterator ind = fInd.begin();
- for ( ; ind != fInd.end(); ind++ )
- {
+ for ( ; ind != fInd.end(); ind++ ) {
const SMDS_MeshNode** nodes = vTool.GetFaceNodes( *ind );
- switch ( vTool.NbFaceNodes( *ind ) ) {
- case 3:
- aMesh->AddFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ] ); break;
- case 4:
- aMesh->AddFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ], nodes[ 3 ] ); break;
+ int nbn = vTool.NbFaceNodes( *ind );
+ switch ( nbn ) {
+ case 3: { ///// triangle
+ const SMDS_MeshFace * f = aMesh->FindFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ]);
+ if ( !f )
+ myLastCreatedElems.Append(aMesh->AddFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ] ));
+ else if ( nodes[ 1 ] != f->GetNode( f->GetNodeIndex( nodes[ 0 ] ) + 1 ))
+ aMesh->ChangeElementNodes( f, nodes, nbn );
+ break;
+ }
+ case 4: { ///// quadrangle
+ const SMDS_MeshFace * f = aMesh->FindFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ], nodes[ 3 ]);
+ if ( !f )
+ myLastCreatedElems.Append(aMesh->AddFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ], nodes[ 3 ] ));
+ else if ( nodes[ 1 ] != f->GetNode( f->GetNodeIndex( nodes[ 0 ] ) + 1 ))
+ aMesh->ChangeElementNodes( f, nodes, nbn );
+ break;
+ }
default:
- {
- int nbPolygonNodes = vTool.NbFaceNodes( *ind );
- vector<const SMDS_MeshNode*> polygon_nodes (nbPolygonNodes);
- for (int inode = 0; inode < nbPolygonNodes; inode++) {
- polygon_nodes[inode] = nodes[inode];
+ if( (*v)->IsQuadratic() ) {
+ if(nbn==6) { /////// quadratic triangle
+ const SMDS_MeshFace * f = aMesh->FindFace( nodes[0], nodes[2], nodes[4],
+ nodes[1], nodes[3], nodes[5] );
+ if ( !f )
+ myLastCreatedElems.Append(aMesh->AddFace(nodes[0], nodes[2], nodes[4],
+ nodes[1], nodes[3], nodes[5]));
+ else if ( nodes[ 2 ] != f->GetNode( f->GetNodeIndex( nodes[ 0 ] ) + 1 ))
+ aMesh->ChangeElementNodes( f, nodes, nbn );
}
- aMesh->AddPolygonalFace(polygon_nodes);
- break;
+ else { /////// quadratic quadrangle
+ const SMDS_MeshFace * f = aMesh->FindFace( nodes[0], nodes[2], nodes[4], nodes[6],
+ nodes[1], nodes[3], nodes[5], nodes[7] );
+ if ( !f )
+ myLastCreatedElems.Append(aMesh->AddFace(nodes[0], nodes[2], nodes[4], nodes[6],
+ nodes[1], nodes[3], nodes[5], nodes[7]));
+ else if ( nodes[ 2 ] != f->GetNode( f->GetNodeIndex( nodes[ 0 ] ) + 1 ))
+ aMesh->ChangeElementNodes( f, nodes, nbn );
+ }
+ }
+ else { //////// polygon
+ vector<const SMDS_MeshNode*> polygon_nodes ( nodes, &nodes[nbn] );
+ const SMDS_MeshFace * f = aMesh->FindFace( polygon_nodes );
+ if ( !f )
+ myLastCreatedElems.Append(aMesh->AddPolygonalFace(polygon_nodes));
+ else if ( nodes[ 1 ] != f->GetNode( f->GetNodeIndex( nodes[ 0 ] ) + 1 ))
+ aMesh->ChangeElementNodes( f, nodes, nbn );
}
}
}
// make a ceiling face with a normal external to a volume
SMDS_VolumeTool lastVol( itElem->second.back() );
+
int iF = lastVol.GetFaceIndex( aFaceLastNodes );
- if ( iF >= 0 )
- {
+ if ( iF >= 0 ) {
lastVol.SetExternalNormal();
const SMDS_MeshNode** nodes = lastVol.GetFaceNodes( iF );
- switch ( lastVol.NbFaceNodes( iF ) ) {
+ int nbn = lastVol.NbFaceNodes( iF );
+ switch ( nbn ) {
case 3:
if (!hasFreeLinks ||
!aMesh->FindFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ]))
- aMesh->AddFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ] );
+ myLastCreatedElems.Append(aMesh->AddFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ] ));
break;
case 4:
if (!hasFreeLinks ||
!aMesh->FindFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ], nodes[ 3 ]))
- aMesh->AddFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ], nodes[ 3 ] );
+ myLastCreatedElems.Append(aMesh->AddFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ], nodes[ 3 ] ));
break;
default:
- {
- int nbPolygonNodes = lastVol.NbFaceNodes( iF );
- vector<const SMDS_MeshNode*> polygon_nodes (nbPolygonNodes);
- for (int inode = 0; inode < nbPolygonNodes; inode++) {
- polygon_nodes[inode] = nodes[inode];
+ if(itElem->second.back()->IsQuadratic()) {
+ if(nbn==6) {
+ if (!hasFreeLinks ||
+ !aMesh->FindFace(nodes[0], nodes[2], nodes[4],
+ nodes[1], nodes[3], nodes[5]) ) {
+ myLastCreatedElems.Append(aMesh->AddFace(nodes[0], nodes[2], nodes[4],
+ nodes[1], nodes[3], nodes[5]));
+ }
}
+ else { // nbn==8
+ if (!hasFreeLinks ||
+ !aMesh->FindFace(nodes[0], nodes[2], nodes[4], nodes[6],
+ nodes[1], nodes[3], nodes[5], nodes[7]) )
+ myLastCreatedElems.Append(aMesh->AddFace(nodes[0], nodes[2], nodes[4], nodes[6],
+ nodes[1], nodes[3], nodes[5], nodes[7]));
+ }
+ }
+ else {
+ vector<const SMDS_MeshNode*> polygon_nodes ( nodes, &nodes[nbn] );
if (!hasFreeLinks || !aMesh->FindFace(polygon_nodes))
- aMesh->AddPolygonalFace(polygon_nodes);
+ myLastCreatedElems.Append(aMesh->AddPolygonalFace(polygon_nodes));
}
- break;
- }
+ } // switch
}
-
} // loop on swept elements
}
//purpose :
//=======================================================================
-void SMESH_MeshEditor::RotationSweep(set<const SMDS_MeshElement*> & theElems,
- const gp_Ax1& theAxis,
- const double theAngle,
- const int theNbSteps,
- const double theTol)
+void SMESH_MeshEditor::RotationSweep(TIDSortedElemSet & theElems,
+ const gp_Ax1& theAxis,
+ const double theAngle,
+ const int theNbSteps,
+ const double theTol)
{
+ myLastCreatedElems.Clear();
+ myLastCreatedNodes.Clear();
+
MESSAGE( "RotationSweep()");
gp_Trsf aTrsf;
aTrsf.SetRotation( theAxis, theAngle );
+ gp_Trsf aTrsf2;
+ aTrsf2.SetRotation( theAxis, theAngle/2. );
gp_Lin aLine( theAxis );
double aSqTol = theTol * theTol;
TElemOfElemListMap newElemsMap;
// loop on theElems
- set< const SMDS_MeshElement* >::iterator itElem;
- for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ )
- {
- const SMDS_MeshElement* elem = (*itElem);
- if ( !elem )
+ TIDSortedElemSet::iterator itElem;
+ for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ ) {
+ const SMDS_MeshElement* elem = *itElem;
+ if ( !elem || elem->GetType() == SMDSAbs_Volume )
continue;
vector<TNodeOfNodeListMapItr> & newNodesItVec = mapElemNewNodes[ elem ];
newNodesItVec.reserve( elem->NbNodes() );
const SMDS_MeshNode* node =
static_cast<const SMDS_MeshNode*>( itN->next() );
TNodeOfNodeListMapItr nIt = mapNewNodes.find( node );
- if ( nIt == mapNewNodes.end() )
- {
+ if ( nIt == mapNewNodes.end() ) {
nIt = mapNewNodes.insert( make_pair( node, list<const SMDS_MeshNode*>() )).first;
list<const SMDS_MeshNode*>& listNewNodes = nIt->second;
const SMDS_MeshNode * newNode = node;
for ( int i = 0; i < theNbSteps; i++ ) {
if ( !isOnAxis ) {
- aTrsf.Transforms( coord[0], coord[1], coord[2] );
+ if( elem->IsQuadratic() && !elem->IsMediumNode(node) ) {
+ // create two nodes
+ aTrsf2.Transforms( coord[0], coord[1], coord[2] );
+ //aTrsf.Transforms( coord[0], coord[1], coord[2] );
+ newNode = aMesh->AddNode( coord[0], coord[1], coord[2] );
+ myLastCreatedNodes.Append(newNode);
+ listNewNodes.push_back( newNode );
+ aTrsf2.Transforms( coord[0], coord[1], coord[2] );
+ //aTrsf.Transforms( coord[0], coord[1], coord[2] );
+ }
+ else {
+ aTrsf.Transforms( coord[0], coord[1], coord[2] );
+ }
newNode = aMesh->AddNode( coord[0], coord[1], coord[2] );
+ myLastCreatedNodes.Append(newNode);
}
listNewNodes.push_back( newNode );
}
}
+ else {
+ // if current elem is quadratic and current node is not medium
+ // we have to check - may be it is needed to insert additional nodes
+ if( elem->IsQuadratic() && !elem->IsMediumNode(node) ) {
+ list< const SMDS_MeshNode* > & listNewNodes = nIt->second;
+ if(listNewNodes.size()==theNbSteps) {
+ listNewNodes.clear();
+ // make new nodes
+ gp_XYZ aXYZ( node->X(), node->Y(), node->Z() );
+ double coord[3];
+ aXYZ.Coord( coord[0], coord[1], coord[2] );
+ const SMDS_MeshNode * newNode = node;
+ for(int i = 0; i<theNbSteps; i++) {
+ aTrsf2.Transforms( coord[0], coord[1], coord[2] );
+ newNode = aMesh->AddNode( coord[0], coord[1], coord[2] );
+ myLastCreatedNodes.Append(newNode);
+ listNewNodes.push_back( newNode );
+ aTrsf2.Transforms( coord[0], coord[1], coord[2] );
+ newNode = aMesh->AddNode( coord[0], coord[1], coord[2] );
+ myLastCreatedNodes.Append(newNode);
+ listNewNodes.push_back( newNode );
+ }
+ }
+ }
+ }
newNodesItVec.push_back( nIt );
}
// make new elements
- sweepElement( aMesh, elem, newNodesItVec, newElemsMap[elem] );
+ sweepElement( aMesh, elem, newNodesItVec, newElemsMap[elem], theNbSteps, myLastCreatedElems );
}
- makeWalls( aMesh, mapNewNodes, newElemsMap, mapElemNewNodes, theElems );
+ makeWalls( aMesh, mapNewNodes, newElemsMap, mapElemNewNodes, theElems, theNbSteps, myLastCreatedElems );
+
+}
+
+
+//=======================================================================
+//function : CreateNode
+//purpose :
+//=======================================================================
+const SMDS_MeshNode* SMESH_MeshEditor::CreateNode(const double x,
+ const double y,
+ const double z,
+ const double tolnode,
+ SMESH_SequenceOfNode& aNodes)
+{
+ myLastCreatedElems.Clear();
+ myLastCreatedNodes.Clear();
+
+ gp_Pnt P1(x,y,z);
+ SMESHDS_Mesh * aMesh = myMesh->GetMeshDS();
+
+ // try to search in sequence of existing nodes
+ // if aNodes.Length()>0 we 'nave to use given sequence
+ // else - use all nodes of mesh
+ if(aNodes.Length()>0) {
+ int i;
+ for(i=1; i<=aNodes.Length(); i++) {
+ gp_Pnt P2(aNodes.Value(i)->X(),aNodes.Value(i)->Y(),aNodes.Value(i)->Z());
+ if(P1.Distance(P2)<tolnode)
+ return aNodes.Value(i);
+ }
+ }
+ else {
+ SMDS_NodeIteratorPtr itn = aMesh->nodesIterator();
+ while(itn->more()) {
+ const SMDS_MeshNode* aN = static_cast<const SMDS_MeshNode*> (itn->next());
+ gp_Pnt P2(aN->X(),aN->Y(),aN->Z());
+ if(P1.Distance(P2)<tolnode)
+ return aN;
+ }
+ }
+ // create new node and return it
+ const SMDS_MeshNode* NewNode = aMesh->AddNode(x,y,z);
+ myLastCreatedNodes.Append(NewNode);
+ return NewNode;
}
+
+
//=======================================================================
//function : ExtrusionSweep
//purpose :
//=======================================================================
-void SMESH_MeshEditor::ExtrusionSweep(set<const SMDS_MeshElement*> & theElems,
- const gp_Vec& theStep,
- const int theNbSteps)
+void SMESH_MeshEditor::ExtrusionSweep (TIDSortedElemSet & theElems,
+ const gp_Vec& theStep,
+ const int theNbSteps,
+ TElemOfElemListMap& newElemsMap,
+ const int theFlags,
+ const double theTolerance)
{
- gp_Trsf aTrsf;
- aTrsf.SetTranslation( theStep );
+ ExtrusParam aParams;
+ aParams.myDir = gp_Dir(theStep);
+ aParams.myNodes.Clear();
+ aParams.mySteps = new TColStd_HSequenceOfReal;
+ int i;
+ for(i=1; i<=theNbSteps; i++)
+ aParams.mySteps->Append(theStep.Magnitude());
+
+ ExtrusionSweep(theElems,aParams,newElemsMap,theFlags,theTolerance);
+
+}
+
+
+//=======================================================================
+//function : ExtrusionSweep
+//purpose :
+//=======================================================================
+
+void SMESH_MeshEditor::ExtrusionSweep (TIDSortedElemSet & theElems,
+ ExtrusParam& theParams,
+ TElemOfElemListMap& newElemsMap,
+ const int theFlags,
+ const double theTolerance)
+{
+ myLastCreatedElems.Clear();
+ myLastCreatedNodes.Clear();
SMESHDS_Mesh* aMesh = GetMeshDS();
+ int nbsteps = theParams.mySteps->Length();
+
TNodeOfNodeListMap mapNewNodes;
+ //TNodeOfNodeVecMap mapNewNodes;
TElemOfVecOfNnlmiMap mapElemNewNodes;
- TElemOfElemListMap newElemsMap;
+ //TElemOfVecOfMapNodesMap mapElemNewNodes;
// loop on theElems
- set< const SMDS_MeshElement* >::iterator itElem;
- for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ )
- {
+ TIDSortedElemSet::iterator itElem;
+ for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ ) {
// check element type
- const SMDS_MeshElement* elem = (*itElem);
- if ( !elem )
+ const SMDS_MeshElement* elem = *itElem;
+ if ( !elem || elem->GetType() == SMDSAbs_Volume )
continue;
vector<TNodeOfNodeListMapItr> & newNodesItVec = mapElemNewNodes[ elem ];
+ //vector<TNodeOfNodeVecMapItr> & newNodesItVec = mapElemNewNodes[ elem ];
newNodesItVec.reserve( elem->NbNodes() );
// loop on elem nodes
const SMDS_MeshNode* node =
static_cast<const SMDS_MeshNode*>( itN->next() );
TNodeOfNodeListMap::iterator nIt = mapNewNodes.find( node );
- if ( nIt == mapNewNodes.end() )
- {
+ //TNodeOfNodeVecMap::iterator nIt = mapNewNodes.find( node );
+ if ( nIt == mapNewNodes.end() ) {
nIt = mapNewNodes.insert( make_pair( node, list<const SMDS_MeshNode*>() )).first;
+ //nIt = mapNewNodes.insert( make_pair( node, vector<const SMDS_MeshNode*>() )).first;
list<const SMDS_MeshNode*>& listNewNodes = nIt->second;
+ //vector<const SMDS_MeshNode*>& vecNewNodes = nIt->second;
+ //vecNewNodes.reserve(nbsteps);
// make new nodes
double coord[] = { node->X(), node->Y(), node->Z() };
- for ( int i = 0; i < theNbSteps; i++ ) {
- aTrsf.Transforms( coord[0], coord[1], coord[2] );
- const SMDS_MeshNode * newNode = aMesh->AddNode( coord[0], coord[1], coord[2] );
- listNewNodes.push_back( newNode );
+ //int nbsteps = theParams.mySteps->Length();
+ for ( int i = 0; i < nbsteps; i++ ) {
+ if( elem->IsQuadratic() && !elem->IsMediumNode(node) ) {
+ // create additional node
+ double x = coord[0] + theParams.myDir.X()*theParams.mySteps->Value(i+1)/2.;
+ double y = coord[1] + theParams.myDir.Y()*theParams.mySteps->Value(i+1)/2.;
+ double z = coord[2] + theParams.myDir.Z()*theParams.mySteps->Value(i+1)/2.;
+ if( theFlags & EXTRUSION_FLAG_SEW ) {
+ const SMDS_MeshNode * newNode = CreateNode(x, y, z,
+ theTolerance, theParams.myNodes);
+ listNewNodes.push_back( newNode );
+ }
+ else {
+ const SMDS_MeshNode * newNode = aMesh->AddNode(x, y, z);
+ myLastCreatedNodes.Append(newNode);
+ listNewNodes.push_back( newNode );
+ }
+ }
+ //aTrsf.Transforms( coord[0], coord[1], coord[2] );
+ coord[0] = coord[0] + theParams.myDir.X()*theParams.mySteps->Value(i+1);
+ coord[1] = coord[1] + theParams.myDir.Y()*theParams.mySteps->Value(i+1);
+ coord[2] = coord[2] + theParams.myDir.Z()*theParams.mySteps->Value(i+1);
+ if( theFlags & EXTRUSION_FLAG_SEW ) {
+ const SMDS_MeshNode * newNode = CreateNode(coord[0], coord[1], coord[2],
+ theTolerance, theParams.myNodes);
+ listNewNodes.push_back( newNode );
+ //vecNewNodes[i]=newNode;
+ }
+ else {
+ const SMDS_MeshNode * newNode = aMesh->AddNode( coord[0], coord[1], coord[2] );
+ myLastCreatedNodes.Append(newNode);
+ listNewNodes.push_back( newNode );
+ //vecNewNodes[i]=newNode;
+ }
+ }
+ }
+ else {
+ // if current elem is quadratic and current node is not medium
+ // we have to check - may be it is needed to insert additional nodes
+ if( elem->IsQuadratic() && !elem->IsMediumNode(node) ) {
+ list< const SMDS_MeshNode* > & listNewNodes = nIt->second;
+ if(listNewNodes.size()==nbsteps) {
+ listNewNodes.clear();
+ double coord[] = { node->X(), node->Y(), node->Z() };
+ for ( int i = 0; i < nbsteps; i++ ) {
+ double x = coord[0] + theParams.myDir.X()*theParams.mySteps->Value(i+1);
+ double y = coord[1] + theParams.myDir.Y()*theParams.mySteps->Value(i+1);
+ double z = coord[2] + theParams.myDir.Z()*theParams.mySteps->Value(i+1);
+ if( theFlags & EXTRUSION_FLAG_SEW ) {
+ const SMDS_MeshNode * newNode = CreateNode(x, y, z,
+ theTolerance, theParams.myNodes);
+ listNewNodes.push_back( newNode );
+ }
+ else {
+ const SMDS_MeshNode * newNode = aMesh->AddNode(x, y, z);
+ myLastCreatedNodes.Append(newNode);
+ listNewNodes.push_back( newNode );
+ }
+ coord[0] = coord[0] + theParams.myDir.X()*theParams.mySteps->Value(i+1);
+ coord[1] = coord[1] + theParams.myDir.Y()*theParams.mySteps->Value(i+1);
+ coord[2] = coord[2] + theParams.myDir.Z()*theParams.mySteps->Value(i+1);
+ if( theFlags & EXTRUSION_FLAG_SEW ) {
+ const SMDS_MeshNode * newNode = CreateNode(coord[0], coord[1], coord[2],
+ theTolerance, theParams.myNodes);
+ listNewNodes.push_back( newNode );
+ }
+ else {
+ const SMDS_MeshNode * newNode = aMesh->AddNode( coord[0], coord[1], coord[2] );
+ myLastCreatedNodes.Append(newNode);
+ listNewNodes.push_back( newNode );
+ }
+ }
+ }
}
}
newNodesItVec.push_back( nIt );
}
// make new elements
- sweepElement( aMesh, elem, newNodesItVec, newElemsMap[elem] );
-
- // fill history
- SMESH_SequenceOfElemPtr SeqNewME;
- list<const SMDS_MeshElement*> tmpList = newElemsMap[elem];
- for(list<const SMDS_MeshElement*>::iterator ite = tmpList.begin();
- ite!=tmpList.end(); ite++) {
- SeqNewME.Append(*ite);
- }
- myExtrusionHistory.Bind(elem,SeqNewME);
- // end fill history
+ sweepElement( aMesh, elem, newNodesItVec, newElemsMap[elem], nbsteps, myLastCreatedElems );
+ }
+ if( theFlags & EXTRUSION_FLAG_BOUNDARY ) {
+ makeWalls( aMesh, mapNewNodes, newElemsMap, mapElemNewNodes, theElems, nbsteps, myLastCreatedElems );
}
- makeWalls( aMesh, mapNewNodes, newElemsMap, mapElemNewNodes, theElems );
}
+
//=======================================================================
//class : SMESH_MeshEditor_PathPoint
//purpose : auxiliary class
//purpose :
//=======================================================================
SMESH_MeshEditor::Extrusion_Error
- SMESH_MeshEditor::ExtrusionAlongTrack (std::set<const SMDS_MeshElement*> & theElements,
- SMESH_subMesh* theTrack,
+ SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet & theElements,
+ SMESH_subMesh* theTrack,
const SMDS_MeshNode* theN1,
- const bool theHasAngles,
- std::list<double>& theAngles,
- const bool theHasRefPoint,
- const gp_Pnt& theRefPoint)
+ const bool theHasAngles,
+ list<double>& theAngles,
+ const bool theHasRefPoint,
+ const gp_Pnt& theRefPoint)
{
+ myLastCreatedElems.Clear();
+ myLastCreatedNodes.Clear();
+
MESSAGE("SMESH_MeshEditor::ExtrusionAlongTrack")
int j, aNbTP, aNbE, aNb;
double aT1, aT2, aT, aAngle, aX, aY, aZ;
std::list<double> aPrms;
std::list<double>::iterator aItD;
- std::set< const SMDS_MeshElement* >::iterator itElem;
+ TIDSortedElemSet::iterator itElem;
Standard_Real aTx1, aTx2, aL2, aTolVec, aTolVec2;
gp_Pnt aP3D, aV0;
itElem = theElements.begin();
for ( ; itElem != theElements.end(); itElem++ ) {
- const SMDS_MeshElement* elem = (*itElem);
+ const SMDS_MeshElement* elem = *itElem;
SMDS_ElemIteratorPtr itN = elem->nodesIterator();
while ( itN->more() ) {
for ( itElem = theElements.begin(); itElem != theElements.end(); itElem++ ) {
// check element type
- const SMDS_MeshElement* elem = (*itElem);
+ const SMDS_MeshElement* elem = *itElem;
aTypeE = elem->GetType();
if ( !elem || ( aTypeE != SMDSAbs_Face && aTypeE != SMDSAbs_Edge ) )
continue;
}
// make new node
+ if( elem->IsQuadratic() && !elem->IsMediumNode(node) ) {
+ // create additional node
+ double x = ( aPN1.X() + aPN0.X() )/2.;
+ double y = ( aPN1.Y() + aPN0.Y() )/2.;
+ double z = ( aPN1.Z() + aPN0.Z() )/2.;
+ const SMDS_MeshNode* newNode = aMesh->AddNode(x,y,z);
+ myLastCreatedNodes.Append(newNode);
+ listNewNodes.push_back( newNode );
+ }
aX = aPN1.X();
aY = aPN1.Y();
aZ = aPN1.Z();
const SMDS_MeshNode* newNode = aMesh->AddNode( aX, aY, aZ );
+ myLastCreatedNodes.Append(newNode);
listNewNodes.push_back( newNode );
aPN0 = aPN1;
aDT0x = aDT1x;
}
}
- newNodesItVec.push_back( nIt );
- }
+
+ else {
+ // if current elem is quadratic and current node is not medium
+ // we have to check - may be it is needed to insert additional nodes
+ if( elem->IsQuadratic() && !elem->IsMediumNode(node) ) {
+ list< const SMDS_MeshNode* > & listNewNodes = nIt->second;
+ if(listNewNodes.size()==aNbTP-1) {
+ vector<const SMDS_MeshNode*> aNodes(2*(aNbTP-1));
+ gp_XYZ P(node->X(), node->Y(), node->Z());
+ list< const SMDS_MeshNode* >::iterator it = listNewNodes.begin();
+ int i;
+ for(i=0; i<aNbTP-1; i++) {
+ const SMDS_MeshNode* N = *it;
+ double x = ( N->X() + P.X() )/2.;
+ double y = ( N->Y() + P.Y() )/2.;
+ double z = ( N->Z() + P.Z() )/2.;
+ const SMDS_MeshNode* newN = aMesh->AddNode(x,y,z);
+ myLastCreatedNodes.Append(newN);
+ aNodes[2*i] = newN;
+ aNodes[2*i+1] = N;
+ P = gp_XYZ(N->X(),N->Y(),N->Z());
+ }
+ listNewNodes.clear();
+ for(i=0; i<2*(aNbTP-1); i++) {
+ listNewNodes.push_back(aNodes[i]);
+ }
+ }
+ }
+ }
+
+ newNodesItVec.push_back( nIt );
+ }
// make new elements
- sweepElement( aMesh, elem, newNodesItVec, newElemsMap[elem] );
+ //sweepElement( aMesh, elem, newNodesItVec, newElemsMap[elem],
+ // newNodesItVec[0]->second.size(), myLastCreatedElems );
+ sweepElement( aMesh, elem, newNodesItVec, newElemsMap[elem],
+ aNbTP-1, myLastCreatedElems );
}
- makeWalls( aMesh, mapNewNodes, newElemsMap, mapElemNewNodes, theElements );
+ makeWalls( aMesh, mapNewNodes, newElemsMap, mapElemNewNodes, theElements,
+ aNbTP-1, myLastCreatedElems );
return EXTR_OK;
}
//purpose :
//=======================================================================
-void SMESH_MeshEditor::Transform (set<const SMDS_MeshElement*> & theElems,
- const gp_Trsf& theTrsf,
- const bool theCopy)
+void SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems,
+ const gp_Trsf& theTrsf,
+ const bool theCopy)
{
+ myLastCreatedElems.Clear();
+ myLastCreatedNodes.Clear();
+
bool needReverse;
switch ( theTrsf.Form() ) {
case gp_PntMirror:
// elements sharing moved nodes; those of them which have all
// nodes mirrored but are not in theElems are to be reversed
- set<const SMDS_MeshElement*> inverseElemSet;
+ TIDSortedElemSet inverseElemSet;
// loop on theElems
- set< const SMDS_MeshElement* >::iterator itElem;
- for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ )
- {
- const SMDS_MeshElement* elem = (*itElem);
+ TIDSortedElemSet::iterator itElem;
+ for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ ) {
+ const SMDS_MeshElement* elem = *itElem;
if ( !elem )
continue;
coord[2] = node->Z();
theTrsf.Transforms( coord[0], coord[1], coord[2] );
const SMDS_MeshNode * newNode = node;
- if ( theCopy )
+ if ( theCopy ) {
newNode = aMesh->AddNode( coord[0], coord[1], coord[2] );
+ myLastCreatedNodes.Append(newNode);
+ }
else {
aMesh->MoveNode( node, coord[0], coord[1], coord[2] );
// node position on shape becomes invalid
// keep inverse elements
if ( !theCopy && needReverse ) {
SMDS_ElemIteratorPtr invElemIt = node->GetInverseElementIterator();
- while ( invElemIt->more() )
- inverseElemSet.insert( invElemIt->next() );
+ while ( invElemIt->more() ) {
+ const SMDS_MeshElement* iel = invElemIt->next();
+ inverseElemSet.insert( iel );
+ }
}
}
}
return;
if ( !inverseElemSet.empty()) {
- set<const SMDS_MeshElement*>::iterator invElemIt = inverseElemSet.begin();
+ TIDSortedElemSet::iterator invElemIt = inverseElemSet.begin();
for ( ; invElemIt != inverseElemSet.end(); invElemIt++ )
theElems.insert( *invElemIt );
}
{ 0, 1, 2, 3, 4, 5, 6, 7 } // FORWARD
};
- for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ )
- {
- const SMDS_MeshElement* elem = (*itElem);
+ for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ ) {
+ const SMDS_MeshElement* elem = *itElem;
if ( !elem || elem->GetType() == SMDSAbs_Node )
continue;
continue; // not all nodes transformed
if ( theCopy ) {
- aMesh->AddPolygonalFace(poly_nodes);
- } else {
+ myLastCreatedElems.Append(aMesh->AddPolygonalFace(poly_nodes));
+ }
+ else {
aMesh->ChangePolygonNodes(elem, poly_nodes);
}
}
continue; // not all nodes transformed
if ( theCopy ) {
- aMesh->AddPolyhedralVolume(poly_nodes, quantities);
- } else {
+ myLastCreatedElems.Append(aMesh->AddPolyhedralVolume(poly_nodes, quantities));
+ }
+ else {
aMesh->ChangePolyhedronNodes(elem, poly_nodes, quantities);
}
}
else
i = index[ nbNodes - 4 ];
+ if(elem->IsQuadratic()) {
+ static int anIds[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
+ i = anIds;
+ if(needReverse) {
+ if(nbNodes==3) { // quadratic edge
+ static int anIds[] = {1,0,2};
+ i = anIds;
+ }
+ else if(nbNodes==6) { // quadratic triangle
+ static int anIds[] = {0,2,1,5,4,3};
+ i = anIds;
+ }
+ else if(nbNodes==8) { // quadratic quadrangle
+ static int anIds[] = {0,3,2,1,7,6,5,4};
+ i = anIds;
+ }
+ else if(nbNodes==10) { // quadratic tetrahedron of 10 nodes
+ static int anIds[] = {0,2,1,3,6,5,4,7,9,8};
+ i = anIds;
+ }
+ else if(nbNodes==13) { // quadratic pyramid of 13 nodes
+ static int anIds[] = {0,3,2,1,4,8,7,6,5,9,12,11,10};
+ i = anIds;
+ }
+ else if(nbNodes==15) { // quadratic pentahedron with 15 nodes
+ static int anIds[] = {0,2,1,3,5,4,8,7,6,11,10,9,12,14,13};
+ i = anIds;
+ }
+ else { // nbNodes==20 - quadratic hexahedron with 20 nodes
+ static int anIds[] = {0,3,2,1,4,7,6,5,11,10,9,8,15,14,13,12,16,19,18,17};
+ i = anIds;
+ }
+ }
+ }
+
// find transformed nodes
const SMDS_MeshNode* nodes[8];
int iNode = 0;
SMDS_ElemIteratorPtr itN = elem->nodesIterator();
- while ( itN->more() )
- {
+ while ( itN->more() ) {
const SMDS_MeshNode* node =
static_cast<const SMDS_MeshNode*>( itN->next() );
TNodeNodeMap::iterator nodeMapIt = nodeMap.find( node );
if ( iNode != nbNodes )
continue; // not all nodes transformed
- if ( theCopy )
- {
+ if ( theCopy ) {
// add a new element
switch ( elemType ) {
case SMDSAbs_Edge:
- aMesh->AddEdge( nodes[ 0 ], nodes[ 1 ] );
+ 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 )
- aMesh->AddFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ] );
- else
- aMesh->AddFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ] , nodes[ 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 )
- aMesh->AddVolume( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ] , nodes[ 3 ] );
+ myLastCreatedElems.Append(aMesh->AddVolume( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ] , nodes[ 3 ] ));
else if ( nbNodes == 8 )
- aMesh->AddVolume( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ] , nodes[ 3 ],
- nodes[ 4 ], nodes[ 5 ], nodes[ 6 ] , nodes[ 7 ]);
+ myLastCreatedElems.Append(aMesh->AddVolume( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ] , nodes[ 3 ],
+ nodes[ 4 ], nodes[ 5 ], nodes[ 6 ] , nodes[ 7 ]));
else if ( nbNodes == 6 )
- aMesh->AddVolume( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ] , nodes[ 3 ],
- nodes[ 4 ], nodes[ 5 ]);
+ myLastCreatedElems.Append(aMesh->AddVolume( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ] , nodes[ 3 ],
+ nodes[ 4 ], nodes[ 5 ]));
else if ( nbNodes == 5 )
- aMesh->AddVolume( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ] , nodes[ 3 ],
- nodes[ 4 ]);
+ 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:;
}
//=======================================================================
//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,
const double theTolerance,
TListOfListOfNodes & theGroupsOfNodes)
{
- double tol2 = theTolerance * theTolerance;
+ myLastCreatedElems.Clear();
+ myLastCreatedNodes.Clear();
- 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.insert( nodes.end(), theNodes.begin(), theNodes.end() );
- }
-
- list<const SMDS_MeshNode*>::iterator it2, it1 = nodes.begin();
- for ( ; it1 != nodes.end(); it1++ )
- {
- const SMDS_MeshNode* n1 = *it1;
- gp_Pnt p1( n1->X(), n1->Y(), n1->Z() );
+ nodes=theNodes;
+ SMESH_OctreeNode::FindCoincidentNodes ( nodes, &theGroupsOfNodes, theTolerance);
- list<const SMDS_MeshNode*> * groupPtr = 0;
- it2 = it1;
- for ( it2++; it2 != nodes.end(); it2++ )
- {
- const SMDS_MeshNode* n2 = *it2;
- gp_Pnt p2( n2->X(), n2->Y(), n2->Z() );
- if ( p1.SquareDistance( p2 ) <= tol2 )
- {
- if ( !groupPtr ) {
- theGroupsOfNodes.push_back( list<const SMDS_MeshNode*>() );
- groupPtr = & theGroupsOfNodes.back();
- groupPtr->push_back( n1 );
- }
- groupPtr->push_back( n2 );
- it2 = nodes.erase( it2 );
- it2--;
- }
- }
- }
}
//=======================================================================
void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes)
{
+ myLastCreatedElems.Clear();
+ myLastCreatedNodes.Clear();
+
SMESHDS_Mesh* aMesh = GetMeshDS();
TNodeNodeMap nodeNodeMap; // node to replace - new node
// Fill nodeNodeMap and elems
TListOfListOfNodes::iterator grIt = theGroupsOfNodes.begin();
- for ( ; grIt != theGroupsOfNodes.end(); grIt++ )
- {
+ for ( ; grIt != theGroupsOfNodes.end(); grIt++ ) {
list<const SMDS_MeshNode*>& nodes = *grIt;
list<const SMDS_MeshNode*>::iterator nIt = nodes.begin();
const SMDS_MeshNode* nToKeep = *nIt;
- for ( ; nIt != nodes.end(); nIt++ )
- {
+ for ( ++nIt; nIt != nodes.end(); nIt++ ) {
const SMDS_MeshNode* nToRemove = *nIt;
nodeNodeMap.insert( TNodeNodeMap::value_type( nToRemove, nToKeep ));
if ( nToRemove != nToKeep ) {
}
SMDS_ElemIteratorPtr invElemIt = nToRemove->GetInverseElementIterator();
- while ( invElemIt->more() )
- elems.insert( invElemIt->next() );
+ while ( invElemIt->more() ) {
+ const SMDS_MeshElement* elem = invElemIt->next();
+ elems.insert(elem);
+ }
}
}
// Change element nodes or remove an element
set<const SMDS_MeshElement*>::iterator eIt = elems.begin();
- for ( ; eIt != elems.end(); eIt++ )
- {
+ for ( ; eIt != elems.end(); eIt++ ) {
const SMDS_MeshElement* elem = *eIt;
int nbNodes = elem->NbNodes();
int aShapeId = FindShape( elem );
// get new seq of nodes
SMDS_ElemIteratorPtr itN = elem->nodesIterator();
- while ( itN->more() )
- {
+ while ( itN->more() ) {
const SMDS_MeshNode* n =
static_cast<const SMDS_MeshNode*>( itN->next() );
bool isOk = true;
int nbUniqueNodes = nodeSet.size();
- if ( nbNodes != nbUniqueNodes ) // some nodes stick
- {
+ if ( nbNodes != nbUniqueNodes ) { // some nodes stick
// Polygons and Polyhedral volumes
if (elem->IsPoly()) {
poly_nodes[ii] = polygons_nodes[inode];
}
SMDS_MeshElement* newElem = aMesh->AddPolygonalFace(poly_nodes);
+ myLastCreatedElems.Append(newElem);
if (aShapeId)
aMesh->SetMeshElementOnShape(newElem, aShapeId);
}
aMesh->ChangeElementNodes(elem, &polygons_nodes[inode], quantities[nbNew - 1]);
- } else {
+ }
+ else {
rmElemIds.push_back(elem->GetID());
}
- } else if (elem->GetType() == SMDSAbs_Volume) {
+ }
+ else if (elem->GetType() == SMDSAbs_Volume) {
// Polyhedral volume
if (nbUniqueNodes < 4) {
rmElemIds.push_back(elem->GetID());
- } else {
+ }
+ else {
// each face has to be analized in order to check volume validity
const SMDS_PolyhedralVolumeOfNodes* aPolyedre =
static_cast<const SMDS_PolyhedralVolumeOfNodes*>( elem );
else
rmElemIds.push_back(elem->GetID());
- } else {
+ }
+ else {
rmElemIds.push_back(elem->GetID());
}
}
- } else {
+ }
+ else {
}
continue;
curNodes[ 4 ],
curNodes[ 5 ],
curNodes[ iRepl[ 0 ] == 2 ? 1 : 2 ]);
+ myLastCreatedElems.Append(newElem);
if ( aShapeId )
aMesh->SetMeshElementOnShape( newElem, aShapeId );
// 2. : reverse a bottom
else
isOk = false;
break;
- case 8: { //////////////////////////////////// HEXAHEDRON
+ case 8: {
+ if(elem->IsQuadratic()) { // Quadratic quadrangle
+ // 1 5 2
+ // +---+---+
+ // | |
+ // | |
+ // 4+ +6
+ // | |
+ // | |
+ // +---+---+
+ // 0 7 3
+ isOk = false;
+ if(nbRepl==3) {
+ nbUniqueNodes = 6;
+ if( iRepl[0]==0 && iRepl[1]==1 && iRepl[2]==4 ) {
+ uniqueNodes[0] = curNodes[0];
+ uniqueNodes[1] = curNodes[2];
+ uniqueNodes[2] = curNodes[3];
+ uniqueNodes[3] = curNodes[5];
+ uniqueNodes[4] = curNodes[6];
+ uniqueNodes[5] = curNodes[7];
+ isOk = true;
+ }
+ if( iRepl[0]==0 && iRepl[1]==3 && iRepl[2]==7 ) {
+ uniqueNodes[0] = curNodes[0];
+ uniqueNodes[1] = curNodes[1];
+ uniqueNodes[2] = curNodes[2];
+ uniqueNodes[3] = curNodes[4];
+ uniqueNodes[4] = curNodes[5];
+ uniqueNodes[5] = curNodes[6];
+ isOk = true;
+ }
+ if( iRepl[0]==0 && iRepl[1]==4 && iRepl[2]==7 ) {
+ uniqueNodes[0] = curNodes[1];
+ uniqueNodes[1] = curNodes[2];
+ uniqueNodes[2] = curNodes[3];
+ uniqueNodes[3] = curNodes[5];
+ uniqueNodes[4] = curNodes[6];
+ uniqueNodes[5] = curNodes[0];
+ isOk = true;
+ }
+ if( iRepl[0]==1 && iRepl[1]==2 && iRepl[2]==5 ) {
+ uniqueNodes[0] = curNodes[0];
+ uniqueNodes[1] = curNodes[1];
+ uniqueNodes[2] = curNodes[3];
+ uniqueNodes[3] = curNodes[4];
+ uniqueNodes[4] = curNodes[6];
+ uniqueNodes[5] = curNodes[7];
+ isOk = true;
+ }
+ if( iRepl[0]==1 && iRepl[1]==4 && iRepl[2]==5 ) {
+ uniqueNodes[0] = curNodes[0];
+ uniqueNodes[1] = curNodes[2];
+ uniqueNodes[2] = curNodes[3];
+ uniqueNodes[3] = curNodes[1];
+ uniqueNodes[4] = curNodes[6];
+ uniqueNodes[5] = curNodes[7];
+ isOk = true;
+ }
+ if( iRepl[0]==2 && iRepl[1]==3 && iRepl[2]==6 ) {
+ uniqueNodes[0] = curNodes[0];
+ uniqueNodes[1] = curNodes[1];
+ uniqueNodes[2] = curNodes[2];
+ uniqueNodes[3] = curNodes[4];
+ uniqueNodes[4] = curNodes[5];
+ uniqueNodes[5] = curNodes[7];
+ isOk = true;
+ }
+ if( iRepl[0]==2 && iRepl[1]==5 && iRepl[2]==6 ) {
+ uniqueNodes[0] = curNodes[0];
+ uniqueNodes[1] = curNodes[1];
+ uniqueNodes[2] = curNodes[3];
+ uniqueNodes[3] = curNodes[4];
+ uniqueNodes[4] = curNodes[2];
+ uniqueNodes[5] = curNodes[7];
+ isOk = true;
+ }
+ if( iRepl[0]==3 && iRepl[1]==6 && iRepl[2]==7 ) {
+ uniqueNodes[0] = curNodes[0];
+ uniqueNodes[1] = curNodes[1];
+ uniqueNodes[2] = curNodes[2];
+ uniqueNodes[3] = curNodes[4];
+ uniqueNodes[4] = curNodes[5];
+ uniqueNodes[5] = curNodes[3];
+ isOk = true;
+ }
+ }
+ break;
+ }
+ //////////////////////////////////// HEXAHEDRON
isOk = false;
SMDS_VolumeTool hexa (elem);
hexa.SetExternalNormal();
curNodes[ind[ 3 ]],
curNodes[ind[ 2 ]],
curNodes[indTop[ 0 ]]);
+ myLastCreatedElems.Append(newElem);
if ( aShapeId )
aMesh->SetMeshElementOnShape( newElem, aShapeId );
isOk = true;
curNodes[ i2 ],
curNodes[ i3d ],
curNodes[ i2t ]);
+ myLastCreatedElems.Append(newElem);
if ( aShapeId )
aMesh->SetMeshElementOnShape( newElem, aShapeId );
isOk = true;
}
aMesh->ChangePolyhedronNodes( elem, poly_nodes, quantities );
}
- } else {
+ }
+ else {
// Change regular element or polygon
aMesh->ChangeElementNodes( elem, uniqueNodes, nbUniqueNodes );
}
- } else {
+ }
+ else {
// Remove invalid regular element or invalid polygon
rmElemIds.push_back( elem->GetID() );
}
}
+
+// =================================================
+// class : SortableElement
+// purpose : auxilary
+// =================================================
+class SortableElement : public set <const SMDS_MeshElement*>
+{
+ public:
+
+ SortableElement( const SMDS_MeshElement* theElem )
+ {
+ myID = theElem->GetID();
+ SMDS_ElemIteratorPtr nodeIt = theElem->nodesIterator();
+ while ( nodeIt->more() )
+ this->insert( nodeIt->next() );
+ }
+
+ const long GetID() const
+ { return myID; }
+
+ void SetID(const long anID) const
+ { myID = anID; }
+
+
+ private:
+ mutable long myID;
+};
+
+
//=======================================================================
//function : MergeEqualElements
//purpose : Remove all but one of elements built on the same nodes.
void SMESH_MeshEditor::MergeEqualElements()
{
+ myLastCreatedElems.Clear();
+ myLastCreatedNodes.Clear();
+
SMESHDS_Mesh* aMesh = GetMeshDS();
SMDS_EdgeIteratorPtr eIt = aMesh->edgesIterator();
for ( int iDim = 1; iDim <= 3; iDim++ ) {
- set< set <const SMDS_MeshElement*> > setOfNodeSet;
-
+ set< SortableElement > setOfNodeSet;
while ( 1 ) {
// get next element
const SMDS_MeshElement* elem = 0;
}
if ( !elem ) break;
- // get elem nodes
- set <const SMDS_MeshElement*> nodeSet;
- SMDS_ElemIteratorPtr nodeIt = elem->nodesIterator();
- while ( nodeIt->more() )
- nodeSet.insert( nodeIt->next() );
+ SortableElement SE(elem);
// check uniqueness
- bool isUnique = setOfNodeSet.insert( nodeSet ).second;
- if ( !isUnique )
- rmElemIds.push_back( elem->GetID() );
+ 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() );
+ }
+ }
}
}
//=======================================================================
const SMDS_MeshElement*
- SMESH_MeshEditor::FindFaceInSet(const SMDS_MeshNode* n1,
- const SMDS_MeshNode* n2,
- const set<const SMDS_MeshElement*>& elemSet,
- const set<const SMDS_MeshElement*>& avoidSet)
+ SMESH_MeshEditor::FindFaceInSet(const SMDS_MeshNode* n1,
+ const SMDS_MeshNode* n2,
+ const TIDSortedElemSet& elemSet,
+ const TIDSortedElemSet& avoidSet)
{
- SMDS_ElemIteratorPtr invElemIt = n1->GetInverseElementIterator();
+ SMDS_ElemIteratorPtr invElemIt = n1->GetInverseElementIterator(SMDSAbs_Face);
while ( invElemIt->more() ) { // loop on inverse elements of n1
const SMDS_MeshElement* elem = invElemIt->next();
- if (elem->GetType() != SMDSAbs_Face ||
- avoidSet.find( elem ) != avoidSet.end() )
+ if (avoidSet.find( elem ) != avoidSet.end() )
continue;
if ( !elemSet.empty() && elemSet.find( elem ) == elemSet.end())
continue;
i1 = iNode - 1;
}
// find a n2 linked to n1
- for ( iNode = 0; iNode < 2; iNode++ ) {
- if ( iNode ) // node before n1
- n = faceNodes[ i1 == 0 ? nbN - 1 : i1 - 1 ];
- else // node after n1
- n = faceNodes[ i1 + 1 == nbN ? 0 : i1 + 1 ];
- if ( n == n2 )
- return elem;
+ if(!elem->IsQuadratic()) {
+ for ( iNode = 0; iNode < 2; iNode++ ) {
+ if ( iNode ) // node before n1
+ n = faceNodes[ i1 == 0 ? nbN - 1 : i1 - 1 ];
+ else // node after n1
+ n = faceNodes[ i1 + 1 == nbN ? 0 : i1 + 1 ];
+ if ( n == n2 )
+ return elem;
+ }
}
+ else { // analysis for quadratic elements
+ bool IsFind = false;
+ // check using only corner nodes
+ for ( iNode = 0; iNode < 2; iNode++ ) {
+ if ( iNode ) // node before n1
+ n = faceNodes[ i1 == 0 ? nbN/2 - 1 : i1 - 1 ];
+ else // node after n1
+ n = faceNodes[ i1 + 1 == nbN/2 ? 0 : i1 + 1 ];
+ if ( n == n2 )
+ IsFind = true;
+ }
+ if(IsFind) {
+ return elem;
+ }
+ else {
+ // check using all nodes
+ const SMDS_QuadraticFaceOfNodes* F =
+ static_cast<const SMDS_QuadraticFaceOfNodes*>(elem);
+ // use special nodes iterator
+ iNode = 0;
+ SMDS_NodeIteratorPtr anIter = F->interlacedNodesIterator();
+ while ( anIter->more() ) {
+ faceNodes[iNode] = static_cast<const SMDS_MeshNode*>(anIter->next());
+ if ( faceNodes[ iNode++ ] == n1 )
+ i1 = iNode - 1;
+ }
+ for ( iNode = 0; iNode < 2; iNode++ ) {
+ if ( iNode ) // node before n1
+ n = faceNodes[ i1 == 0 ? nbN - 1 : i1 - 1 ];
+ else // node after n1
+ n = faceNodes[ i1 + 1 == nbN ? 0 : i1 + 1 ];
+ if ( n == n2 ) {
+ return elem;
+ }
+ }
+ }
+ } // end analysis for quadratic elements
}
return 0;
}
const SMDS_MeshNode* n2,
const SMDS_MeshElement* elem)
{
- set<const SMDS_MeshElement*> elemSet, avoidSet;
+ TIDSortedElemSet elemSet, avoidSet;
if ( elem )
avoidSet.insert ( elem );
return SMESH_MeshEditor::FindFaceInSet( n1, n2, elemSet, avoidSet );
}
//=======================================================================
-//function : findFreeBorder
+//function : FindFreeBorder
//purpose :
//=======================================================================
#define ControlFreeBorder SMESH::Controls::FreeEdges::IsFreeEdge
-static bool findFreeBorder (const SMDS_MeshNode* theFirstNode,
- const SMDS_MeshNode* theSecondNode,
- const SMDS_MeshNode* theLastNode,
- list< const SMDS_MeshNode* > & theNodes,
- list< const SMDS_MeshElement* > & theFaces)
+bool SMESH_MeshEditor::FindFreeBorder (const SMDS_MeshNode* theFirstNode,
+ const SMDS_MeshNode* theSecondNode,
+ const SMDS_MeshNode* theLastNode,
+ list< const SMDS_MeshNode* > & theNodes,
+ list< const SMDS_MeshElement* >& theFaces)
{
if ( !theFirstNode || !theSecondNode )
return false;
theNodes.push_back( theFirstNode );
theNodes.push_back( theSecondNode );
- const SMDS_MeshNode* nodes [5], *nIgnore = theFirstNode, * nStart = theSecondNode;
+ //vector<const SMDS_MeshNode*> nodes;
+ const SMDS_MeshNode *nIgnore = theFirstNode, *nStart = theSecondNode;
set < const SMDS_MeshElement* > foundElems;
bool needTheLast = ( theLastNode != 0 );
- while ( nStart != theLastNode )
- {
+ while ( nStart != theLastNode ) {
if ( nStart == theFirstNode )
return !needTheLast;
list< const SMDS_MeshElement* > curElemList;
list< const SMDS_MeshNode* > nStartList;
- SMDS_ElemIteratorPtr invElemIt = nStart->facesIterator();
+ SMDS_ElemIteratorPtr invElemIt = nStart->GetInverseElementIterator(SMDSAbs_Face);
while ( invElemIt->more() ) {
const SMDS_MeshElement* e = invElemIt->next();
- if ( e == curElem || foundElems.insert( e ).second )
- {
+ if ( e == curElem || foundElems.insert( e ).second ) {
// get nodes
- SMDS_ElemIteratorPtr nIt = e->nodesIterator();
int iNode = 0, nbNodes = e->NbNodes();
- while ( nIt->more() )
- nodes[ iNode++ ] = static_cast<const SMDS_MeshNode*>( nIt->next() );
+ const SMDS_MeshNode* nodes[nbNodes+1];
+ if(e->IsQuadratic()) {
+ const SMDS_QuadraticFaceOfNodes* F =
+ static_cast<const SMDS_QuadraticFaceOfNodes*>(e);
+ // use special nodes iterator
+ SMDS_NodeIteratorPtr anIter = F->interlacedNodesIterator();
+ while( anIter->more() ) {
+ nodes[ iNode++ ] = anIter->next();
+ }
+ }
+ else {
+ SMDS_ElemIteratorPtr nIt = e->nodesIterator();
+ while ( nIt->more() )
+ nodes[ iNode++ ] = static_cast<const SMDS_MeshNode*>( nIt->next() );
+ }
nodes[ iNode ] = nodes[ 0 ];
// check 2 links
for ( iNode = 0; iNode < nbNodes; iNode++ )
cNL = & contNodes[ contNodes[0].empty() ? 0 : 1 ];
cFL = & contFaces[ contFaces[0].empty() ? 0 : 1 ];
// find one more free border
- if ( ! findFreeBorder( nIgnore, nStart, theLastNode, *cNL, *cFL )) {
+ if ( ! FindFreeBorder( nStart, *nStartIt, theLastNode, *cNL, *cFL )) {
cNL->clear();
cFL->clear();
}
{
list< const SMDS_MeshNode* > nodes;
list< const SMDS_MeshElement* > faces;
- return findFreeBorder( theNode1, theNode2, theNode3, nodes, faces);
+ return FindFreeBorder( theNode1, theNode2, theNode3, nodes, faces);
}
//=======================================================================
const bool toCreatePolygons,
const bool toCreatePolyedrs)
{
+ myLastCreatedElems.Clear();
+ myLastCreatedNodes.Clear();
+
MESSAGE("::SewFreeBorder()");
Sew_Error aResult = SEW_OK;
// Free border 1
// --------------
- if (!findFreeBorder(theBordFirstNode,theBordSecondNode,theBordLastNode,
+ if (!FindFreeBorder(theBordFirstNode,theBordSecondNode,theBordLastNode,
nSide[0], eSide[0])) {
MESSAGE(" Free Border 1 not found " );
aResult = SEW_BORDER1_NOT_FOUND;
}
- if (theSideIsFreeBorder)
- {
+ if (theSideIsFreeBorder) {
// Free border 2
// --------------
- if (!findFreeBorder(theSideFirstNode, theSideSecondNode, theSideThirdNode,
+ if (!FindFreeBorder(theSideFirstNode, theSideSecondNode, theSideThirdNode,
nSide[1], eSide[1])) {
MESSAGE(" Free Border 2 not found " );
aResult = ( aResult != SEW_OK ? SEW_BOTH_BORDERS_NOT_FOUND : SEW_BORDER2_NOT_FOUND );
if ( aResult != SEW_OK )
return aResult;
- if (!theSideIsFreeBorder)
- {
+ if (!theSideIsFreeBorder) {
// Side 2
// --------------
gp_XYZ Ps2( theSideSecondNode->X(), theSideSecondNode->Y(), theSideSecondNode->Z() );
double tol2 = 1.e-8;
gp_Vec Vbs1( Pb1 - Ps1 ),Vbs2( Pb2 - Ps2 );
- if ( Vbs1.SquareMagnitude() > tol2 || Vbs2.SquareMagnitude() > tol2 )
- {
+ if ( Vbs1.SquareMagnitude() > tol2 || Vbs2.SquareMagnitude() > tol2 ) {
// Need node movement.
// find X and Z axes to create trsf
nBordXYZ.insert( TNodeXYZMap::value_type( n, xyz ));
}
}
- else
- {
+ else {
// just insert nodes XYZ in the nBordXYZ map
for ( nBordIt = bordNodes.begin(); nBordIt != bordNodes.end(); nBordIt++ ) {
const SMDS_MeshNode* n = *nBordIt;
checkedLinkIDs.clear();
gp_XYZ prevXYZ( prevSideNode->X(), prevSideNode->Y(), prevSideNode->Z() );
- SMDS_ElemIteratorPtr invElemIt
- = prevSideNode->GetInverseElementIterator();
- while ( invElemIt->more() ) { // loop on inverse elements on the Side 2
+ // loop on inverse elements of current node (prevSideNode) on the Side 2
+ SMDS_ElemIteratorPtr invElemIt = prevSideNode->GetInverseElementIterator();
+ while ( invElemIt->more() )
+ {
const SMDS_MeshElement* elem = invElemIt->next();
- // prepare data for a loop on links, of a face or a volume
+ // prepare data for a loop on links coming to prevSideNode, of a face or a volume
int iPrevNode, iNode = 0, nbNodes = elem->NbNodes();
const SMDS_MeshNode* faceNodes[ nbNodes ];
bool isVolume = volume.Set( elem );
const SMDS_MeshNode** nodes = isVolume ? volume.GetNodes() : faceNodes;
if ( isVolume ) // --volume
hasVolumes = true;
- else if ( nbNodes > 2 ) { // --face
+ //else if ( nbNodes > 2 ) { // --face
+ else if ( elem->GetType()==SMDSAbs_Face ) { // --face
// retrieve all face nodes and find iPrevNode - an index of the prevSideNode
- SMDS_ElemIteratorPtr nIt = elem->nodesIterator();
- while ( nIt->more() ) {
- nodes[ iNode ] = static_cast<const SMDS_MeshNode*>( nIt->next() );
- if ( nodes[ iNode++ ] == prevSideNode )
- iPrevNode = iNode - 1;
+ if(elem->IsQuadratic()) {
+ const SMDS_QuadraticFaceOfNodes* F =
+ static_cast<const SMDS_QuadraticFaceOfNodes*>(elem);
+ // use special nodes iterator
+ SMDS_NodeIteratorPtr anIter = F->interlacedNodesIterator();
+ while( anIter->more() ) {
+ nodes[ iNode ] = anIter->next();
+ if ( nodes[ iNode++ ] == prevSideNode )
+ iPrevNode = iNode - 1;
+ }
+ }
+ else {
+ SMDS_ElemIteratorPtr nIt = elem->nodesIterator();
+ while ( nIt->more() ) {
+ nodes[ iNode ] = static_cast<const SMDS_MeshNode*>( nIt->next() );
+ if ( nodes[ iNode++ ] == prevSideNode )
+ iPrevNode = iNode - 1;
+ }
}
// there are 2 links to check
nbNodes = 2;
if ( isVolume ) {
if ( !volume.IsLinked( n, prevSideNode ))
continue;
- } else {
+ }
+ else {
if ( iNode ) // a node before prevSideNode
n = nodes[ iPrevNode == 0 ? elem->NbNodes() - 1 : iPrevNode - 1 ];
else // a node after prevSideNode
long iLink = aLinkID_Gen.GetLinkID( prevSideNode, n );
bool isJustChecked = !checkedLinkIDs.insert( iLink ).second;
if (!isJustChecked &&
- foundSideLinkIDs.find( iLink ) == foundSideLinkIDs.end() ) {
+ foundSideLinkIDs.find( iLink ) == foundSideLinkIDs.end() )
+ {
// test a link geometrically
gp_XYZ nextXYZ ( n->X(), n->Y(), n->Z() );
bool linkIsBetter = false;
// find the next border link to compare with
gp_XYZ sidePos( sideNode->X(), sideNode->Y(), sideNode->Z() );
searchByDir = ( bordDir * ( sidePos - bordPos ) <= 0 );
+ // move to next border node if sideNode is before forward border node (bordPos)
while ( *nBordIt != theBordLastNode && !searchByDir ) {
prevBordNode = *nBordIt;
nBordIt++;
int iNode = 0, il1, il2, i3, i4;
il1 = il2 = i3 = i4 = -1;
const SMDS_MeshNode* nodes[ theFace->NbNodes() ];
- SMDS_ElemIteratorPtr nodeIt = theFace->nodesIterator();
- while ( nodeIt->more() ) {
- const SMDS_MeshNode* n = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
- if ( n == theBetweenNode1 )
- il1 = iNode;
- else if ( n == theBetweenNode2 )
- il2 = iNode;
- else if ( i3 < 0 )
- i3 = iNode;
- else
- i4 = iNode;
- nodes[ iNode++ ] = n;
+
+ if(theFace->IsQuadratic()) {
+ const SMDS_QuadraticFaceOfNodes* F =
+ static_cast<const SMDS_QuadraticFaceOfNodes*>(theFace);
+ // use special nodes iterator
+ SMDS_NodeIteratorPtr anIter = F->interlacedNodesIterator();
+ while( anIter->more() ) {
+ const SMDS_MeshNode* n = anIter->next();
+ if ( n == theBetweenNode1 )
+ il1 = iNode;
+ else if ( n == theBetweenNode2 )
+ il2 = iNode;
+ else if ( i3 < 0 )
+ i3 = iNode;
+ else
+ i4 = iNode;
+ nodes[ iNode++ ] = n;
+ }
+ }
+ else {
+ SMDS_ElemIteratorPtr nodeIt = theFace->nodesIterator();
+ while ( nodeIt->more() ) {
+ const SMDS_MeshNode* n = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
+ if ( n == theBetweenNode1 )
+ il1 = iNode;
+ else if ( n == theBetweenNode2 )
+ il2 = iNode;
+ else if ( i3 < 0 )
+ i3 = iNode;
+ else
+ i4 = iNode;
+ nodes[ iNode++ ] = n;
+ }
}
if ( il1 < 0 || il2 < 0 || i3 < 0 )
return ;
// add nodes of face up to first node of link
bool isFLN = false;
- nodeIt = theFace->nodesIterator();
- while ( nodeIt->more() && !isFLN ) {
- const SMDS_MeshNode* n = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
- poly_nodes[iNode++] = n;
- if (n == nodes[il1]) {
- isFLN = true;
- }
- }
- // add nodes to insert
- list<const SMDS_MeshNode*>::iterator nIt = aNodesToInsert.begin();
- for (; nIt != aNodesToInsert.end(); nIt++) {
- poly_nodes[iNode++] = *nIt;
+ if(theFace->IsQuadratic()) {
+ const SMDS_QuadraticFaceOfNodes* F =
+ static_cast<const SMDS_QuadraticFaceOfNodes*>(theFace);
+ // use special nodes iterator
+ SMDS_NodeIteratorPtr anIter = F->interlacedNodesIterator();
+ while( anIter->more() && !isFLN ) {
+ const SMDS_MeshNode* n = anIter->next();
+ poly_nodes[iNode++] = n;
+ if (n == nodes[il1]) {
+ isFLN = true;
+ }
+ }
+ // add nodes to insert
+ list<const SMDS_MeshNode*>::iterator nIt = aNodesToInsert.begin();
+ for (; nIt != aNodesToInsert.end(); nIt++) {
+ poly_nodes[iNode++] = *nIt;
+ }
+ // add nodes of face starting from last node of link
+ while ( anIter->more() ) {
+ poly_nodes[iNode++] = anIter->next();
+ }
}
-
- // add nodes of face starting from last node of link
- while ( nodeIt->more() ) {
- const SMDS_MeshNode* n = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
- poly_nodes[iNode++] = n;
+ else {
+ SMDS_ElemIteratorPtr nodeIt = theFace->nodesIterator();
+ while ( nodeIt->more() && !isFLN ) {
+ const SMDS_MeshNode* n = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
+ poly_nodes[iNode++] = n;
+ if (n == nodes[il1]) {
+ isFLN = true;
+ }
+ }
+ // add nodes to insert
+ list<const SMDS_MeshNode*>::iterator nIt = aNodesToInsert.begin();
+ for (; nIt != aNodesToInsert.end(); nIt++) {
+ poly_nodes[iNode++] = *nIt;
+ }
+ // add nodes of face starting from last node of link
+ while ( nodeIt->more() ) {
+ const SMDS_MeshNode* n = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
+ poly_nodes[iNode++] = n;
+ }
}
// edit or replace the face
if (theFace->IsPoly()) {
aMesh->ChangePolygonNodes(theFace, poly_nodes);
-
- } else {
+ }
+ else {
int aShapeId = FindShape( theFace );
SMDS_MeshElement* newElem = aMesh->AddPolygonalFace(poly_nodes);
+ myLastCreatedElems.Append(newElem);
if ( aShapeId && newElem )
aMesh->SetMeshElementOnShape( newElem, aShapeId );
return;
}
- // put aNodesToInsert between theBetweenNode1 and theBetweenNode2
- int nbLinkNodes = 2 + aNodesToInsert.size();
- const SMDS_MeshNode* linkNodes[ nbLinkNodes ];
- linkNodes[ 0 ] = nodes[ il1 ];
- linkNodes[ nbLinkNodes - 1 ] = nodes[ il2 ];
- list<const SMDS_MeshNode*>::iterator nIt = aNodesToInsert.begin();
- for ( iNode = 1; nIt != aNodesToInsert.end(); nIt++ ) {
- linkNodes[ iNode++ ] = *nIt;
- }
- // decide how to split a quadrangle: compare possible variants
- // and choose which of splits to be a quadrangle
- int i1, i2, iSplit, nbSplits = nbLinkNodes - 1, iBestQuad;
- if ( nbFaceNodes == 3 )
- {
- iBestQuad = nbSplits;
- i4 = i3;
- }
- else if ( nbFaceNodes == 4 )
- {
- SMESH::Controls::NumericalFunctorPtr aCrit( new SMESH::Controls::AspectRatio);
- double aBestRate = DBL_MAX;
- for ( int iQuad = 0; iQuad < nbSplits; iQuad++ ) {
- i1 = 0; i2 = 1;
- double aBadRate = 0;
- // evaluate elements quality
- for ( iSplit = 0; iSplit < nbSplits; iSplit++ ) {
- if ( iSplit == iQuad ) {
- SMDS_FaceOfNodes quad (linkNodes[ i1++ ],
- linkNodes[ i2++ ],
- nodes[ i3 ],
- nodes[ i4 ]);
- aBadRate += getBadRate( &quad, aCrit );
+ if( !theFace->IsQuadratic() ) {
+
+ // put aNodesToInsert between theBetweenNode1 and theBetweenNode2
+ int nbLinkNodes = 2 + aNodesToInsert.size();
+ const SMDS_MeshNode* linkNodes[ nbLinkNodes ];
+ linkNodes[ 0 ] = nodes[ il1 ];
+ linkNodes[ nbLinkNodes - 1 ] = nodes[ il2 ];
+ list<const SMDS_MeshNode*>::iterator nIt = aNodesToInsert.begin();
+ for ( iNode = 1; nIt != aNodesToInsert.end(); nIt++ ) {
+ linkNodes[ iNode++ ] = *nIt;
+ }
+ // decide how to split a quadrangle: compare possible variants
+ // and choose which of splits to be a quadrangle
+ int i1, i2, iSplit, nbSplits = nbLinkNodes - 1, iBestQuad;
+ if ( nbFaceNodes == 3 ) {
+ iBestQuad = nbSplits;
+ i4 = i3;
+ }
+ else if ( nbFaceNodes == 4 ) {
+ SMESH::Controls::NumericalFunctorPtr aCrit( new SMESH::Controls::AspectRatio);
+ double aBestRate = DBL_MAX;
+ for ( int iQuad = 0; iQuad < nbSplits; iQuad++ ) {
+ i1 = 0; i2 = 1;
+ double aBadRate = 0;
+ // evaluate elements quality
+ for ( iSplit = 0; iSplit < nbSplits; iSplit++ ) {
+ if ( iSplit == iQuad ) {
+ SMDS_FaceOfNodes quad (linkNodes[ i1++ ],
+ linkNodes[ i2++ ],
+ nodes[ i3 ],
+ nodes[ i4 ]);
+ aBadRate += getBadRate( &quad, aCrit );
+ }
+ else {
+ SMDS_FaceOfNodes tria (linkNodes[ i1++ ],
+ linkNodes[ i2++ ],
+ nodes[ iSplit < iQuad ? i4 : i3 ]);
+ aBadRate += getBadRate( &tria, aCrit );
+ }
}
- else {
- SMDS_FaceOfNodes tria (linkNodes[ i1++ ],
- linkNodes[ i2++ ],
- nodes[ iSplit < iQuad ? i4 : i3 ]);
- aBadRate += getBadRate( &tria, aCrit );
+ // choice
+ if ( aBadRate < aBestRate ) {
+ iBestQuad = iQuad;
+ aBestRate = aBadRate;
}
}
- // choice
- if ( aBadRate < aBestRate ) {
- iBestQuad = iQuad;
- aBestRate = aBadRate;
+ }
+
+ // 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 ( iSplit == iBestQuad )
+ newElem = aMesh->AddFace (linkNodes[ i1++ ],
+ linkNodes[ i2++ ],
+ nodes[ i3 ],
+ nodes[ i4 ]);
+ else
+ newElem = aMesh->AddFace (linkNodes[ i1++ ],
+ linkNodes[ i2++ ],
+ nodes[ iSplit < iBestQuad ? i4 : i3 ]);
+ myLastCreatedElems.Append(newElem);
+ if ( aShapeId && newElem )
+ aMesh->SetMeshElementOnShape( newElem, aShapeId );
+ }
+
+ // change nodes of theFace
+ const SMDS_MeshNode* newNodes[ 4 ];
+ newNodes[ 0 ] = linkNodes[ i1 ];
+ newNodes[ 1 ] = linkNodes[ i2 ];
+ newNodes[ 2 ] = nodes[ iSplit >= iBestQuad ? i3 : i4 ];
+ newNodes[ 3 ] = nodes[ i4 ];
+ aMesh->ChangeElementNodes( theFace, newNodes, iSplit == iBestQuad ? 4 : 3 );
+ } // end if(!theFace->IsQuadratic())
+ else { // theFace is quadratic
+ // we have to split theFace on simple triangles and one simple quadrangle
+ int tmp = il1/2;
+ int nbshift = tmp*2;
+ // shift nodes in nodes[] by nbshift
+ int i,j;
+ for(i=0; i<nbshift; i++) {
+ const SMDS_MeshNode* n = nodes[0];
+ for(j=0; j<nbFaceNodes-1; j++) {
+ nodes[j] = nodes[j+1];
}
+ nodes[nbFaceNodes-1] = n;
}
- }
+ 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
+ // \ / | |
+ // \ / | |
+ // + +-----+-----+
+ // n4 n6 n5 n4
+
+ // create new elements
+ SMESHDS_Mesh *aMesh = GetMeshDS();
+ int aShapeId = FindShape( theFace );
- // 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 ( iSplit == iBestQuad )
- newElem = aMesh->AddFace (linkNodes[ i1++ ],
- linkNodes[ i2++ ],
- nodes[ i3 ],
- nodes[ i4 ]);
- else
- newElem = aMesh->AddFace (linkNodes[ i1++ ],
- linkNodes[ i2++ ],
- nodes[ iSplit < iBestQuad ? i4 : i3 ]);
- if ( aShapeId && newElem )
- aMesh->SetMeshElementOnShape( newElem, aShapeId );
+ int n1,n2,n3;
+ if(nbFaceNodes==6) { // quadratic triangle
+ SMDS_MeshElement* newElem =
+ aMesh->AddFace(nodes[3],nodes[4],nodes[5]);
+ myLastCreatedElems.Append(newElem);
+ if ( aShapeId && newElem )
+ aMesh->SetMeshElementOnShape( newElem, aShapeId );
+ if(theFace->IsMediumNode(nodes[il1])) {
+ // create quadrangle
+ newElem = aMesh->AddFace(nodes[0],nodes[1],nodes[3],nodes[5]);
+ myLastCreatedElems.Append(newElem);
+ if ( aShapeId && newElem )
+ aMesh->SetMeshElementOnShape( newElem, aShapeId );
+ n1 = 1;
+ n2 = 2;
+ n3 = 3;
+ }
+ else {
+ // create quadrangle
+ newElem = aMesh->AddFace(nodes[1],nodes[2],nodes[3],nodes[5]);
+ myLastCreatedElems.Append(newElem);
+ if ( aShapeId && newElem )
+ aMesh->SetMeshElementOnShape( newElem, aShapeId );
+ n1 = 0;
+ n2 = 1;
+ n3 = 5;
+ }
+ }
+ else { // nbFaceNodes==8 - quadratic quadrangle
+ SMDS_MeshElement* newElem =
+ aMesh->AddFace(nodes[3],nodes[4],nodes[5]);
+ myLastCreatedElems.Append(newElem);
+ if ( aShapeId && newElem )
+ aMesh->SetMeshElementOnShape( newElem, aShapeId );
+ newElem = aMesh->AddFace(nodes[5],nodes[6],nodes[7]);
+ myLastCreatedElems.Append(newElem);
+ if ( aShapeId && newElem )
+ aMesh->SetMeshElementOnShape( newElem, aShapeId );
+ newElem = aMesh->AddFace(nodes[5],nodes[7],nodes[3]);
+ myLastCreatedElems.Append(newElem);
+ if ( aShapeId && newElem )
+ aMesh->SetMeshElementOnShape( newElem, aShapeId );
+ if(theFace->IsMediumNode(nodes[il1])) {
+ // create quadrangle
+ newElem = aMesh->AddFace(nodes[0],nodes[1],nodes[3],nodes[7]);
+ myLastCreatedElems.Append(newElem);
+ if ( aShapeId && newElem )
+ aMesh->SetMeshElementOnShape( newElem, aShapeId );
+ n1 = 1;
+ n2 = 2;
+ n3 = 3;
+ }
+ else {
+ // create quadrangle
+ newElem = aMesh->AddFace(nodes[1],nodes[2],nodes[3],nodes[7]);
+ myLastCreatedElems.Append(newElem);
+ if ( aShapeId && newElem )
+ aMesh->SetMeshElementOnShape( newElem, aShapeId );
+ n1 = 0;
+ n2 = 1;
+ n3 = 7;
+ }
+ }
+ // create needed triangles using n1,n2,n3 and inserted nodes
+ int nbn = 2 + aNodesToInsert.size();
+ const SMDS_MeshNode* aNodes[nbn];
+ aNodes[0] = nodes[n1];
+ aNodes[nbn-1] = nodes[n2];
+ list<const SMDS_MeshNode*>::iterator nIt = aNodesToInsert.begin();
+ for ( iNode = 1; nIt != aNodesToInsert.end(); nIt++ ) {
+ aNodes[iNode++] = *nIt;
+ }
+ for(i=1; i<nbn; i++) {
+ SMDS_MeshElement* newElem =
+ aMesh->AddFace(aNodes[i-1],aNodes[i],nodes[n3]);
+ myLastCreatedElems.Append(newElem);
+ if ( aShapeId && newElem )
+ aMesh->SetMeshElementOnShape( newElem, aShapeId );
+ }
+ // remove old quadratic face
+ aMesh->RemoveElement(theFace);
}
-
- // change nodes of theFace
- const SMDS_MeshNode* newNodes[ 4 ];
- newNodes[ 0 ] = linkNodes[ i1 ];
- newNodes[ 1 ] = linkNodes[ i2 ];
- newNodes[ 2 ] = nodes[ iSplit >= iBestQuad ? i3 : i4 ];
- newNodes[ 3 ] = nodes[ i4 ];
- aMesh->ChangeElementNodes( theFace, newNodes, iSplit == iBestQuad ? 4 : 3 );
}
//=======================================================================
const SMDS_MeshNode* theBetweenNode2,
list<const SMDS_MeshNode*>& theNodesToInsert)
{
- SMDS_ElemIteratorPtr invElemIt = theBetweenNode1->GetInverseElementIterator();
+ myLastCreatedElems.Clear();
+ myLastCreatedNodes.Clear();
+
+ SMDS_ElemIteratorPtr invElemIt = theBetweenNode1->GetInverseElementIterator(SMDSAbs_Volume);
while (invElemIt->more()) { // loop on inverse elements of theBetweenNode1
const SMDS_MeshElement* elem = invElemIt->next();
- if (elem->GetType() != SMDSAbs_Volume)
- continue;
// check, if current volume has link theBetweenNode1 - theBetweenNode2
SMDS_VolumeTool aVolume (elem);
poly_nodes.push_back(*nIt);
}
}
- } else if (faceNodes[inode] == theBetweenNode2) {
+ }
+ else if (faceNodes[inode] == theBetweenNode2) {
if (faceNodes[inode + 1] == theBetweenNode1) {
nbInserted = theNodesToInsert.size();
}
poly_nodes.push_back(*nIt);
}
- } else {
+ }
+ else {
}
}
}
if (elem->IsPoly()) {
aMesh->ChangePolyhedronNodes(elem, poly_nodes, quantities);
- } else {
+ }
+ else {
int aShapeId = FindShape( elem );
SMDS_MeshElement* newElem =
aMesh->AddPolyhedralVolume(poly_nodes, quantities);
+ myLastCreatedElems.Append(newElem);
if (aShapeId && newElem)
aMesh->SetMeshElementOnShape(newElem, aShapeId);
}
}
+//=======================================================================
+//function : ConvertElemToQuadratic
+//purpose :
+//=======================================================================
+void SMESH_MeshEditor::ConvertElemToQuadratic(SMESHDS_SubMesh *theSm,
+ SMESH_MesherHelper* theHelper,
+ const bool theForce3d)
+{
+ if( !theSm ) return;
+ SMESHDS_Mesh* meshDS = GetMeshDS();
+ SMDS_ElemIteratorPtr ElemItr = theSm->GetElements();
+ while(ElemItr->more())
+ {
+ const SMDS_MeshElement* elem = ElemItr->next();
+ if( !elem ) 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();
+ const SMDS_MeshElement* NewElem = 0;
+
+ switch( aType )
+ {
+ case SMDSAbs_Edge :
+ {
+ meshDS->RemoveFreeElement(elem, theSm);
+ NewElem = theHelper->AddQuadraticEdge(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);
+ break;
+ case 4:
+ NewElem = theHelper->AddFace(aNds[0], aNds[1], aNds[2], aNds[3], id, theForce3d);
+ break;
+ default:
+ continue;
+ }
+ 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);
+ break;
+ case 6:
+ 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);
+ break;
+ default:
+ continue;
+ }
+ break;
+ }
+ default :
+ continue;
+ }
+ if( NewElem )
+ {
+ AddToSameGroups( NewElem, elem, meshDS);
+ theSm->AddElement( NewElem );
+ }
+ }
+}
+
+//=======================================================================
+//function : ConvertToQuadratic
+//purpose :
+//=======================================================================
+void SMESH_MeshEditor::ConvertToQuadratic(const bool theForce3d)
+{
+ SMESHDS_Mesh* meshDS = GetMeshDS();
+
+ SMESH_MesherHelper* aHelper = new SMESH_MesherHelper(*myMesh);
+ aHelper->SetKeyIsQuadratic( 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() );
+ ConvertElemToQuadratic(sm, aHelper, theForce3d);
+ }
+ aHelper->SetSubShape( aSubMesh->GetSubShape() );
+ ConvertElemToQuadratic(aSubMesh->GetSubMeshDS(), aHelper, theForce3d);
+ }
+ else
+ {
+ SMDS_EdgeIteratorPtr aEdgeItr = meshDS->edgesIterator();
+ while(aEdgeItr->more())
+ {
+ const SMDS_MeshEdge* edge = aEdgeItr->next();
+ if(edge)
+ {
+ 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);
+ }
+ }
+ SMDS_FaceIteratorPtr aFaceItr = meshDS->facesIterator();
+ while(aFaceItr->more())
+ {
+ 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);
+
+ for(int i = 0; i < nbNodes; i++)
+ {
+ 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);
+ break;
+ case 4:
+ NewFace = aHelper->AddFace(aNds[0], aNds[1], aNds[2], aNds[3], id, theForce3d);
+ break;
+ default:
+ continue;
+ }
+ AddToSameGroups(NewFace, 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);
+
+ for(int i = 0; i < nbNodes; i++)
+ {
+ 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 );
+ break;
+ case 6:
+ 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);
+ break;
+ default:
+ continue;
+ }
+ AddToSameGroups(NewVolume, volume, meshDS);
+ }
+ }
+ delete aHelper;
+}
+
+//=======================================================================
+//function : RemoveQuadElem
+//purpose :
+//=======================================================================
+void SMESH_MeshEditor::RemoveQuadElem(SMESHDS_SubMesh *theSm,
+ SMDS_ElemIteratorPtr theItr,
+ RemoveQuadNodeMap& theRemoveNodeMap)
+{
+ SMESHDS_Mesh* meshDS = GetMeshDS();
+ while( theItr->more() )
+ {
+ const SMDS_MeshElement* elem = theItr->next();
+ if( elem )
+ {
+ if( !elem->IsQuadratic() )
+ continue;
+
+ int id = elem->GetID();
+
+ int nbNodes = elem->NbNodes(), idx = 0;
+ vector<const SMDS_MeshNode *> aNds;
+
+ 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
+ aNds.push_back( n );
+ }
+
+ idx = aNds.size();
+ if( !idx ) 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 )
+ theSm->AddElement( NewElem );
+ }
+ }
+}
+//=======================================================================
+//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 );
+ }
+ SMESHDS_SubMesh *Sm = aSubMesh->GetSubMeshDS();
+ if( Sm )
+ RemoveQuadElem( Sm, Sm->GetElements(), aRemoveNodeMap );
+ }
+ 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 );
+ }
+
+ return true;
+}
+
//=======================================================================
//function : SewSideElements
//purpose :
//=======================================================================
SMESH_MeshEditor::Sew_Error
- SMESH_MeshEditor::SewSideElements (set<const SMDS_MeshElement*>& theSide1,
- set<const SMDS_MeshElement*>& theSide2,
- const SMDS_MeshNode* theFirstNode1,
- const SMDS_MeshNode* theFirstNode2,
- const SMDS_MeshNode* theSecondNode1,
- const SMDS_MeshNode* theSecondNode2)
+ SMESH_MeshEditor::SewSideElements (TIDSortedElemSet& theSide1,
+ TIDSortedElemSet& theSide2,
+ const SMDS_MeshNode* theFirstNode1,
+ const SMDS_MeshNode* theFirstNode2,
+ const SMDS_MeshNode* theSecondNode1,
+ const SMDS_MeshNode* theSecondNode2)
{
+ myLastCreatedElems.Clear();
+ myLastCreatedNodes.Clear();
+
MESSAGE ("::::SewSideElements()");
if ( theSide1.size() != theSide2.size() )
return SEW_DIFF_NB_OF_ELEMENTS;
set<const SMDS_MeshElement*> * faceSetPtr[] = { &faceSet1, &faceSet2 };
set<const SMDS_MeshElement*> * volSetPtr[] = { &volSet1, &volSet2 };
set<const SMDS_MeshNode*> * nodeSetPtr[] = { &nodeSet1, &nodeSet2 };
- set<const SMDS_MeshElement*> * elemSetPtr[] = { &theSide1, &theSide2 };
+ TIDSortedElemSet * elemSetPtr[] = { &theSide1, &theSide2 };
int iSide, iFace, iNode;
for ( iSide = 0; iSide < 2; iSide++ ) {
set<const SMDS_MeshNode*> * nodeSet = nodeSetPtr[ iSide ];
- set<const SMDS_MeshElement*> * elemSet = elemSetPtr[ iSide ];
+ TIDSortedElemSet * elemSet = elemSetPtr[ iSide ];
set<const SMDS_MeshElement*> * faceSet = faceSetPtr[ iSide ];
set<const SMDS_MeshElement*> * volSet = volSetPtr [ iSide ];
- set<const SMDS_MeshElement*>::iterator vIt, eIt;
+ set<const SMDS_MeshElement*>::iterator vIt;
+ TIDSortedElemSet::iterator eIt;
set<const SMDS_MeshNode*>::iterator nIt;
- // -----------------------------------------------------------
- // 1a. Collect nodes of existing faces
- // and build set of face nodes in order to detect missing
- // faces corresponing to sides of volumes
- // -----------------------------------------------------------
+ // check that given nodes belong to given elements
+ const SMDS_MeshNode* n1 = ( iSide == 0 ) ? theFirstNode1 : theFirstNode2;
+ const SMDS_MeshNode* n2 = ( iSide == 0 ) ? theSecondNode1 : theSecondNode2;
+ int firstIndex = -1, secondIndex = -1;
+ for (eIt = elemSet->begin(); eIt != elemSet->end(); eIt++ ) {
+ const SMDS_MeshElement* elem = *eIt;
+ if ( firstIndex < 0 ) firstIndex = elem->GetNodeIndex( n1 );
+ if ( secondIndex < 0 ) secondIndex = elem->GetNodeIndex( n2 );
+ if ( firstIndex > -1 && secondIndex > -1 ) break;
+ }
+ if ( firstIndex < 0 || secondIndex < 0 ) {
+ // we can simply return until temporary faces created
+ return (iSide == 0 ) ? SEW_BAD_SIDE1_NODES : SEW_BAD_SIDE2_NODES;
+ }
+
+ // -----------------------------------------------------------
+ // 1a. Collect nodes of existing faces
+ // and build set of face nodes in order to detect missing
+ // faces corresponing to sides of volumes
+ // -----------------------------------------------------------
set< set <const SMDS_MeshNode*> > setOfFaceNodeSet;
// loop on the given element of a side
for (eIt = elemSet->begin(); eIt != elemSet->end(); eIt++ ) {
+ //const SMDS_MeshElement* elem = *eIt;
const SMDS_MeshElement* elem = *eIt;
if ( elem->GetType() == SMDSAbs_Face ) {
faceSet->insert( elem );
// ------------------------------------------------------------------------------
for ( nIt = nodeSet->begin(); nIt != nodeSet->end(); nIt++ ) { // loop on nodes of iSide
- SMDS_ElemIteratorPtr fIt = (*nIt)->facesIterator();
+ SMDS_ElemIteratorPtr fIt = (*nIt)->GetInverseElementIterator(SMDSAbs_Face);
while ( fIt->more() ) { // loop on faces sharing a node
const SMDS_MeshElement* f = fIt->next();
if ( faceSet->find( f ) == faceSet->end() ) {
// face does not exist
// -------------------------------------------------------------------------
- if ( !volSet->empty() )
- {
+ if ( !volSet->empty() ) {
//int nodeSetSize = nodeSet->size();
// loop on given volumes
// no such a face is given but it still can exist, check it
if ( nbNodes == 3 ) {
aFreeFace = aMesh->FindFace( fNodes[0],fNodes[1],fNodes[2] );
- } else if ( nbNodes == 4 ) {
+ }
+ 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];
- }
+ }
+ else {
+ vector<const SMDS_MeshNode *> poly_nodes ( fNodes, & fNodes[nbNodes]);
aFreeFace = aMesh->FindFace(poly_nodes);
}
}
// create a temporary face
if ( nbNodes == 3 ) {
aFreeFace = aTmpFacesMesh.AddFace( fNodes[0],fNodes[1],fNodes[2] );
- } else if ( nbNodes == 4 ) {
+ }
+ 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];
- }
+ }
+ else {
+ vector<const SMDS_MeshNode *> poly_nodes ( fNodes, & fNodes[nbNodes]);
aFreeFace = aTmpFacesMesh.AddPolygonalFace(poly_nodes);
}
}
// choose a face most close to the bary center of the opposite side
gp_XYZ aBC( 0., 0., 0. );
set <const SMDS_MeshNode*> addedNodes;
- set<const SMDS_MeshElement*> * elemSet2 = elemSetPtr[ 1 - iSide ];
+ TIDSortedElemSet * elemSet2 = elemSetPtr[ 1 - iSide ];
eIt = elemSet2->begin();
for ( eIt = elemSet2->begin(); eIt != elemSet2->end(); eIt++ ) {
SMDS_ElemIteratorPtr nodeIt = (*eIt)->nodesIterator();
// // ----------------------------------------------------------
// if ( nodeSetSize != nodeSet->size() ) {
// for ( ; nIt != nodeSet->end(); nIt++ ) { // loop on nodes of iSide
-// SMDS_ElemIteratorPtr fIt = (*nIt)->facesIterator();
+// SMDS_ElemIteratorPtr fIt = (*nIt)->GetInverseElementIterator(SMDSAbs_Face);
// while ( fIt->more() ) { // loop on faces sharing a node
// const SMDS_MeshElement* f = fIt->next();
// if ( faceSet->find( f ) == faceSet->end() ) {
set< long > linkIdSet; // links to process
linkIdSet.insert( aLinkID_Gen.GetLinkID( theFirstNode1, theSecondNode1 ));
- typedef pair< const SMDS_MeshNode*, const SMDS_MeshNode* > TPairOfNodes;
- list< TPairOfNodes > linkList[2];
- linkList[0].push_back( TPairOfNodes( theFirstNode1, theSecondNode1 ));
- linkList[1].push_back( TPairOfNodes( theFirstNode2, theSecondNode2 ));
+ typedef pair< const SMDS_MeshNode*, const SMDS_MeshNode* > NLink;
+ list< NLink > linkList[2];
+ linkList[0].push_back( NLink( theFirstNode1, theSecondNode1 ));
+ linkList[1].push_back( NLink( theFirstNode2, theSecondNode2 ));
// loop on links in linkList; find faces by links and append links
// of the found faces to linkList
- list< TPairOfNodes >::iterator linkIt[] = { linkList[0].begin(), linkList[1].begin() } ;
- for ( ; linkIt[0] != linkList[0].end(); linkIt[0]++, linkIt[1]++ )
- {
- TPairOfNodes link[] = { *linkIt[0], *linkIt[1] };
+ list< NLink >::iterator linkIt[] = { linkList[0].begin(), linkList[1].begin() } ;
+ for ( ; linkIt[0] != linkList[0].end(); linkIt[0]++, linkIt[1]++ ) {
+ NLink link[] = { *linkIt[0], *linkIt[1] };
long linkID = aLinkID_Gen.GetLinkID( link[0].first, link[0].second );
if ( linkIdSet.find( linkID ) == linkIdSet.end() )
continue;
// ---------------------------------------------------------------
const SMDS_MeshElement* face[] = { 0, 0 };
- const SMDS_MeshNode* faceNodes[ 2 ][ 5 ];
- const SMDS_MeshNode* notLinkNodes[ 2 ][ 2 ] = {{ 0, 0 },{ 0, 0 }} ;
+ //const SMDS_MeshNode* faceNodes[ 2 ][ 5 ];
+ vector<const SMDS_MeshNode*> fnodes1(9);
+ vector<const SMDS_MeshNode*> fnodes2(9);
+ //const SMDS_MeshNode* notLinkNodes[ 2 ][ 2 ] = {{ 0, 0 },{ 0, 0 }} ;
+ vector<const SMDS_MeshNode*> notLinkNodes1(6);
+ vector<const SMDS_MeshNode*> notLinkNodes2(6);
int iLinkNode[2][2];
for ( iSide = 0; iSide < 2; iSide++ ) { // loop on 2 sides
const SMDS_MeshNode* n1 = link[iSide].first;
set< const SMDS_MeshElement* > fMap;
for ( int i = 0; i < 2; i++ ) { // loop on 2 nodes of a link
const SMDS_MeshNode* n = i ? n1 : n2; // a node of a link
- SMDS_ElemIteratorPtr fIt = n->facesIterator();
+ SMDS_ElemIteratorPtr fIt = n->GetInverseElementIterator(SMDSAbs_Face);
while ( fIt->more() ) { // loop on faces sharing a node
const SMDS_MeshElement* f = fIt->next();
if (faceSet->find( f ) != faceSet->end() && // f is in face set
faceSet->erase( f );
// get face nodes and find ones of a link
iNode = 0;
- SMDS_ElemIteratorPtr nIt = f->nodesIterator();
- while ( nIt->more() ) {
- const SMDS_MeshNode* n =
- static_cast<const SMDS_MeshNode*>( nIt->next() );
- if ( n == n1 )
- iLinkNode[ iSide ][ 0 ] = iNode;
- else if ( n == n2 )
- iLinkNode[ iSide ][ 1 ] = iNode;
- else if ( notLinkNodes[ iSide ][ 0 ] )
- notLinkNodes[ iSide ][ 1 ] = n;
- else
- notLinkNodes[ iSide ][ 0 ] = n;
- faceNodes[ iSide ][ iNode++ ] = n;
+ int nbl = -1;
+ if(f->IsPoly()) {
+ if(iSide==0) {
+ fnodes1.resize(f->NbNodes()+1);
+ notLinkNodes1.resize(f->NbNodes()-2);
+ }
+ else {
+ fnodes2.resize(f->NbNodes()+1);
+ notLinkNodes2.resize(f->NbNodes()-2);
+ }
+ }
+ if(!f->IsQuadratic()) {
+ SMDS_ElemIteratorPtr nIt = f->nodesIterator();
+ while ( nIt->more() ) {
+ const SMDS_MeshNode* n =
+ static_cast<const SMDS_MeshNode*>( nIt->next() );
+ if ( n == n1 ) {
+ iLinkNode[ iSide ][ 0 ] = iNode;
+ }
+ else if ( n == n2 ) {
+ iLinkNode[ iSide ][ 1 ] = iNode;
+ }
+ //else if ( notLinkNodes[ iSide ][ 0 ] )
+ // notLinkNodes[ iSide ][ 1 ] = n;
+ //else
+ // notLinkNodes[ iSide ][ 0 ] = n;
+ else {
+ nbl++;
+ if(iSide==0)
+ notLinkNodes1[nbl] = n;
+ //notLinkNodes1.push_back(n);
+ else
+ notLinkNodes2[nbl] = n;
+ //notLinkNodes2.push_back(n);
+ }
+ //faceNodes[ iSide ][ iNode++ ] = n;
+ if(iSide==0) {
+ fnodes1[iNode++] = n;
+ }
+ else {
+ fnodes2[iNode++] = n;
+ }
+ }
+ }
+ else { // f->IsQuadratic()
+ const SMDS_QuadraticFaceOfNodes* F =
+ static_cast<const SMDS_QuadraticFaceOfNodes*>(f);
+ // use special nodes iterator
+ SMDS_NodeIteratorPtr anIter = F->interlacedNodesIterator();
+ while ( anIter->more() ) {
+ const SMDS_MeshNode* n =
+ static_cast<const SMDS_MeshNode*>( anIter->next() );
+ if ( n == n1 ) {
+ iLinkNode[ iSide ][ 0 ] = iNode;
+ }
+ else if ( n == n2 ) {
+ iLinkNode[ iSide ][ 1 ] = iNode;
+ }
+ else {
+ nbl++;
+ if(iSide==0) {
+ notLinkNodes1[nbl] = n;
+ }
+ else {
+ notLinkNodes2[nbl] = n;
+ }
+ }
+ if(iSide==0) {
+ fnodes1[iNode++] = n;
+ }
+ else {
+ fnodes2[iNode++] = n;
+ }
+ }
+ }
+ //faceNodes[ iSide ][ iNode ] = faceNodes[ iSide ][ 0 ];
+ if(iSide==0) {
+ fnodes1[iNode] = fnodes1[0];
+ }
+ else {
+ fnodes2[iNode] = fnodes1[0];
}
- faceNodes[ iSide ][ iNode ] = faceNodes[ iSide ][ 0 ];
}
}
}
}
+
// check similarity of elements of the sides
if (aResult == SEW_OK && ( face[0] && !face[1] ) || ( !face[0] && face[1] )) {
MESSAGE("Correspondent face not found on side " << ( face[0] ? 1 : 0 ));
- if ( nReplaceMap.size() == 2 ) // faces on input nodes not found
+ if ( nReplaceMap.size() == 2 ) { // faces on input nodes not found
aResult = ( face[0] ? SEW_BAD_SIDE2_NODES : SEW_BAD_SIDE1_NODES );
- else
+ }
+ else {
aResult = SEW_TOPO_DIFF_SETS_OF_ELEMENTS;
+ }
break; // do not return because it s necessary to remove tmp faces
}
// set nodes to merge
// -------------------
- if ( face[0] && face[1] )
- {
+ if ( face[0] && face[1] ) {
int nbNodes = face[0]->NbNodes();
if ( nbNodes != face[1]->NbNodes() ) {
MESSAGE("Diff nb of face nodes");
break; // do not return because it s necessary to remove tmp faces
}
bool reverse[] = { false, false }; // order of notLinkNodes of quadrangle
- if ( nbNodes == 3 )
+ if ( nbNodes == 3 ) {
+ //nReplaceMap.insert( TNodeNodeMap::value_type
+ // ( notLinkNodes[0][0], notLinkNodes[1][0] ));
nReplaceMap.insert( TNodeNodeMap::value_type
- ( notLinkNodes[0][0], notLinkNodes[1][0] ));
+ ( notLinkNodes1[0], notLinkNodes2[0] ));
+ }
else {
for ( iSide = 0; iSide < 2; iSide++ ) { // loop on 2 sides
// analyse link orientation in faces
reverse[ iSide ] = !reverse[ iSide ];
}
if ( reverse[0] == reverse[1] ) {
- nReplaceMap.insert( TNodeNodeMap::value_type
- ( notLinkNodes[0][0], notLinkNodes[1][0] ));
- nReplaceMap.insert( TNodeNodeMap::value_type
- ( notLinkNodes[0][1], notLinkNodes[1][1] ));
+ //nReplaceMap.insert( TNodeNodeMap::value_type
+ // ( notLinkNodes[0][0], notLinkNodes[1][0] ));
+ //nReplaceMap.insert( TNodeNodeMap::value_type
+ // ( notLinkNodes[0][1], notLinkNodes[1][1] ));
+ for(int nn=0; nn<nbNodes-2; nn++) {
+ nReplaceMap.insert( TNodeNodeMap::value_type
+ ( notLinkNodes1[nn], notLinkNodes2[nn] ));
+ }
}
else {
- nReplaceMap.insert( TNodeNodeMap::value_type
- ( notLinkNodes[0][0], notLinkNodes[1][1] ));
- nReplaceMap.insert( TNodeNodeMap::value_type
- ( notLinkNodes[0][1], notLinkNodes[1][0] ));
+ //nReplaceMap.insert( TNodeNodeMap::value_type
+ // ( notLinkNodes[0][0], notLinkNodes[1][1] ));
+ //nReplaceMap.insert( TNodeNodeMap::value_type
+ // ( notLinkNodes[0][1], notLinkNodes[1][0] ));
+ for(int nn=0; nn<nbNodes-2; nn++) {
+ nReplaceMap.insert( TNodeNodeMap::value_type
+ ( notLinkNodes1[nn], notLinkNodes2[nbNodes-3-nn] ));
+ }
}
}
// add other links of the faces to linkList
// -----------------------------------------
- const SMDS_MeshNode** nodes = faceNodes[ 0 ];
- for ( iNode = 0; iNode < nbNodes; iNode++ )
- {
- linkID = aLinkID_Gen.GetLinkID( nodes[iNode], nodes[iNode+1] );
+ //const SMDS_MeshNode** nodes = faceNodes[ 0 ];
+ for ( iNode = 0; iNode < nbNodes; iNode++ ) {
+ //linkID = aLinkID_Gen.GetLinkID( nodes[iNode], nodes[iNode+1] );
+ linkID = aLinkID_Gen.GetLinkID( fnodes1[iNode], fnodes1[iNode+1] );
pair< set<long>::iterator, bool > iter_isnew = linkIdSet.insert( linkID );
if ( !iter_isnew.second ) { // already in a set: no need to process
linkIdSet.erase( iter_isnew.first );
}
else // new in set == encountered for the first time: add
{
- const SMDS_MeshNode* n1 = nodes[ iNode ];
- const SMDS_MeshNode* n2 = nodes[ iNode + 1];
- linkList[0].push_back ( TPairOfNodes( n1, n2 ));
- linkList[1].push_back ( TPairOfNodes( nReplaceMap[n1], nReplaceMap[n2] ));
+ //const SMDS_MeshNode* n1 = nodes[ iNode ];
+ //const SMDS_MeshNode* n2 = nodes[ iNode + 1];
+ const SMDS_MeshNode* n1 = fnodes1[ iNode ];
+ const SMDS_MeshNode* n2 = fnodes1[ iNode + 1];
+ linkList[0].push_back ( NLink( n1, n2 ));
+ linkList[1].push_back ( NLink( nReplaceMap[n1], nReplaceMap[n2] ));
}
}
} // 2 faces found
// loop on nodes replacement map
TNodeNodeMap::iterator nReplaceMapIt = nReplaceMap.begin(), nnIt;
for ( ; nReplaceMapIt != nReplaceMap.end(); nReplaceMapIt++ )
- if ( (*nReplaceMapIt).first != (*nReplaceMapIt).second )
- {
+ if ( (*nReplaceMapIt).first != (*nReplaceMapIt).second ) {
const SMDS_MeshNode* nToRemove = (*nReplaceMapIt).first;
nodeIDsToRemove.push_back( nToRemove->GetID() );
// loop on elements sharing nToRemove
const SMDS_MeshElement* e = invElemIt->next();
// get a new suite of nodes: make replacement
int nbReplaced = 0, i = 0, nbNodes = e->NbNodes();
- const SMDS_MeshNode* nodes[ 8 ];
+ vector< const SMDS_MeshNode*> nodes( nbNodes );
SMDS_ElemIteratorPtr nIt = e->nodesIterator();
while ( nIt->more() ) {
const SMDS_MeshNode* n =
// elemIDsToRemove.push_back( e->GetID() );
// else
if ( nbReplaced )
- aMesh->ChangeElementNodes( e, nodes, nbNodes );
+ aMesh->ChangeElementNodes( e, & nodes[0], nbNodes );
}
- }
+ }
Remove( nodeIDsToRemove, 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
+ * \param theSide1 - first face set
+ * \param theSide2 - second first face
+ * \param theFirstNode1 - a boundary node of set 1
+ * \param theFirstNode2 - a node of set 2 corresponding to theFirstNode1
+ * \param theSecondNode1 - a boundary node of set 1 linked with theFirstNode1
+ * \param theSecondNode2 - a node of set 2 corresponding to theSecondNode1
+ * \param nReplaceMap - output map of corresponding nodes
+ * \retval bool - is a success or not
+ */
+//================================================================================
+
+//#define DEBUG_MATCHING_NODES
+
+SMESH_MeshEditor::Sew_Error
+SMESH_MeshEditor::FindMatchingNodes(set<const SMDS_MeshElement*>& theSide1,
+ set<const SMDS_MeshElement*>& theSide2,
+ const SMDS_MeshNode* theFirstNode1,
+ const SMDS_MeshNode* theFirstNode2,
+ const SMDS_MeshNode* theSecondNode1,
+ const SMDS_MeshNode* theSecondNode2,
+ TNodeNodeMap & nReplaceMap)
+{
+ set<const SMDS_MeshElement*> * faceSetPtr[] = { &theSide1, &theSide2 };
+
+ nReplaceMap.clear();
+ if ( theFirstNode1 != theFirstNode2 )
+ nReplaceMap.insert( make_pair( theFirstNode1, theFirstNode2 ));
+ if ( theSecondNode1 != theSecondNode2 )
+ nReplaceMap.insert( make_pair( theSecondNode1, theSecondNode2 ));
+
+ set< TLink > linkSet; // set of nodes where order of nodes is ignored
+ linkSet.insert( TLink( theFirstNode1, theSecondNode1 ));
+
+ list< NLink > linkList[2];
+ linkList[0].push_back( NLink( theFirstNode1, theSecondNode1 ));
+ linkList[1].push_back( NLink( theFirstNode2, theSecondNode2 ));
+
+ // loop on links in linkList; find faces by links and append links
+ // of the found faces to linkList
+ list< NLink >::iterator linkIt[] = { linkList[0].begin(), linkList[1].begin() } ;
+ for ( ; linkIt[0] != linkList[0].end(); linkIt[0]++, linkIt[1]++ ) {
+ NLink link[] = { *linkIt[0], *linkIt[1] };
+ if ( linkSet.find( link[0] ) == linkSet.end() )
+ continue;
+
+ // by links, find faces in the face sets,
+ // and find indices of link nodes in the found faces;
+ // in a face set, there is only one or no face sharing a link
+ // ---------------------------------------------------------------
+
+ const SMDS_MeshElement* face[] = { 0, 0 };
+ list<const SMDS_MeshNode*> notLinkNodes[2];
+ //bool reverse[] = { false, false }; // order of notLinkNodes
+ int nbNodes[2];
+ for ( int iSide = 0; iSide < 2; iSide++ ) // loop on 2 sides
+ {
+ const SMDS_MeshNode* n1 = link[iSide].first;
+ const SMDS_MeshNode* n2 = link[iSide].second;
+ set<const SMDS_MeshElement*> * faceSet = faceSetPtr[ iSide ];
+ set< const SMDS_MeshElement* > facesOfNode1;
+ for ( int iNode = 0; iNode < 2; iNode++ ) // loop on 2 nodes of a link
+ {
+ // during a loop of the first node, we find all faces around n1,
+ // during a loop of the second node, we find one face sharing both n1 and n2
+ const SMDS_MeshNode* n = iNode ? n1 : n2; // a node of a link
+ SMDS_ElemIteratorPtr fIt = n->GetInverseElementIterator(SMDSAbs_Face);
+ while ( fIt->more() ) { // loop on faces sharing a node
+ const SMDS_MeshElement* f = fIt->next();
+ if (faceSet->find( f ) != faceSet->end() && // f is in face set
+ ! facesOfNode1.insert( f ).second ) // f encounters twice
+ {
+ if ( face[ iSide ] ) {
+ MESSAGE( "2 faces per link " );
+ return ( iSide ? SEW_BAD_SIDE2_NODES : SEW_BAD_SIDE1_NODES );
+ }
+ face[ iSide ] = f;
+ faceSet->erase( f );
+
+ // get not link nodes
+ int nbN = f->NbNodes();
+ if ( f->IsQuadratic() )
+ nbN /= 2;
+ nbNodes[ iSide ] = nbN;
+ list< const SMDS_MeshNode* > & nodes = notLinkNodes[ iSide ];
+ int i1 = f->GetNodeIndex( n1 );
+ int i2 = f->GetNodeIndex( n2 );
+ int iEnd = nbN, iBeg = -1, iDelta = 1;
+ bool reverse = ( Abs( i1 - i2 ) == 1 ? i1 > i2 : i2 > i1 );
+ if ( reverse ) {
+ std::swap( iEnd, iBeg ); iDelta = -1;
+ }
+ int i = i2;
+ while ( true ) {
+ i += iDelta;
+ if ( i == iEnd ) i = iBeg + iDelta;
+ if ( i == i1 ) break;
+ nodes.push_back ( f->GetNode( i ) );
+ }
+ }
+ }
+ }
+ }
+ // check similarity of elements of the sides
+ if (( face[0] && !face[1] ) || ( !face[0] && face[1] )) {
+ MESSAGE("Correspondent face not found on side " << ( face[0] ? 1 : 0 ));
+ if ( nReplaceMap.size() == 2 ) { // faces on input nodes not found
+ return ( face[0] ? SEW_BAD_SIDE2_NODES : SEW_BAD_SIDE1_NODES );
+ }
+ else {
+ return SEW_TOPO_DIFF_SETS_OF_ELEMENTS;
+ }
+ }
+
+ // set nodes to merge
+ // -------------------
+
+ if ( face[0] && face[1] ) {
+ if ( nbNodes[0] != nbNodes[1] ) {
+ MESSAGE("Diff nb of face nodes");
+ return SEW_TOPO_DIFF_SETS_OF_ELEMENTS;
+ }
+#ifdef DEBUG_MATCHING_NODES
+ cout << " Link 1: " << link[0].first->GetID() <<" "<< link[0].second->GetID()
+ << " F 1: " << face[0];
+ cout << "| Link 2: " << link[1].first->GetID() <<" "<< link[1].second->GetID()
+ << " F 2: " << face[1] << " | Bind: "<<endl ;
+#endif
+ int nbN = nbNodes[0];
+ {
+ list<const SMDS_MeshNode*>::iterator n1 = notLinkNodes[0].begin();
+ list<const SMDS_MeshNode*>::iterator n2 = notLinkNodes[1].begin();
+ for ( int i = 0 ; i < nbN - 2; ++i ) {
+#ifdef DEBUG_MATCHING_NODES
+ cout << (*n1)->GetID() << " to " << (*n2)->GetID() << endl;
+#endif
+ nReplaceMap.insert( make_pair( *(n1++), *(n2++) ));
+ }
+ }
+
+ // add other links of the face 1 to linkList
+ // -----------------------------------------
+
+ const SMDS_MeshElement* f0 = face[0];
+ const SMDS_MeshNode* n1 = f0->GetNode( nbN - 1 );
+ for ( int i = 0; i < nbN; i++ )
+ {
+ const SMDS_MeshNode* n2 = f0->GetNode( i );
+ pair< set< TLink >::iterator, bool > iter_isnew =
+ linkSet.insert( TLink( n1, n2 ));
+ if ( !iter_isnew.second ) { // already in a set: no need to process
+ linkSet.erase( iter_isnew.first );
+ }
+ else // new in set == encountered for the first time: add
+ {
+#ifdef DEBUG_MATCHING_NODES
+ cout << "Add link 1: " << n1->GetID() << " " << n2->GetID() << " ";
+ cout << " | link 2: " << nReplaceMap[n1]->GetID() << " " << nReplaceMap[n2]->GetID() << " " << endl;
+#endif
+ linkList[0].push_back ( NLink( n1, n2 ));
+ linkList[1].push_back ( NLink( nReplaceMap[n1], nReplaceMap[n2] ));
+ }
+ n1 = n2;
+ }
+ } // 2 faces found
+ } // loop on link lists
+
+ return SEW_OK;
+}