From: skl Date: Mon, 20 Feb 2006 07:50:46 +0000 (+0000) Subject: Changes for working with quadratic elements. X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=75b33910e09d2e967ef946aab69f0b133eac378b;p=modules%2Fsmesh.git Changes for working with quadratic elements. --- diff --git a/src/Controls/SMESH_Controls.cxx b/src/Controls/SMESH_Controls.cxx index 153a0baee..fdb9bfe62 100644 --- a/src/Controls/SMESH_Controls.cxx +++ b/src/Controls/SMESH_Controls.cxx @@ -164,9 +164,9 @@ bool NumericalFunctor::GetPoints(const SMDS_MeshElement* anElem, // Get nodes of the element - const SMDS_QuadraticFaceOfNodes* F = - static_cast(anElem); - if(F) { + if(anElem->IsQuadratic()) { + const SMDS_QuadraticFaceOfNodes* F = + static_cast(anElem); // use special nodes iterator SMDS_NodeIteratorPtr anIter = F->interlacedNodesIterator(); if ( anIter != 0 ) { diff --git a/src/OBJECT/SMESH_Object.cxx b/src/OBJECT/SMESH_Object.cxx index db595bc46..e49f04681 100644 --- a/src/OBJECT/SMESH_Object.cxx +++ b/src/OBJECT/SMESH_Object.cxx @@ -616,15 +616,12 @@ static inline vtkIdType getCellType( const SMDSAbs_ElementType theType, else if ( theNbNodes == 6 ) return VTK_WEDGE; else if ( theNbNodes == 8 ) return VTK_HEXAHEDRON; else if ( theNbNodes == 10 ) { - cout<<"QUADRATIC_TETRA"<( edge )->ChangeNodes( nodes[0], nodes[1] ); } + else if ( nbnodes == 3 ) { + const SMDS_QuadraticEdge* edge = dynamic_cast( elem ); + if ( edge ) + Ok = const_cast( edge )->ChangeNodes( nodes[0], nodes[1], nodes[2] ); + } break; } case SMDSAbs_Face: { const SMDS_FaceOfNodes* face = dynamic_cast( elem ); if ( face ) { Ok = const_cast( face )->ChangeNodes( nodes, nbnodes ); - } else { - /// ??? begin - const SMDS_PolygonalFaceOfNodes* face = dynamic_cast(elem); - if (face) { - Ok = const_cast(face)->ChangeNodes(nodes, nbnodes); + } + else { + const SMDS_QuadraticFaceOfNodes* QF = + dynamic_cast( elem ); + if ( QF ) { + Ok = const_cast( QF )->ChangeNodes( nodes, nbnodes ); + } + else { + /// ??? begin + const SMDS_PolygonalFaceOfNodes* face = dynamic_cast(elem); + if (face) { + Ok = const_cast(face)->ChangeNodes(nodes, nbnodes); + } + /// ??? end } - /// ??? end } break; } @@ -1112,8 +1125,15 @@ bool SMDS_Mesh::ChangeElementNodes(const SMDS_MeshElement * elem, //} case SMDSAbs_Volume: { const SMDS_VolumeOfNodes* vol = dynamic_cast( elem ); - if ( vol ) + if ( vol ) { Ok = const_cast( vol )->ChangeNodes( nodes, nbnodes ); + } + else { + const SMDS_QuadraticVolumeOfNodes* QV = dynamic_cast( elem ); + if ( QV ) { + Ok = const_cast( QV )->ChangeNodes( nodes, nbnodes ); + } + } break; } default: @@ -1203,6 +1223,7 @@ bool SMDS_Mesh::ChangePolyhedronNodes (const SMDS_MeshElement * elem, return Ok; } + //======================================================================= //function : FindEdge //purpose : @@ -1210,54 +1231,95 @@ bool SMDS_Mesh::ChangePolyhedronNodes (const SMDS_MeshElement * elem, const SMDS_MeshEdge* SMDS_Mesh::FindEdge(int idnode1, int idnode2) const { - const SMDS_MeshNode * node1=FindNode(idnode1); - const SMDS_MeshNode * node2=FindNode(idnode2); - if((node1==NULL)||(node2==NULL)) return NULL; - return FindEdge(node1,node2); + const SMDS_MeshNode * node1=FindNode(idnode1); + const SMDS_MeshNode * node2=FindNode(idnode2); + if((node1==NULL)||(node2==NULL)) return NULL; + return FindEdge(node1,node2); } //#include "Profiler.h" const SMDS_MeshEdge* SMDS_Mesh::FindEdge(const SMDS_MeshNode * node1, const SMDS_MeshNode * node2) { - const SMDS_MeshEdge * toReturn=NULL; - //PROFILER_Init(); - //PROFILER_Set(); - SMDS_ElemIteratorPtr it1=node1->edgesIterator(); - //PROFILER_Get(0); - //PROFILER_Set(); - while(it1->more()) - { - const SMDS_MeshEdge * e=static_cast - (it1->next()); - SMDS_ElemIteratorPtr it2=e->nodesIterator(); - while(it2->more()) - { - if(it2->next()->GetID()==node2->GetID()) - { - toReturn=e; - break; - } - } - } - //PROFILER_Get(1); - return toReturn; + const SMDS_MeshEdge * toReturn=NULL; + //PROFILER_Init(); + //PROFILER_Set(); + SMDS_ElemIteratorPtr it1=node1->edgesIterator(); + //PROFILER_Get(0); + //PROFILER_Set(); + while(it1->more()) { + const SMDS_MeshEdge * e=static_cast (it1->next()); + SMDS_ElemIteratorPtr it2=e->nodesIterator(); + while(it2->more()) { + if(it2->next()->GetID()==node2->GetID()) { + toReturn = e; + break; + } + } + } + //PROFILER_Get(1); + return toReturn; } +//======================================================================= +//function : FindEdgeOrCreate +//purpose : +//======================================================================= + SMDS_MeshEdge* SMDS_Mesh::FindEdgeOrCreate(const SMDS_MeshNode * node1, - const SMDS_MeshNode * node2) + const SMDS_MeshNode * node2) { - SMDS_MeshEdge * toReturn=NULL; - toReturn=const_cast(FindEdge(node1,node2)); - if(toReturn==NULL) - { - toReturn=new SMDS_MeshEdge(node1,node2); - myEdges.Add(toReturn); - } - return toReturn; + SMDS_MeshEdge * toReturn=NULL; + toReturn=const_cast(FindEdge(node1,node2)); + if(toReturn==NULL) { + toReturn=new SMDS_MeshEdge(node1,node2); + myEdges.Add(toReturn); + } + return toReturn; +} + + +//======================================================================= +//function : FindEdge +//purpose : +//======================================================================= + +const SMDS_MeshEdge* SMDS_Mesh::FindEdge(int idnode1, int idnode2, + int idnode3) const +{ + const SMDS_MeshNode * node1=FindNode(idnode1); + const SMDS_MeshNode * node2=FindNode(idnode2); + const SMDS_MeshNode * node3=FindNode(idnode3); + if( (node1==NULL) || (node2==NULL) || (node3==NULL) ) return NULL; + return FindEdge(node1,node2,node3); +} + +const SMDS_MeshEdge* SMDS_Mesh::FindEdge(const SMDS_MeshNode * node1, + const SMDS_MeshNode * node2, + const SMDS_MeshNode * node3) +{ + const SMDS_MeshEdge * toReturn = NULL; + SMDS_ElemIteratorPtr it1 = node1->edgesIterator(); + while(it1->more()) { + const SMDS_MeshEdge * e = static_cast (it1->next()); + SMDS_ElemIteratorPtr it2 = e->nodesIterator(); + int tmp = 0; + while(it2->more()) { + int nID = it2->next()->GetID(); + if( nID==node2->GetID() || nID==node3->GetID() ) { + tmp++; + if(tmp==2) { + toReturn = e; + break; + } + } + } + } + return toReturn; } + //======================================================================= //function : FindFace //purpose : @@ -1266,118 +1328,219 @@ SMDS_MeshEdge* SMDS_Mesh::FindEdgeOrCreate(const SMDS_MeshNode * node1, const SMDS_MeshFace* SMDS_Mesh::FindFace(int idnode1, int idnode2, int idnode3) const { - const SMDS_MeshNode * node1=FindNode(idnode1); - const SMDS_MeshNode * node2=FindNode(idnode2); - const SMDS_MeshNode * node3=FindNode(idnode3); - if((node1==NULL)||(node2==NULL)||(node3==NULL)) return NULL; - return FindFace(node1, node2, node3); + const SMDS_MeshNode * node1=FindNode(idnode1); + const SMDS_MeshNode * node2=FindNode(idnode2); + const SMDS_MeshNode * node3=FindNode(idnode3); + if( (node1==NULL) || (node2==NULL) || (node3==NULL) ) return NULL; + return FindFace(node1, node2, node3); } -const SMDS_MeshFace* SMDS_Mesh::FindFace( - const SMDS_MeshNode *node1, - const SMDS_MeshNode *node2, - const SMDS_MeshNode *node3) +const SMDS_MeshFace* SMDS_Mesh::FindFace(const SMDS_MeshNode *node1, + const SMDS_MeshNode *node2, + const SMDS_MeshNode *node3) { - const SMDS_MeshFace * face; - const SMDS_MeshElement * node; - bool node2found, node3found; - - SMDS_ElemIteratorPtr it1=node1->facesIterator(); - while(it1->more()) - { - face=static_cast(it1->next()); - if(face->NbNodes()!=3) continue; - SMDS_ElemIteratorPtr it2=face->nodesIterator(); - node2found=false; - node3found=false; - while(it2->more()) - { - node=it2->next(); - if(node->GetID()==node2->GetID()) node2found=true; - if(node->GetID()==node3->GetID()) node3found=true; - } - if(node2found&&node3found) - return face; - } - return NULL; + const SMDS_MeshFace * face; + const SMDS_MeshElement * node; + bool node2found, node3found; + + SMDS_ElemIteratorPtr it1 = node1->facesIterator(); + while(it1->more()) { + face = static_cast(it1->next()); + if(face->NbNodes()!=3) continue; + SMDS_ElemIteratorPtr it2 = face->nodesIterator(); + node2found = false; + node3found = false; + while(it2->more()) { + node = it2->next(); + if(node->GetID()==node2->GetID()) node2found = true; + if(node->GetID()==node3->GetID()) node3found = true; + } + if( node2found && node3found ) + return face; + } + return NULL; } -SMDS_MeshFace* SMDS_Mesh::FindFaceOrCreate( - const SMDS_MeshNode *node1, - const SMDS_MeshNode *node2, - const SMDS_MeshNode *node3) +SMDS_MeshFace* SMDS_Mesh::FindFaceOrCreate(const SMDS_MeshNode *node1, + const SMDS_MeshNode *node2, + const SMDS_MeshNode *node3) { - SMDS_MeshFace * toReturn=NULL; - toReturn=const_cast(FindFace(node1,node2,node3)); - if(toReturn==NULL) - { - toReturn=createTriangle(node1,node2,node3); - } - return toReturn; + SMDS_MeshFace * toReturn=NULL; + toReturn = const_cast(FindFace(node1,node2,node3)); + if(toReturn==NULL) { + toReturn = createTriangle(node1,node2,node3); + } + return toReturn; } + //======================================================================= //function : FindFace //purpose : //======================================================================= -const SMDS_MeshFace* SMDS_Mesh::FindFace(int idnode1, int idnode2, int idnode3, - int idnode4) const +const SMDS_MeshFace* SMDS_Mesh::FindFace(int idnode1, int idnode2, + int idnode3, int idnode4) const { - const SMDS_MeshNode * node1=FindNode(idnode1); - const SMDS_MeshNode * node2=FindNode(idnode2); - const SMDS_MeshNode * node3=FindNode(idnode3); - const SMDS_MeshNode * node4=FindNode(idnode4); - if((node1==NULL)||(node2==NULL)||(node3==NULL)||(node4==NULL)) return NULL; - return FindFace(node1, node2, node3, node4); + const SMDS_MeshNode * node1=FindNode(idnode1); + const SMDS_MeshNode * node2=FindNode(idnode2); + const SMDS_MeshNode * node3=FindNode(idnode3); + const SMDS_MeshNode * node4=FindNode(idnode4); + if( (node1==NULL) || (node2==NULL) || (node3==NULL) || (node4==NULL) ) + return NULL; + return FindFace(node1, node2, node3, node4); } -const SMDS_MeshFace* SMDS_Mesh::FindFace( - const SMDS_MeshNode *node1, - const SMDS_MeshNode *node2, - const SMDS_MeshNode *node3, - const SMDS_MeshNode *node4) +const SMDS_MeshFace* SMDS_Mesh::FindFace(const SMDS_MeshNode *node1, + const SMDS_MeshNode *node2, + const SMDS_MeshNode *node3, + const SMDS_MeshNode *node4) { - const SMDS_MeshFace * face; - const SMDS_MeshElement * node; - bool node2found, node3found, node4found; - SMDS_ElemIteratorPtr it1=node1->facesIterator(); - while(it1->more()) - { - face=static_cast(it1->next()); - if(face->NbNodes()!=4) continue; - SMDS_ElemIteratorPtr it2=face->nodesIterator(); - node2found=false; - node3found=false; - node4found=false; - while(it2->more()) - { - node=it2->next(); - if(node->GetID()==node2->GetID()) node2found=true; - if(node->GetID()==node3->GetID()) node3found=true; - if(node->GetID()==node4->GetID()) node4found=true; - } - if(node2found&&node3found&&node4found) - return face; - } - return NULL; + const SMDS_MeshFace * face; + const SMDS_MeshElement * node; + bool node2found, node3found, node4found; + SMDS_ElemIteratorPtr it1 = node1->facesIterator(); + while(it1->more()) { + face = static_cast(it1->next()); + if(face->NbNodes()!=4) continue; + SMDS_ElemIteratorPtr it2 = face->nodesIterator(); + node2found = false; + node3found = false; + node4found = false; + while(it2->more()) { + node=it2->next(); + if(node->GetID()==node2->GetID()) node2found = true; + if(node->GetID()==node3->GetID()) node3found = true; + if(node->GetID()==node4->GetID()) node4found = true; + } + if( node2found && node3found && node4found ) + return face; + } + return NULL; } -SMDS_MeshFace* SMDS_Mesh::FindFaceOrCreate( - const SMDS_MeshNode *node1, - const SMDS_MeshNode *node2, - const SMDS_MeshNode *node3, - const SMDS_MeshNode *node4) +SMDS_MeshFace* SMDS_Mesh::FindFaceOrCreate(const SMDS_MeshNode *node1, + const SMDS_MeshNode *node2, + const SMDS_MeshNode *node3, + const SMDS_MeshNode *node4) { - SMDS_MeshFace * toReturn=NULL; - toReturn=const_cast(FindFace(node1,node2,node3,node4)); - if(toReturn==NULL) - { - toReturn=createQuadrangle(node1,node2,node3,node4); - } - return toReturn; + SMDS_MeshFace * toReturn=NULL; + toReturn=const_cast(FindFace(node1,node2,node3,node4)); + if(toReturn==NULL) { + toReturn=createQuadrangle(node1,node2,node3,node4); + } + return toReturn; +} + + +//======================================================================= +//function : FindFace +//purpose :quadratic triangle +//======================================================================= + +const SMDS_MeshFace* SMDS_Mesh::FindFace(int idnode1, int idnode2, + int idnode3, int idnode4, + int idnode5, int idnode6) const +{ + const SMDS_MeshNode * node1 = FindNode(idnode1); + const SMDS_MeshNode * node2 = FindNode(idnode2); + const SMDS_MeshNode * node3 = FindNode(idnode3); + const SMDS_MeshNode * node4 = FindNode(idnode4); + const SMDS_MeshNode * node5 = FindNode(idnode5); + const SMDS_MeshNode * node6 = FindNode(idnode6); + if( (node1==NULL) || (node2==NULL) || (node3==NULL) || + (node4==NULL) || (node5==NULL) || (node6==NULL) ) return NULL; + return FindFace(node1, node2, node3, node4, node5, node6); +} + +const SMDS_MeshFace* SMDS_Mesh::FindFace(const SMDS_MeshNode *node1, + const SMDS_MeshNode *node2, + const SMDS_MeshNode *node3, + const SMDS_MeshNode *node4, + const SMDS_MeshNode *node5, + const SMDS_MeshNode *node6) +{ + const SMDS_MeshFace * face; + const SMDS_MeshElement * node; + SMDS_ElemIteratorPtr it1 = node1->facesIterator(); + while(it1->more()) { + face = static_cast(it1->next()); + if(face->NbNodes()!=6) continue; + SMDS_ElemIteratorPtr it2 = face->nodesIterator(); + int tmp = 0; + while(it2->more()) { + node = it2->next(); + if(node->GetID()==node2->GetID()) tmp++; + if(node->GetID()==node3->GetID()) tmp++; + if(node->GetID()==node4->GetID()) tmp++; + if(node->GetID()==node5->GetID()) tmp++; + if(node->GetID()==node6->GetID()) tmp++; + } + if( tmp==5 ) + return static_cast(face); + } + return NULL; +} + + +//======================================================================= +//function : FindFace +//purpose : quadratic quadrangle +//======================================================================= + +const SMDS_MeshFace* SMDS_Mesh::FindFace(int idnode1, int idnode2, + int idnode3, int idnode4, + int idnode5, int idnode6, + int idnode7, int idnode8) const +{ + const SMDS_MeshNode * node1 = FindNode(idnode1); + const SMDS_MeshNode * node2 = FindNode(idnode2); + const SMDS_MeshNode * node3 = FindNode(idnode3); + const SMDS_MeshNode * node4 = FindNode(idnode4); + const SMDS_MeshNode * node5 = FindNode(idnode5); + const SMDS_MeshNode * node6 = FindNode(idnode6); + const SMDS_MeshNode * node7 = FindNode(idnode7); + const SMDS_MeshNode * node8 = FindNode(idnode8); + if( (node1==NULL) || (node2==NULL) || (node3==NULL) || (node4==NULL) || + (node5==NULL) || (node6==NULL) || (node7==NULL) || (node8==NULL) ) + return NULL; + return FindFace(node1, node2, node3, node4, node5, node6, node7, node8); +} + +const SMDS_MeshFace* SMDS_Mesh::FindFace(const SMDS_MeshNode *node1, + const SMDS_MeshNode *node2, + const SMDS_MeshNode *node3, + const SMDS_MeshNode *node4, + const SMDS_MeshNode *node5, + const SMDS_MeshNode *node6, + const SMDS_MeshNode *node7, + const SMDS_MeshNode *node8) +{ + const SMDS_MeshFace * face; + const SMDS_MeshElement * node; + SMDS_ElemIteratorPtr it1 = node1->facesIterator(); + while(it1->more()) { + face = static_cast(it1->next()); + if(face->NbNodes()!=8) continue; + SMDS_ElemIteratorPtr it2 = face->nodesIterator(); + int tmp = 0; + while(it2->more()) { + node = it2->next(); + if(node->GetID()==node2->GetID()) tmp++; + if(node->GetID()==node3->GetID()) tmp++; + if(node->GetID()==node4->GetID()) tmp++; + if(node->GetID()==node5->GetID()) tmp++; + if(node->GetID()==node6->GetID()) tmp++; + if(node->GetID()==node7->GetID()) tmp++; + if(node->GetID()==node8->GetID()) tmp++; + } + if( tmp==7 ) + return face; + } + return NULL; } + //======================================================================= //function : FindElement //purpose : @@ -1385,7 +1548,7 @@ SMDS_MeshFace* SMDS_Mesh::FindFaceOrCreate( const SMDS_MeshElement* SMDS_Mesh::FindElement(int IDelem) const { - return myElementIDFactory->MeshElement(IDelem); + return myElementIDFactory->MeshElement(IDelem); } //======================================================================= diff --git a/src/SMDS/SMDS_Mesh.hxx b/src/SMDS/SMDS_Mesh.hxx index 2dad43052..f0835eae3 100644 --- a/src/SMDS/SMDS_Mesh.hxx +++ b/src/SMDS/SMDS_Mesh.hxx @@ -378,7 +378,7 @@ public: const SMDS_MeshNode * n12, const SMDS_MeshNode * n23, const SMDS_MeshNode * n34, - const SMDS_MeshNode * n51, + const SMDS_MeshNode * n41, const SMDS_MeshNode * n56, const SMDS_MeshNode * n67, const SMDS_MeshNode * n78, @@ -399,7 +399,7 @@ public: const SMDS_MeshNode * n12, const SMDS_MeshNode * n23, const SMDS_MeshNode * n34, - const SMDS_MeshNode * n51, + const SMDS_MeshNode * n41, const SMDS_MeshNode * n56, const SMDS_MeshNode * n67, const SMDS_MeshNode * n78, @@ -456,11 +456,19 @@ public: const SMDS_MeshNode *FindNode(int idnode) const; const SMDS_MeshEdge *FindEdge(int idnode1, int idnode2) const; + const SMDS_MeshEdge *FindEdge(int idnode1, int idnode2, int idnode3) const; const SMDS_MeshFace *FindFace(int idnode1, int idnode2, int idnode3) const; const SMDS_MeshFace *FindFace(int idnode1, int idnode2, int idnode3, int idnode4) const; + const SMDS_MeshFace *FindFace(int idnode1, int idnode2, int idnode3, + int idnode4, int idnode5, int idnode6) const; + const SMDS_MeshFace *FindFace(int idnode1, int idnode2, int idnode3, int idnode4, + int idnode5, int idnode6, int idnode7, int idnode8) const; const SMDS_MeshElement *FindElement(int IDelem) const; static const SMDS_MeshEdge* FindEdge(const SMDS_MeshNode * n1, const SMDS_MeshNode * n2); + static const SMDS_MeshEdge* FindEdge(const SMDS_MeshNode * n1, + const SMDS_MeshNode * n2, + const SMDS_MeshNode * n3); static const SMDS_MeshFace* FindFace(const SMDS_MeshNode *n1, const SMDS_MeshNode *n2, const SMDS_MeshNode *n3); @@ -468,6 +476,20 @@ public: const SMDS_MeshNode *n2, const SMDS_MeshNode *n3, const SMDS_MeshNode *n4); + static const SMDS_MeshFace* FindFace(const SMDS_MeshNode *n1, + const SMDS_MeshNode *n2, + const SMDS_MeshNode *n3, + const SMDS_MeshNode *n4, + const SMDS_MeshNode *n5, + const SMDS_MeshNode *n6); + static const SMDS_MeshFace* FindFace(const SMDS_MeshNode *n1, + const SMDS_MeshNode *n2, + const SMDS_MeshNode *n3, + const SMDS_MeshNode *n4, + const SMDS_MeshNode *n5, + const SMDS_MeshNode *n6, + const SMDS_MeshNode *n7, + const SMDS_MeshNode *n8); const SMDS_MeshFace *FindFace(std::vector nodes_ids) const; static const SMDS_MeshFace* FindFace(std::vector nodes); diff --git a/src/SMDS/SMDS_MeshElement.cxx b/src/SMDS/SMDS_MeshElement.cxx index f2df1fd89..518feb1ad 100644 --- a/src/SMDS/SMDS_MeshElement.cxx +++ b/src/SMDS/SMDS_MeshElement.cxx @@ -218,7 +218,7 @@ bool SMDS_MeshElement::IsQuadratic() const return false; } -bool SMDS_MeshElement::IsMediumNode(class SMDS_MeshNode* node) const +bool SMDS_MeshElement::IsMediumNode(const SMDS_MeshNode* node) const { return false; } diff --git a/src/SMDS/SMDS_MeshElement.hxx b/src/SMDS/SMDS_MeshElement.hxx index 4ba69f7ab..e8672cd90 100644 --- a/src/SMDS/SMDS_MeshElement.hxx +++ b/src/SMDS/SMDS_MeshElement.hxx @@ -82,7 +82,7 @@ public: virtual bool IsPoly() const { return false; }; virtual bool IsQuadratic() const; - virtual bool IsMediumNode(class SMDS_MeshNode* node) const; + virtual bool IsMediumNode(const SMDS_MeshNode* node) const; friend std::ostream & operator <<(std::ostream & OS, const SMDS_MeshElement *); friend bool SMDS_MeshElementIDFactory::BindID(int ID,SMDS_MeshElement*elem); diff --git a/src/SMDS/SMDS_VolumeTool.cxx b/src/SMDS/SMDS_VolumeTool.cxx index 817d3ceb4..9f35e0158 100644 --- a/src/SMDS/SMDS_VolumeTool.cxx +++ b/src/SMDS/SMDS_VolumeTool.cxx @@ -970,7 +970,8 @@ bool SMDS_VolumeTool::GetFaceNormal (int faceIndex, double & X, double & Y, doub XYZ aVec13( p3 - p1 ); XYZ cross = aVec12.Crossed( aVec13 ); - if ( myFaceNbNodes == 4 ) { + //if ( myFaceNbNodes == 4 ) { + if ( myFaceNbNodes >3 ) { XYZ p4 ( myFaceNodes[3] ); XYZ aVec14( p4 - p1 ); XYZ cross2 = aVec13.Crossed( aVec14 ); @@ -1106,7 +1107,7 @@ bool SMDS_VolumeTool::IsLinked (const SMDS_MeshNode* theNode1, bool SMDS_VolumeTool::IsLinked (const int theNode1Index, const int theNode2Index) const { - if (myVolume->IsPoly()) { + if ( myVolume->IsPoly() ) { return IsLinked(myVolumeNodes[theNode1Index], myVolumeNodes[theNode2Index]); } @@ -1144,6 +1145,57 @@ bool SMDS_VolumeTool::IsLinked (const int theNode1Index, default:; } break; + case 10: + { + switch ( minInd ) { + case 0: if( maxInd==4 || maxInd==6 || maxInd==7 ) return true; + case 1: if( maxInd==4 || maxInd==5 || maxInd==8 ) return true; + case 2: if( maxInd==5 || maxInd==6 || maxInd==9 ) return true; + case 3: if( maxInd==7 || maxInd==8 || maxInd==9 ) return true; + default:; + } + break; + } + case 13: + { + switch ( minInd ) { + case 0: if( maxInd==5 || maxInd==8 || maxInd==9 ) return true; + case 1: if( maxInd==5 || maxInd==6 || maxInd==10 ) return true; + case 2: if( maxInd==6 || maxInd==7 || maxInd==11 ) return true; + case 3: if( maxInd==7 || maxInd==8 || maxInd==12 ) return true; + case 4: if( maxInd==9 || maxInd==10 || maxInd==11 || maxInd==12 ) return true; + default:; + } + break; + } + case 15: + { + switch ( minInd ) { + case 0: if( maxInd==6 || maxInd==8 || maxInd==12 ) return true; + case 1: if( maxInd==6 || maxInd==7 || maxInd==13 ) return true; + case 2: if( maxInd==7 || maxInd==8 || maxInd==14 ) return true; + case 3: if( maxInd==9 || maxInd==11 || maxInd==12 ) return true; + case 4: if( maxInd==9 || maxInd==10 || maxInd==13 ) return true; + case 5: if( maxInd==10 || maxInd==11 || maxInd==14 ) return true; + default:; + } + break; + } + case 20: + { + switch ( minInd ) { + case 0: if( maxInd==8 || maxInd==11 || maxInd==16 ) return true; + case 1: if( maxInd==8 || maxInd==9 || maxInd==17 ) return true; + case 2: if( maxInd==9 || maxInd==10 || maxInd==18 ) return true; + case 3: if( maxInd==10 || maxInd==11 || maxInd==19 ) return true; + case 4: if( maxInd==12 || maxInd==15 || maxInd==16 ) return true; + case 5: if( maxInd==12 || maxInd==13 || maxInd==17 ) return true; + case 6: if( maxInd==13 || maxInd==14 || maxInd==18 ) return true; + case 7: if( maxInd==14 || maxInd==15 || maxInd==19 ) return true; + default:; + } + break; + } default:; } return false; @@ -1185,8 +1237,7 @@ bool SMDS_VolumeTool::IsFreeFace( int faceIndex ) typedef map< const SMDS_MeshElement*, int > TElemIntMap; TElemIntMap volNbShared; TElemIntMap::iterator vNbIt; - for ( int iNode = 0; iNode < nbFaceNodes; iNode++ ) - { + for ( int iNode = 0; iNode < nbFaceNodes; iNode++ ) { const SMDS_MeshNode* n = nodes[ iNode ]; SMDS_ElemIteratorPtr eIt = n->GetInverseElementIterator(); while ( eIt->more() ) { @@ -1194,10 +1245,12 @@ bool SMDS_VolumeTool::IsFreeFace( int faceIndex ) if ( elem != myVolume && elem->GetType() == SMDSAbs_Volume ) { int nbShared = 1; vNbIt = volNbShared.find( elem ); - if ( vNbIt == volNbShared.end() ) + if ( vNbIt == volNbShared.end() ) { volNbShared.insert ( TElemIntMap::value_type( elem, nbShared )); - else + } + else { nbShared = ++(*vNbIt).second; + } if ( nbShared > maxNbShared ) maxNbShared = nbShared; } @@ -1213,8 +1266,7 @@ bool SMDS_VolumeTool::IsFreeFace( int faceIndex ) if ( IsFaceExternal( faceIndex )) intNormal = XYZ( -intNormal.x, -intNormal.y, -intNormal.z ); XYZ p0 ( nodes[0] ), baryCenter; - for ( vNbIt = volNbShared.begin(); vNbIt != volNbShared.end(); vNbIt++ ) - { + for ( vNbIt = volNbShared.begin(); vNbIt != volNbShared.end(); vNbIt++ ) { int nbShared = (*vNbIt).second; if ( nbShared >= 3 ) { SMDS_VolumeTool volume( (*vNbIt).first ); @@ -1226,20 +1278,20 @@ bool SMDS_VolumeTool::IsFreeFace( int faceIndex ) // remove a volume from volNbShared map volNbShared.erase( vNbIt ); } + // here volNbShared contains only volumes laying on the // opposite side of the face - if ( volNbShared.empty() ) + if ( volNbShared.empty() ) { return free; // is free + } // check if the whole area of a face is shared bool isShared[] = { false, false, false, false }; // 4 triangle parts of a quadrangle - for ( vNbIt = volNbShared.begin(); vNbIt != volNbShared.end(); vNbIt++ ) - { + for ( vNbIt = volNbShared.begin(); vNbIt != volNbShared.end(); vNbIt++ ) { SMDS_VolumeTool volume( (*vNbIt).first ); bool prevLinkShared = false; int nbSharedLinks = 0; - for ( int iNode = 0; iNode < nbFaceNodes; iNode++ ) - { + for ( int iNode = 0; iNode < nbFaceNodes; iNode++ ) { bool linkShared = volume.IsLinked( nodes[ iNode ], nodes[ iNode + 1] ); if ( linkShared ) nbSharedLinks++; diff --git a/src/SMESH/SMESH_2D_Algo.cxx b/src/SMESH/SMESH_2D_Algo.cxx index d1084f7d4..ea44619be 100644 --- a/src/SMESH/SMESH_2D_Algo.cxx +++ b/src/SMESH/SMESH_2D_Algo.cxx @@ -29,7 +29,7 @@ using namespace std; #include "SMESH_2D_Algo.hxx" #include "SMESH_Gen.hxx" -#include "SMESH_subMesh.hxx" +#include #include "utilities.h" @@ -45,6 +45,7 @@ SMESH_2D_Algo::SMESH_2D_Algo(int hypId, int studyId, SMESH_Gen* gen) // _compatibleHypothesis.push_back("hypothese_2D_bidon"); _type = ALGO_2D; gen->_map2D_Algo[hypId] = this; + myCreateQuadratic = false; } //============================================================================= @@ -55,6 +56,7 @@ SMESH_2D_Algo::SMESH_2D_Algo(int hypId, int studyId, SMESH_Gen* gen) SMESH_2D_Algo::~SMESH_2D_Algo() { + myCreateQuadratic = false; } //============================================================================= @@ -80,13 +82,16 @@ int SMESH_2D_Algo::NumberOfWires(const TopoDS_Shape& S) int SMESH_2D_Algo::NumberOfPoints(SMESH_Mesh& aMesh, const TopoDS_Wire& W) { int nbPoints = 0; - for (TopExp_Explorer exp(W,TopAbs_EDGE); exp.More(); exp.Next()) - { - const TopoDS_Edge& E = TopoDS::Edge(exp.Current()); - int nb = aMesh.GetSubMesh(E)->GetSubMeshDS()->NbNodes(); - //SCRUTE(nb); - nbPoints += nb +1; // internal points plus 1 vertex of 2 (last point ?) - } + for (TopExp_Explorer exp(W,TopAbs_EDGE); exp.More(); exp.Next()) { + const TopoDS_Edge& E = TopoDS::Edge(exp.Current()); + int nb = aMesh.GetSubMesh(E)->GetSubMeshDS()->NbNodes(); + if(myCreateQuadratic) + nb = nb/2; + //SCRUTE(nb); + nbPoints += nb +1; // internal points plus 1 vertex of 2 (last point ?) + } //SCRUTE(nbPoints); return nbPoints; } + + diff --git a/src/SMESH/SMESH_2D_Algo.hxx b/src/SMESH/SMESH_2D_Algo.hxx index 5c904e22e..65857fced 100644 --- a/src/SMESH/SMESH_2D_Algo.hxx +++ b/src/SMESH/SMESH_2D_Algo.hxx @@ -30,7 +30,8 @@ #define _SMESH_2D_ALGO_HXX_ #include "SMESH_Algo.hxx" -#include +#include "SMESH_subMesh.hxx" +#include "TopoDS_Wire.hxx" class SMESH_2D_Algo: public SMESH_Algo @@ -41,6 +42,9 @@ public: int NumberOfWires(const TopoDS_Shape& S); int NumberOfPoints(SMESH_Mesh& aMesh,const TopoDS_Wire& W); + +protected: + bool myCreateQuadratic; }; #endif diff --git a/src/SMESH/SMESH_3D_Algo.cxx b/src/SMESH/SMESH_3D_Algo.cxx index d42680f62..6a05c16af 100644 --- a/src/SMESH/SMESH_3D_Algo.cxx +++ b/src/SMESH/SMESH_3D_Algo.cxx @@ -29,7 +29,6 @@ using namespace std; #include "SMESH_3D_Algo.hxx" #include "SMESH_Gen.hxx" -#include "SMESH_subMesh.hxx" #include "utilities.h" @@ -56,3 +55,5 @@ SMESH_3D_Algo::SMESH_3D_Algo(int hypId, int studyId, SMESH_Gen* gen) SMESH_3D_Algo::~SMESH_3D_Algo() { } + + diff --git a/src/SMESH/SMESH_3D_Algo.hxx b/src/SMESH/SMESH_3D_Algo.hxx index 62621ce3c..21c53ca0f 100644 --- a/src/SMESH/SMESH_3D_Algo.hxx +++ b/src/SMESH/SMESH_3D_Algo.hxx @@ -37,6 +37,7 @@ class SMESH_3D_Algo: public: SMESH_3D_Algo(int hypId, int studyId, SMESH_Gen* gen); virtual ~SMESH_3D_Algo(); + }; #endif diff --git a/src/SMESH/SMESH_Algo.hxx b/src/SMESH/SMESH_Algo.hxx index 12c72d828..5acc2b242 100644 --- a/src/SMESH/SMESH_Algo.hxx +++ b/src/SMESH/SMESH_Algo.hxx @@ -33,15 +33,18 @@ #include #include +#include #include #include #include +#include class SMESH_Gen; class SMESH_Mesh; class TopoDS_Face; class SMESHDS_Mesh; +class SMDS_MeshNode; class SMESH_Algo:public SMESH_Hypothesis { @@ -97,6 +100,7 @@ class SMESH_Algo:public SMESH_Hypothesis std::vector _compatibleHypothesis; std::list _appliedHypList; std::list _usedHypList; + }; #endif diff --git a/src/SMESH/SMESH_Mesh.cxx b/src/SMESH/SMESH_Mesh.cxx index ffd77cd55..f36f08964 100644 --- a/src/SMESH/SMESH_Mesh.cxx +++ b/src/SMESH/SMESH_Mesh.cxx @@ -861,7 +861,8 @@ int SMESH_Mesh::NbTriangles() throw(SALOME_Exception) const SMDS_MeshFace * curFace; while (itFaces->more()) { curFace = itFaces->next(); - if (!curFace->IsPoly() && curFace->NbNodes() == 3) Nb++; + if ( !curFace->IsPoly() && + ( curFace->NbNodes()==3 || curFace->NbNodes()==6 ) ) Nb++; } return Nb; } @@ -879,7 +880,8 @@ int SMESH_Mesh::NbQuadrangles() throw(SALOME_Exception) const SMDS_MeshFace * curFace; while (itFaces->more()) { curFace = itFaces->next(); - if (!curFace->IsPoly() && curFace->NbNodes() == 4) Nb++; + if ( !curFace->IsPoly() && + ( curFace->NbNodes() == 4 || curFace->NbNodes()==8 ) ) Nb++; } return Nb; } @@ -917,7 +919,8 @@ int SMESH_Mesh::NbTetras() throw(SALOME_Exception) const SMDS_MeshVolume * curVolume; while (itVolumes->more()) { curVolume = itVolumes->next(); - if (!curVolume->IsPoly() && curVolume->NbNodes() == 4) Nb++; + if ( !curVolume->IsPoly() && + ( curVolume->NbNodes() == 4 || curVolume->NbNodes()==10 ) ) Nb++; } return Nb; } @@ -931,7 +934,8 @@ int SMESH_Mesh::NbHexas() throw(SALOME_Exception) const SMDS_MeshVolume * curVolume; while (itVolumes->more()) { curVolume = itVolumes->next(); - if (!curVolume->IsPoly() && curVolume->NbNodes() == 8) Nb++; + if ( !curVolume->IsPoly() && + ( curVolume->NbNodes() == 8 || curVolume->NbNodes()==20 ) ) Nb++; } return Nb; } @@ -945,7 +949,8 @@ int SMESH_Mesh::NbPyramids() throw(SALOME_Exception) const SMDS_MeshVolume * curVolume; while (itVolumes->more()) { curVolume = itVolumes->next(); - if (!curVolume->IsPoly() && curVolume->NbNodes() == 5) Nb++; + if ( !curVolume->IsPoly() && + ( curVolume->NbNodes() == 5 || curVolume->NbNodes()==13 ) ) Nb++; } return Nb; } @@ -959,7 +964,8 @@ int SMESH_Mesh::NbPrisms() throw(SALOME_Exception) const SMDS_MeshVolume * curVolume; while (itVolumes->more()) { curVolume = itVolumes->next(); - if (!curVolume->IsPoly() && curVolume->NbNodes() == 6) Nb++; + if ( !curVolume->IsPoly() && + ( curVolume->NbNodes() == 6 || curVolume->NbNodes()==15 ) ) Nb++; } return Nb; } diff --git a/src/SMESH/SMESH_MeshEditor.cxx b/src/SMESH/SMESH_MeshEditor.cxx index d75adf3e7..ea1334bfb 100644 --- a/src/SMESH/SMESH_MeshEditor.cxx +++ b/src/SMESH/SMESH_MeshEditor.cxx @@ -34,6 +34,7 @@ #include "SMDS_PolyhedralVolumeOfNodes.hxx" #include "SMDS_FacePosition.hxx" #include "SMDS_SpacePosition.hxx" +#include "SMDS_QuadraticFaceOfNodes.hxx" #include "SMESHDS_Group.hxx" #include "SMESHDS_Mesh.hxx" @@ -75,8 +76,12 @@ typedef map > TElemOfNode typedef map > TElemOfElemListMap; typedef map > TNodeOfNodeListMap; typedef TNodeOfNodeListMap::iterator TNodeOfNodeListMapItr; +//typedef map > TNodeOfNodeVecMap; +//typedef TNodeOfNodeVecMap::iterator TNodeOfNodeVecMapItr; typedef map > TElemOfVecOfNnlmiMap; +//typedef map > TElemOfVecOfMapNodesMap; +typedef pair NLink; //======================================================================= //function : SMESH_MeshEditor @@ -102,8 +107,7 @@ bool SMESH_MeshEditor::Remove (const list< int >& theIDs, set< SMESH_subMesh *> smmap; list::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 ); @@ -114,8 +118,7 @@ bool SMESH_MeshEditor::Remove (const list< int >& theIDs, // Find sub-meshes to notify about modification SMDS_ElemIteratorPtr nodeIt = elem->nodesIterator(); - while ( nodeIt->more() ) - { + while ( nodeIt->more() ) { const SMDS_MeshNode* node = static_cast( nodeIt->next() ); const SMDS_PositionPtr& aPosition = node->GetPosition(); if ( aPosition.get() ) { @@ -142,6 +145,7 @@ bool SMESH_MeshEditor::Remove (const list< int >& theIDs, for ( smIt = smmap.begin(); smIt != smmap.end(); smIt++ ) (*smIt)->ComputeStateEngine( SMESH_subMesh::MESH_ENTITY_REMOVED ); } + return true; } @@ -157,8 +161,7 @@ int SMESH_MeshEditor::FindShape (const SMDS_MeshElement * theElem) if ( aMesh->ShapeToMesh().IsNull() ) return 0; - if ( theElem->GetType() == SMDSAbs_Node ) - { + if ( theElem->GetType() == SMDSAbs_Node ) { const SMDS_PositionPtr& aPosition = static_cast( theElem )->GetPosition(); if ( aPosition.get() ) @@ -169,25 +172,22 @@ int SMESH_MeshEditor::FindShape (const SMDS_MeshElement * theElem) 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( 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, @@ -197,17 +197,89 @@ int SMESH_MeshEditor::FindShape (const SMDS_MeshElement * theElem) 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 : 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( it->next() ); + i++; + } + if(it->more()) return false; + it = theTria2->nodesIterator(); + i=0; + while(i<6) { + N2[i] = static_cast( 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 @@ -220,71 +292,116 @@ bool SMESH_MeshEditor::InverseDiag (const SMDS_MeshElement * theTria1, { if (!theTria1 || !theTria2) return false; + const SMDS_FaceOfNodes* F1 = dynamic_cast( theTria1 ); - if (!F1) return false; const SMDS_FaceOfNodes* F2 = dynamic_cast( 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( 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( 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; + + // theTria1: A->2 + aNodes[ iA ] = aNodes[ i2 ]; + // theTria2: B->1 + aNodes[ sameInd[ iB ]] = aNodes[ i1 ]; + + //MESSAGE( theTria1 << theTria2 ); + + GetMeshDS()->ChangeElementNodes( theTria1, aNodes, 3 ); + GetMeshDS()->ChangeElementNodes( theTria2, &aNodes[ 3 ], 3 ); + + //MESSAGE( theTria1 << theTria2 ); - // 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 true; + + } // end if(F1 && F2) + + // check case of quadratic faces + const SMDS_QuadraticFaceOfNodes* QF1 = + dynamic_cast (theTria1); + if(!QF1) return false; + const SMDS_QuadraticFaceOfNodes* QF2 = + dynamic_cast (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; - - - // theTria1: A->2 - aNodes[ iA ] = aNodes[ i2 ]; - // theTria2: B->1 - aNodes[ sameInd[ iB ]] = aNodes[ i1 ]; - - //MESSAGE( theTria1 << theTria2 ); - - GetMeshDS()->ChangeElementNodes( theTria1, aNodes, 3 ); - GetMeshDS()->ChangeElementNodes( theTria2, &aNodes[ 3 ], 3 ); - - //MESSAGE( theTria1 << theTria2 ); + // 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; } @@ -318,7 +435,8 @@ static bool findTriangles(const SMDS_MeshNode * theNode1, if ( theTria1 ) { theTria2 = elem; break; - } else { + } + else { theTria1 = elem; } } @@ -342,55 +460,65 @@ bool SMESH_MeshEditor::InverseDiag (const SMDS_MeshNode * theNode1, return false; const SMDS_FaceOfNodes* F1 = dynamic_cast( tr1 ); - if (!F1) return false; + //if (!F1) return false; const SMDS_FaceOfNodes* F2 = dynamic_cast( 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( 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( 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; - - // tr1: A->2 - aNodes1[ iA1 ] = aNodes2[ i2 ]; - // tr2: B->1 - aNodes2[ iB2 ] = aNodes1[ i1 ]; + //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( 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( 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; - //MESSAGE( tr1 << tr2 ); + // tr1: A->2 + aNodes1[ iA1 ] = aNodes2[ i2 ]; + // tr2: B->1 + aNodes2[ iB2 ] = aNodes1[ i1 ]; - GetMeshDS()->ChangeElementNodes( tr1, aNodes1, 3 ); - GetMeshDS()->ChangeElementNodes( tr2, aNodes2, 3 ); + //MESSAGE( tr1 << tr2 ); - //MESSAGE( tr1 << tr2 ); + GetMeshDS()->ChangeElementNodes( tr1, aNodes1, 3 ); + GetMeshDS()->ChangeElementNodes( tr2, aNodes2, 3 ); - return true; + //MESSAGE( tr1 << tr2 ); + + return true; + } + // check case of quadratic faces + const SMDS_QuadraticFaceOfNodes* QF1 = + dynamic_cast (tr1); + if(!QF1) return false; + const SMDS_QuadraticFaceOfNodes* QF2 = + dynamic_cast (tr2); + if(!QF2) return false; + return InverseDiag(tr1,tr2); } //======================================================================= @@ -406,12 +534,16 @@ bool getQuadrangleNodes(const SMDS_MeshNode * theQuadNodes [], 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( it->next() ); + i++; bool isDiag = ( n == theNode1 || n == theNode2 ); if ( !isDiag ) n4 = n; @@ -419,19 +551,19 @@ bool getQuadrangleNodes(const SMDS_MeshNode * theQuadNodes [], // 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( 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; @@ -459,20 +591,66 @@ bool SMESH_MeshEditor::DeleteDiag (const SMDS_MeshNode * theNode1, return false; const SMDS_FaceOfNodes* F1 = dynamic_cast( tr1 ); - if (!F1) return false; + //if (!F1) return false; const SMDS_FaceOfNodes* F2 = dynamic_cast( 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 ); + GetMeshDS()->RemoveElement( tr2 ); - //MESSAGE( endl << tr1 << tr2 ); + //MESSAGE( endl << tr1 ); - GetMeshDS()->ChangeElementNodes( tr1, aNodes, 4 ); + return true; + } + + // check case of quadratic faces + const SMDS_QuadraticFaceOfNodes* QF1 = + dynamic_cast (tr1); + if(!QF1) return false; + const SMDS_QuadraticFaceOfNodes* QF2 = + dynamic_cast (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 ); GetMeshDS()->RemoveElement( tr2 ); - //MESSAGE( endl << tr1 ); + // remove middle node (9) + GetMeshDS()->RemoveNode( N1[4] ); return true; } @@ -493,16 +671,39 @@ bool SMESH_MeshEditor::Reorient (const SMDS_MeshElement * theElem) switch ( theElem->GetType() ) { case SMDSAbs_Edge: - case SMDSAbs_Face: - { - int i = theElem->NbNodes(); - vector aNodes( i ); - while ( it->more() ) - aNodes[ --i ]= static_cast( it->next() ); - return GetMeshDS()->ChangeElementNodes( theElem, &aNodes[0], theElem->NbNodes() ); + case SMDSAbs_Face: { + if(!theElem->IsQuadratic()) { + int i = theElem->NbNodes(); + vector aNodes( i ); + while ( it->more() ) + aNodes[ --i ]= static_cast( it->next() ); + return GetMeshDS()->ChangeElementNodes( theElem, &aNodes[0], theElem->NbNodes() ); + } + else { + // quadratic elements + if(theElem->GetType()==SMDSAbs_Edge) { + vector aNodes(3); + aNodes[1]= static_cast( it->next() ); + aNodes[0]= static_cast( it->next() ); + aNodes[2]= static_cast( it->next() ); + return GetMeshDS()->ChangeElementNodes( theElem, &aNodes[0], 3 ); + } + else { + int nbn = theElem->NbNodes(); + vector aNodes(nbn); + aNodes[0]= static_cast( it->next() ); + int i=1; + for(; i( it->next() ); + } + for(i=0; i( it->next() ); + } + return GetMeshDS()->ChangeElementNodes( theElem, &aNodes[0], nbn ); + } + } } - case SMDSAbs_Volume: - { + case SMDSAbs_Volume: { if (theElem->IsPoly()) { const SMDS_PolyhedralVolumeOfNodes* aPolyedre = static_cast( theElem ); @@ -519,16 +720,17 @@ bool SMESH_MeshEditor::Reorient (const SMDS_MeshElement * theElem) for (int iface = 1; iface <= nbFaces; iface++) { int inode, nbFaceNodes = aPolyedre->NbFaceNodes(iface); quantities[iface - 1] = nbFaceNodes; - + for (inode = nbFaceNodes; inode >= 1; inode--) { const SMDS_MeshNode* curNode = aPolyedre->GetFaceNode(iface, inode); poly_nodes.push_back(curNode); } } - + return GetMeshDS()->ChangePolyhedronNodes( theElem, poly_nodes, quantities ); - } else { + } + else { SMDS_VolumeTool vTool; if ( !vTool.Set( theElem )) return false; @@ -574,54 +776,119 @@ bool SMESH_MeshEditor::QuadToTri (set & theElems, SMESHDS_Mesh * aMesh = GetMeshDS(); set< const SMDS_MeshElement * >::iterator itElem; - for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ ) - { + for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ ) { const SMDS_MeshElement* elem = (*itElem); - if ( !elem || elem->GetType() != SMDSAbs_Face || elem->NbNodes() != 4 ) + if ( !elem || elem->GetType() != SMDSAbs_Face ) continue; - // retrieve element nodes - const SMDS_MeshNode* aNodes [4]; - SMDS_ElemIteratorPtr itN = elem->nodesIterator(); - int i = 0; - while ( itN->more() ) - aNodes[ i++ ] = static_cast( 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 ); + if(elem->NbNodes()==4) { - 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 ); + // retrieve element nodes + const SMDS_MeshNode* aNodes [4]; + SMDS_ElemIteratorPtr itN = elem->nodesIterator(); + int i = 0; + while ( itN->more() ) + aNodes[ i++ ] = static_cast( 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 ); - int aShapeId = FindShape( elem ); - //MESSAGE( "aBadRate1 = " << aBadRate1 << "; aBadRate2 = " << aBadRate2 + int aShapeId = FindShape( elem ); + //MESSAGE( "aBadRate1 = " << aBadRate1 << "; aBadRate2 = " << aBadRate2 // << " ShapeID = " << aShapeId << endl << elem ); - if ( aBadRate1 <= aBadRate2 ) { - // tr1 + tr2 is better - aMesh->ChangeElementNodes( elem, aNodes, 3 ); + if ( aBadRate1 <= aBadRate2 ) { + // tr1 + tr2 is better + aMesh->ChangeElementNodes( elem, aNodes, 3 ); + //MESSAGE( endl << elem ); + + elem = aMesh->AddFace( aNodes[2], aNodes[3], aNodes[0] ); + } + 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 ); - elem = aMesh->AddFace( aNodes[2], aNodes[3], aNodes[0] ); + // put a new triangle on the same shape + if ( aShapeId ) + aMesh->SetMeshElementOnShape( elem, aShapeId ); } - else { - // tr3 + tr4 is better - aMesh->ChangeElementNodes( elem, &aNodes[1], 3 ); - //MESSAGE( endl << elem ); - elem = aMesh->AddFace( aNodes[3], aNodes[0], aNodes[1] ); + if( elem->NbNodes()==8 && elem->IsQuadratic() ) { + const SMDS_MeshNode* aNodes [8]; + SMDS_ElemIteratorPtr itN = elem->nodesIterator(); + int i = 0; + while ( itN->more() ) { + aNodes[ i++ ] = static_cast( itN->next() ); + } + + // compare two sets of possible triangles + // use for comparing simple triangles (not quadratic) + 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 ); + + int aShapeId = FindShape( elem ); + + // find middle point for (0,1,2,3) + // and create node in this point; + double x=0., y=0., z=0.; + for(i=0; i<4; i++) { + x += aNodes[i]->X(); + y += aNodes[i]->Y(); + z += aNodes[i]->Z(); + } + const SMDS_MeshNode* newN = aMesh->AddNode(x/4, y/4, z/4); + + if ( aBadRate1 <= aBadRate2 ) { + // tr1 + tr2 is better + const SMDS_MeshNode* N[6]; + N[0] = aNodes[0]; + N[1] = aNodes[1]; + N[2] = aNodes[2]; + N[3] = aNodes[4]; + N[4] = aNodes[5]; + N[5] = newN; + aMesh->ChangeElementNodes( elem, N, 6 ); + elem = aMesh->AddFace(aNodes[2], aNodes[3], aNodes[0], + aNodes[6], aNodes[7], newN ); + } + else { + // tr3 + tr4 is better + const SMDS_MeshNode* N[6]; + N[0] = aNodes[1]; + N[1] = aNodes[2]; + N[2] = aNodes[3]; + N[3] = aNodes[5]; + N[4] = aNodes[6]; + N[5] = newN; + aMesh->ChangeElementNodes( elem, N, 6 ); + elem = aMesh->AddFace(aNodes[3], aNodes[0], aNodes[1], + aNodes[7], aNodes[4], newN ); + } + // put a new triangle on the same shape + if ( aShapeId ) { + aMesh->SetMeshElementOnShape( elem, aShapeId ); + } } - //MESSAGE( endl << elem ); - // put a new triangle on the same shape - if ( aShapeId ) - aMesh->SetMeshElementOnShape( elem, aShapeId ); } - return true; } @@ -635,30 +902,36 @@ int SMESH_MeshEditor::BestSplit (const SMDS_MeshElement* theQuad, 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( 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( 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; } //======================================================================= @@ -693,38 +966,86 @@ bool SMESH_MeshEditor::QuadToTri (std::set & theElems, SMESHDS_Mesh * aMesh = GetMeshDS(); set< const SMDS_MeshElement * >::iterator itElem; - for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ ) - { + for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ ) { const SMDS_MeshElement* elem = (*itElem); - if ( !elem || elem->GetType() != SMDSAbs_Face || elem->NbNodes() != 4 ) + 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( 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( 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] ); + } + // 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 + if( elem->NbNodes()==8 && elem->IsQuadratic() ) { + const SMDS_MeshNode* aNodes [8]; + SMDS_ElemIteratorPtr itN = elem->nodesIterator(); + int i = 0; + while ( itN->more() ) { + aNodes[ i++ ] = static_cast( itN->next() ); + } - if ( aShapeId ) - aMesh->SetMeshElementOnShape( newElem, aShapeId ); + // find middle point for (0,1,2,3) + // and create node in this point; + double x=0., y=0., z=0.; + for(i=0; i<4; i++) { + x += aNodes[i]->X(); + y += aNodes[i]->Y(); + z += aNodes[i]->Z(); + } + const SMDS_MeshNode* newN = aMesh->AddNode(x/4, y/4, z/4); - AddToSameGroups( newElem, elem, aMesh ); + int aShapeId = FindShape( elem ); + const SMDS_MeshElement* newElem = 0; + if ( the13Diag ) { + const SMDS_MeshNode* N[6]; + N[0] = aNodes[0]; + N[1] = aNodes[1]; + N[2] = aNodes[2]; + N[3] = aNodes[4]; + N[4] = aNodes[5]; + N[5] = newN; + aMesh->ChangeElementNodes( elem, N, 6 ); + elem = aMesh->AddFace(aNodes[2], aNodes[3], aNodes[0], + aNodes[6], aNodes[7], newN ); + } + else { + const SMDS_MeshNode* N[6]; + N[0] = aNodes[1]; + N[1] = aNodes[2]; + N[2] = aNodes[3]; + N[3] = aNodes[5]; + N[4] = aNodes[6]; + N[5] = newN; + aMesh->ChangeElementNodes( elem, N, 6 ); + elem = aMesh->AddFace(aNodes[3], aNodes[0], aNodes[1], + aNodes[7], aNodes[4], newN ); + } + // 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; @@ -747,18 +1068,24 @@ double getAngle(const SMDS_MeshElement * tr1, 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()) { @@ -788,7 +1115,6 @@ double getAngle(const SMDS_MeshElement * tr1, // class generating a unique ID for a pair of nodes // and able to return nodes by that ID // ================================================= - class LinkID_Gen { public: @@ -819,6 +1145,7 @@ class LinkID_Gen { long myMaxID; }; + //======================================================================= //function : TriToQuad //purpose : Fuse neighbour triangles into quadrangles. @@ -837,65 +1164,76 @@ bool SMESH_MeshEditor::TriToQuad (set & theElems, 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; + //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; set::iterator itElem; - for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ ) - { + for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ ) { const SMDS_MeshElement* elem = (*itElem); - if ( !elem || elem->NbNodes() != 3 ) - continue; + //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( 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 ); @@ -904,18 +1242,15 @@ bool SMESH_MeshEditor::TriToQuad (set & theElems, // 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 ) @@ -925,17 +1260,16 @@ bool SMESH_MeshEditor::TriToQuad (set & theElems, // 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++ ) @@ -945,69 +1279,83 @@ bool SMESH_MeshEditor::TriToQuad (set & theElems, } } - 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 ); @@ -1018,24 +1366,66 @@ bool SMESH_MeshEditor::TriToQuad (set & theElems, 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) { + aMesh->ChangeElementNodes( tr1, n12, 4 ); + aMesh->RemoveElement( tr2 ); + } + 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]; + GetMeshDS()->ChangeElementNodes( tr1, aNodes, 8 ); + GetMeshDS()->RemoveElement( tr2 ); + // 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) { + aMesh->ChangeElementNodes( tr1, n13, 4 ); + aMesh->RemoveElement( tr3 ); + } + 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]; + GetMeshDS()->ChangeElementNodes( tr1, aNodes, 8 ); + GetMeshDS()->RemoveElement( tr3 ); + // remove middle node (9) + GetMeshDS()->RemoveNode( N1[4] ); + } } // Next element to fuse: the rejected one @@ -1352,13 +1742,25 @@ void laplacianSmooth(const SMDS_MeshNode* theNode, // 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( itN->next() ); - if ( aNodes[ nbNodes ] == theNode ) - iNode = nbNodes; // index of theNode within aNodes - nbNodes++; + if(!elem->IsQuadratic()) { + SMDS_ElemIteratorPtr itN = elem->nodesIterator(); + while ( itN->more() ) { + aNodes[ nbNodes ] = static_cast( itN->next() ); + if ( aNodes[ nbNodes ] == theNode ) + iNode = nbNodes; // index of theNode within aNodes + nbNodes++; + } + } + else { + int nbn = elem->NbNodes()/2; + aNodes.resize(nbn); + SMDS_ElemIteratorPtr itN = elem->nodesIterator(); + while ( nbNodes( itN->next() ); + if ( aNodes[ nbNodes ] == theNode ) + iNode = nbNodes; // index of theNode within aNodes + nbNodes++; + } } // add linked nodes int iAfter = ( iNode + 1 == nbNodes ) ? 0 : iNode + 1; @@ -1435,9 +1837,13 @@ void centroidalSmooth(const SMDS_MeshNode* theNode, 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( itN->next() ); + i++; gp_XYZ aP( aNode->X(), aNode->Y(), aNode->Z() ); aNodePoints.push_back( aP ); if ( !theSurface.IsNull() ) { // smooth in 2D @@ -1509,6 +1915,8 @@ void SMESH_MeshEditor::Smooth (set & theElems, if ( theTgtAspectRatio < 1.0 ) theTgtAspectRatio = 1.0; + double disttol = 1.e-16; + SMESH::Controls::AspectRatio aQualityFunc; SMESHDS_Mesh* aMesh = GetMeshDS(); @@ -1540,9 +1948,10 @@ void SMESH_MeshEditor::Smooth (set & theElems, // smooth elements on each TopoDS_Face separately // =============================================== + set QuadElems; + 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; @@ -1583,8 +1992,7 @@ void SMESH_MeshEditor::Smooth (set & theElems, 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 @@ -1595,6 +2003,9 @@ void SMESH_MeshEditor::Smooth (set & theElems, continue; } elemsOnFace.push_back( elem ); + if(elem->IsQuadratic()) { + QuadElems.insert(elem); + } theElems.erase( itElem++ ); nbElemOnFace++; @@ -1602,7 +2013,13 @@ void SMESH_MeshEditor::Smooth (set & theElems, const SMDS_MeshNode* node; SMDS_TypeOfPosition posType; SMDS_ElemIteratorPtr itN = elem->nodesIterator(); - while ( itN->more() ) { + int nbn = elem->NbNodes(); + if(elem->IsQuadratic()) + nbn = nbn/2; + int nn = 0; + //while ( itN->more() ) { + while ( nn( itN->next() ); const SMDS_PositionPtr& pos = node->GetPosition(); posType = pos.get() ? pos->GetTypeOfPosition() : SMDS_TOP_3DSPACE; @@ -1657,8 +2074,7 @@ void SMESH_MeshEditor::Smooth (set & theElems, } // 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(); @@ -1725,21 +2141,31 @@ void SMESH_MeshEditor::Smooth (set & theElems, // fix nodes on mesh boundary - if ( checkBoundaryNodes ) - { + if ( checkBoundaryNodes ) { typedef pair 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 ) - { + for ( ; elemIt != elemsOnFace.end(); ++elemIt ) { + const SMDS_MeshElement* elem = (*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( itN->next() )); + if(!elem->IsQuadratic()) { + nodes.reserve( elem->NbNodes() + 1 ); + SMDS_ElemIteratorPtr itN = elem->nodesIterator(); + while ( itN->more() ) + nodes.push_back( static_cast( itN->next() )); + } + else { + nodes.reserve( elem->NbNodes()/2 + 1 ); + SMDS_ElemIteratorPtr itN = elem->nodesIterator(); + int nbn = 0; + while ( nbnNbNodes()/2 ) { + nbn++; + nodes.push_back( static_cast( itN->next() )); + } + } nodes.push_back( nodes.front() ); // loop on elem links: insert them in linkNbMap for ( int iN = 1; iN < nodes.size(); ++iN ) { @@ -1771,11 +2197,9 @@ void SMESH_MeshEditor::Smooth (set & theElems, // ----------------------------------------------------- set 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; @@ -1812,8 +2236,7 @@ void SMESH_MeshEditor::Smooth (set & theElems, } // 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() ) @@ -1829,8 +2252,7 @@ void SMESH_MeshEditor::Smooth (set & theElems, // collect movable nodes linked to ones on seam in nodesNearSeam SMDS_ElemIteratorPtr eIt = nSeam->GetInverseElementIterator(); - while ( eIt->more() ) - { + while ( eIt->more() ) { const SMDS_MeshElement* e = eIt->next(); if ( e->GetType() != SMDSAbs_Face ) continue; @@ -1858,8 +2280,7 @@ void SMESH_MeshEditor::Smooth (set & theElems, } // 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() ) { const SMDS_MeshNode* n = @@ -1884,12 +2305,10 @@ void SMESH_MeshEditor::Smooth (set & theElems, int it = -1; double maxRatio = -1., maxDisplacement = -1.; set::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() ); @@ -1907,7 +2326,8 @@ void SMESH_MeshEditor::Smooth (set & theElems, maxDisplacement = aDispl; } // no node movement => exit - if ( maxDisplacement < 1.e-16 ) { + //if ( maxDisplacement < 1.e-16 ) { + if ( maxDisplacement < disttol ) { MESSAGE("-- no node movement --"); break; } @@ -1915,8 +2335,7 @@ void SMESH_MeshEditor::Smooth (set & theElems, // 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; @@ -1945,10 +2364,8 @@ void SMESH_MeshEditor::Smooth (set & theElems, // 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 ); @@ -1960,6 +2377,38 @@ void SMESH_MeshEditor::Smooth (set & theElems, } } // loop on face ids + + set< const SMDS_MeshElement* >::iterator itq; + for ( itq = QuadElems.begin(); itq != QuadElems.end(); itq++ ) { + const SMDS_QuadraticFaceOfNodes* QF = + dynamic_cast (*itq); + if(QF) { + vector Ns(QF->NbNodes()+1); + SMDS_NodeIteratorPtr anIter = QF->interlacedNodesIterator(); + int nn = 0; + while( anIter->more() ) { + Ns[nn++] = anIter->next(); + //Ns.push_back(anIter->next()); + } + Ns[nn] = Ns[0]; + //Ns.push_back(Ns[0]); + int i=0; + for(; iNbNodes(); i=i+2) { + double x = (Ns[i]->X() + Ns[i+2]->X())/2; + double y = (Ns[i]->Y() + Ns[i+2]->Y())/2; + double 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 + const_cast(Ns[i+1])->setXYZ(x,y,z); + aMesh->MoveNode( Ns[i+1], x, y, z ); + } + } + } + } + QuadElems.clear(); + } //======================================================================= @@ -2000,38 +2449,57 @@ static bool isReverse(const SMDS_MeshNode* prevNodes[], static void sweepElement(SMESHDS_Mesh* aMesh, const SMDS_MeshElement* elem, const vector & newNodesItVec, - list& newElems) + list& newElems, + const int nbSteps) { // Loop on elem nodes: // find new nodes and detect same nodes indices int nbNodes = elem->NbNodes(); list::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 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="<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 ); @@ -2039,6 +2507,12 @@ static void sweepElement(SMESHDS_Mesh* aMesh, 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]< 2 && !isReverse( prevNod, nextNod, nbNodes, iNotSameNode )) { @@ -2053,82 +2527,195 @@ static void sweepElement(SMESHDS_Mesh* aMesh, } // 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 polyedre_nodes (nbNodes*2 + 4*nbNodes); + //vector 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 polyedre_nodes (nbNodes*2 + 4*nbNodes); vector quantities (nbNodes + 2); @@ -2153,9 +2740,10 @@ static void sweepElement(SMESHDS_Mesh* aMesh, } aNewElem = aMesh->AddPolyhedralVolume (polyedre_nodes, quantities); } - } - if ( aNewElem ) + + if ( aNewElem ) { newElems.push_back( aNewElem ); + } // set new prev nodes for ( iNode = 0; iNode < nbNodes; iNode++ ) @@ -2173,26 +2761,33 @@ static void makeWalls (SMESHDS_Mesh* aMesh, TNodeOfNodeListMap & mapNewNodes, TElemOfElemListMap & newElemsMap, TElemOfVecOfNnlmiMap & elemNewNodesMap, - set& elemSet) + set& elemSet, + const int nbSteps) { 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( 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; + while ( eIt->more() && nbInitElems < 2 ) { + el = eIt->next(); + //if ( elemSet.find( eIt->next() ) != elemSet.end() ) + if ( elemSet.find(el) != elemSet.end() ) nbInitElems++; + } if ( nbInitElems < 2 ) { - vector newNodesItVec( 1, nList ); - list newEdges; - sweepElement( aMesh, node, newNodesItVec, newEdges ); + bool NotCreateEdge = el->IsQuadratic() && el->IsMediumNode(node); + if(!NotCreateEdge) { + vector newNodesItVec( 1, nList ); + list newEdges; + sweepElement( aMesh, node, newNodesItVec, newEdges, nbSteps ); + } } } @@ -2201,16 +2796,22 @@ static void makeWalls (SMESHDS_Mesh* aMesh, 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& vecNewNodes = itElemNodes->second; - if ( elem->GetType() == SMDSAbs_Edge ) - { - // create a ceiling edge - aMesh->AddEdge(vecNewNodes[ 0 ]->second.back(), - vecNewNodes[ 1 ]->second.back() ); + if ( elem->GetType() == SMDSAbs_Edge ) { + if(!elem->IsQuadratic()) { + // create a ceiling edge + aMesh->AddEdge(vecNewNodes[ 0 ]->second.back(), + vecNewNodes[ 1 ]->second.back() ); + } + else { + // create a ceiling edge + aMesh->AddEdge(vecNewNodes[ 0 ]->second.back(), + vecNewNodes[ 1 ]->second.back(), + vecNewNodes[ 2 ]->second.back()); + } } if ( elem->GetType() != SMDSAbs_Face ) continue; @@ -2220,43 +2821,72 @@ static void makeWalls (SMESHDS_Mesh* aMesh, set avoidSet; avoidSet.insert( elem ); - // loop on a face nodes set 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 a face nodes + 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 ); + } + } + } + } + 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 )) { + 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 )) { + 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 & 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 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::iterator v = newVolumes.begin(); iVol = 0; while ( iVol++ < volNb ) v++; @@ -2264,36 +2894,50 @@ static void makeWalls (SMESHDS_Mesh* aMesh, 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++ ) - { + 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 ) ) { + int nbn = vTool.NbFaceNodes( *ind ); + //switch ( vTool.NbFaceNodes( *ind ) ) { + switch ( nbn ) { case 3: aMesh->AddFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ] ); break; case 4: aMesh->AddFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ], nodes[ 3 ] ); break; default: { - int nbPolygonNodes = vTool.NbFaceNodes( *ind ); - vector polygon_nodes (nbPolygonNodes); - for (int inode = 0; inode < nbPolygonNodes; inode++) { - polygon_nodes[inode] = nodes[inode]; + if( (*v)->IsQuadratic() ) { + if(nbn==6) { + aMesh->AddFace(nodes[0], nodes[2], nodes[4], + nodes[1], nodes[3], nodes[5]); break; + } + else { + aMesh->AddFace(nodes[0], nodes[2], nodes[4], nodes[6], + nodes[1], nodes[3], nodes[5], nodes[7]); + break; + } + } + else { + int nbPolygonNodes = vTool.NbFaceNodes( *ind ); + vector polygon_nodes (nbPolygonNodes); + for (int inode = 0; inode < nbPolygonNodes; inode++) { + polygon_nodes[inode] = nodes[inode]; + } + aMesh->AddPolygonalFace(polygon_nodes); } - aMesh->AddPolygonalFace(polygon_nodes); break; } } @@ -2308,12 +2952,13 @@ static void makeWalls (SMESHDS_Mesh* aMesh, // 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 ])) @@ -2326,18 +2971,36 @@ static void makeWalls (SMESHDS_Mesh* aMesh, break; default: { - int nbPolygonNodes = lastVol.NbFaceNodes( iF ); - vector 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]) ) { + aMesh->AddFace(nodes[0], nodes[2], nodes[4], + nodes[1], nodes[3], nodes[5]); break; + } + } + else { // nbn==8 + if (!hasFreeLinks || + !aMesh->FindFace(nodes[0], nodes[2], nodes[4], nodes[6], + nodes[1], nodes[3], nodes[5], nodes[7]) ) + aMesh->AddFace(nodes[0], nodes[2], nodes[4], nodes[6], + nodes[1], nodes[3], nodes[5], nodes[7]); + } + } + else { + int nbPolygonNodes = lastVol.NbFaceNodes( iF ); + vector polygon_nodes (nbPolygonNodes); + for (int inode = 0; inode < nbPolygonNodes; inode++) { + polygon_nodes[inode] = nodes[inode]; + } + if (!hasFreeLinks || !aMesh->FindFace(polygon_nodes)) + aMesh->AddPolygonalFace(polygon_nodes); } - if (!hasFreeLinks || !aMesh->FindFace(polygon_nodes)) - aMesh->AddPolygonalFace(polygon_nodes); } break; } } - } // loop on swept elements } @@ -2355,6 +3018,8 @@ void SMESH_MeshEditor::RotationSweep(set & theElems, 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; @@ -2367,8 +3032,7 @@ void SMESH_MeshEditor::RotationSweep(set & theElems, // loop on theElems set< const SMDS_MeshElement* >::iterator itElem; - for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ ) - { + for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ ) { const SMDS_MeshElement* elem = (*itElem); if ( !elem ) continue; @@ -2383,8 +3047,7 @@ void SMESH_MeshEditor::RotationSweep(set & theElems, const SMDS_MeshNode* node = static_cast( itN->next() ); TNodeOfNodeListMapItr nIt = mapNewNodes.find( node ); - if ( nIt == mapNewNodes.end() ) - { + if ( nIt == mapNewNodes.end() ) { nIt = mapNewNodes.insert( make_pair( node, list() )).first; list& listNewNodes = nIt->second; @@ -2396,19 +3059,53 @@ void SMESH_MeshEditor::RotationSweep(set & theElems, 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] ); + 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] ); } - listNewNodes.push_back( 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; iAddNode( coord[0], coord[1], coord[2] ); + listNewNodes.push_back( newNode ); + aTrsf2.Transforms( coord[0], coord[1], coord[2] ); + newNode = aMesh->AddNode( coord[0], coord[1], coord[2] ); + listNewNodes.push_back( newNode ); + } + } } } newNodesItVec.push_back( nIt ); } // make new elements - sweepElement( aMesh, elem, newNodesItVec, newElemsMap[elem] ); + sweepElement( aMesh, elem, newNodesItVec, newElemsMap[elem], theNbSteps ); } - makeWalls( aMesh, mapNewNodes, newElemsMap, mapElemNewNodes, theElems ); + makeWalls( aMesh, mapNewNodes, newElemsMap, mapElemNewNodes, theElems, theNbSteps ); } @@ -2493,19 +3190,23 @@ void SMESH_MeshEditor::ExtrusionSweep { SMESHDS_Mesh* aMesh = GetMeshDS(); + int nbsteps = theParams.mySteps->Length(); + TNodeOfNodeListMap mapNewNodes; + //TNodeOfNodeVecMap mapNewNodes; TElemOfVecOfNnlmiMap mapElemNewNodes; + //TElemOfVecOfMapNodesMap mapElemNewNodes; // loop on theElems set< const SMDS_MeshElement* >::iterator itElem; - for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ ) - { + for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ ) { // check element type const SMDS_MeshElement* elem = (*itElem); if ( !elem ) continue; vector & newNodesItVec = mapElemNewNodes[ elem ]; + //vector & newNodesItVec = mapElemNewNodes[ elem ]; newNodesItVec.reserve( elem->NbNodes() ); // loop on elem nodes @@ -2516,15 +3217,33 @@ void SMESH_MeshEditor::ExtrusionSweep const SMDS_MeshNode* node = static_cast( 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() )).first; + //nIt = mapNewNodes.insert( make_pair( node, vector() )).first; list& listNewNodes = nIt->second; + //vector& vecNewNodes = nIt->second; + //vecNewNodes.reserve(nbsteps); // make new nodes double coord[] = { node->X(), node->Y(), node->Z() }; - int nbsteps = theParams.mySteps->Length(); + //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); + 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); @@ -2533,20 +3252,59 @@ void SMESH_MeshEditor::ExtrusionSweep 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] ); 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); + 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] ); + listNewNodes.push_back( newNode ); + } + } } } } newNodesItVec.push_back( nIt ); } // make new elements - sweepElement( aMesh, elem, newNodesItVec, newElemsMap[elem] ); + sweepElement( aMesh, elem, newNodesItVec, newElemsMap[elem], nbsteps ); } if( theFlags & EXTRUSION_FLAG_BOUNDARY ) { - makeWalls( aMesh, mapNewNodes, newElemsMap, mapElemNewNodes, theElems ); + makeWalls( aMesh, mapNewNodes, newElemsMap, mapElemNewNodes, theElems, nbsteps ); } } @@ -2855,6 +3613,14 @@ SMESH_MeshEditor::Extrusion_Error } // 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); + listNewNodes.push_back( newNode ); + } aX = aPN1.X(); aY = aPN1.Y(); aZ = aPN1.Z(); @@ -2867,13 +3633,44 @@ SMESH_MeshEditor::Extrusion_Error aDT0x = aDT1x; } } + + 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 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; iX() + 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); + 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() ); } - makeWalls( aMesh, mapNewNodes, newElemsMap, mapElemNewNodes, theElements ); + makeWalls( aMesh, mapNewNodes, newElemsMap, mapElemNewNodes, theElements, + aNbTP-1 ); return EXTR_OK; } @@ -2908,8 +3705,7 @@ void SMESH_MeshEditor::Transform (set & theElems, // loop on theElems set< const SMDS_MeshElement* >::iterator itElem; - for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ ) - { + for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ ) { const SMDS_MeshElement* elem = (*itElem); if ( !elem ) continue; @@ -2979,8 +3775,7 @@ void SMESH_MeshEditor::Transform (set & theElems, { 0, 1, 2, 3, 4, 5, 6, 7 } // FORWARD }; - for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ ) - { + for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ ) { const SMDS_MeshElement* elem = (*itElem); if ( !elem || elem->GetType() == SMDSAbs_Node ) continue; @@ -3071,12 +3866,46 @@ void SMESH_MeshEditor::Transform (set & theElems, 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( itN->next() ); TNodeNodeMap::iterator nodeMapIt = nodeMap.find( node ); @@ -3087,18 +3916,26 @@ void SMESH_MeshEditor::Transform (set & theElems, 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 ) + aMesh->AddEdge( nodes[ 0 ], nodes[ 1 ] ); + else + aMesh->AddEdge( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ] ); break; case SMDSAbs_Face: if ( nbNodes == 3 ) aMesh->AddFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ] ); - else + else if(nbNodes==4) aMesh->AddFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ] , nodes[ 3 ]); + else if(nbNodes==6) + aMesh->AddFace(nodes[0], nodes[1], nodes[2], nodes[3], + nodes[4], nodes[5]); + else // nbNodes==8 + 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 ) @@ -3112,6 +3949,22 @@ void SMESH_MeshEditor::Transform (set & theElems, else if ( nbNodes == 5 ) aMesh->AddVolume( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ] , nodes[ 3 ], nodes[ 4 ]); + else if(nbNodes==10) + 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) + 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) + 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 + 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:; } @@ -3275,13 +4128,11 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes) // Fill nodeNodeMap and elems TListOfListOfNodes::iterator grIt = theGroupsOfNodes.begin(); - for ( ; grIt != theGroupsOfNodes.end(); grIt++ ) - { + for ( ; grIt != theGroupsOfNodes.end(); grIt++ ) { list& nodes = *grIt; list::iterator nIt = nodes.begin(); const SMDS_MeshNode* nToKeep = *nIt; - for ( ; nIt != nodes.end(); nIt++ ) - { + for ( ; nIt != nodes.end(); nIt++ ) { const SMDS_MeshNode* nToRemove = *nIt; nodeNodeMap.insert( TNodeNodeMap::value_type( nToRemove, nToKeep )); if ( nToRemove != nToKeep ) { @@ -3290,15 +4141,16 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes) } 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::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 ); @@ -3309,8 +4161,7 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes) // get new seq of nodes SMDS_ElemIteratorPtr itN = elem->nodesIterator(); - while ( itN->more() ) - { + while ( itN->more() ) { const SMDS_MeshNode* n = static_cast( itN->next() ); @@ -3330,8 +4181,7 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes) 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()) { @@ -3360,15 +4210,18 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes) 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( elem ); @@ -3403,11 +4256,13 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes) else rmElemIds.push_back(elem->GetID()); - } else { + } + else { rmElemIds.push_back(elem->GetID()); } } - } else { + } + else { } continue; @@ -3478,7 +4333,96 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes) 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(); @@ -3682,11 +4626,13 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes) } 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() ); } @@ -3779,14 +4725,52 @@ const SMDS_MeshElement* 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(elem); + // use special nodes iterator + SMDS_NodeIteratorPtr anIter = F->interlacedNodesIterator(); + while ( anIter->more() ) { + faceNodes[iNode] = static_cast(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; } @@ -3830,12 +4814,12 @@ static bool findFreeBorder (const SMDS_MeshNode* theFirstNode, theNodes.push_back( theFirstNode ); theNodes.push_back( theSecondNode ); - const SMDS_MeshNode* nodes [5], *nIgnore = theFirstNode, * nStart = theSecondNode; + //vector 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; @@ -3846,13 +4830,24 @@ static bool findFreeBorder (const SMDS_MeshNode* theFirstNode, SMDS_ElemIteratorPtr invElemIt = nStart->facesIterator(); 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( nIt->next() ); + const SMDS_MeshNode* nodes[nbNodes+1]; + if(e->IsQuadratic()) { + const SMDS_QuadraticFaceOfNodes* F = + static_cast(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( nIt->next() ); + } nodes[ iNode ] = nodes[ 0 ]; // check 2 links for ( iNode = 0; iNode < nbNodes; iNode++ ) @@ -3987,8 +4982,7 @@ SMESH_MeshEditor::Sew_Error MESSAGE(" Free Border 1 not found " ); aResult = SEW_BORDER1_NOT_FOUND; } - if (theSideIsFreeBorder) - { + if (theSideIsFreeBorder) { // Free border 2 // -------------- if (!findFreeBorder(theSideFirstNode, theSideSecondNode, theSideThirdNode, @@ -4000,8 +4994,7 @@ SMESH_MeshEditor::Sew_Error if ( aResult != SEW_OK ) return aResult; - if (!theSideIsFreeBorder) - { + if (!theSideIsFreeBorder) { // Side 2 // -------------- @@ -4027,8 +5020,7 @@ SMESH_MeshEditor::Sew_Error 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 @@ -4057,8 +5049,7 @@ SMESH_MeshEditor::Sew_Error 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; @@ -4110,13 +5101,27 @@ SMESH_MeshEditor::Sew_Error 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( nIt->next() ); - if ( nodes[ iNode++ ] == prevSideNode ) - iPrevNode = iNode - 1; + if(elem->IsQuadratic()) { + const SMDS_QuadraticFaceOfNodes* F = + static_cast(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( nIt->next() ); + if ( nodes[ iNode++ ] == prevSideNode ) + iPrevNode = iNode - 1; + } } // there are 2 links to check nbNodes = 2; @@ -4129,7 +5134,8 @@ SMESH_MeshEditor::Sew_Error 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 @@ -4408,18 +5414,39 @@ void SMESH_MeshEditor::InsertNodesIntoLink(const SMDS_MeshElement* theFace, 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( 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(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( 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 ; @@ -4448,25 +5475,48 @@ void SMESH_MeshEditor::InsertNodesIntoLink(const SMDS_MeshElement* theFace, // 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( nodeIt->next() ); - poly_nodes[iNode++] = n; - if (n == nodes[il1]) { - isFLN = true; - } - } - // add nodes to insert - list::iterator nIt = aNodesToInsert.begin(); - for (; nIt != aNodesToInsert.end(); nIt++) { - poly_nodes[iNode++] = *nIt; + if(theFace->IsQuadratic()) { + const SMDS_QuadraticFaceOfNodes* F = + static_cast(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::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( nodeIt->next() ); - poly_nodes[iNode++] = n; + else { + SMDS_ElemIteratorPtr nodeIt = theFace->nodesIterator(); + while ( nodeIt->more() && !isFLN ) { + const SMDS_MeshNode* n = static_cast( nodeIt->next() ); + poly_nodes[iNode++] = n; + if (n == nodes[il1]) { + isFLN = true; + } + } + // add nodes to insert + list::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( nodeIt->next() ); + poly_nodes[iNode++] = n; + } } // edit or replace the face @@ -4474,8 +5524,8 @@ void SMESH_MeshEditor::InsertNodesIntoLink(const SMDS_MeshElement* theFace, if (theFace->IsPoly()) { aMesh->ChangePolygonNodes(theFace, poly_nodes); - - } else { + } + else { int aShapeId = FindShape( theFace ); SMDS_MeshElement* newElem = aMesh->AddPolygonalFace(poly_nodes); @@ -4487,81 +5537,184 @@ void SMESH_MeshEditor::InsertNodesIntoLink(const SMDS_MeshElement* theFace, 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::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::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 ]); + 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; iAddFace (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]); + 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]); + 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]); + 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]); + if ( aShapeId && newElem ) + aMesh->SetMeshElementOnShape( newElem, aShapeId ); + newElem = aMesh->AddFace(nodes[5],nodes[6],nodes[7]); + if ( aShapeId && newElem ) + aMesh->SetMeshElementOnShape( newElem, aShapeId ); + newElem = aMesh->AddFace(nodes[5],nodes[7],nodes[3]); + 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]); + 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]); + 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::iterator nIt = aNodesToInsert.begin(); + for ( iNode = 1; nIt != aNodesToInsert.end(); nIt++ ) { + aNodes[iNode++] = *nIt; + } + for(i=1; iAddFace(aNodes[i-1],aNodes[i],nodes[n3]); + 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 ); } //======================================================================= @@ -4607,7 +5760,8 @@ void SMESH_MeshEditor::UpdateVolumes (const SMDS_MeshNode* theBetweenNode poly_nodes.push_back(*nIt); } } - } else if (faceNodes[inode] == theBetweenNode2) { + } + else if (faceNodes[inode] == theBetweenNode2) { if (faceNodes[inode + 1] == theBetweenNode1) { nbInserted = theNodesToInsert.size(); @@ -4619,7 +5773,8 @@ void SMESH_MeshEditor::UpdateVolumes (const SMDS_MeshNode* theBetweenNode } poly_nodes.push_back(*nIt); } - } else { + } + else { } } } @@ -4632,7 +5787,8 @@ void SMESH_MeshEditor::UpdateVolumes (const SMDS_MeshNode* theBetweenNode if (elem->IsPoly()) { aMesh->ChangePolyhedronNodes(elem, poly_nodes, quantities); - } else { + } + else { int aShapeId = FindShape( elem ); SMDS_MeshElement* newElem = @@ -4709,11 +5865,24 @@ SMESH_MeshEditor::Sew_Error if ( elem->GetType() == SMDSAbs_Face ) { faceSet->insert( elem ); set faceNodeSet; - SMDS_ElemIteratorPtr nodeIt = elem->nodesIterator(); - while ( nodeIt->more() ) { - const SMDS_MeshNode* n = static_cast( nodeIt->next() ); - nodeSet->insert( n ); - faceNodeSet.insert( n ); + if(elem->IsQuadratic()) { + const SMDS_QuadraticFaceOfNodes* F = + static_cast(elem); + // use special nodes iterator + SMDS_NodeIteratorPtr anIter = F->interlacedNodesIterator(); + while( anIter->more() ) { + const SMDS_MeshNode* n = anIter->next(); + nodeSet->insert( n ); + faceNodeSet.insert( n ); + } + } + else { + SMDS_ElemIteratorPtr nodeIt = elem->nodesIterator(); + while ( nodeIt->more() ) { + const SMDS_MeshNode* n = static_cast( nodeIt->next() ); + nodeSet->insert( n ); + faceNodeSet.insert( n ); + } } setOfFaceNodeSet.insert( faceNodeSet ); } @@ -4754,8 +5923,7 @@ SMESH_MeshEditor::Sew_Error // face does not exist // ------------------------------------------------------------------------- - if ( !volSet->empty() ) - { + if ( !volSet->empty() ) { //int nodeSetSize = nodeSet->size(); // loop on given volumes @@ -4778,9 +5946,11 @@ SMESH_MeshEditor::Sew_Error // 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 { + } + else { vector poly_nodes (nbNodes); for (int inode = 0; inode < nbNodes; inode++) { poly_nodes[inode] = fNodes[inode]; @@ -4792,9 +5962,11 @@ SMESH_MeshEditor::Sew_Error // 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 { + } + else { vector poly_nodes (nbNodes); for (int inode = 0; inode < nbNodes; inode++) { poly_nodes[inode] = fNodes[inode]; @@ -4946,8 +6118,7 @@ SMESH_MeshEditor::Sew_Error // 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]++ ) - { + for ( ; linkIt[0] != linkList[0].end(); linkIt[0]++, linkIt[1]++ ) { TPairOfNodes link[] = { *linkIt[0], *linkIt[1] }; long linkID = aLinkID_Gen.GetLinkID( link[0].first, link[0].second ); if ( linkIdSet.find( linkID ) == linkIdSet.end() ) @@ -4959,8 +6130,12 @@ SMESH_MeshEditor::Sew_Error // --------------------------------------------------------------- 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 fnodes1(9); + vector fnodes2(9); + //const SMDS_MeshNode* notLinkNodes[ 2 ][ 2 ] = {{ 0, 0 },{ 0, 0 }} ; + vector notLinkNodes1(6); + vector notLinkNodes2(6); int iLinkNode[2][2]; for ( iSide = 0; iSide < 2; iSide++ ) { // loop on 2 sides const SMDS_MeshNode* n1 = link[iSide].first; @@ -4984,40 +6159,109 @@ SMESH_MeshEditor::Sew_Error 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( 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( 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(f); + // use special nodes iterator + SMDS_NodeIteratorPtr anIter = F->interlacedNodesIterator(); + while ( anIter->more() ) { + const SMDS_MeshNode* n = + static_cast( 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"); @@ -5025,9 +6269,12 @@ SMESH_MeshEditor::Sew_Error 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 @@ -5041,34 +6288,44 @@ SMESH_MeshEditor::Sew_Error 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::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]; + //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 ( TPairOfNodes( n1, n2 )); linkList[1].push_back ( TPairOfNodes( nReplaceMap[n1], nReplaceMap[n2] )); } @@ -5100,8 +6357,7 @@ SMESH_MeshEditor::Sew_Error // 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 @@ -5128,7 +6384,7 @@ SMESH_MeshEditor::Sew_Error if ( nbReplaced ) aMesh->ChangeElementNodes( e, nodes, nbNodes ); } - } + } Remove( nodeIDsToRemove, true ); diff --git a/src/SMESHGUI/SMESHGUI_MultiEditDlg.cxx b/src/SMESHGUI/SMESHGUI_MultiEditDlg.cxx index 6a70e8d5e..512a0ca7d 100755 --- a/src/SMESHGUI/SMESHGUI_MultiEditDlg.cxx +++ b/src/SMESHGUI/SMESHGUI_MultiEditDlg.cxx @@ -388,6 +388,35 @@ SMESH::long_array_var SMESHGUI_MultiEditDlg::getIds() anActor = myActor; if (anActor != 0) { + // skl 07.02.2006 + SMDS_Mesh* aMesh = myActor->GetObject()->GetMesh(); + if( myFilterType == SMESHGUI_TriaFilter || + myFilterType == SMESHGUI_QuadFilter || + myFilterType == SMESHGUI_FaceFilter ) { + SMDS_FaceIteratorPtr it = aMesh->facesIterator(); + while(it->more()) { + const SMDS_MeshFace* f = it->next(); + if(myFilterType == SMESHGUI_FaceFilter) { + myIds.Add(f->GetID()); + } + else if( myFilterType==SMESHGUI_TriaFilter && + ( f->NbNodes()==3 || f->NbNodes()==6 ) ) { + myIds.Add(f->GetID()); + } + else if( myFilterType==SMESHGUI_QuadFilter && + ( f->NbNodes()==4 || f->NbNodes()==8 ) ) { + myIds.Add(f->GetID()); + } + } + } + else if(myFilterType == SMESHGUI_VolumeFilter) { + SMDS_VolumeIteratorPtr it = aMesh->volumesIterator(); + while(it->more()) { + const SMDS_MeshVolume* f = it->next(); + myIds.Add(f->GetID()); + } + } + /* commented by skl 07.02.2006 TVisualObjPtr aVisualObj = anActor->GetObject(); vtkUnstructuredGrid* aGrid = aVisualObj->GetUnstructuredGrid(); if (aGrid != 0) { @@ -411,6 +440,7 @@ SMESH::long_array_var SMESHGUI_MultiEditDlg::getIds() } } } + */ } } diff --git a/src/StdMeshers/Makefile.in b/src/StdMeshers/Makefile.in index e0d879a73..d21007816 100644 --- a/src/StdMeshers/Makefile.in +++ b/src/StdMeshers/Makefile.in @@ -51,6 +51,7 @@ EXPORT_HEADERS = \ StdMeshers_AutomaticLength.hxx \ StdMeshers_Distribution.hxx \ StdMeshers_QuadranglePreference.hxx \ + StdMeshers_Helper.hxx \ StdMeshers_QuadraticMesh.hxx EXPORT_PYSCRIPTS = @@ -78,6 +79,7 @@ LIB_SRC = \ StdMeshers_AutomaticLength.cxx \ StdMeshers_Distribution.cxx \ StdMeshers_QuadranglePreference.cxx \ + StdMeshers_Helper.cxx \ StdMeshers_QuadraticMesh.cxx LIB_SERVER_IDL = diff --git a/src/StdMeshers/StdMeshers_Helper.cxx b/src/StdMeshers/StdMeshers_Helper.cxx new file mode 100644 index 000000000..219f8c44b --- /dev/null +++ b/src/StdMeshers/StdMeshers_Helper.cxx @@ -0,0 +1,433 @@ +// File: StdMeshers_Helper.cxx +// Created: 15.02.06 15:22:41 +// Author: Sergey KUUL +// Copyright: Open CASCADE 2006 + + +#include "StdMeshers_Helper.hxx" + +#include "TopTools_MapOfShape.hxx" +#include "BRepTools.hxx" +#include "BRepTools_WireExplorer.hxx" +#include "SMDS_FacePosition.hxx" +#include "SMDS_EdgePosition.hxx" +#include "SMESH_subMesh.hxx" +#include "Geom2d_Curve.hxx" +#include "Geom_Curve.hxx" +#include "Geom_Surface.hxx" +#include "BRep_Tool.hxx" +#include "gp_Pnt2d.hxx" + + +//======================================================================= +//function : CheckShape +//purpose : +//======================================================================= + +bool StdMeshers_Helper::IsQuadraticSubMesh(const TopoDS_Shape& aSh, + const bool QuadMode) +{ + SMESHDS_Mesh* meshDS = GetMesh()->GetMeshDS(); + myShapeID = meshDS->ShapeToIndex(aSh); + myCreateQuadratic = false; + if(QuadMode) { + // we can create quadratic elements only if each elements + // created on given shape is quadratic + // also we have to fill myNLinkNodeMap + myCreateQuadratic = true; + if(aSh.ShapeType()!=TopAbs_FACE) { + for (TopExp_Explorer exp(aSh, TopAbs_FACE); exp.More() && myCreateQuadratic; exp.Next()) { + const TopoDS_Face& F = TopoDS::Face(exp.Current()); + SMDS_ElemIteratorPtr itf = GetMesh()->GetSubMesh(F)->GetSubMeshDS()->GetElements(); + while(itf->more()) { + const SMDS_MeshElement* f = itf->next(); + if( f->GetType()==SMDSAbs_Face && !f->IsQuadratic() ) { + myCreateQuadratic = false; + break; + } + SMDS_ElemIteratorPtr itn = f->nodesIterator(); + if(f->NbNodes()==6) { + const SMDS_MeshNode* Ns[6]; + int i = 0; + while(itn->more()) { + Ns[i++] = static_cast( itn->next() ); + } + AddNLinkNode(Ns[0],Ns[1],Ns[3]); + AddNLinkNode(Ns[1],Ns[2],Ns[4]); + AddNLinkNode(Ns[2],Ns[0],Ns[5]); + } + else if(f->NbNodes()==8) { + const SMDS_MeshNode* Ns[8]; + int i = 0; + while(itn->more()) { + Ns[i++] = static_cast( itn->next() ); + } + AddNLinkNode(Ns[0],Ns[1],Ns[4]); + AddNLinkNode(Ns[1],Ns[2],Ns[5]); + AddNLinkNode(Ns[2],Ns[3],Ns[6]); + AddNLinkNode(Ns[3],Ns[0],Ns[7]); + } + } + } + } + else { + TopTools_MapOfShape aMap; + // check edges + const TopoDS_Face& F = TopoDS::Face(aSh); + const TopoDS_Wire& W = BRepTools::OuterWire(F); + BRepTools_WireExplorer wexp (W, F); + for (wexp.Init(W, F); wexp.More() && myCreateQuadratic; wexp.Next()) { + const TopoDS_Edge& E = wexp.Current(); + if(aMap.Contains(E)) + continue; + aMap.Add(E); + SMDS_ElemIteratorPtr it = GetMesh()->GetSubMesh(E)->GetSubMeshDS()->GetElements(); + while(it->more()) { + const SMDS_MeshElement* e = it->next(); + if( e->GetType()==SMDSAbs_Edge && !e->IsQuadratic() ) { + myCreateQuadratic = false; + break; + } + // fill NLinkNodeMap + SMDS_ElemIteratorPtr nodeIt = e->nodesIterator(); + const SMDS_MeshNode* n1 = static_cast( nodeIt->next() ); + const SMDS_MeshNode* n2 = static_cast( nodeIt->next() ); + const SMDS_MeshNode* n3 = static_cast( nodeIt->next() ); + NLink link(( n1 < n2 ? n1 : n2 ), ( n1 < n2 ? n2 : n1 )); + myNLinkNodeMap.insert(NLinkNodeMap::value_type(link,n3)); + myNLinkNodeMap[link] = n3; + } + } + } + } + + if(!myCreateQuadratic) { + myNLinkNodeMap.clear(); + } + + return myCreateQuadratic; +} + + +//======================================================================= +//function : IsMedium +//purpose : +//======================================================================= + +bool StdMeshers_Helper::IsMedium(const SMDS_MeshNode* n) +{ + SMDS_ElemIteratorPtr it = n->GetInverseElementIterator(); + while (it->more()) { + const SMDS_MeshElement* elem = it->next(); + return elem->IsMediumNode(n); + } + return false; +} + + +//======================================================================= +//function : AddNLinkNode +//purpose : +//======================================================================= +/*! + * Auxilary function for filling myNLinkNodeMap + */ +void StdMeshers_Helper::AddNLinkNode(const SMDS_MeshNode* n1, + const SMDS_MeshNode* n2, + const SMDS_MeshNode* n12) +{ + NLink link(( n1 < n2 ? n1 : n2 ), ( n1 < n2 ? n2 : n1 )); + ItNLinkNode itLN = myNLinkNodeMap.find( link ); + if ( itLN == myNLinkNodeMap.end() ) { + // add new record to map + myNLinkNodeMap.insert(NLinkNodeMap::value_type(link,n12)); + } +} + + +//======================================================================= +//function : GetNodeUV +//purpose : +//======================================================================= +/*! + * Auxilary function for GetMediumNode() + */ +gp_XY StdMeshers_Helper::GetNodeUV(const TopoDS_Face& F, + const SMDS_MeshNode* n) +{ + gp_Pnt2d p2d; + const SMDS_PositionPtr Pos = n->GetPosition(); + if(Pos->GetTypeOfPosition()==SMDS_TOP_FACE) { +//cout<<"face"<(n->GetPosition().get()); + p2d = gp_Pnt2d(fpos->GetUParameter(),fpos->GetVParameter()); +//cout<<"fpos->GetUParameter()="<GetUParameter()<<" fpos->GetVParameter()="<GetVParameter()<GetTypeOfPosition()==SMDS_TOP_EDGE) { + // node has position on edge => it is needed to find + // corresponding edge from face, get pcurve for this + // edge and recieve value from this pcurve + const SMDS_EdgePosition* epos = + static_cast(n->GetPosition().get()); + double param = epos->GetUParameter(); + SMESHDS_Mesh* meshDS = GetMesh()->GetMeshDS(); + int edgeID = Pos->GetShapeId(); + const TopoDS_Edge& E = TopoDS::Edge(meshDS->IndexToShape(edgeID)); + double f, l; + Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(E, F, f, l); + p2d = C2d->Value(param); + } + else { // vertex position + SMESHDS_Mesh * meshDS = GetMesh()->GetMeshDS(); + const TopoDS_Wire& W = BRepTools::OuterWire(F); + BRepTools_WireExplorer wexp (W, F); + TopoDS_Edge E; + for (wexp.Init(W, F); wexp.More(); wexp.Next()) { + E = wexp.Current(); + TopoDS_Vertex V1 = TopExp::FirstVertex(E); + TopoDS_Vertex V2 = TopExp::LastVertex(E); + if( meshDS->ShapeToIndex(V1) != Pos->GetShapeId() && + meshDS->ShapeToIndex(V2) != Pos->GetShapeId() ) continue; + double f2, l2; + Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(E, F, f2, l2); + double f, l; + TopLoc_Location L; + Handle(Geom_Curve) C = BRep_Tool::Curve(E, L, f, l); + gp_Pnt P = C->Value(f); + if(!L.IsIdentity()) P = P.Transformed(L.Transformation()); + double tol = BRep_Tool::Tolerance(E); + double dx = n->X() - P.X(); + double dy = n->Y() - P.Y(); + double dz = n->Z() - P.Z(); + double dist = sqrt(dx*dx + dy*dy + dz*dz); + if(distValue(f2); + } + else { + p2d = C2d->Value(l2); + } + } + } + return p2d.XY(); +} + + +//======================================================================= +//function : GetMediumNode +//purpose : +//======================================================================= +/*! + * Special function for search or creation medium node + */ +const SMDS_MeshNode* StdMeshers_Helper::GetMediumNode(const SMDS_MeshNode* n1, + const SMDS_MeshNode* n2, + const bool force3d) +{ +//cout<<"n1: "<GetMeshDS(); + if(!force3d) { + // we try to create medium node using UV parameters of + // nodes, else - medium between corresponding 3d points + const SMDS_PositionPtr Pos1 = n1->GetPosition(); + const SMDS_PositionPtr Pos2 = n2->GetPosition(); + int faceID = -1; + if( Pos1->GetTypeOfPosition()==SMDS_TOP_FACE ) { + faceID = Pos1->GetShapeId(); + } + else if( Pos2->GetTypeOfPosition()==SMDS_TOP_FACE ) { + faceID = Pos2->GetShapeId(); + } + if(faceID>-1) { + TopoDS_Face F = TopoDS::Face(meshDS->IndexToShape(faceID)); + gp_XY p1 = GetNodeUV(F,n1); + gp_XY p2 = GetNodeUV(F,n2); + double u = (p1.X()+p2.X())/2.; + double v = (p1.Y()+p2.Y())/2.; + Handle(Geom_Surface) S = BRep_Tool::Surface(F); + gp_Pnt P = S->Value(u, v); + n12 = meshDS->AddNode(P.X(), P.Y(), P.Z()); + meshDS->SetNodeOnFace(n12, faceID, u, v); + myNLinkNodeMap.insert(NLinkNodeMap::value_type(link,n12)); + return n12; + } + } + // 3d variant + double x = ( n1->X() + n2->X() )/2.; + double y = ( n1->Y() + n2->Y() )/2.; + double z = ( n1->Z() + n2->Z() )/2.; + n12 = meshDS->AddNode(x,y,z); + meshDS->SetNodeInVolume(n12, myShapeID); + myNLinkNodeMap.insert(NLinkNodeMap::value_type(link,n12)); + return n12; + } +} + + +//======================================================================= +//function : AddFace +//purpose : +//======================================================================= +/*! + * Special function for creation quadratic triangle + */ +SMDS_MeshFace* StdMeshers_Helper::AddFace(const SMDS_MeshNode* n1, + const SMDS_MeshNode* n2, + const SMDS_MeshNode* n3) +{ + SMESHDS_Mesh * meshDS = GetMesh()->GetMeshDS(); + if(!myCreateQuadratic) { + return meshDS->AddFace(n1, n2, n3); + } + + const SMDS_MeshNode* n12 = GetMediumNode(n1,n2,false); + const SMDS_MeshNode* n23 = GetMediumNode(n2,n3,false); + const SMDS_MeshNode* n31 = GetMediumNode(n3,n1,false); + + return meshDS->AddFace(n1, n2, n3, n12, n23, n31); +} + + +//======================================================================= +//function : AddFace +//purpose : +//======================================================================= +/*! + * Special function for creation quadratic quadrangle + */ +SMDS_MeshFace* StdMeshers_Helper::AddFace(const SMDS_MeshNode* n1, + const SMDS_MeshNode* n2, + const SMDS_MeshNode* n3, + const SMDS_MeshNode* n4) +{ + SMESHDS_Mesh * meshDS = GetMesh()->GetMeshDS(); + if(!myCreateQuadratic) { + return meshDS->AddFace(n1, n2, n3, n4); + } + + const SMDS_MeshNode* n12 = GetMediumNode(n1,n2,false); + const SMDS_MeshNode* n23 = GetMediumNode(n2,n3,false); + const SMDS_MeshNode* n34 = GetMediumNode(n3,n4,false); + const SMDS_MeshNode* n41 = GetMediumNode(n4,n1,false); + + return meshDS->AddFace(n1, n2, n3, n4, n12, n23, n34, n41); +} + + +//======================================================================= +//function : AddVolume +//purpose : +//======================================================================= +/*! + * Special function for creation quadratic volume + */ +SMDS_MeshVolume* StdMeshers_Helper::AddVolume(const SMDS_MeshNode* n1, + const SMDS_MeshNode* n2, + const SMDS_MeshNode* n3, + const SMDS_MeshNode* n4, + const SMDS_MeshNode* n5, + const SMDS_MeshNode* n6) +{ + SMESHDS_Mesh * meshDS = GetMesh()->GetMeshDS(); + if(!myCreateQuadratic) { + return meshDS->AddVolume(n1, n2, n3, n4, n5, n6); + } + + const SMDS_MeshNode* n12 = GetMediumNode(n1,n2,true); + const SMDS_MeshNode* n23 = GetMediumNode(n2,n3,true); + const SMDS_MeshNode* n31 = GetMediumNode(n3,n1,true); + + const SMDS_MeshNode* n45 = GetMediumNode(n4,n5,true); + const SMDS_MeshNode* n56 = GetMediumNode(n5,n6,true); + const SMDS_MeshNode* n64 = GetMediumNode(n6,n4,true); + + const SMDS_MeshNode* n14 = GetMediumNode(n1,n4,true); + const SMDS_MeshNode* n25 = GetMediumNode(n2,n5,true); + const SMDS_MeshNode* n36 = GetMediumNode(n3,n6,true); + + return meshDS->AddVolume(n1, n2, n3, n4, n5, n6, + n12, n23, n31, n45, n56, n64, n14, n25, n36); +} + + +//======================================================================= +//function : AddVolume +//purpose : +//======================================================================= +/*! + * Special function for creation quadratic volume + */ +SMDS_MeshVolume* StdMeshers_Helper::AddVolume(const SMDS_MeshNode* n1, + const SMDS_MeshNode* n2, + const SMDS_MeshNode* n3, + const SMDS_MeshNode* n4) +{ + SMESHDS_Mesh * meshDS = GetMesh()->GetMeshDS(); + if(!myCreateQuadratic) { + return meshDS->AddVolume(n1, n2, n3, n4); + } + + const SMDS_MeshNode* n12 = GetMediumNode(n1,n2,true); + const SMDS_MeshNode* n23 = GetMediumNode(n2,n3,true); + const SMDS_MeshNode* n31 = GetMediumNode(n3,n1,true); + + const SMDS_MeshNode* n14 = GetMediumNode(n1,n4,true); + const SMDS_MeshNode* n24 = GetMediumNode(n2,n4,true); + const SMDS_MeshNode* n34 = GetMediumNode(n3,n4,true); + + return meshDS->AddVolume(n1, n2, n3, n4, n12, n23, n31, n14, n24, n34); +} + + +//======================================================================= +//function : AddVolume +//purpose : +//======================================================================= +/*! + * Special function for creation quadratic volume + */ +SMDS_MeshVolume* StdMeshers_Helper::AddVolume(const SMDS_MeshNode* n1, + const SMDS_MeshNode* n2, + const SMDS_MeshNode* n3, + const SMDS_MeshNode* n4, + const SMDS_MeshNode* n5, + const SMDS_MeshNode* n6, + const SMDS_MeshNode* n7, + const SMDS_MeshNode* n8) +{ + SMESHDS_Mesh * meshDS = GetMesh()->GetMeshDS(); + if(!myCreateQuadratic) { + return meshDS->AddVolume(n1, n2, n3, n4, n5, n6, n7, n8); + } + + const SMDS_MeshNode* n12 = GetMediumNode(n1,n2,true); + const SMDS_MeshNode* n23 = GetMediumNode(n2,n3,true); + const SMDS_MeshNode* n34 = GetMediumNode(n3,n4,true); + const SMDS_MeshNode* n41 = GetMediumNode(n4,n1,true); + + const SMDS_MeshNode* n56 = GetMediumNode(n5,n6,true); + const SMDS_MeshNode* n67 = GetMediumNode(n6,n7,true); + const SMDS_MeshNode* n78 = GetMediumNode(n7,n8,true); + const SMDS_MeshNode* n85 = GetMediumNode(n8,n5,true); + + const SMDS_MeshNode* n15 = GetMediumNode(n1,n5,true); + const SMDS_MeshNode* n26 = GetMediumNode(n2,n6,true); + const SMDS_MeshNode* n37 = GetMediumNode(n3,n7,true); + const SMDS_MeshNode* n48 = GetMediumNode(n4,n8,true); + + return meshDS->AddVolume(n1, n2, n3, n4, n5, n6, n7, n8, + n12, n23, n34, n41, n56, n67, + n78, n85, n15, n26, n37, n48); +} + + diff --git a/src/StdMeshers/StdMeshers_Helper.hxx b/src/StdMeshers/StdMeshers_Helper.hxx new file mode 100644 index 000000000..33c1853b9 --- /dev/null +++ b/src/StdMeshers/StdMeshers_Helper.hxx @@ -0,0 +1,149 @@ +// File: StdMeshers_Helper.hxx +// Created: 15.02.06 14:48:09 +// Author: Sergey KUUL +// Copyright: Open CASCADE 2006 + + +#ifndef StdMeshers_Helper_HeaderFile +#define StdMeshers_Helper_HeaderFile + +#include +#include +#include +#include +#include + +#include + +typedef pair NLink; +typedef map NLinkNodeMap; +typedef map::iterator ItNLinkNode; + +/// Class StdMeshers_Helper +// + +class StdMeshers_Helper +{ + public: + // ---------- PUBLIC METHODS ---------- + + /// Empty constructor + StdMeshers_Helper(SMESH_Mesh& theMesh) + { myMesh=(void *)&theMesh; myCreateQuadratic = false; } + + SMESH_Mesh* GetMesh() const + { return (SMESH_Mesh*)myMesh; } + + /// Copy constructor + //Standard_EXPORT StdMeshers_Helper (const StdMeshers_Helper& theOther); + + /// Destructor + //Standard_EXPORT virtual ~StdMeshers_Helper (); + + /** + * Check submesh for given shape + * If QuadMode is true: check if all elements on this shape + * are quadratic, if yes => set true to myCreateQuadratic + * (default value is false). Also fill myNLinkNodeMap + * Returns myCreateQuadratic + */ + bool IsQuadraticSubMesh(const TopoDS_Shape& aSh, const bool QuadMode); + + /** + * Returns true if given node is medium + */ + bool IsMedium(const SMDS_MeshNode* n); + + /** + * Auxilary function for filling myNLinkNodeMap + */ + void AddNLinkNode(const SMDS_MeshNode* n1, + const SMDS_MeshNode* n2, + const SMDS_MeshNode* n12); + + /** + * Auxilary function for filling myNLinkNodeMap + */ + void AddNLinkNodeMap(const NLinkNodeMap& aMap) + { myNLinkNodeMap.insert(aMap.begin(), aMap.end()); } + + /** + * Returns myNLinkNodeMap + */ + const NLinkNodeMap& GetNLinkNodeMap() { return myNLinkNodeMap; } + + /** + * Auxilary function for GetMediumNode() + */ + gp_XY GetNodeUV(const TopoDS_Face& F, + const SMDS_MeshNode* n); + + /** + * Special function for search or creation medium node + */ + const SMDS_MeshNode* GetMediumNode(const SMDS_MeshNode* n1, + const SMDS_MeshNode* n2, + const bool force3d); + /** + * Special function for creation quadratic triangle + */ + SMDS_MeshFace* AddFace(const SMDS_MeshNode* n1, + const SMDS_MeshNode* n2, + const SMDS_MeshNode* n3); + + /** + * Special function for creation quadratic quadrangle + */ + SMDS_MeshFace* AddFace(const SMDS_MeshNode* n1, + const SMDS_MeshNode* n2, + const SMDS_MeshNode* n3, + const SMDS_MeshNode* n4); + + /** + * Special function for creation quadratic tetraahedron + */ + SMDS_MeshVolume* AddVolume(const SMDS_MeshNode* n1, + const SMDS_MeshNode* n2, + const SMDS_MeshNode* n3, + const SMDS_MeshNode* n4); + + /** + * Special function for creation quadratic pentahedron + */ + SMDS_MeshVolume* AddVolume(const SMDS_MeshNode* n1, + const SMDS_MeshNode* n2, + const SMDS_MeshNode* n3, + const SMDS_MeshNode* n4, + const SMDS_MeshNode* n5, + const SMDS_MeshNode* n6); + + /** + * Special function for creation quadratic hexahedron + */ + SMDS_MeshVolume* AddVolume(const SMDS_MeshNode* n1, + const SMDS_MeshNode* n2, + const SMDS_MeshNode* n3, + const SMDS_MeshNode* n4, + const SMDS_MeshNode* n5, + const SMDS_MeshNode* n6, + const SMDS_MeshNode* n7, + const SMDS_MeshNode* n8); + + + + private: + + void* myMesh; + + int myShapeID; + + // Key for creation quadratic faces + bool myCreateQuadratic; + + // special map for using during creation quadratic faces + NLinkNodeMap myNLinkNodeMap; + +}; + + +#endif diff --git a/src/StdMeshers/StdMeshers_Hexa_3D.cxx b/src/StdMeshers/StdMeshers_Hexa_3D.cxx index a3ed4f11a..30384f31d 100644 --- a/src/StdMeshers/StdMeshers_Hexa_3D.cxx +++ b/src/StdMeshers/StdMeshers_Hexa_3D.cxx @@ -45,6 +45,7 @@ using namespace std; #include #include #include +#include #include #include @@ -146,6 +147,7 @@ static bool findIJ (const SMDS_MeshNode* node, const FaceQuadStruct * quad, int& return true; } + //============================================================================= /*! * Hexahedron mesh on hexaedron like form @@ -163,534 +165,529 @@ bool StdMeshers_Hexa_3D::Compute(SMESH_Mesh & aMesh, const TopoDS_Shape & aShape)throw(SALOME_Exception) { Unexpect aCatch(SalomeException); - MESSAGE("StdMeshers_Hexa_3D::Compute"); - //bool isOk = false; - SMESHDS_Mesh * meshDS = aMesh.GetMeshDS(); - //SMESH_subMesh *theSubMesh = aMesh.GetSubMesh(aShape); - //const SMESHDS_SubMesh *& subMeshDS = theSubMesh->GetSubMeshDS(); - - // 0. - shape and face mesh verification - // 0.1 - shape must be a solid (or a shell) with 6 faces - //MESSAGE("---"); - - vector < SMESH_subMesh * >meshFaces; - for (TopExp_Explorer exp(aShape, TopAbs_FACE); exp.More(); exp.Next()) - { - SMESH_subMesh *aSubMesh = aMesh.GetSubMeshContaining(exp.Current()); - ASSERT(aSubMesh); - meshFaces.push_back(aSubMesh); - } - if (meshFaces.size() != 6) - { - SCRUTE(meshFaces.size()); -// ASSERT(0); - return false; - } - - // 0.2 - is each face meshed with Quadrangle_2D? (so, with a wire of 4 edges) - //MESSAGE("---"); - - for (int i = 0; i < 6; i++) - { - TopoDS_Shape aFace = meshFaces[i]->GetSubShape(); - SMESH_Algo *algo = _gen->GetAlgo(aMesh, aFace); - string algoName = algo->GetName(); - bool isAllQuad = false; - if (algoName == "Quadrangle_2D") { - SMESHDS_SubMesh * sm = meshDS->MeshElements( aFace ); - if ( sm ) { - isAllQuad = true; - SMDS_ElemIteratorPtr eIt = sm->GetElements(); - while ( isAllQuad && eIt->more() ) - isAllQuad = ( eIt->next()->NbNodes() == 4 ); - } - } - if ( ! isAllQuad ) { - //modified by NIZNHY-PKV Wed Nov 17 15:31:37 2004 f - bool bIsOk; - // - bIsOk=ComputePentahedralMesh(aMesh, aShape); - if (bIsOk) { - return true; - } - //modified by NIZNHY-PKV Wed Nov 17 15:31:42 2004 t - SCRUTE(algoName); - // ASSERT(0); - return false; - } - StdMeshers_Quadrangle_2D *quadAlgo = - dynamic_cast < StdMeshers_Quadrangle_2D * >(algo); - ASSERT(quadAlgo); - try - { - _quads[i] = quadAlgo->CheckAnd2Dcompute(aMesh, aFace); - // *** to delete after usage - } - catch(SALOME_Exception & S_ex) - { - // *** delete _quads - // *** throw exception - // ASSERT(0); - return false; - } - - // 0.2.1 - number of points on the opposite edges must be the same - if (_quads[i]->nbPts[0] != _quads[i]->nbPts[2] || - _quads[i]->nbPts[1] != _quads[i]->nbPts[3]) - { - MESSAGE("different number of points on the opposite edges of face " << i); - // ASSERT(0); - return false; - } - } - - // 1. - identify faces and vertices of the "cube" - // 1.1 - ancestor maps vertex->edges in the cube - //MESSAGE("---"); - - TopTools_IndexedDataMapOfShapeListOfShape MS; - TopExp::MapShapesAndAncestors(aShape, TopAbs_VERTEX, TopAbs_EDGE, MS); - - // 1.2 - first face is choosen as face Y=0 of the unit cube - //MESSAGE("---"); - - const TopoDS_Shape & aFace = meshFaces[0]->GetSubShape(); - const TopoDS_Face & F = TopoDS::Face(aFace); - - // 1.3 - identify the 4 vertices of the face Y=0: V000, V100, V101, V001 - //MESSAGE("---"); - - int i = 0; - TopoDS_Edge E = _quads[0]->edge[i]; //edge will be Y=0,Z=0 on unit cube - double f, l; - Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(E, F, f, l); - TopoDS_Vertex VFirst, VLast; - TopExp::Vertices(E, VFirst, VLast); // corresponds to f and l - bool isForward = - (((l - f) * (_quads[0]->last[i] - _quads[0]->first[i])) > 0); + MESSAGE("StdMeshers_Hexa_3D::Compute"); + //bool isOk = false; + SMESHDS_Mesh * meshDS = aMesh.GetMeshDS(); + //SMESH_subMesh *theSubMesh = aMesh.GetSubMesh(aShape); + //const SMESHDS_SubMesh *& subMeshDS = theSubMesh->GetSubMeshDS(); + + // 0. - shape and face mesh verification + // 0.1 - shape must be a solid (or a shell) with 6 faces + //MESSAGE("---"); - if (isForward) - { - _cube.V000 = VFirst; // will be (0,0,0) on the unit cube - _cube.V100 = VLast; // will be (1,0,0) on the unit cube - } - else - { - _cube.V000 = VLast; - _cube.V100 = VFirst; - } + bool QuadMode = true; - i = 1; - E = _quads[0]->edge[i]; - C2d = BRep_Tool::CurveOnSurface(E, F, f, l); - TopExp::Vertices(E, VFirst, VLast); - isForward = (((l - f) * (_quads[0]->last[i] - _quads[0]->first[i])) > 0); - if (isForward) - _cube.V101 = VLast; // will be (1,0,1) on the unit cube - else - _cube.V101 = VFirst; + myTool = new StdMeshers_Helper(aMesh); + myCreateQuadratic = myTool->IsQuadraticSubMesh(aShape,QuadMode); - i = 2; - E = _quads[0]->edge[i]; - C2d = BRep_Tool::CurveOnSurface(E, F, f, l); - TopExp::Vertices(E, VFirst, VLast); - isForward = (((l - f) * (_quads[0]->last[i] - _quads[0]->first[i])) > 0); - if (isForward) - _cube.V001 = VLast; // will be (0,0,1) on the unit cube - else - _cube.V001 = VFirst; + vector < SMESH_subMesh * >meshFaces; + for (TopExp_Explorer exp(aShape, TopAbs_FACE); exp.More(); exp.Next()) { + SMESH_subMesh *aSubMesh = aMesh.GetSubMeshContaining(exp.Current()); + ASSERT(aSubMesh); + meshFaces.push_back(aSubMesh); + } + if (meshFaces.size() != 6) { + SCRUTE(meshFaces.size()); +// ASSERT(0); + return false; + } - // 1.4 - find edge X=0, Z=0 (ancestor of V000 not in face Y=0) - // - find edge X=1, Z=0 (ancestor of V100 not in face Y=0) - // - find edge X=1, Z=1 (ancestor of V101 not in face Y=0) - // - find edge X=0, Z=1 (ancestor of V001 not in face Y=0) - //MESSAGE("---"); + // 0.2 - is each face meshed with Quadrangle_2D? (so, with a wire of 4 edges) + //MESSAGE("---"); + + for (int i = 0; i < 6; i++) { + TopoDS_Shape aFace = meshFaces[i]->GetSubShape(); + SMESH_Algo *algo = _gen->GetAlgo(aMesh, aFace); + string algoName = algo->GetName(); + bool isAllQuad = false; + if (algoName == "Quadrangle_2D") { + SMESHDS_SubMesh * sm = meshDS->MeshElements( aFace ); + if ( sm ) { + isAllQuad = true; + SMDS_ElemIteratorPtr eIt = sm->GetElements(); + while ( isAllQuad && eIt->more() ) { + const SMDS_MeshElement* elem = eIt->next(); + isAllQuad = ( elem->NbNodes()==4 ||(myCreateQuadratic && elem->NbNodes()==8) ); + } + } + } + if ( ! isAllQuad ) { + //modified by NIZNHY-PKV Wed Nov 17 15:31:37 2004 f + bool bIsOk; + // + bIsOk = ComputePentahedralMesh(aMesh, aShape); + if (bIsOk) { + return true; + } + //modified by NIZNHY-PKV Wed Nov 17 15:31:42 2004 t + SCRUTE(algoName); + // ASSERT(0); + return false; + } + StdMeshers_Quadrangle_2D *quadAlgo = + dynamic_cast < StdMeshers_Quadrangle_2D * >(algo); + ASSERT(quadAlgo); + try { + _quads[i] = quadAlgo->CheckAnd2Dcompute(aMesh, aFace, myCreateQuadratic); + // add links created in quadAlgo into myNLinkNodeMap +// NLinkNodeMap aMap = quadAlgo->GetNLinkNodeMap(); +// myNLinkNodeMap.insert(aMap.begin(), aMap.end()); + myTool->AddNLinkNodeMap(quadAlgo->GetNLinkNodeMap()); + // *** to delete after usage + } + catch(SALOME_Exception & S_ex) { + // *** delete _quads + // *** throw exception + // ASSERT(0); + return false; + } - TopoDS_Edge E_0Y0 = EdgeNotInFace(aMesh, aShape, F, _cube.V000, MS); - ASSERT(!E_0Y0.IsNull()); + // 0.2.1 - number of points on the opposite edges must be the same + if (_quads[i]->nbPts[0] != _quads[i]->nbPts[2] || + _quads[i]->nbPts[1] != _quads[i]->nbPts[3]) { + MESSAGE("different number of points on the opposite edges of face " << i); + // ASSERT(0); + return false; + } + } - TopoDS_Edge E_1Y0 = EdgeNotInFace(aMesh, aShape, F, _cube.V100, MS); - ASSERT(!E_1Y0.IsNull()); + // 1. - identify faces and vertices of the "cube" + // 1.1 - ancestor maps vertex->edges in the cube + //MESSAGE("---"); - TopoDS_Edge E_1Y1 = EdgeNotInFace(aMesh, aShape, F, _cube.V101, MS); - ASSERT(!E_1Y1.IsNull()); + TopTools_IndexedDataMapOfShapeListOfShape MS; + TopExp::MapShapesAndAncestors(aShape, TopAbs_VERTEX, TopAbs_EDGE, MS); - TopoDS_Edge E_0Y1 = EdgeNotInFace(aMesh, aShape, F, _cube.V001, MS); - ASSERT(!E_0Y1.IsNull()); + // 1.2 - first face is choosen as face Y=0 of the unit cube + //MESSAGE("---"); - // 1.5 - identify the 4 vertices in face Y=1: V010, V110, V111, V011 - //MESSAGE("---"); + const TopoDS_Shape & aFace = meshFaces[0]->GetSubShape(); + const TopoDS_Face & F = TopoDS::Face(aFace); - TopExp::Vertices(E_0Y0, VFirst, VLast); - if (VFirst.IsSame(_cube.V000)) - _cube.V010 = VLast; - else - _cube.V010 = VFirst; + // 1.3 - identify the 4 vertices of the face Y=0: V000, V100, V101, V001 + //MESSAGE("---"); - TopExp::Vertices(E_1Y0, VFirst, VLast); - if (VFirst.IsSame(_cube.V100)) - _cube.V110 = VLast; - else - _cube.V110 = VFirst; + int i = 0; + TopoDS_Edge E = _quads[0]->edge[i]; //edge will be Y=0,Z=0 on unit cube + double f, l; + Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(E, F, f, l); + TopoDS_Vertex VFirst, VLast; + TopExp::Vertices(E, VFirst, VLast); // corresponds to f and l + bool isForward = (((l - f) * (_quads[0]->last[i] - _quads[0]->first[i])) > 0); - TopExp::Vertices(E_1Y1, VFirst, VLast); - if (VFirst.IsSame(_cube.V101)) - _cube.V111 = VLast; - else - _cube.V111 = VFirst; + if (isForward) { + _cube.V000 = VFirst; // will be (0,0,0) on the unit cube + _cube.V100 = VLast; // will be (1,0,0) on the unit cube + } + else { + _cube.V000 = VLast; + _cube.V100 = VFirst; + } - TopExp::Vertices(E_0Y1, VFirst, VLast); - if (VFirst.IsSame(_cube.V001)) - _cube.V011 = VLast; - else - _cube.V011 = VFirst; - - // 1.6 - find remaining faces given 4 vertices - //MESSAGE("---"); - - _indY0 = 0; - _cube.quad_Y0 = _quads[_indY0]; - - _indY1 = GetFaceIndex(aMesh, aShape, meshFaces, - _cube.V010, _cube.V011, _cube.V110, _cube.V111); - _cube.quad_Y1 = _quads[_indY1]; - - _indZ0 = GetFaceIndex(aMesh, aShape, meshFaces, - _cube.V000, _cube.V010, _cube.V100, _cube.V110); - _cube.quad_Z0 = _quads[_indZ0]; - - _indZ1 = GetFaceIndex(aMesh, aShape, meshFaces, - _cube.V001, _cube.V011, _cube.V101, _cube.V111); - _cube.quad_Z1 = _quads[_indZ1]; - - _indX0 = GetFaceIndex(aMesh, aShape, meshFaces, - _cube.V000, _cube.V001, _cube.V010, _cube.V011); - _cube.quad_X0 = _quads[_indX0]; - - _indX1 = GetFaceIndex(aMesh, aShape, meshFaces, - _cube.V100, _cube.V101, _cube.V110, _cube.V111); - _cube.quad_X1 = _quads[_indX1]; - - //MESSAGE("---"); - - // 1.7 - get convertion coefs from face 2D normalized to 3D normalized - - Conv2DStruct cx0; // for face X=0 - Conv2DStruct cx1; // for face X=1 - Conv2DStruct cy0; - Conv2DStruct cy1; - Conv2DStruct cz0; - Conv2DStruct cz1; - - GetConv2DCoefs(*_cube.quad_X0, meshFaces[_indX0]->GetSubShape(), - _cube.V000, _cube.V010, _cube.V011, _cube.V001, cx0); - GetConv2DCoefs(*_cube.quad_X1, meshFaces[_indX1]->GetSubShape(), - _cube.V100, _cube.V110, _cube.V111, _cube.V101, cx1); - GetConv2DCoefs(*_cube.quad_Y0, meshFaces[_indY0]->GetSubShape(), - _cube.V000, _cube.V100, _cube.V101, _cube.V001, cy0); - GetConv2DCoefs(*_cube.quad_Y1, meshFaces[_indY1]->GetSubShape(), - _cube.V010, _cube.V110, _cube.V111, _cube.V011, cy1); - GetConv2DCoefs(*_cube.quad_Z0, meshFaces[_indZ0]->GetSubShape(), - _cube.V000, _cube.V100, _cube.V110, _cube.V010, cz0); - GetConv2DCoefs(*_cube.quad_Z1, meshFaces[_indZ1]->GetSubShape(), - _cube.V001, _cube.V101, _cube.V111, _cube.V011, cz1); - - // 1.8 - create a 3D structure for normalized values - - //MESSAGE("---"); - int nbx = _cube.quad_Z0->nbPts[0]; - if (cz0.a1 == 0.) nbx = _cube.quad_Z0->nbPts[1]; + i = 1; + E = _quads[0]->edge[i]; + C2d = BRep_Tool::CurveOnSurface(E, F, f, l); + TopExp::Vertices(E, VFirst, VLast); + isForward = (((l - f) * (_quads[0]->last[i] - _quads[0]->first[i])) > 0); + if (isForward) + _cube.V101 = VLast; // will be (1,0,1) on the unit cube + else + _cube.V101 = VFirst; + + i = 2; + E = _quads[0]->edge[i]; + C2d = BRep_Tool::CurveOnSurface(E, F, f, l); + TopExp::Vertices(E, VFirst, VLast); + isForward = (((l - f) * (_quads[0]->last[i] - _quads[0]->first[i])) > 0); + if (isForward) + _cube.V001 = VLast; // will be (0,0,1) on the unit cube + else + _cube.V001 = VFirst; + + // 1.4 - find edge X=0, Z=0 (ancestor of V000 not in face Y=0) + // - find edge X=1, Z=0 (ancestor of V100 not in face Y=0) + // - find edge X=1, Z=1 (ancestor of V101 not in face Y=0) + // - find edge X=0, Z=1 (ancestor of V001 not in face Y=0) + //MESSAGE("---"); + + TopoDS_Edge E_0Y0 = EdgeNotInFace(aMesh, aShape, F, _cube.V000, MS); + ASSERT(!E_0Y0.IsNull()); + + TopoDS_Edge E_1Y0 = EdgeNotInFace(aMesh, aShape, F, _cube.V100, MS); + ASSERT(!E_1Y0.IsNull()); + + TopoDS_Edge E_1Y1 = EdgeNotInFace(aMesh, aShape, F, _cube.V101, MS); + ASSERT(!E_1Y1.IsNull()); + + TopoDS_Edge E_0Y1 = EdgeNotInFace(aMesh, aShape, F, _cube.V001, MS); + ASSERT(!E_0Y1.IsNull()); + + // 1.5 - identify the 4 vertices in face Y=1: V010, V110, V111, V011 + //MESSAGE("---"); + + TopExp::Vertices(E_0Y0, VFirst, VLast); + if (VFirst.IsSame(_cube.V000)) + _cube.V010 = VLast; + else + _cube.V010 = VFirst; + + TopExp::Vertices(E_1Y0, VFirst, VLast); + if (VFirst.IsSame(_cube.V100)) + _cube.V110 = VLast; + else + _cube.V110 = VFirst; + + TopExp::Vertices(E_1Y1, VFirst, VLast); + if (VFirst.IsSame(_cube.V101)) + _cube.V111 = VLast; + else + _cube.V111 = VFirst; + + TopExp::Vertices(E_0Y1, VFirst, VLast); + if (VFirst.IsSame(_cube.V001)) + _cube.V011 = VLast; + else + _cube.V011 = VFirst; + + // 1.6 - find remaining faces given 4 vertices + //MESSAGE("---"); + + _indY0 = 0; + _cube.quad_Y0 = _quads[_indY0]; + + _indY1 = GetFaceIndex(aMesh, aShape, meshFaces, + _cube.V010, _cube.V011, _cube.V110, _cube.V111); + _cube.quad_Y1 = _quads[_indY1]; + + _indZ0 = GetFaceIndex(aMesh, aShape, meshFaces, + _cube.V000, _cube.V010, _cube.V100, _cube.V110); + _cube.quad_Z0 = _quads[_indZ0]; + + _indZ1 = GetFaceIndex(aMesh, aShape, meshFaces, + _cube.V001, _cube.V011, _cube.V101, _cube.V111); + _cube.quad_Z1 = _quads[_indZ1]; + + _indX0 = GetFaceIndex(aMesh, aShape, meshFaces, + _cube.V000, _cube.V001, _cube.V010, _cube.V011); + _cube.quad_X0 = _quads[_indX0]; + + _indX1 = GetFaceIndex(aMesh, aShape, meshFaces, + _cube.V100, _cube.V101, _cube.V110, _cube.V111); + _cube.quad_X1 = _quads[_indX1]; + + //MESSAGE("---"); + + // 1.7 - get convertion coefs from face 2D normalized to 3D normalized + + Conv2DStruct cx0; // for face X=0 + Conv2DStruct cx1; // for face X=1 + Conv2DStruct cy0; + Conv2DStruct cy1; + Conv2DStruct cz0; + Conv2DStruct cz1; + + GetConv2DCoefs(*_cube.quad_X0, meshFaces[_indX0]->GetSubShape(), + _cube.V000, _cube.V010, _cube.V011, _cube.V001, cx0); + GetConv2DCoefs(*_cube.quad_X1, meshFaces[_indX1]->GetSubShape(), + _cube.V100, _cube.V110, _cube.V111, _cube.V101, cx1); + GetConv2DCoefs(*_cube.quad_Y0, meshFaces[_indY0]->GetSubShape(), + _cube.V000, _cube.V100, _cube.V101, _cube.V001, cy0); + GetConv2DCoefs(*_cube.quad_Y1, meshFaces[_indY1]->GetSubShape(), + _cube.V010, _cube.V110, _cube.V111, _cube.V011, cy1); + GetConv2DCoefs(*_cube.quad_Z0, meshFaces[_indZ0]->GetSubShape(), + _cube.V000, _cube.V100, _cube.V110, _cube.V010, cz0); + GetConv2DCoefs(*_cube.quad_Z1, meshFaces[_indZ1]->GetSubShape(), + _cube.V001, _cube.V101, _cube.V111, _cube.V011, cz1); + + // 1.8 - create a 3D structure for normalized values + + //MESSAGE("---"); + int nbx = _cube.quad_Z0->nbPts[0]; + if (cz0.a1 == 0.) nbx = _cube.quad_Z0->nbPts[1]; - int nby = _cube.quad_X0->nbPts[0]; - if (cx0.a1 == 0.) nby = _cube.quad_X0->nbPts[1]; + int nby = _cube.quad_X0->nbPts[0]; + if (cx0.a1 == 0.) nby = _cube.quad_X0->nbPts[1]; - int nbz = _cube.quad_Y0->nbPts[0]; - if (cy0.a1 != 0.) nbz = _cube.quad_Y0->nbPts[1]; - - int i1, j1, nbxyz = nbx * nby * nbz; - Point3DStruct *np = new Point3DStruct[nbxyz]; + int nbz = _cube.quad_Y0->nbPts[0]; + if (cy0.a1 != 0.) nbz = _cube.quad_Y0->nbPts[1]; - // 1.9 - store node indexes of faces + int i1, j1, nbxyz = nbx * nby * nbz; + Point3DStruct *np = new Point3DStruct[nbxyz]; - { - const TopoDS_Face & F = TopoDS::Face(meshFaces[_indX0]->GetSubShape()); + // 1.9 - store node indexes of faces - faceQuadStruct *quad = _cube.quad_X0; - int i = 0; // j = x/face , k = y/face - int nbdown = quad->nbPts[0]; - int nbright = quad->nbPts[1]; + { + const TopoDS_Face & F = TopoDS::Face(meshFaces[_indX0]->GetSubShape()); + faceQuadStruct *quad = _cube.quad_X0; + int i = 0; // j = x/face , k = y/face + int nbdown = quad->nbPts[0]; + int nbright = quad->nbPts[1]; - SMDS_NodeIteratorPtr itf= aMesh.GetSubMesh(F)->GetSubMeshDS()->GetNodes(); + SMDS_NodeIteratorPtr itf= aMesh.GetSubMesh(F)->GetSubMeshDS()->GetNodes(); - while(itf->more()) - { - const SMDS_MeshNode * node = itf->next(); - findIJ( node, quad, i1, j1 ); - int ij1 = j1 * nbdown + i1; - quad->uv_grid[ij1].node = node; - } - - for (int i1 = 0; i1 < nbdown; i1++) - for (int j1 = 0; j1 < nbright; j1++) - { - int ij1 = j1 * nbdown + i1; - int j = cx0.ia * i1 + cx0.ib * j1 + cx0.ic; // j = x/face - int k = cx0.ja * i1 + cx0.jb * j1 + cx0.jc; // k = y/face - int ijk = k * nbx * nby + j * nbx + i; - //MESSAGE(" "<uv_grid[ij1].node; - //SCRUTE(np[ijk].nodeId); - } - } - - { - const TopoDS_Face & F = TopoDS::Face(meshFaces[_indX1]->GetSubShape()); - - SMDS_NodeIteratorPtr itf= aMesh.GetSubMesh(F)->GetSubMeshDS()->GetNodes(); + while(itf->more()) { + const SMDS_MeshNode * node = itf->next(); + if(myTool->IsMedium(node)) + continue; + findIJ( node, quad, i1, j1 ); + int ij1 = j1 * nbdown + i1; + quad->uv_grid[ij1].node = node; + } - faceQuadStruct *quad = _cube.quad_X1; - int i = nbx - 1; // j = x/face , k = y/face - int nbdown = quad->nbPts[0]; - int nbright = quad->nbPts[1]; + for (int i1 = 0; i1 < nbdown; i1++) + for (int j1 = 0; j1 < nbright; j1++) { + int ij1 = j1 * nbdown + i1; + int j = cx0.ia * i1 + cx0.ib * j1 + cx0.ic; // j = x/face + int k = cx0.ja * i1 + cx0.jb * j1 + cx0.jc; // k = y/face + int ijk = k * nbx * nby + j * nbx + i; + //MESSAGE(" "<uv_grid[ij1].node; + //SCRUTE(np[ijk].nodeId); + } + } - while(itf->more()) - { - const SMDS_MeshNode * node = itf->next(); - findIJ( node, quad, i1, j1 ); - int ij1 = j1 * nbdown + i1; - quad->uv_grid[ij1].node = node; - } + { + const TopoDS_Face & F = TopoDS::Face(meshFaces[_indX1]->GetSubShape()); - for (int i1 = 0; i1 < nbdown; i1++) - for (int j1 = 0; j1 < nbright; j1++) - { - int ij1 = j1 * nbdown + i1; - int j = cx1.ia * i1 + cx1.ib * j1 + cx1.ic; // j = x/face - int k = cx1.ja * i1 + cx1.jb * j1 + cx1.jc; // k = y/face - int ijk = k * nbx * nby + j * nbx + i; - //MESSAGE(" "<uv_grid[ij1].node; - //SCRUTE(np[ijk].nodeId); - } - } + SMDS_NodeIteratorPtr itf= aMesh.GetSubMesh(F)->GetSubMeshDS()->GetNodes(); - { - const TopoDS_Face & F = TopoDS::Face(meshFaces[_indY0]->GetSubShape()); + faceQuadStruct *quad = _cube.quad_X1; + int i = nbx - 1; // j = x/face , k = y/face + int nbdown = quad->nbPts[0]; + int nbright = quad->nbPts[1]; - SMDS_NodeIteratorPtr itf= aMesh.GetSubMesh(F)->GetSubMeshDS()->GetNodes(); + while(itf->more()) { + const SMDS_MeshNode * node = itf->next(); + if(myTool->IsMedium(node)) + continue; + findIJ( node, quad, i1, j1 ); + int ij1 = j1 * nbdown + i1; + quad->uv_grid[ij1].node = node; + } - faceQuadStruct *quad = _cube.quad_Y0; - int j = 0; // i = x/face , k = y/face - int nbdown = quad->nbPts[0]; - int nbright = quad->nbPts[1]; + for (int i1 = 0; i1 < nbdown; i1++) + for (int j1 = 0; j1 < nbright; j1++) { + int ij1 = j1 * nbdown + i1; + int j = cx1.ia * i1 + cx1.ib * j1 + cx1.ic; // j = x/face + int k = cx1.ja * i1 + cx1.jb * j1 + cx1.jc; // k = y/face + int ijk = k * nbx * nby + j * nbx + i; + //MESSAGE(" "<uv_grid[ij1].node; + //SCRUTE(np[ijk].nodeId); + } + } - while(itf->more()) - { - const SMDS_MeshNode * node = itf->next(); - findIJ( node, quad, i1, j1 ); - int ij1 = j1 * nbdown + i1; - quad->uv_grid[ij1].node = node; - } + { + const TopoDS_Face & F = TopoDS::Face(meshFaces[_indY0]->GetSubShape()); - for (int i1 = 0; i1 < nbdown; i1++) - for (int j1 = 0; j1 < nbright; j1++) - { - int ij1 = j1 * nbdown + i1; - int i = cy0.ia * i1 + cy0.ib * j1 + cy0.ic; // i = x/face - int k = cy0.ja * i1 + cy0.jb * j1 + cy0.jc; // k = y/face - int ijk = k * nbx * nby + j * nbx + i; - //MESSAGE(" "<uv_grid[ij1].node; - //SCRUTE(np[ijk].nodeId); - } - } + SMDS_NodeIteratorPtr itf= aMesh.GetSubMesh(F)->GetSubMeshDS()->GetNodes(); - { - const TopoDS_Face & F = TopoDS::Face(meshFaces[_indY1]->GetSubShape()); + faceQuadStruct *quad = _cube.quad_Y0; + int j = 0; // i = x/face , k = y/face + int nbdown = quad->nbPts[0]; + int nbright = quad->nbPts[1]; - SMDS_NodeIteratorPtr itf= aMesh.GetSubMesh(F)->GetSubMeshDS()->GetNodes(); + while(itf->more()) { + const SMDS_MeshNode * node = itf->next(); + if(myTool->IsMedium(node)) + continue; + findIJ( node, quad, i1, j1 ); + int ij1 = j1 * nbdown + i1; + quad->uv_grid[ij1].node = node; + } - faceQuadStruct *quad = _cube.quad_Y1; - int j = nby - 1; // i = x/face , k = y/face - int nbdown = quad->nbPts[0]; - int nbright = quad->nbPts[1]; + for (int i1 = 0; i1 < nbdown; i1++) + for (int j1 = 0; j1 < nbright; j1++) { + int ij1 = j1 * nbdown + i1; + int i = cy0.ia * i1 + cy0.ib * j1 + cy0.ic; // i = x/face + int k = cy0.ja * i1 + cy0.jb * j1 + cy0.jc; // k = y/face + int ijk = k * nbx * nby + j * nbx + i; + //MESSAGE(" "<uv_grid[ij1].node; + //SCRUTE(np[ijk].nodeId); + } + } - while(itf->more()) - { - const SMDS_MeshNode * node = itf->next(); - findIJ( node, quad, i1, j1 ); - int ij1 = j1 * nbdown + i1; - quad->uv_grid[ij1].node = node; - } + { + const TopoDS_Face & F = TopoDS::Face(meshFaces[_indY1]->GetSubShape()); - for (int i1 = 0; i1 < nbdown; i1++) - for (int j1 = 0; j1 < nbright; j1++) - { - int ij1 = j1 * nbdown + i1; - int i = cy1.ia * i1 + cy1.ib * j1 + cy1.ic; // i = x/face - int k = cy1.ja * i1 + cy1.jb * j1 + cy1.jc; // k = y/face - int ijk = k * nbx * nby + j * nbx + i; - //MESSAGE(" "<uv_grid[ij1].node; - //SCRUTE(np[ijk].nodeId); - } - } + SMDS_NodeIteratorPtr itf= aMesh.GetSubMesh(F)->GetSubMeshDS()->GetNodes(); - { - const TopoDS_Face & F = TopoDS::Face(meshFaces[_indZ0]->GetSubShape()); + faceQuadStruct *quad = _cube.quad_Y1; + int j = nby - 1; // i = x/face , k = y/face + int nbdown = quad->nbPts[0]; + int nbright = quad->nbPts[1]; - SMDS_NodeIteratorPtr itf= aMesh.GetSubMesh(F)->GetSubMeshDS()->GetNodes(); + while(itf->more()) { + const SMDS_MeshNode * node = itf->next(); + if(myTool->IsMedium(node)) + continue; + findIJ( node, quad, i1, j1 ); + int ij1 = j1 * nbdown + i1; + quad->uv_grid[ij1].node = node; + } - faceQuadStruct *quad = _cube.quad_Z0; - int k = 0; // i = x/face , j = y/face - int nbdown = quad->nbPts[0]; - int nbright = quad->nbPts[1]; + for (int i1 = 0; i1 < nbdown; i1++) + for (int j1 = 0; j1 < nbright; j1++) { + int ij1 = j1 * nbdown + i1; + int i = cy1.ia * i1 + cy1.ib * j1 + cy1.ic; // i = x/face + int k = cy1.ja * i1 + cy1.jb * j1 + cy1.jc; // k = y/face + int ijk = k * nbx * nby + j * nbx + i; + //MESSAGE(" "<uv_grid[ij1].node; + //SCRUTE(np[ijk].nodeId); + } + } - while(itf->more()) - { - const SMDS_MeshNode * node = itf->next(); - findIJ( node, quad, i1, j1 ); - int ij1 = j1 * nbdown + i1; - quad->uv_grid[ij1].node = node; - } + { + const TopoDS_Face & F = TopoDS::Face(meshFaces[_indZ0]->GetSubShape()); - for (int i1 = 0; i1 < nbdown; i1++) - for (int j1 = 0; j1 < nbright; j1++) - { - int ij1 = j1 * nbdown + i1; - int i = cz0.ia * i1 + cz0.ib * j1 + cz0.ic; // i = x/face - int j = cz0.ja * i1 + cz0.jb * j1 + cz0.jc; // j = y/face - int ijk = k * nbx * nby + j * nbx + i; - //MESSAGE(" "<uv_grid[ij1].node; - //SCRUTE(np[ijk].nodeId); - } - } + SMDS_NodeIteratorPtr itf= aMesh.GetSubMesh(F)->GetSubMeshDS()->GetNodes(); - { - const TopoDS_Face & F = TopoDS::Face(meshFaces[_indZ1]->GetSubShape()); + faceQuadStruct *quad = _cube.quad_Z0; + int k = 0; // i = x/face , j = y/face + int nbdown = quad->nbPts[0]; + int nbright = quad->nbPts[1]; - SMDS_NodeIteratorPtr itf= aMesh.GetSubMesh(F)->GetSubMeshDS()->GetNodes(); + while(itf->more()) { + const SMDS_MeshNode * node = itf->next(); + if(myTool->IsMedium(node)) + continue; + findIJ( node, quad, i1, j1 ); + int ij1 = j1 * nbdown + i1; + quad->uv_grid[ij1].node = node; + } - faceQuadStruct *quad = _cube.quad_Z1; - int k = nbz - 1; // i = x/face , j = y/face - int nbdown = quad->nbPts[0]; - int nbright = quad->nbPts[1]; + for (int i1 = 0; i1 < nbdown; i1++) + for (int j1 = 0; j1 < nbright; j1++) { + int ij1 = j1 * nbdown + i1; + int i = cz0.ia * i1 + cz0.ib * j1 + cz0.ic; // i = x/face + int j = cz0.ja * i1 + cz0.jb * j1 + cz0.jc; // j = y/face + int ijk = k * nbx * nby + j * nbx + i; + //MESSAGE(" "<uv_grid[ij1].node; + //SCRUTE(np[ijk].nodeId); + } + } - while(itf->more()) - { - const SMDS_MeshNode * node = itf->next(); - findIJ( node, quad, i1, j1 ); - int ij1 = j1 * nbdown + i1; - quad->uv_grid[ij1].node = node; - } + { + const TopoDS_Face & F = TopoDS::Face(meshFaces[_indZ1]->GetSubShape()); + + SMDS_NodeIteratorPtr itf= aMesh.GetSubMesh(F)->GetSubMeshDS()->GetNodes(); + + faceQuadStruct *quad = _cube.quad_Z1; + int k = nbz - 1; // i = x/face , j = y/face + int nbdown = quad->nbPts[0]; + int nbright = quad->nbPts[1]; + + while(itf->more()) { + const SMDS_MeshNode * node = itf->next(); + if(myTool->IsMedium(node)) + continue; + findIJ( node, quad, i1, j1 ); + int ij1 = j1 * nbdown + i1; + quad->uv_grid[ij1].node = node; + } - for (int i1 = 0; i1 < nbdown; i1++) - for (int j1 = 0; j1 < nbright; j1++) - { - int ij1 = j1 * nbdown + i1; - int i = cz1.ia * i1 + cz1.ib * j1 + cz1.ic; // i = x/face - int j = cz1.ja * i1 + cz1.jb * j1 + cz1.jc; // j = y/face - int ijk = k * nbx * nby + j * nbx + i; - //MESSAGE(" "<uv_grid[ij1].node; - //SCRUTE(np[ijk].nodeId); - } - } + for (int i1 = 0; i1 < nbdown; i1++) + for (int j1 = 0; j1 < nbright; j1++) { + int ij1 = j1 * nbdown + i1; + int i = cz1.ia * i1 + cz1.ib * j1 + cz1.ic; // i = x/face + int j = cz1.ja * i1 + cz1.jb * j1 + cz1.jc; // j = y/face + int ijk = k * nbx * nby + j * nbx + i; + //MESSAGE(" "<uv_grid[ij1].node; + //SCRUTE(np[ijk].nodeId); + } + } - // 2.0 - for each node of the cube: - // - get the 8 points 3D = 8 vertices of the cube - // - get the 12 points 3D on the 12 edges of the cube - // - get the 6 points 3D on the 6 faces with their ID - // - compute the point 3D - // - store the point 3D in SMESHDS, store its ID in 3D structure - - int shapeID = meshDS->ShapeToIndex( aShape ); - - Pt3 p000, p001, p010, p011, p100, p101, p110, p111; - Pt3 px00, px01, px10, px11; - Pt3 p0y0, p0y1, p1y0, p1y1; - Pt3 p00z, p01z, p10z, p11z; - Pt3 pxy0, pxy1, px0z, px1z, p0yz, p1yz; - - GetPoint(p000, 0, 0, 0, nbx, nby, nbz, np, meshDS); - GetPoint(p001, 0, 0, nbz - 1, nbx, nby, nbz, np, meshDS); - GetPoint(p010, 0, nby - 1, 0, nbx, nby, nbz, np, meshDS); - GetPoint(p011, 0, nby - 1, nbz - 1, nbx, nby, nbz, np, meshDS); - GetPoint(p100, nbx - 1, 0, 0, nbx, nby, nbz, np, meshDS); - GetPoint(p101, nbx - 1, 0, nbz - 1, nbx, nby, nbz, np, meshDS); - GetPoint(p110, nbx - 1, nby - 1, 0, nbx, nby, nbz, np, meshDS); - GetPoint(p111, nbx - 1, nby - 1, nbz - 1, nbx, nby, nbz, np, meshDS); - - for (int i = 1; i < nbx - 1; i++) - { - for (int j = 1; j < nby - 1; j++) - { - for (int k = 1; k < nbz - 1; k++) - { - // *** seulement maillage regulier - // 12 points on edges - GetPoint(px00, i, 0, 0, nbx, nby, nbz, np, meshDS); - GetPoint(px01, i, 0, nbz - 1, nbx, nby, nbz, np, meshDS); - GetPoint(px10, i, nby - 1, 0, nbx, nby, nbz, np, meshDS); - GetPoint(px11, i, nby - 1, nbz - 1, nbx, nby, nbz, np, meshDS); - - GetPoint(p0y0, 0, j, 0, nbx, nby, nbz, np, meshDS); - GetPoint(p0y1, 0, j, nbz - 1, nbx, nby, nbz, np, meshDS); - GetPoint(p1y0, nbx - 1, j, 0, nbx, nby, nbz, np, meshDS); - GetPoint(p1y1, nbx - 1, j, nbz - 1, nbx, nby, nbz, np, meshDS); - - GetPoint(p00z, 0, 0, k, nbx, nby, nbz, np, meshDS); - GetPoint(p01z, 0, nby - 1, k, nbx, nby, nbz, np, meshDS); - GetPoint(p10z, nbx - 1, 0, k, nbx, nby, nbz, np, meshDS); - GetPoint(p11z, nbx - 1, nby - 1, k, nbx, nby, nbz, np, meshDS); - - // 12 points on faces - GetPoint(pxy0, i, j, 0, nbx, nby, nbz, np, meshDS); - GetPoint(pxy1, i, j, nbz - 1, nbx, nby, nbz, np, meshDS); - GetPoint(px0z, i, 0, k, nbx, nby, nbz, np, meshDS); - GetPoint(px1z, i, nby - 1, k, nbx, nby, nbz, np, meshDS); - GetPoint(p0yz, 0, j, k, nbx, nby, nbz, np, meshDS); - GetPoint(p1yz, nbx - 1, j, k, nbx, nby, nbz, np, meshDS); - - int ijk = k * nbx * nby + j * nbx + i; - double x = double (i) / double (nbx - 1); // *** seulement - double y = double (j) / double (nby - 1); // *** maillage - double z = double (k) / double (nbz - 1); // *** regulier - - Pt3 X; - for (int i = 0; i < 3; i++) - { - X[i] = - (1 - x) * p0yz[i] + x * p1yz[i] - + (1 - y) * px0z[i] + y * px1z[i] - + (1 - z) * pxy0[i] + z * pxy1[i] - - (1 - x) * ((1 - y) * p00z[i] + y * p01z[i]) - - x * ((1 - y) * p10z[i] + y * p11z[i]) - - (1 - y) * ((1 - z) * px00[i] + z * px01[i]) - - y * ((1 - z) * px10[i] + z * px11[i]) - - (1 - z) * ((1 - x) * p0y0[i] + x * p1y0[i]) - - z * ((1 - x) * p0y1[i] + x * p1y1[i]) - + (1 - x) * ((1 - y) * ((1 - z) * p000[i] + z * p001[i]) - + y * ((1 - z) * p010[i] + z * p011[i])) - + x * ((1 - y) * ((1 - z) * p100[i] + z * p101[i]) - + y * ((1 - z) * p110[i] + z * p111[i])); - } - - SMDS_MeshNode * node = meshDS->AddNode(X[0], X[1], X[2]); - np[ijk].node = node; - meshDS->SetNodeInVolume(node, shapeID); - } - } - } + // 2.0 - for each node of the cube: + // - get the 8 points 3D = 8 vertices of the cube + // - get the 12 points 3D on the 12 edges of the cube + // - get the 6 points 3D on the 6 faces with their ID + // - compute the point 3D + // - store the point 3D in SMESHDS, store its ID in 3D structure + + int shapeID = meshDS->ShapeToIndex( aShape ); + + Pt3 p000, p001, p010, p011, p100, p101, p110, p111; + Pt3 px00, px01, px10, px11; + Pt3 p0y0, p0y1, p1y0, p1y1; + Pt3 p00z, p01z, p10z, p11z; + Pt3 pxy0, pxy1, px0z, px1z, p0yz, p1yz; + + GetPoint(p000, 0, 0, 0, nbx, nby, nbz, np, meshDS); + GetPoint(p001, 0, 0, nbz - 1, nbx, nby, nbz, np, meshDS); + GetPoint(p010, 0, nby - 1, 0, nbx, nby, nbz, np, meshDS); + GetPoint(p011, 0, nby - 1, nbz - 1, nbx, nby, nbz, np, meshDS); + GetPoint(p100, nbx - 1, 0, 0, nbx, nby, nbz, np, meshDS); + GetPoint(p101, nbx - 1, 0, nbz - 1, nbx, nby, nbz, np, meshDS); + GetPoint(p110, nbx - 1, nby - 1, 0, nbx, nby, nbz, np, meshDS); + GetPoint(p111, nbx - 1, nby - 1, nbz - 1, nbx, nby, nbz, np, meshDS); + + for (int i = 1; i < nbx - 1; i++) { + for (int j = 1; j < nby - 1; j++) { + for (int k = 1; k < nbz - 1; k++) { + // *** seulement maillage regulier + // 12 points on edges + GetPoint(px00, i, 0, 0, nbx, nby, nbz, np, meshDS); + GetPoint(px01, i, 0, nbz - 1, nbx, nby, nbz, np, meshDS); + GetPoint(px10, i, nby - 1, 0, nbx, nby, nbz, np, meshDS); + GetPoint(px11, i, nby - 1, nbz - 1, nbx, nby, nbz, np, meshDS); + + GetPoint(p0y0, 0, j, 0, nbx, nby, nbz, np, meshDS); + GetPoint(p0y1, 0, j, nbz - 1, nbx, nby, nbz, np, meshDS); + GetPoint(p1y0, nbx - 1, j, 0, nbx, nby, nbz, np, meshDS); + GetPoint(p1y1, nbx - 1, j, nbz - 1, nbx, nby, nbz, np, meshDS); + + GetPoint(p00z, 0, 0, k, nbx, nby, nbz, np, meshDS); + GetPoint(p01z, 0, nby - 1, k, nbx, nby, nbz, np, meshDS); + GetPoint(p10z, nbx - 1, 0, k, nbx, nby, nbz, np, meshDS); + GetPoint(p11z, nbx - 1, nby - 1, k, nbx, nby, nbz, np, meshDS); + + // 12 points on faces + GetPoint(pxy0, i, j, 0, nbx, nby, nbz, np, meshDS); + GetPoint(pxy1, i, j, nbz - 1, nbx, nby, nbz, np, meshDS); + GetPoint(px0z, i, 0, k, nbx, nby, nbz, np, meshDS); + GetPoint(px1z, i, nby - 1, k, nbx, nby, nbz, np, meshDS); + GetPoint(p0yz, 0, j, k, nbx, nby, nbz, np, meshDS); + GetPoint(p1yz, nbx - 1, j, k, nbx, nby, nbz, np, meshDS); + + int ijk = k * nbx * nby + j * nbx + i; + double x = double (i) / double (nbx - 1); // *** seulement + double y = double (j) / double (nby - 1); // *** maillage + double z = double (k) / double (nbz - 1); // *** regulier + + Pt3 X; + for (int i = 0; i < 3; i++) { + X[i] = (1 - x) * p0yz[i] + x * p1yz[i] + + (1 - y) * px0z[i] + y * px1z[i] + + (1 - z) * pxy0[i] + z * pxy1[i] + - (1 - x) * ((1 - y) * p00z[i] + y * p01z[i]) + - x * ((1 - y) * p10z[i] + y * p11z[i]) + - (1 - y) * ((1 - z) * px00[i] + z * px01[i]) + - y * ((1 - z) * px10[i] + z * px11[i]) + - (1 - z) * ((1 - x) * p0y0[i] + x * p1y0[i]) + - z * ((1 - x) * p0y1[i] + x * p1y1[i]) + + (1 - x) * ((1 - y) * ((1 - z) * p000[i] + z * p001[i]) + + y * ((1 - z) * p010[i] + z * p011[i])) + + x * ((1 - y) * ((1 - z) * p100[i] + z * p101[i]) + + y * ((1 - z) * p110[i] + z * p111[i])); + } + + SMDS_MeshNode * node = meshDS->AddNode(X[0], X[1], X[2]); + np[ijk].node = node; + meshDS->SetNodeInVolume(node, shapeID); + } + } + } // find orientation of furute volumes according to MED convention vector< bool > forward( nbx * nby ); SMDS_VolumeTool vTool; - for (int i = 0; i < nbx - 1; i++) - for (int j = 0; j < nby - 1; j++) - { + for (int i = 0; i < nbx - 1; i++) { + for (int j = 0; j < nby - 1; j++) { int n1 = j * nbx + i; int n2 = j * nbx + i + 1; int n3 = (j + 1) * nbx + i + 1; @@ -705,51 +702,53 @@ bool StdMeshers_Hexa_3D::Compute(SMESH_Mesh & aMesh, vTool.Set( &tmpVol ); forward[ n1 ] = vTool.IsForward(); } + } - //2.1 - for each node of the cube (less 3 *1 Faces): - // - store hexahedron in SMESHDS - MESSAGE("Storing hexahedron into the DS"); - for (int i = 0; i < nbx - 1; i++) - for (int j = 0; j < nby - 1; j++) - { - bool isForw = forward.at( j * nbx + i ); - for (int k = 0; k < nbz - 1; k++) - { - int n1 = k * nbx * nby + j * nbx + i; - int n2 = k * nbx * nby + j * nbx + i + 1; - int n3 = k * nbx * nby + (j + 1) * nbx + i + 1; - int n4 = k * nbx * nby + (j + 1) * nbx + i; - int n5 = (k + 1) * nbx * nby + j * nbx + i; - int n6 = (k + 1) * nbx * nby + j * nbx + i + 1; - int n7 = (k + 1) * nbx * nby + (j + 1) * nbx + i + 1; - int n8 = (k + 1) * nbx * nby + (j + 1) * nbx + i; - - SMDS_MeshVolume * elt; - if ( isForw ) - elt = meshDS->AddVolume(np[n1].node, - np[n2].node, - np[n3].node, - np[n4].node, - np[n5].node, - np[n6].node, - np[n7].node, - np[n8].node); - else - elt = meshDS->AddVolume(np[n1].node, - np[n4].node, - np[n3].node, - np[n2].node, - np[n5].node, - np[n8].node, - np[n7].node, - np[n6].node); - - meshDS->SetMeshElementOnShape(elt, shapeID); - } - } + //2.1 - for each node of the cube (less 3 *1 Faces): + // - store hexahedron in SMESHDS + MESSAGE("Storing hexahedron into the DS"); + for (int i = 0; i < nbx - 1; i++) { + for (int j = 0; j < nby - 1; j++) { + bool isForw = forward.at( j * nbx + i ); + for (int k = 0; k < nbz - 1; k++) { + int n1 = k * nbx * nby + j * nbx + i; + int n2 = k * nbx * nby + j * nbx + i + 1; + int n3 = k * nbx * nby + (j + 1) * nbx + i + 1; + int n4 = k * nbx * nby + (j + 1) * nbx + i; + int n5 = (k + 1) * nbx * nby + j * nbx + i; + int n6 = (k + 1) * nbx * nby + j * nbx + i + 1; + int n7 = (k + 1) * nbx * nby + (j + 1) * nbx + i + 1; + int n8 = (k + 1) * nbx * nby + (j + 1) * nbx + i; + + SMDS_MeshVolume * elt; + if ( isForw ) { + //elt = meshDS->AddVolume(np[n1].node, np[n2].node, + // np[n3].node, np[n4].node, + // np[n5].node, np[n6].node, + // np[n7].node, np[n8].node); + elt = myTool->AddVolume(np[n1].node, np[n2].node, + np[n3].node, np[n4].node, + np[n5].node, np[n6].node, + np[n7].node, np[n8].node); + } + else { + //elt = meshDS->AddVolume(np[n1].node, np[n4].node, + // np[n3].node, np[n2].node, + // np[n5].node, np[n8].node, + // np[n7].node, np[n6].node); + elt = myTool->AddVolume(np[n1].node, np[n4].node, + np[n3].node, np[n2].node, + np[n5].node, np[n8].node, + np[n7].node, np[n6].node); + } + + meshDS->SetMeshElementOnShape(elt, shapeID); + } + } + } if ( np ) delete [] np; - //MESSAGE("End of StdMeshers_Hexa_3D::Compute()"); - return true; + //MESSAGE("End of StdMeshers_Hexa_3D::Compute()"); + return true; } //============================================================================= @@ -1066,3 +1065,4 @@ bool ComputePentahedralMesh(SMESH_Mesh & aMesh, const TopoDS_Shape & aShape) return bOK; } + diff --git a/src/StdMeshers/StdMeshers_Hexa_3D.hxx b/src/StdMeshers/StdMeshers_Hexa_3D.hxx index a9e20459c..dd733e55c 100644 --- a/src/StdMeshers/StdMeshers_Hexa_3D.hxx +++ b/src/StdMeshers/StdMeshers_Hexa_3D.hxx @@ -35,6 +35,8 @@ #include "StdMeshers_Quadrangle_2D.hxx" #include "Utils_SALOME_Exception.hxx" +#include "StdMeshers_Helper.hxx" + typedef struct point3Dstruct { const SMDS_MeshNode * node; @@ -135,6 +137,9 @@ protected: int _indY1; int _indZ0; int _indZ1; + + bool myCreateQuadratic; + StdMeshers_Helper* myTool; // toll for working with quadratic elements }; #endif diff --git a/src/StdMeshers/StdMeshers_MEFISTO_2D.cxx b/src/StdMeshers/StdMeshers_MEFISTO_2D.cxx index ed166fc03..22b1702b2 100644 --- a/src/StdMeshers/StdMeshers_MEFISTO_2D.cxx +++ b/src/StdMeshers/StdMeshers_MEFISTO_2D.cxx @@ -184,73 +184,76 @@ bool StdMeshers_MEFISTO_2D::CheckHypothesis bool StdMeshers_MEFISTO_2D::Compute(SMESH_Mesh & aMesh, const TopoDS_Shape & aShape) { - MESSAGE("StdMeshers_MEFISTO_2D::Compute"); + MESSAGE("StdMeshers_MEFISTO_2D::Compute"); - if (_hypLengthFromEdges) - _edgeLength = ComputeEdgeElementLength(aMesh, aShape); + if (_hypLengthFromEdges) + _edgeLength = ComputeEdgeElementLength(aMesh, aShape); + + bool isOk = false; + //const SMESHDS_Mesh * meshDS = aMesh.GetMeshDS(); + //SMESH_subMesh *theSubMesh = aMesh.GetSubMesh(aShape); - bool isOk = false; - //const SMESHDS_Mesh * meshDS = aMesh.GetMeshDS(); - //SMESH_subMesh *theSubMesh = aMesh.GetSubMesh(aShape); - - const TopoDS_Face & FF = TopoDS::Face(aShape); - bool faceIsForward = (FF.Orientation() == TopAbs_FORWARD); - TopoDS_Face F = TopoDS::Face(FF.Oriented(TopAbs_FORWARD)); - - Z nblf; //nombre de lignes fermees (enveloppe en tete) - Z *nudslf = NULL; //numero du dernier sommet de chaque ligne fermee - R2 *uvslf = NULL; - Z nbpti = 0; //nombre points internes futurs sommets de la triangulation - R2 *uvpti = NULL; - - Z nbst; - R2 *uvst = NULL; - Z nbt; - Z *nust = NULL; - Z ierr = 0; - - Z nutysu = 1; // 1: il existe un fonction areteideale_() - // Z nutysu=0; // 0: on utilise aretmx - R aretmx = _edgeLength; // longueur max aretes future triangulation - - nblf = NumberOfWires(F); - - nudslf = new Z[1 + nblf]; - nudslf[0] = 0; - int iw = 1; - int nbpnt = 0; - - myOuterWire = BRepTools::OuterWire(F); - nbpnt += NumberOfPoints(aMesh, myOuterWire); - if ( nbpnt < 3 ) // ex: a circle with 2 segments - return false; - nudslf[iw++] = nbpnt; + const TopoDS_Face & FF = TopoDS::Face(aShape); + bool faceIsForward = (FF.Orientation() == TopAbs_FORWARD); + TopoDS_Face F = TopoDS::Face(FF.Oriented(TopAbs_FORWARD)); - for (TopExp_Explorer exp(F, TopAbs_WIRE); exp.More(); exp.Next()) - { - const TopoDS_Wire & W = TopoDS::Wire(exp.Current()); - if (!myOuterWire.IsSame(W)) - { - nbpnt += NumberOfPoints(aMesh, W); - nudslf[iw++] = nbpnt; - } - } + Z nblf; //nombre de lignes fermees (enveloppe en tete) + Z *nudslf = NULL; //numero du dernier sommet de chaque ligne fermee + R2 *uvslf = NULL; + Z nbpti = 0; //nombre points internes futurs sommets de la triangulation + R2 *uvpti = NULL; + + Z nbst; + R2 *uvst = NULL; + Z nbt; + Z *nust = NULL; + Z ierr = 0; + + Z nutysu = 1; // 1: il existe un fonction areteideale_() + // Z nutysu=0; // 0: on utilise aretmx + R aretmx = _edgeLength; // longueur max aretes future triangulation + + nblf = NumberOfWires(F); + + nudslf = new Z[1 + nblf]; + nudslf[0] = 0; + int iw = 1; + int nbpnt = 0; + + bool QuadMode = true; + + myTool = new StdMeshers_Helper(aMesh); + myCreateQuadratic = myTool->IsQuadraticSubMesh(aShape,QuadMode); + + myOuterWire = BRepTools::OuterWire(F); + nbpnt += NumberOfPoints(aMesh, myOuterWire); + if ( nbpnt < 3 ) // ex: a circle with 2 segments + return false; + nudslf[iw++] = nbpnt; + + for (TopExp_Explorer exp(F, TopAbs_WIRE); exp.More(); exp.Next()) { + const TopoDS_Wire & W = TopoDS::Wire(exp.Current()); + if (!myOuterWire.IsSame(W)) { + nbpnt += NumberOfPoints(aMesh, W); + nudslf[iw++] = nbpnt; + } + } - // avoid passing same uv points for a vertex common to 2 wires - TopTools_IndexedDataMapOfShapeListOfShape VWMap; - if ( iw - 1 > 1 ) // nbofWires > 1 - TopExp::MapShapesAndAncestors( F , TopAbs_VERTEX, TopAbs_WIRE, VWMap ); + // avoid passing same uv points for a vertex common to 2 wires + TopTools_IndexedDataMapOfShapeListOfShape VWMap; + if ( iw - 1 > 1 ) // nbofWires > 1 + TopExp::MapShapesAndAncestors( F , TopAbs_VERTEX, TopAbs_WIRE, VWMap ); - uvslf = new R2[nudslf[nblf]]; - int m = 0; + uvslf = new R2[nudslf[nblf]]; + int m = 0; - double scalex, scaley; - ComputeScaleOnFace(aMesh, F, scalex, scaley); + double scalex, scaley; + ComputeScaleOnFace(aMesh, F, scalex, scaley); - map mefistoToDS; // correspondence mefisto index--> points IDNodes - if ( !LoadPoints(aMesh, F, myOuterWire, uvslf, m, - mefistoToDS, scalex, scaley, VWMap)) - return false; + map mefistoToDS; // correspondence mefisto index--> points IDNodes + if ( !LoadPoints(aMesh, F, myOuterWire, uvslf, m, + mefistoToDS, scalex, scaley, VWMap) ) + return false; for (TopExp_Explorer exp(F, TopAbs_WIRE); exp.More(); exp.Next()) { @@ -352,7 +355,8 @@ static bool fixCommonVertexUV (gp_Pnt2d & theUV, const TopoDS_Wire& theOW, const TopoDS_Face& theF, const TopTools_IndexedDataMapOfShapeListOfShape & theVWMap, - SMESH_Mesh & theMesh) + SMESH_Mesh & theMesh, + bool CreateQuadratic) { if( theW.IsSame( theOW ) || !theVWMap.Contains( theV )) return false; @@ -415,10 +419,25 @@ static bool fixCommonVertexUV (gp_Pnt2d & theUV, umin = l; umax = f; } - else - { + else { while ( nIt->more() ) { const SMDS_MeshNode* node = nIt->next(); + if(CreateQuadratic) { + // check if node is medium + bool IsMedium = false; + SMDS_ElemIteratorPtr itn = node->GetInverseElementIterator(); + while (itn->more()) { + const SMDS_MeshElement* elem = itn->next(); + if ( elem->GetType() != SMDSAbs_Edge ) + continue; + if(elem->IsMediumNode(node)) { + IsMedium = true; + break; + } + } + if(IsMedium) + continue; + } const SMDS_EdgePosition* epos = static_cast(node->GetPosition().get()); double u = epos->GetUParameter(); @@ -486,8 +505,7 @@ bool StdMeshers_MEFISTO_2D::LoadPoints(SMESH_Mesh & aMesh, TopoDS_Wire W = TopoDS::Wire(WW.Oriented(TopAbs_FORWARD)); BRepTools_WireExplorer wexp(W, F); - for (wexp.Init(W, F), iEdge = 0; wexp.More(); wexp.Next(), iEdge++) - { + for (wexp.Init(W, F), iEdge = 0; wexp.More(); wexp.Next(), iEdge++) { const TopoDS_Edge & E = wexp.Current(); // --- IDNodes of first and last Vertex @@ -496,7 +514,7 @@ bool StdMeshers_MEFISTO_2D::LoadPoints(SMESH_Mesh & aMesh, TopExp::Vertices(E, VFirst, VLast); // corresponds to f and l ASSERT(!VFirst.IsNull()); - SMDS_NodeIteratorPtr lid= + SMDS_NodeIteratorPtr lid = aMesh.GetSubMesh(VFirst)->GetSubMeshDS()->GetNodes(); if ( !lid->more() ) { MESSAGE (" NO NODE BUILT ON VERTEX "); @@ -505,7 +523,7 @@ bool StdMeshers_MEFISTO_2D::LoadPoints(SMESH_Mesh & aMesh, const SMDS_MeshNode* idFirst = lid->next(); ASSERT(!VLast.IsNull()); - lid=aMesh.GetSubMesh(VLast)->GetSubMeshDS()->GetNodes(); + lid = aMesh.GetSubMesh(VLast)->GetSubMeshDS()->GetNodes(); if ( !lid->more() ) { MESSAGE (" NO NODE BUILT ON VERTEX "); return false; @@ -514,6 +532,21 @@ bool StdMeshers_MEFISTO_2D::LoadPoints(SMESH_Mesh & aMesh, // --- edge internal IDNodes (relies on good order storage, not checked) +// if(myCreateQuadratic) { + // fill myNLinkNodeMap +// SMDS_ElemIteratorPtr iter = aMesh.GetSubMesh(E)->GetSubMeshDS()->GetElements(); +// while(iter->more()) { +// const SMDS_MeshElement* elem = iter->next(); +// SMDS_ElemIteratorPtr nodeIt = elem->nodesIterator(); +// const SMDS_MeshNode* n1 = static_cast( nodeIt->next() ); +// const SMDS_MeshNode* n2 = static_cast( nodeIt->next() ); +// const SMDS_MeshNode* n3 = static_cast( nodeIt->next() ); +// NLink link(( n1 < n2 ? n1 : n2 ), ( n1 < n2 ? n2 : n1 )); +// myNLinkNodeMap.insert(NLinkNodeMap::value_type(link,n3)); +// myNLinkNodeMap[link] = n3; +// } +// } + int nbPoints = aMesh.GetSubMesh(E)->GetSubMeshDS()->NbNodes(); double f, l; @@ -524,16 +557,41 @@ bool StdMeshers_MEFISTO_2D::LoadPoints(SMESH_Mesh & aMesh, //bool isForward = (E.Orientation() == TopAbs_FORWARD); map params; - while(ite->more()) - { - const SMDS_MeshNode * node = ite->next(); - const SMDS_EdgePosition* epos = - static_cast(node->GetPosition().get()); - double param = epos->GetUParameter(); - params[param] = node; + if(!myCreateQuadratic) { + while(ite->more()) { + const SMDS_MeshNode * node = ite->next(); + const SMDS_EdgePosition* epos = + static_cast(node->GetPosition().get()); + double param = epos->GetUParameter(); + params[param] = node; + } } - if ( nbPoints != params.size()) - { + else { + nbPoints = nbPoints/2; + while(ite->more()) { + const SMDS_MeshNode* node = ite->next(); + // check if node is medium + bool IsMedium = false; + SMDS_ElemIteratorPtr itn = node->GetInverseElementIterator(); + while (itn->more()) { + const SMDS_MeshElement* elem = itn->next(); + if ( elem->GetType() != SMDSAbs_Edge ) + continue; + if(elem->IsMediumNode(node)) { + IsMedium = true; + break; + } + } + if(IsMedium) + continue; + const SMDS_EdgePosition* epos = + static_cast(node->GetPosition().get()); + double param = epos->GetUParameter(); + params[param] = node; + } + } + + if ( nbPoints != params.size()) { MESSAGE( "BAD NODE ON EDGE POSITIONS" ); return false; } @@ -542,10 +600,9 @@ bool StdMeshers_MEFISTO_2D::LoadPoints(SMESH_Mesh & aMesh, // --- load 2D values into MEFISTO structure, // add IDNodes in mefistoToDS map - if (E.Orientation() == TopAbs_FORWARD) - { + if (E.Orientation() == TopAbs_FORWARD) { gp_Pnt2d p = C2d->Value(f).XY().Multiplied( scale ); // first point = Vertex Forward - if ( fixCommonVertexUV( p, VFirst, W, myOuterWire, F, VWMap, aMesh )) + if ( fixCommonVertexUV( p, VFirst, W, myOuterWire, F, VWMap, aMesh, myCreateQuadratic )) myNodesOnCommonV.push_back( idFirst ); uvslf[m].x = p.X(); uvslf[m].y = p.Y(); @@ -554,8 +611,7 @@ bool StdMeshers_MEFISTO_2D::LoadPoints(SMESH_Mesh & aMesh, //MESSAGE("__ f "<::iterator itp = params.begin(); - for (int i = 1; i <= nbPoints; i++) // nbPoints internal - { + for (int i = 1; i <= nbPoints; i++) { // nbPoints internal double param = (*itp).first; gp_Pnt2d p = C2d->Value(param).XY().Multiplied( scale ); uvslf[m].x = p.X(); @@ -567,10 +623,9 @@ bool StdMeshers_MEFISTO_2D::LoadPoints(SMESH_Mesh & aMesh, itp++; } } - else - { + else { gp_Pnt2d p = C2d->Value(l).XY().Multiplied( scale ); // last point = Vertex Reversed - if ( fixCommonVertexUV( p, VLast, W, myOuterWire, F, VWMap, aMesh )) + if ( fixCommonVertexUV( p, VLast, W, myOuterWire, F, VWMap, aMesh, myCreateQuadratic )) myNodesOnCommonV.push_back( idLast ); uvslf[m].x = p.X(); uvslf[m].y = p.Y(); @@ -758,9 +813,11 @@ void StdMeshers_MEFISTO_2D::StoreResult(SMESH_Mesh & aMesh, SMDS_MeshElement * elt; if (triangleIsWellOriented) - elt = meshDS->AddFace(n1, n2, n3); + //elt = meshDS->AddFace(n1, n2, n3); + elt = myTool->AddFace(n1, n2, n3); else - elt = meshDS->AddFace(n1, n3, n2); + //elt = meshDS->AddFace(n1, n3, n2); + elt = myTool->AddFace(n1, n3, n2); meshDS->SetMeshElementOnShape(elt, faceID); m++; diff --git a/src/StdMeshers/StdMeshers_MEFISTO_2D.hxx b/src/StdMeshers/StdMeshers_MEFISTO_2D.hxx index fac85f07d..180ceb760 100644 --- a/src/StdMeshers/StdMeshers_MEFISTO_2D.hxx +++ b/src/StdMeshers/StdMeshers_MEFISTO_2D.hxx @@ -33,6 +33,8 @@ #include "SMESH_2D_Algo.hxx" #include +#include "StdMeshers_Helper.hxx" + class SMDS_MeshNode; class TopTools_IndexedDataMapOfShapeListOfShape; class TopoDS_Face; @@ -95,6 +97,8 @@ protected: TopoDS_Wire myOuterWire; std::list myNodesOnCommonV; + + StdMeshers_Helper* myTool; // toll for working with quadratic elements }; #endif diff --git a/src/StdMeshers/StdMeshers_Penta_3D.cxx b/src/StdMeshers/StdMeshers_Penta_3D.cxx index ad6ebc831..6c432f704 100644 --- a/src/StdMeshers/StdMeshers_Penta_3D.cxx +++ b/src/StdMeshers/StdMeshers_Penta_3D.cxx @@ -51,6 +51,9 @@ #include #include #include +#include +#include +#include #include #include @@ -71,6 +74,8 @@ StdMeshers_Penta_3D::StdMeshers_Penta_3D() myWallNodesMaps.resize( SMESH_Block::NbFaces() ); myShapeXYZ.resize( SMESH_Block::NbSubShapes() ); } + + //======================================================================= //function : Compute //purpose : @@ -91,9 +96,20 @@ bool StdMeshers_Penta_3D::Compute(SMESH_Mesh& aMesh, if (myErrorStatus){ return bOK; } + + bool QuadMode = true; + + myTool = new StdMeshers_Helper(aMesh); + myCreateQuadratic = myTool->IsQuadraticSubMesh(aShape,QuadMode); + // MakeBlock(); - if (myErrorStatus){ + if (myErrorStatus){ + return bOK; + } + // + ClearMeshOnFxy1(); + if (myErrorStatus) { return bOK; } // @@ -104,11 +120,6 @@ bool StdMeshers_Penta_3D::Compute(SMESH_Mesh& aMesh, // MakeConnectingMap(); // - ClearMeshOnFxy1(); - if (myErrorStatus) { - return bOK; - } - // MakeMeshOnFxy1(); if (myErrorStatus) { return bOK; @@ -118,6 +129,7 @@ bool StdMeshers_Penta_3D::Compute(SMESH_Mesh& aMesh, // return !bOK; } + //======================================================================= //function : MakeNodes //purpose : @@ -144,12 +156,24 @@ void StdMeshers_Penta_3D::MakeNodes() // 1.1 Horizontal size myJSize=0; for (i=0; iGetSubMeshContaining(aS); ASSERT(aSubMesh); - SMESHDS_SubMesh *aSM=aSubMesh->GetSubMeshDS(); - iNbN=aSM->NbNodes(); - myJSize+=iNbN; + SMESHDS_SubMesh *aSM = aSubMesh->GetSubMeshDS(); + if(!myCreateQuadratic) { + iNbN = aSM->NbNodes(); + } + else { + iNbN = 0; + SMDS_NodeIteratorPtr itn = aSM->GetNodes(); + while(itn->more()) { + const SMDS_MeshNode* aNode = itn->next(); + if(myTool->IsMedium(aNode)) + continue; + iNbN++; + } + } + myJSize += iNbN; } //printf("*** Horizontal: number of nodes summary=%d\n", myJSize); // @@ -159,9 +183,21 @@ void StdMeshers_Penta_3D::MakeNodes() const TopoDS_Shape& aS=myBlock.Shape(SMESH_Block::ID_E00z); SMESH_subMesh *aSubMesh = pMesh->GetSubMeshContaining(aS); ASSERT(aSubMesh); - SMESHDS_SubMesh *aSM=aSubMesh->GetSubMeshDS(); - iNbN=aSM->NbNodes(); - myISize+=iNbN; + SMESHDS_SubMesh *aSM = aSubMesh->GetSubMeshDS(); + if(!myCreateQuadratic) { + iNbN = aSM->NbNodes(); + } + else { + iNbN = 0; + SMDS_NodeIteratorPtr itn = aSM->GetNodes(); + while(itn->more()) { + const SMDS_MeshNode* aNode = itn->next(); + if(myTool->IsMedium(aNode)) + continue; + iNbN++; + } + } + myISize += iNbN; } //printf("*** Vertical: number of nodes on edges and vertices=%d\n", myISize); // @@ -177,18 +213,19 @@ void StdMeshers_Penta_3D::MakeNodes() // vertices for (k=0; kGetSubMeshContaining(aS)->GetSubMeshDS()->GetNodes(); + const TopoDS_Shape& aS = myBlock.Shape(aSID); + SMDS_NodeIteratorPtr ite = pMesh->GetSubMeshContaining(aS)->GetSubMeshDS()->GetNodes(); while(ite->more()) { const SMDS_MeshNode* aNode = ite->next(); + if(myTool->IsMedium(aNode)) + continue; aNodeID=aNode->GetID(); // aTNode.SetNode(aNode); aTNode.SetShapeSupportID(aSID); aTNode.SetBaseNodeID(aNodeID); // - if ( SMESH_Block::IsEdgeID (aSID)) - { + if ( SMESH_Block::IsEdgeID (aSID)) { const SMDS_EdgePosition* epos = static_cast(aNode->GetPosition().get()); myBlock.ComputeParameters( epos->GetUParameter(), aS, aCoords ); @@ -200,7 +237,7 @@ void StdMeshers_Penta_3D::MakeNodes() aP3D.SetCoord(aX, aY, aZ); myBlock.ComputeParameters(aP3D, aS, aCoords); } - iErr=myBlock.ErrorStatus(); + iErr = myBlock.ErrorStatus(); if (iErr) { MESSAGE("StdMeshers_Penta_3D::MakeNodes()," << "SMESHBlock: ComputeParameters operation failed"); @@ -325,8 +362,7 @@ void StdMeshers_Penta_3D::MakeNodes() // 3.3 set XYZ of vertices, and initialize of the rest SMESHDS_Mesh* aMesh = GetMesh()->GetMeshDS(); - for ( int id = SMESH_Block::ID_V000; id < SMESH_Block::ID_Shell; ++id ) - { + for ( int id = SMESH_Block::ID_V000; id < SMESH_Block::ID_Shell; ++id ) { if ( SMESH_Block::IsVertexID( id )) { TopoDS_Shape V = myBlock.Shape( id ); SMESHDS_SubMesh* sm = aMesh->MeshElements( V ); @@ -344,23 +380,46 @@ void StdMeshers_Penta_3D::MakeNodes() SMESH_Block::TShapeID aSSID, aBNSSID; StdMeshers_TNode aTN; // - for (j=0; jGetMeshDS(); + int topfaceID = meshDS->ShapeToIndex(TopFace); + const TopoDS_Vertex& v001 = TopoDS::Vertex(myBlock.Shape(SMESH_Block::ID_V001)); + SMDS_NodeIteratorPtr itn = pMesh->GetSubMeshContaining(v001)->GetSubMeshDS()->GetNodes(); + const SMDS_MeshNode* N = itn->next(); + gp_XY UV001 = myTool->GetNodeUV(TopFace,N); + const TopoDS_Vertex& v101 = TopoDS::Vertex(myBlock.Shape(SMESH_Block::ID_V101)); + itn = pMesh->GetSubMeshContaining(v101)->GetSubMeshDS()->GetNodes(); + N = itn->next(); + gp_XY UV101 = myTool->GetNodeUV(TopFace,N); + const TopoDS_Vertex& v011 = TopoDS::Vertex(myBlock.Shape(SMESH_Block::ID_V011)); + itn = pMesh->GetSubMeshContaining(v011)->GetSubMeshDS()->GetNodes(); + N = itn->next(); + gp_XY UV011 = myTool->GetNodeUV(TopFace,N); + const TopoDS_Vertex& v111 = TopoDS::Vertex(myBlock.Shape(SMESH_Block::ID_V111)); + itn = pMesh->GetSubMeshContaining(v111)->GetSubMeshDS()->GetNodes(); + N = itn->next(); + gp_XY UV111 = myTool->GetNodeUV(TopFace,N); + + for (j=0; j* nColumns[8]; double ratio[4]; // base node position between columns [0.-1.] - if ( createNode ) - for ( k = 0; k < 4; ++k ) + if ( createNode ) { + for ( k = 0; k < 4; ++k ) { ratio[ k ] = SetHorizEdgeXYZ (aBNXYZ, wallFaceID[ k ], nColumns[k*2], nColumns[k*2+1]); + } + } // // XYZ on the bottom and top faces const SMDS_MeshNode* n = aBN.Node(); @@ -368,8 +427,9 @@ void StdMeshers_Penta_3D::MakeNodes() myShapeXYZ[ SMESH_Block::ID_Fxy1 ].SetCoord( 0., 0., 0. ); // // first create or find a top node, then the rest ones in a column - for (i=myISize-1; i>0; --i) - { + for (i=myISize-1; i>0; --i) { + bIsUpperLayer = (i==(myISize-1)); + gp_XY UV_Ex01, UV_Ex11, UV_E0y1, UV_E1y1; if ( createNode ) { // set XYZ on vertical edges and faces for ( k = 0; k < 4; ++k ) { @@ -377,11 +437,28 @@ void StdMeshers_Penta_3D::MakeNodes() myShapeXYZ[ verticEdgeID[ k ] ].SetCoord( n->X(), n->Y(), n->Z() ); // n = (*nColumns[k*2]) [ i ]; + gp_XY tmp1; + if( i==myISize-1 ) { + tmp1 = myTool->GetNodeUV(TopFace,n); + tmp1 = ( 1. - ratio[ k ]) * tmp1; + } gp_XYZ xyz( n->X(), n->Y(), n->Z() ); myShapeXYZ[ wallFaceID[ k ]] = ( 1. - ratio[ k ]) * xyz; n = (*nColumns[k*2+1]) [ i ]; xyz.SetCoord( n->X(), n->Y(), n->Z() ); myShapeXYZ[ wallFaceID[ k ]] += ratio[ k ] * xyz; + if( i==myISize-1 ) { + gp_XY tmp2 = myTool->GetNodeUV(TopFace,n); + tmp1 += ratio[ k ] * tmp2; + if( k==0 ) + UV_Ex01 = tmp1; + else if( k==1 ) + UV_Ex11 = tmp1; + else if( k==2 ) + UV_E0y1 = tmp1; + else + UV_E1y1 = tmp1; + } } } // fill current node info @@ -395,7 +472,6 @@ void StdMeshers_Penta_3D::MakeNodes() aCoords.SetCoord(aX, aY, aZ); // // suporting shape ID - bIsUpperLayer=(i==(myISize-1)); ShapeSupportID(bIsUpperLayer, aBNSSID, aSSID); if (myErrorStatus) { MESSAGE("StdMeshers_Penta_3D::MakeNodes() "); @@ -418,6 +494,30 @@ void StdMeshers_Penta_3D::MakeNodes() if ( bIsUpperLayer ) { const SMDS_MeshNode* n = aTN.Node(); myShapeXYZ[ SMESH_Block::ID_Fxy1 ].SetCoord( n->X(), n->Y(), n->Z() ); + // set node on top face: + // find UV parameter for this node + // UV_Ex11 + // UV011+-----+----------+UV111 + // | | + // | | + // UV_E0y1+ +node +UV_E1y1 + // | | + // | | + // | | + // UV001+-----+----------+UV101 + // UV_Ex01 + gp_Pnt2d aP; + double u = aCoords.X(), v = aCoords.Y(); + double u1 = ( 1. - u ), v1 = ( 1. - v ); + aP.ChangeCoord() = UV_Ex01 * v1; + aP.ChangeCoord() += UV_Ex11 * v; + aP.ChangeCoord() += UV_E0y1 * u1; + aP.ChangeCoord() += UV_E1y1 * u; + aP.ChangeCoord() -= UV001 * u1 * v1; + aP.ChangeCoord() -= UV101 * u * v1; + aP.ChangeCoord() -= UV011 * u1 * v; + aP.ChangeCoord() -= UV111 * u * v; + meshDS->SetNodeOnFace((SMDS_MeshNode*)n, topfaceID, aP.X(), aP.Y()); } } if (myErrorStatus) { @@ -456,10 +556,13 @@ void StdMeshers_Penta_3D::MakeNodes() */ //DEB t } + + //======================================================================= //function : FindNodeOnShape //purpose : //======================================================================= + void StdMeshers_Penta_3D::FindNodeOnShape(const TopoDS_Shape& aS, const gp_XYZ& aParams, const int z, @@ -470,14 +573,13 @@ void StdMeshers_Penta_3D::FindNodeOnShape(const TopoDS_Shape& aS, double aX, aY, aZ, aD, aTol2, minD; gp_Pnt aP1, aP2; // - SMESH_Mesh* pMesh=GetMesh(); - aTol2=myTol3D*myTol3D; + SMESH_Mesh* pMesh = GetMesh(); + aTol2 = myTol3D*myTol3D; minD = 1.e100; - SMDS_MeshNode* pNode=NULL; + SMDS_MeshNode* pNode = NULL; // if ( aS.ShapeType() == TopAbs_FACE || - aS.ShapeType() == TopAbs_EDGE ) - { + aS.ShapeType() == TopAbs_EDGE ) { // find a face ID to which aTN belongs to int faceID; if ( aS.ShapeType() == TopAbs_FACE ) @@ -492,13 +594,13 @@ void StdMeshers_Penta_3D::FindNodeOnShape(const TopoDS_Shape& aS, } ASSERT( SMESH_Block::IsFaceID( faceID )); int fIndex = SMESH_Block::ShapeIndex( faceID ); - StdMeshers_IJNodeMap & ijNodes= myWallNodesMaps[ fIndex ]; + StdMeshers_IJNodeMap & ijNodes = myWallNodesMaps[ fIndex ]; // look for a base node in ijNodes const SMDS_MeshNode* baseNode = pMesh->GetMeshDS()->FindNode( aTN.BaseNodeID() ); StdMeshers_IJNodeMap::const_iterator par_nVec = ijNodes.begin(); for ( ; par_nVec != ijNodes.end(); par_nVec++ ) if ( par_nVec->second[ 0 ] == baseNode ) { - pNode=(SMDS_MeshNode*)par_nVec->second.at( z ); + pNode = (SMDS_MeshNode*)par_nVec->second.at( z ); aTN.SetNode(pNode); return; } @@ -510,6 +612,8 @@ void StdMeshers_Penta_3D::FindNodeOnShape(const TopoDS_Shape& aS, pMesh->GetSubMeshContaining(aS)->GetSubMeshDS()->GetNodes(); while(ite->more()) { const SMDS_MeshNode* aNode = ite->next(); + if(myTool->IsMedium(aNode)) + continue; aX=aNode->X(); aY=aNode->Y(); aZ=aNode->Z(); @@ -532,6 +636,7 @@ void StdMeshers_Penta_3D::FindNodeOnShape(const TopoDS_Shape& aS, //myErrorStatus=11; // can not find the node; } + //======================================================================= //function : SetHorizEdgeXYZ //purpose : @@ -583,6 +688,7 @@ double StdMeshers_Penta_3D::SetHorizEdgeXYZ(const gp_XYZ& aBase return r; } + //======================================================================= //function : MakeVolumeMesh //purpose : @@ -593,20 +699,20 @@ void StdMeshers_Penta_3D::MakeVolumeMesh() // int i, j, ij, ik, i1, i2, aSSID; // - SMESH_Mesh* pMesh =GetMesh(); - SMESHDS_Mesh* meshDS=pMesh->GetMeshDS(); + SMESH_Mesh* pMesh = GetMesh(); + SMESHDS_Mesh* meshDS = pMesh->GetMeshDS(); // int shapeID = meshDS->ShapeToIndex( myShape ); // // 1. Set Node In Volume - ik=myISize-1; + ik = myISize-1; for (i=1; iSetNodeInVolume(aNode, shapeID); } } @@ -621,22 +727,28 @@ void StdMeshers_Penta_3D::MakeVolumeMesh() const TopoDS_Face& aFxy0= TopoDS::Face(myBlock.Shape(SMESH_Block::ID_Fxy0)); SMESH_subMesh *aSubMesh0 = pMesh->GetSubMeshContaining(aFxy0); - SMESHDS_SubMesh *aSM0=aSubMesh0->GetSubMeshDS(); + SMESHDS_SubMesh *aSM0 = aSubMesh0->GetSubMeshDS(); // - itf=aSM0->GetElements(); + itf = aSM0->GetElements(); while(itf->more()) { - const SMDS_MeshElement* pE0=itf->next(); + const SMDS_MeshElement* pE0 = itf->next(); // int nbFaceNodes = pE0->NbNodes(); + if(myCreateQuadratic) + nbFaceNodes = nbFaceNodes/2; if ( aN.size() < nbFaceNodes * 2 ) aN.resize( nbFaceNodes * 2 ); // k=0; aItNodes=pE0->nodesIterator(); while (aItNodes->more()) { - const SMDS_MeshElement* pNode=aItNodes->next(); - aID0=pNode->GetID(); - aJ[k]=GetIndexOnLayer(aID0); + //const SMDS_MeshElement* pNode = aItNodes->next(); + const SMDS_MeshNode* pNode = + static_cast (aItNodes->next()); + if(myTool->IsMedium(pNode)) + continue; + aID0 = pNode->GetID(); + aJ[k] = GetIndexOnLayer(aID0); if (myErrorStatus) { MESSAGE("StdMeshers_Penta_3D::MakeVolumeMesh"); return; @@ -646,19 +758,19 @@ void StdMeshers_Penta_3D::MakeVolumeMesh() } // bool forward = true; - for (i=0; iAddVolume(aN[0], aN[1], aN[2], - aN[3], aN[4], aN[5]); - else - aV = meshDS->AddVolume(aN[0], aN[2], aN[1], - aN[3], aN[5], aN[4]); + if ( forward ) { + //aV = meshDS->AddVolume(aN[0], aN[1], aN[2], + // aN[3], aN[4], aN[5]); + aV = myTool->AddVolume(aN[0], aN[1], aN[2], aN[3], aN[4], aN[5]); + } + else { + //aV = meshDS->AddVolume(aN[0], aN[2], aN[1], + // aN[3], aN[5], aN[4]); + aV = myTool->AddVolume(aN[0], aN[2], aN[1], aN[3], aN[5], aN[4]); + } break; case 4: - if ( forward ) - aV = meshDS->AddVolume(aN[0], aN[1], aN[2], aN[3], + if ( forward ) { + //aV = meshDS->AddVolume(aN[0], aN[1], aN[2], aN[3], + // aN[4], aN[5], aN[6], aN[7]); + aV = myTool->AddVolume(aN[0], aN[1], aN[2], aN[3], aN[4], aN[5], aN[6], aN[7]); - else - aV = meshDS->AddVolume(aN[0], aN[3], aN[2], aN[1], + } + else { + //aV = meshDS->AddVolume(aN[0], aN[3], aN[2], aN[1], + // aN[4], aN[7], aN[6], aN[5]); + aV = myTool->AddVolume(aN[0], aN[3], aN[2], aN[1], aN[4], aN[7], aN[6], aN[5]); + } break; default: continue; @@ -727,74 +849,68 @@ void StdMeshers_Penta_3D::MakeMeshOnFxy1() const TopoDS_Face& aFxy1= TopoDS::Face(myBlock.Shape(SMESH_Block::ID_Fxy1)); // - SMESH_Mesh* pMesh=GetMesh(); + SMESH_Mesh* pMesh = GetMesh(); SMESHDS_Mesh * meshDS = pMesh->GetMeshDS(); // SMESH_subMesh *aSubMesh0 = pMesh->GetSubMeshContaining(aFxy0); - SMESHDS_SubMesh *aSM0=aSubMesh0->GetSubMeshDS(); + SMESHDS_SubMesh *aSM0 = aSubMesh0->GetSubMeshDS(); // // set nodes on aFxy1 - aLevel=myISize-1; - itn=aSM0->GetNodes(); - aNbNodes=aSM0->NbNodes(); + aLevel = myISize-1; + itn = aSM0->GetNodes(); + aNbNodes = aSM0->NbNodes(); //printf("** aNbNodes=%d\n", aNbNodes); - while(itn->more()) { - const SMDS_MeshNode* aN0=itn->next(); - aID0=aN0->GetID(); - aJ=GetIndexOnLayer(aID0); - if (myErrorStatus) { - MESSAGE("StdMeshers_Penta_3D::MakeMeshOnFxy1() "); - return; - } - // - ij=aLevel*myJSize+aJ; - const StdMeshers_TNode& aTN1=myTNodes[ij]; - SMDS_MeshNode* aN1=(SMDS_MeshNode*)aTN1.Node(); - // - meshDS->SetNodeOnFace(aN1, aFxy1); - } + // // set elements on aFxy1 vector aNodes1; // - itf=aSM0->GetElements(); + itf = aSM0->GetElements(); while(itf->more()) { - const SMDS_MeshElement * pE0=itf->next(); - aElementType=pE0->GetType(); + const SMDS_MeshElement* pE0 = itf->next(); + aElementType = pE0->GetType(); if (!aElementType==SMDSAbs_Face) { continue; } - aNbNodes=pE0->NbNodes(); + aNbNodes = pE0->NbNodes(); + if(myCreateQuadratic) + aNbNodes = aNbNodes/2; // if (aNbNodes!=3) { // continue; // } if ( aNodes1.size() < aNbNodes ) aNodes1.resize( aNbNodes ); // - k=aNbNodes-1; // reverse a face - aItNodes=pE0->nodesIterator(); + k = aNbNodes-1; // reverse a face + aItNodes = pE0->nodesIterator(); while (aItNodes->more()) { - const SMDS_MeshElement* pNode=aItNodes->next(); - aID0=pNode->GetID(); - aJ=GetIndexOnLayer(aID0); + //const SMDS_MeshElement* pNode = aItNodes->next(); + const SMDS_MeshNode* pNode = + static_cast (aItNodes->next()); + if(myTool->IsMedium(pNode)) + continue; + aID0 = pNode->GetID(); + aJ = GetIndexOnLayer(aID0); if (myErrorStatus) { MESSAGE("StdMeshers_Penta_3D::MakeMeshOnFxy1() "); return; } // - ij=aLevel*myJSize+aJ; - const StdMeshers_TNode& aTN1=myTNodes[ij]; - const SMDS_MeshNode* aN1=aTN1.Node(); - aNodes1[k]=aN1; + ij = aLevel*myJSize + aJ; + const StdMeshers_TNode& aTN1 = myTNodes[ij]; + const SMDS_MeshNode* aN1 = aTN1.Node(); + aNodes1[k] = aN1; --k; } SMDS_MeshFace * face = 0; switch ( aNbNodes ) { case 3: - face = meshDS->AddFace(aNodes1[0], aNodes1[1], aNodes1[2]); + //face = meshDS->AddFace(aNodes1[0], aNodes1[1], aNodes1[2]); + face = myTool->AddFace(aNodes1[0], aNodes1[1], aNodes1[2]); break; case 4: - face = meshDS->AddFace(aNodes1[0], aNodes1[1], aNodes1[2], aNodes1[3]); + //face = meshDS->AddFace(aNodes1[0], aNodes1[1], aNodes1[2], aNodes1[3]); + face = myTool->AddFace(aNodes1[0], aNodes1[1], aNodes1[2], aNodes1[3]); break; default: continue; @@ -802,6 +918,7 @@ void StdMeshers_Penta_3D::MakeMeshOnFxy1() meshDS->SetMeshElementOnShape(face, aFxy1); } } + //======================================================================= //function : ClearMeshOnFxy1 //purpose : @@ -838,6 +955,7 @@ int StdMeshers_Penta_3D::GetIndexOnLayer(const int aID) j=(*aMapIt).second; return j; } + //======================================================================= //function : MakeConnectingMap //purpose : @@ -852,6 +970,7 @@ void StdMeshers_Penta_3D::MakeConnectingMap() myConnectingMap[aBNID]=j; } } + //======================================================================= //function : CreateNode //purpose : @@ -879,8 +998,7 @@ void StdMeshers_Penta_3D::CreateNode(const bool bIsUpperLayer, // // point inside solid // myBlock.Point(aParams, aP); // } - if (bIsUpperLayer) - { + if (bIsUpperLayer) { double u = aParams.X(), v = aParams.Y(); double u1 = ( 1. - u ), v1 = ( 1. - v ); aP.ChangeCoord() = myShapeXYZ[ SMESH_Block::ID_Ex01 ] * v1; @@ -893,8 +1011,7 @@ void StdMeshers_Penta_3D::CreateNode(const bool bIsUpperLayer, aP.ChangeCoord() -= myShapeXYZ[ SMESH_Block::ID_V011 ] * u1 * v; aP.ChangeCoord() -= myShapeXYZ[ SMESH_Block::ID_V111 ] * u * v; } - else - { + else { SMESH_Block::ShellPoint( aParams, myShapeXYZ, aP.ChangeCoord() ); } // @@ -906,12 +1023,14 @@ void StdMeshers_Penta_3D::CreateNode(const bool bIsUpperLayer, // aX=aP.X(); aY=aP.Y(); aZ=aP.Z(); // - SMESH_Mesh* pMesh=GetMesh(); - SMESHDS_Mesh* pMeshDS=pMesh->GetMeshDS(); + SMESH_Mesh* pMesh = GetMesh(); + SMESHDS_Mesh* pMeshDS = pMesh->GetMeshDS(); // pNode = pMeshDS->AddNode(aX, aY, aZ); + aTN.SetNode(pNode); } + //======================================================================= //function : ShapeSupportID //purpose : @@ -980,21 +1099,21 @@ void StdMeshers_Penta_3D::MakeBlock() SMDSAbs_ElementType aElementType; SMESH_Mesh* pMesh=GetMesh(); // - iCnt=0; - iNbF=aM.Extent(); + iCnt = 0; + iNbF = aM.Extent(); for (i=1; i<=iNbF; ++i) { - const TopoDS_Shape& aF=aM(i); + const TopoDS_Shape& aF = aM(i); SMESH_subMesh *aSubMesh = pMesh->GetSubMeshContaining(aF); ASSERT(aSubMesh); - SMESHDS_SubMesh *aSM=aSubMesh->GetSubMeshDS(); - SMDS_ElemIteratorPtr itf=aSM->GetElements(); + SMESHDS_SubMesh *aSM = aSubMesh->GetSubMeshDS(); + SMDS_ElemIteratorPtr itf = aSM->GetElements(); while(itf->more()) { - const SMDS_MeshElement * pElement=itf->next(); - aElementType=pElement->GetType(); + const SMDS_MeshElement * pElement = itf->next(); + aElementType = pElement->GetType(); if (aElementType==SMDSAbs_Face) { - iNbNodes=pElement->NbNodes(); - if (iNbNodes==3) { - aFTr=aF; + iNbNodes = pElement->NbNodes(); + if ( iNbNodes==3 || (myCreateQuadratic && iNbNodes==6) ) { + aFTr = aF; ++iCnt; if (iCnt>1) { MESSAGE("StdMeshers_Penta_3D::MakeBlock() "); @@ -1013,7 +1132,7 @@ void StdMeshers_Penta_3D::MakeBlock() TopExp::MapShapesAndAncestors(myShape, TopAbs_VERTEX, TopAbs_EDGE, aMVES); // // 1.1 Base vertex V000 - iNbE=aME.Extent(); + iNbE = aME.Extent(); if (iNbE!=4){ MESSAGE("StdMeshers_Penta_3D::MakeBlock() "); myErrorStatus=7; // too few edges are in base face aFTr @@ -1080,7 +1199,7 @@ void StdMeshers_Penta_3D::MakeBlock() // 2. Load Block const TopoDS_Shell& aShell=TopoDS::Shell(aME(1)); myBlock.Load(aShell, aV000, aV001); - iErr=myBlock.ErrorStatus(); + iErr = myBlock.ErrorStatus(); if (iErr) { MESSAGE("StdMeshers_Penta_3D::MakeBlock() "); myErrorStatus=100; // SMESHBlock: Load operation failed @@ -1154,10 +1273,10 @@ bool StdMeshers_Penta_3D::LoadIJNodes(StdMeshers_IJNodeMap & theIJNodes, bool rev1, CumOri = false; TopExp_Explorer exp( theFace, TopAbs_EDGE ); int nbEdges = 0; - for ( ; exp.More(); exp.Next() ) - { - if ( ++nbEdges > 4 ) + for ( ; exp.More(); exp.Next() ) { + if ( ++nbEdges > 4 ) { return false; // more than 4 edges in theFace + } TopoDS_Edge e = TopoDS::Edge( exp.Current() ); if ( theBaseEdge.IsSame( e )) continue; @@ -1174,8 +1293,9 @@ bool StdMeshers_Penta_3D::LoadIJNodes(StdMeshers_IJNodeMap & theIJNodes, else e2 = e; } - if ( nbEdges < 4 ) - return false; // lass than 4 edges in theFace + if ( nbEdges < 4 ) { + return false; // less than 4 edges in theFace + } // submeshes corresponding to shapes SMESHDS_SubMesh* smFace = theMesh->MeshElements( theFace ); @@ -1200,13 +1320,32 @@ bool StdMeshers_Penta_3D::LoadIJNodes(StdMeshers_IJNodeMap & theIJNodes, return false; } if ( sm1->NbNodes() * smb->NbNodes() != smFace->NbNodes() ) { - MESSAGE( "Wrong nb face nodes: " << - sm1->NbNodes()<<" "<NbNodes()<<" "<NbNodes()); - return false; + // check quadratic case + if ( myCreateQuadratic ) { + int n1 = sm1->NbNodes()/2; + int n2 = smb->NbNodes()/2; + int n3 = sm1->NbNodes() - n1; + int n4 = smb->NbNodes() - n2; + int nf = sm1->NbNodes()*smb->NbNodes() - n3*n4; + if( nf != smFace->NbNodes() ) { + MESSAGE( "Wrong nb face nodes: " << + sm1->NbNodes()<<" "<NbNodes()<<" "<NbNodes()); + return false; + } + } + else { + MESSAGE( "Wrong nb face nodes: " << + sm1->NbNodes()<<" "<NbNodes()<<" "<NbNodes()); + return false; + } } // IJ size int vsize = sm1->NbNodes() + 2; int hsize = smb->NbNodes() + 2; + if(myCreateQuadratic) { + vsize = vsize - sm1->NbNodes()/2 -1; + hsize = hsize - smb->NbNodes()/2 -1; + } // load nodes from theBaseEdge @@ -1226,12 +1365,15 @@ bool StdMeshers_Penta_3D::LoadIJNodes(StdMeshers_IJNodeMap & theIJNodes, double range = l - f; SMDS_NodeIteratorPtr nIt = smb->GetNodes(); const SMDS_MeshNode* node; - while ( nIt->more() ) - { + while ( nIt->more() ) { node = nIt->next(); + if(myTool->IsMedium(node)) + continue; const SMDS_EdgePosition* pos = dynamic_cast( node->GetPosition().get() ); - if ( !pos ) return false; + if ( !pos ) { + return false; + } double u = ( pos->GetUParameter() - f ) / range; vector & nVec = theIJNodes[ u ]; nVec.resize( vsize, nullNode ); @@ -1246,19 +1388,21 @@ bool StdMeshers_Penta_3D::LoadIJNodes(StdMeshers_IJNodeMap & theIJNodes, map< double, const SMDS_MeshNode*> sortedNodes; // sort by param on edge nIt = sm1->GetNodes(); - while ( nIt->more() ) - { + while ( nIt->more() ) { node = nIt->next(); + if(myTool->IsMedium(node)) + continue; const SMDS_EdgePosition* pos = dynamic_cast( node->GetPosition().get() ); - if ( !pos ) return false; + if ( !pos ) { + return false; + } sortedNodes.insert( make_pair( pos->GetUParameter(), node )); } loadedNodes.insert( nVecf[ vsize - 1 ] = smVft->GetNodes()->next() ); map< double, const SMDS_MeshNode*>::iterator u_n = sortedNodes.begin(); int row = rev1 ? vsize - 1 : 0; - for ( ; u_n != sortedNodes.end(); u_n++ ) - { + for ( ; u_n != sortedNodes.end(); u_n++ ) { if ( rev1 ) row--; else row++; loadedNodes.insert( nVecf[ row ] = u_n->second ); @@ -1285,8 +1429,7 @@ bool StdMeshers_Penta_3D::LoadIJNodes(StdMeshers_IJNodeMap & theIJNodes, StdMeshers_IJNodeMap::iterator par_nVec_2 = par_nVec_1; // loop on columns int col = 0; - for ( par_nVec_2++; par_nVec_2 != theIJNodes.end(); par_nVec_1++, par_nVec_2++ ) - { + for ( par_nVec_2++; par_nVec_2 != theIJNodes.end(); par_nVec_1++, par_nVec_2++ ) { col++; row = 0; const SMDS_MeshNode* n1 = par_nVec_1->second[ row ]; @@ -1295,10 +1438,10 @@ bool StdMeshers_Penta_3D::LoadIJNodes(StdMeshers_IJNodeMap & theIJNodes, do { // look for a face by 2 nodes face = SMESH_MeshEditor::FindFaceInSet( n1, n2, allFaces, foundFaces ); - if ( face ) - { + if ( face ) { int nbFaceNodes = face->NbNodes(); - if ( nbFaceNodes > 4 ) { + if ( (!myCreateQuadratic && nbFaceNodes>4) || + (myCreateQuadratic && nbFaceNodes>8) ) { MESSAGE(" Too many nodes in a face: " << nbFaceNodes ); return false; } @@ -1308,6 +1451,8 @@ bool StdMeshers_Penta_3D::LoadIJNodes(StdMeshers_IJNodeMap & theIJNodes, eIt = face->nodesIterator() ; while ( !found && eIt->more() ) { node = static_cast( eIt->next() ); + if(myTool->IsMedium(node)) + continue; found = loadedNodes.insert( node ).second; if ( !found && node != n1 && node != n2 ) n3 = node; @@ -1320,18 +1465,21 @@ bool StdMeshers_Penta_3D::LoadIJNodes(StdMeshers_IJNodeMap & theIJNodes, par_nVec_2->second[ row ] = node; foundFaces.insert( face ); n2 = node; - if ( nbFaceNodes == 4 ) + if ( nbFaceNodes==4 || (myCreateQuadratic && nbFaceNodes==8) ) { n1 = par_nVec_1->second[ row ]; + } } - else if (nbFaceNodes == 3 && - n3 == par_nVec_1->second[ row ] ) + else if ( (nbFaceNodes==3 || (myCreateQuadratic && nbFaceNodes==6) ) && + n3 == par_nVec_1->second[ row ] ) { n1 = n3; + } else { MESSAGE( "Not quad mesh, column "<< col ); return false; } } - } while ( face && n1 && n2 ); + } + while ( face && n1 && n2 ); if ( row < vsize - 1 ) { MESSAGE( "Too few nodes in column "<< col <<": "<< row+1); @@ -1390,17 +1538,18 @@ int StdMeshers_SMESHBlock::ErrorStatus() const { return myErrorStatus; } + //======================================================================= //function : Load //purpose : //======================================================================= void StdMeshers_SMESHBlock::Load(const TopoDS_Shell& theShell) { - TopoDS_Vertex aV000, aV001; // Load(theShell, aV000, aV001); } + //======================================================================= //function : Load //purpose : @@ -1416,12 +1565,13 @@ void StdMeshers_SMESHBlock::Load(const TopoDS_Shell& theShell, bool bOk; // myShapeIDMap.Clear(); - bOk=myTBlock.LoadBlockShapes(myShell, theV000, theV001, myShapeIDMap); + bOk = myTBlock.LoadBlockShapes(myShell, theV000, theV001, myShapeIDMap); if (!bOk) { myErrorStatus=2; return; } } + //======================================================================= //function : ComputeParameters //purpose : @@ -1431,24 +1581,25 @@ void StdMeshers_SMESHBlock::ComputeParameters(const gp_Pnt& thePnt, { ComputeParameters(thePnt, myShell, theXYZ); } + //======================================================================= //function : ComputeParameters //purpose : //======================================================================= void StdMeshers_SMESHBlock::ComputeParameters(const gp_Pnt& thePnt, const TopoDS_Shape& theShape, - gp_XYZ& theXYZ) + gp_XYZ& theXYZ) { myErrorStatus=0; // int aID; bool bOk; // - aID=ShapeID(theShape); + aID = ShapeID(theShape); if (myErrorStatus) { return; } - bOk=myTBlock.ComputeParameters(thePnt, theXYZ, aID); + bOk = myTBlock.ComputeParameters(thePnt, theXYZ, aID); if (!bOk) { myErrorStatus=4; // problems with computation Parameters return; @@ -1469,12 +1620,12 @@ void StdMeshers_SMESHBlock::ComputeParameters(const double& theU, int aID; bool bOk=false; // - aID=ShapeID(theShape); + aID = ShapeID(theShape); if (myErrorStatus) { return; } if ( SMESH_Block::IsEdgeID( aID )) - bOk=myTBlock.EdgeParameters( aID, theU, theXYZ ); + bOk = myTBlock.EdgeParameters( aID, theU, theXYZ ); if (!bOk) { myErrorStatus=4; // problems with computation Parameters return; @@ -1492,6 +1643,7 @@ void StdMeshers_SMESHBlock::ComputeParameters(const double& theU, // Point(theParams, aS, aP3D); } + //======================================================================= //function : Point //purpose : @@ -1500,15 +1652,15 @@ void StdMeshers_SMESHBlock::ComputeParameters(const double& theU, const TopoDS_Shape& theShape, gp_Pnt& aP3D) { - myErrorStatus=0; + myErrorStatus = 0; // int aID; - bool bOk=false; + bool bOk = false; gp_XYZ aXYZ(99.,99.,99.); aP3D.SetXYZ(aXYZ); // if (theShape.IsNull()) { - bOk=myTBlock.ShellPoint(theParams, aXYZ); + bOk = myTBlock.ShellPoint(theParams, aXYZ); } // else { @@ -1518,14 +1670,14 @@ void StdMeshers_SMESHBlock::ComputeParameters(const double& theU, } // if (SMESH_Block::IsVertexID(aID)) { - bOk=myTBlock.VertexPoint(aID, aXYZ); + bOk = myTBlock.VertexPoint(aID, aXYZ); } else if (SMESH_Block::IsEdgeID(aID)) { - bOk=myTBlock.EdgePoint(aID, theParams, aXYZ); + bOk = myTBlock.EdgePoint(aID, theParams, aXYZ); } // else if (SMESH_Block::IsFaceID(aID)) { - bOk=myTBlock.FacePoint(aID, theParams, aXYZ); + bOk = myTBlock.FacePoint(aID, theParams, aXYZ); } } if (!bOk) { @@ -1534,6 +1686,7 @@ void StdMeshers_SMESHBlock::ComputeParameters(const double& theU, } aP3D.SetXYZ(aXYZ); } + //======================================================================= //function : ShapeID //purpose : @@ -1561,6 +1714,7 @@ int StdMeshers_SMESHBlock::ShapeID(const TopoDS_Shape& theShape) myErrorStatus=2; // unknown shape; return aID; } + //======================================================================= //function : Shape //purpose : @@ -1580,3 +1734,5 @@ const TopoDS_Shape& StdMeshers_SMESHBlock::Shape(const int theID) const TopoDS_Shape& aS=myShapeIDMap.FindKey(theID); return aS; } + + diff --git a/src/StdMeshers/StdMeshers_Penta_3D.hxx b/src/StdMeshers/StdMeshers_Penta_3D.hxx index dc8ba72cf..1b5efab6d 100644 --- a/src/StdMeshers/StdMeshers_Penta_3D.hxx +++ b/src/StdMeshers/StdMeshers_Penta_3D.hxx @@ -39,9 +39,12 @@ #include #include #include +#include #include "SMESH_Block.hxx" +#include "StdMeshers_Helper.hxx" + typedef std::map< double, std::vector > StdMeshers_IJNodeMap; class StdMeshers_SMESHBlock { @@ -181,10 +184,10 @@ class StdMeshers_Penta_3D { return myTol3D; } - static bool LoadIJNodes(StdMeshers_IJNodeMap & theIJNodes, - const TopoDS_Face& theFace, - const TopoDS_Edge& theBaseEdge, - SMESHDS_Mesh* theMesh); + bool LoadIJNodes(StdMeshers_IJNodeMap & theIJNodes, + const TopoDS_Face& theFace, + const TopoDS_Edge& theBaseEdge, + SMESHDS_Mesh* theMesh); // Load nodes bound to theFace into column (vectors) and rows // of theIJNodes. // The value of theIJNodes map is a vector of ordered nodes so @@ -251,6 +254,9 @@ class StdMeshers_Penta_3D { // vector myWallNodesMaps; // nodes on a face vector myShapeXYZ; // point on each sub-shape + + bool myCreateQuadratic; + StdMeshers_Helper* myTool; // toll for working with quadratic elements }; #endif diff --git a/src/StdMeshers/StdMeshers_Quadrangle_2D.cxx b/src/StdMeshers/StdMeshers_Quadrangle_2D.cxx index 9ffa37d1f..3a2eb8780 100644 --- a/src/StdMeshers/StdMeshers_Quadrangle_2D.cxx +++ b/src/StdMeshers/StdMeshers_Quadrangle_2D.cxx @@ -47,6 +47,7 @@ using namespace std; #include #include #include +#include #include #include @@ -128,6 +129,11 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh, SMESHDS_Mesh * meshDS = aMesh.GetMeshDS(); aMesh.GetSubMesh(aShape); + bool QuadMode = true; + + myTool = new StdMeshers_Helper(aMesh); + myCreateQuadratic = myTool->IsQuadraticSubMesh(aShape,QuadMode); + //FaceQuadStruct *quad = CheckAnd2Dcompute(aMesh, aShape); FaceQuadStruct* quad = CheckNbEdges(aMesh, aShape); @@ -180,7 +186,7 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh, quad->uv_grid[ij].node = node; } } - + // mesh faces // [2] @@ -194,16 +200,16 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh, // 0 > > > > > > > > nbhoriz // i // [0] - + i = 0; int ilow = 0; int iup = nbhoriz - 1; if (quad->isEdgeOut[3]) { ilow++; } else { if (quad->isEdgeOut[1]) iup--; } - + int jlow = 0; int jup = nbvertic - 1; if (quad->isEdgeOut[0]) { jlow++; } else { if (quad->isEdgeOut[2]) jup--; } - + // regular quadrangles for (i = ilow; i < iup; i++) { for (j = jlow; j < jup; j++) { @@ -212,11 +218,12 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh, b = quad->uv_grid[j * nbhoriz + i + 1].node; c = quad->uv_grid[(j + 1) * nbhoriz + i + 1].node; d = quad->uv_grid[(j + 1) * nbhoriz + i].node; - SMDS_MeshFace * face = meshDS->AddFace(a, b, c, d); + //SMDS_MeshFace * face = meshDS->AddFace(a, b, c, d); + SMDS_MeshFace* face = myTool->AddFace(a, b, c, d); meshDS->SetMeshElementOnShape(face, geomFaceID); } } - + UVPtStruct *uv_e0 = quad->uv_edges[0]; UVPtStruct *uv_e1 = quad->uv_edges[1]; UVPtStruct *uv_e2 = quad->uv_edges[2]; @@ -225,7 +232,7 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh, double eps = Precision::Confusion(); // Boundary quadrangles - + if (quad->isEdgeOut[0]) { // Down edge is out // @@ -237,14 +244,14 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh, // . . . . . . . . . __ down edge nodes // // >->->->->->->->->->->->-> -- direction of processing - + int g = 0; // number of last processed node in the regular grid - + // number of last node of the down edge to be processed int stop = nbdown - 1; // if right edge is out, we will stop at a node, previous to the last one if (quad->isEdgeOut[1]) stop--; - + // for each node of the down edge find nearest node // in the first row of the regular grid and link them for (i = 0; i < stop; i++) { @@ -252,18 +259,19 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh, a = uv_e0[i].node; b = uv_e0[i + 1].node; gp_Pnt pb (b->X(), b->Y(), b->Z()); - + // find node c in the regular grid, which will be linked with node b int near = g; if (i == stop - 1) { // right bound reached, link with the rightmost node near = iup; c = quad->uv_grid[nbhoriz + iup].node; - } else { + } + else { // find in the grid node c, nearest to the b double mind = RealLast(); for (int k = g; k <= iup; k++) { - + const SMDS_MeshNode *nk; if (k < ilow) // this can be, if left edge is out nk = uv_e3[1].node; // get node from the left edge @@ -283,14 +291,17 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh, } if (near == g) { // make triangle - SMDS_MeshFace* face = meshDS->AddFace(a, b, c); + //SMDS_MeshFace* face = meshDS->AddFace(a, b, c); + SMDS_MeshFace* face = myTool->AddFace(a, b, c); meshDS->SetMeshElementOnShape(face, geomFaceID); - } else { // make quadrangle + } + else { // make quadrangle if (near - 1 < ilow) d = uv_e3[1].node; else d = quad->uv_grid[nbhoriz + near - 1].node; - SMDS_MeshFace* face = meshDS->AddFace(a, b, c, d); + //SMDS_MeshFace* face = meshDS->AddFace(a, b, c, d); + SMDS_MeshFace* face = myTool->AddFace(a, b, c, d); meshDS->SetMeshElementOnShape(face, geomFaceID); // if node d is not at position g - make additional triangles @@ -301,7 +312,8 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh, d = uv_e3[1].node; else d = quad->uv_grid[nbhoriz + k - 1].node; - SMDS_MeshFace* face = meshDS->AddFace(a, c, d); + //SMDS_MeshFace* face = meshDS->AddFace(a, c, d); + SMDS_MeshFace* face = myTool->AddFace(a, c, d); meshDS->SetMeshElementOnShape(face, geomFaceID); } } @@ -363,14 +375,17 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh, } if (near == g) { // make triangle - SMDS_MeshFace* face = meshDS->AddFace(a, b, c); + //SMDS_MeshFace* face = meshDS->AddFace(a, b, c); + SMDS_MeshFace* face = myTool->AddFace(a, b, c); meshDS->SetMeshElementOnShape(face, geomFaceID); - } else { // make quadrangle + } + else { // make quadrangle if (near + 1 > iup) d = uv_e1[nbright - 2].node; else d = quad->uv_grid[nbhoriz*(nbvertic - 2) + near + 1].node; - SMDS_MeshFace* face = meshDS->AddFace(a, b, c, d); + //SMDS_MeshFace* face = meshDS->AddFace(a, b, c, d); + SMDS_MeshFace* face = myTool->AddFace(a, b, c, d); meshDS->SetMeshElementOnShape(face, geomFaceID); if (near + 1 < g) { // if d not is at g - make additional triangles @@ -380,7 +395,8 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh, d = uv_e1[nbright - 2].node; else d = quad->uv_grid[nbhoriz*(nbvertic - 2) + k + 1].node; - SMDS_MeshFace* face = meshDS->AddFace(a, c, d); + //SMDS_MeshFace* face = meshDS->AddFace(a, c, d); + SMDS_MeshFace* face = myTool->AddFace(a, c, d); meshDS->SetMeshElementOnShape(face, geomFaceID); } } @@ -428,14 +444,17 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh, } if (near == g) { // make triangle - SMDS_MeshFace* face = meshDS->AddFace(a, b, c); + //SMDS_MeshFace* face = meshDS->AddFace(a, b, c); + SMDS_MeshFace* face = myTool->AddFace(a, b, c); meshDS->SetMeshElementOnShape(face, geomFaceID); - } else { // make quadrangle + } + else { // make quadrangle if (near - 1 < jlow) d = uv_e0[nbdown - 2].node; else d = quad->uv_grid[nbhoriz*near - 2].node; - SMDS_MeshFace* face = meshDS->AddFace(a, b, c, d); + //SMDS_MeshFace* face = meshDS->AddFace(a, b, c, d); + SMDS_MeshFace* face = myTool->AddFace(a, b, c, d); meshDS->SetMeshElementOnShape(face, geomFaceID); if (near - 1 > g) { // if d not is at g - make additional triangles @@ -445,7 +464,8 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh, d = uv_e0[nbdown - 2].node; else d = quad->uv_grid[nbhoriz*k - 2].node; - SMDS_MeshFace* face = meshDS->AddFace(a, c, d); + //SMDS_MeshFace* face = meshDS->AddFace(a, c, d); + SMDS_MeshFace* face = myTool->AddFace(a, c, d); meshDS->SetMeshElementOnShape(face, geomFaceID); } } @@ -490,14 +510,17 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh, } if (near == g) { // make triangle - SMDS_MeshFace* face = meshDS->AddFace(a, b, c); + //SMDS_MeshFace* face = meshDS->AddFace(a, b, c); + SMDS_MeshFace* face = myTool->AddFace(a, b, c); meshDS->SetMeshElementOnShape(face, geomFaceID); - } else { // make quadrangle + } + else { // make quadrangle if (near + 1 > jup) d = uv_e2[1].node; else d = quad->uv_grid[nbhoriz*(near + 1) + 1].node; - SMDS_MeshFace* face = meshDS->AddFace(a, b, c, d); + //SMDS_MeshFace* face = meshDS->AddFace(a, b, c, d); + SMDS_MeshFace* face = myTool->AddFace(a, b, c, d); meshDS->SetMeshElementOnShape(face, geomFaceID); if (near + 1 < g) { // if d not is at g - make additional triangles @@ -507,7 +530,8 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh, d = uv_e2[1].node; else d = quad->uv_grid[nbhoriz*(k + 1) + 1].node; - SMDS_MeshFace* face = meshDS->AddFace(a, c, d); + //SMDS_MeshFace* face = meshDS->AddFace(a, c, d); + SMDS_MeshFace* face = myTool->AddFace(a, c, d); meshDS->SetMeshElementOnShape(face, geomFaceID); } } @@ -557,7 +581,13 @@ FaceQuadStruct* StdMeshers_Quadrangle_2D::CheckNbEdges(SMESH_Mesh & aMesh, int nb = aMesh.GetSubMesh(E)->GetSubMeshDS()->NbNodes(); if (nbEdges < 4) { quad->edge[nbEdges] = E; - quad->nbPts[nbEdges] = nb + 2; // internal points + 2 extrema + if(!myCreateQuadratic) { + quad->nbPts[nbEdges] = nb + 2; // internal points + 2 extrema + } + else { + int tmp = nb/2; + quad->nbPts[nbEdges] = tmp + 2; // internal not medium points + 2 extrema + } } nbEdges++; } @@ -574,15 +604,35 @@ FaceQuadStruct* StdMeshers_Quadrangle_2D::CheckNbEdges(SMESH_Mesh & aMesh, //============================================================================= /*! - * + * CheckAnd2Dcompute */ //============================================================================= FaceQuadStruct *StdMeshers_Quadrangle_2D::CheckAnd2Dcompute (SMESH_Mesh & aMesh, const TopoDS_Shape & aShape) throw(SALOME_Exception) +{ + bool QuadMode = true; + myTool = new StdMeshers_Helper(aMesh); + myCreateQuadratic = myTool->IsQuadraticSubMesh(aShape,QuadMode); + return CheckAnd2Dcompute(aMesh,aShape,myCreateQuadratic); +} + + +//============================================================================= +/*! + * CheckAnd2Dcompute + */ +//============================================================================= + +FaceQuadStruct *StdMeshers_Quadrangle_2D::CheckAnd2Dcompute + (SMESH_Mesh & aMesh, + const TopoDS_Shape & aShape, + const bool CreateQuadratic) throw(SALOME_Exception) { Unexpect aCatch(SalomeException); + myCreateQuadratic = CreateQuadratic; + FaceQuadStruct *quad = CheckNbEdges(aMesh, aShape); if(!quad) return 0; @@ -1185,13 +1235,13 @@ bool StdMeshers_Quadrangle_2D::ComputeQuadPref for(j=1; jAddFace(NodesL.Value(i,j), NodesL.Value(i+1,j), + myTool->AddFace(NodesL.Value(i,j), NodesL.Value(i+1,j), NodesL.Value(i+1,j+1), NodesL.Value(i,j+1)); meshDS->SetMeshElementOnShape(F, geomFaceID); } else { SMDS_MeshFace* F = - meshDS->AddFace(NodesL.Value(i,j), NodesL.Value(i,j+1), + myTool->AddFace(NodesL.Value(i,j), NodesL.Value(i,j+1), NodesL.Value(i+1,j+1), NodesL.Value(i+1,j)); meshDS->SetMeshElementOnShape(F, geomFaceID); } @@ -1252,13 +1302,13 @@ bool StdMeshers_Quadrangle_2D::ComputeQuadPref for(j=1; jAddFace(NodesR.Value(i,j), NodesR.Value(i+1,j), + myTool->AddFace(NodesR.Value(i,j), NodesR.Value(i+1,j), NodesR.Value(i+1,j+1), NodesR.Value(i,j+1)); meshDS->SetMeshElementOnShape(F, geomFaceID); } else { SMDS_MeshFace* F = - meshDS->AddFace(NodesR.Value(i,j), NodesR.Value(i,j+1), + myTool->AddFace(NodesR.Value(i,j), NodesR.Value(i,j+1), NodesR.Value(i+1,j+1), NodesR.Value(i+1,j)); meshDS->SetMeshElementOnShape(F, geomFaceID); } @@ -1335,13 +1385,13 @@ bool StdMeshers_Quadrangle_2D::ComputeQuadPref for(j=1; jAddFace(NodesC.Value(i,j), NodesC.Value(i+1,j), + myTool->AddFace(NodesC.Value(i,j), NodesC.Value(i+1,j), NodesC.Value(i+1,j+1), NodesC.Value(i,j+1)); meshDS->SetMeshElementOnShape(F, geomFaceID); } else { SMDS_MeshFace* F = - meshDS->AddFace(NodesC.Value(i,j), NodesC.Value(i,j+1), + myTool->AddFace(NodesC.Value(i,j), NodesC.Value(i,j+1), NodesC.Value(i+1,j+1), NodesC.Value(i+1,j)); meshDS->SetMeshElementOnShape(F, geomFaceID); } @@ -1387,18 +1437,64 @@ UVPtStruct* StdMeshers_Quadrangle_2D::LoadEdgePoints2 (SMESH_Mesh & aMesh, // --- edge internal IDNodes (relies on good order storage, not checked) +// if(myCreateQuadratic) { + // fill myNLinkNodeMap +// SMDS_ElemIteratorPtr iter = aMesh.GetSubMesh(E)->GetSubMeshDS()->GetElements(); +// while(iter->more()) { +// const SMDS_MeshElement* elem = iter->next(); +// SMDS_ElemIteratorPtr nodeIt = elem->nodesIterator(); +// const SMDS_MeshNode* n1 = static_cast( nodeIt->next() ); +// const SMDS_MeshNode* n2 = static_cast( nodeIt->next() ); +// const SMDS_MeshNode* n3 = static_cast( nodeIt->next() ); +// NLink link(( n1 < n2 ? n1 : n2 ), ( n1 < n2 ? n2 : n1 )); +// myNLinkNodeMap.insert(NLinkNodeMap::value_type(link,n3)); +// myNLinkNodeMap[link] = n3; +// } +// } + map params; SMDS_NodeIteratorPtr ite = aMesh.GetSubMesh(E)->GetSubMeshDS()->GetNodes(); + int nbPoints = aMesh.GetSubMesh(E)->GetSubMeshDS()->NbNodes(); - while(ite->more()) { - const SMDS_MeshNode* node = ite->next(); - const SMDS_EdgePosition* epos = - static_cast(node->GetPosition().get()); - double param = epos->GetUParameter(); - params[param] = node; + if(!myCreateQuadratic) { + while(ite->more()) { + const SMDS_MeshNode* node = ite->next(); + const SMDS_EdgePosition* epos = + static_cast(node->GetPosition().get()); + double param = epos->GetUParameter(); + params[param] = node; + } + } + else { + vector nodes(nbPoints+2); + nodes[0] = idFirst; + nodes[nbPoints+1] = idLast; + nbPoints = nbPoints/2; + int nn = 1; + while(ite->more()) { + const SMDS_MeshNode* node = ite->next(); + nodes[nn++] = node; + // check if node is medium + bool IsMedium = false; + SMDS_ElemIteratorPtr itn = node->GetInverseElementIterator(); + while (itn->more()) { + const SMDS_MeshElement* elem = itn->next(); + if ( elem->GetType() != SMDSAbs_Edge ) + continue; + if(elem->IsMediumNode(node)) { + IsMedium = true; + break; + } + } + if(IsMedium) + continue; + const SMDS_EdgePosition* epos = + static_cast(node->GetPosition().get()); + double param = epos->GetUParameter(); + params[param] = node; + } } - int nbPoints = aMesh.GetSubMesh(E)->GetSubMeshDS()->NbNodes(); if (nbPoints != params.size()) { MESSAGE( "BAD NODE ON EDGE POSITIONS" ); return 0; @@ -1523,21 +1619,60 @@ UVPtStruct* StdMeshers_Quadrangle_2D::LoadEdgePoints (SMESH_Mesh & aMesh, // --- edge internal IDNodes (relies on good order storage, not checked) +// if(myCreateQuadratic) { + // fill myNLinkNodeMap +// SMDS_ElemIteratorPtr iter = aMesh.GetSubMesh(E)->GetSubMeshDS()->GetElements(); +// while(iter->more()) { +// const SMDS_MeshElement* elem = iter->next(); +// SMDS_ElemIteratorPtr nodeIt = elem->nodesIterator(); +// const SMDS_MeshNode* n1 = static_cast( nodeIt->next() ); +// const SMDS_MeshNode* n2 = static_cast( nodeIt->next() ); +// const SMDS_MeshNode* n3 = static_cast( nodeIt->next() ); +// NLink link(( n1 < n2 ? n1 : n2 ), ( n1 < n2 ? n2 : n1 )); +// myNLinkNodeMap.insert(NLinkNodeMap::value_type(link,n3)); +// myNLinkNodeMap[link] = n3; +// } +// } + map params; SMDS_NodeIteratorPtr ite = aMesh.GetSubMesh(E)->GetSubMeshDS()->GetNodes(); + int nbPoints = aMesh.GetSubMesh(E)->GetSubMeshDS()->NbNodes(); - while(ite->more()) - { - const SMDS_MeshNode* node = ite->next(); - const SMDS_EdgePosition* epos = - static_cast(node->GetPosition().get()); - double param = epos->GetUParameter(); - params[param] = node; + if(!myCreateQuadratic) { + while(ite->more()) { + const SMDS_MeshNode* node = ite->next(); + const SMDS_EdgePosition* epos = + static_cast(node->GetPosition().get()); + double param = epos->GetUParameter(); + params[param] = node; + } + } + else { + nbPoints = nbPoints/2; + while(ite->more()) { + const SMDS_MeshNode* node = ite->next(); + // check if node is medium + bool IsMedium = false; + SMDS_ElemIteratorPtr itn = node->GetInverseElementIterator(); + while (itn->more()) { + const SMDS_MeshElement* elem = itn->next(); + if ( elem->GetType() != SMDSAbs_Edge ) + continue; + if(elem->IsMediumNode(node)) { + IsMedium = true; + break; + } + } + if(IsMedium) + continue; + const SMDS_EdgePosition* epos = + static_cast(node->GetPosition().get()); + double param = epos->GetUParameter(); + params[param] = node; + } } - int nbPoints = aMesh.GetSubMesh(E)->GetSubMeshDS()->NbNodes(); - if (nbPoints != params.size()) - { + if (nbPoints != params.size()) { MESSAGE( "BAD NODE ON EDGE POSITIONS" ); return 0; } diff --git a/src/StdMeshers/StdMeshers_Quadrangle_2D.hxx b/src/StdMeshers/StdMeshers_Quadrangle_2D.hxx index afb3498cb..437910c19 100644 --- a/src/StdMeshers/StdMeshers_Quadrangle_2D.hxx +++ b/src/StdMeshers/StdMeshers_Quadrangle_2D.hxx @@ -34,7 +34,11 @@ #include "SMESH_Mesh.hxx" #include "Utils_SALOME_Exception.hxx" -class SMDS_MeshNode; +#include "gp_XY.hxx" + +#include "StdMeshers_Helper.hxx" + +//class SMDS_MeshNode; typedef struct uvPtStruct { @@ -78,8 +82,18 @@ public: const TopoDS_Shape& aShape) throw (SALOME_Exception); + FaceQuadStruct* CheckAnd2Dcompute(SMESH_Mesh& aMesh, + const TopoDS_Shape& aShape, + const bool CreateQuadratic) + throw (SALOME_Exception); + static void QuadDelete(FaceQuadStruct* quad); + /** + * Returns NLinkNodeMap from myTool + */ + const NLinkNodeMap& GetNLinkNodeMap() { return myTool->GetNLinkNodeMap(); } + ostream & SaveTo(ostream & save); istream & LoadFrom(istream & load); friend ostream & operator << (ostream & save, StdMeshers_Quadrangle_2D & hyp); @@ -120,6 +134,8 @@ protected: // construction of quadrangles if the number of nodes on opposite edges // is not the same in the case where the global number of nodes on edges is even bool myQuadranglePreference; + + StdMeshers_Helper* myTool; // toll for working with quadratic elements }; #endif diff --git a/src/StdMeshers/StdMeshers_QuadraticMesh.cxx b/src/StdMeshers/StdMeshers_QuadraticMesh.cxx index 86b4379c3..ebb8ed9ec 100644 --- a/src/StdMeshers/StdMeshers_QuadraticMesh.cxx +++ b/src/StdMeshers/StdMeshers_QuadraticMesh.cxx @@ -42,7 +42,10 @@ StdMeshers_QuadraticMesh::StdMeshers_QuadraticMesh(int hypId, :SMESH_Hypothesis(hypId, studyId, gen) { _name = "QuadraticMesh"; - _param_algo_dim = 1; // is used by StdMeshers_Regular_1D + // only one hypo of the same dim can be assigned to the shape so + // we use -3 in order to distingush from any usual 1D hypothsis and + // from "NotConformAllowed" (-1) and "Propagation" (-2) + _param_algo_dim = -3; } //============================================================================= diff --git a/src/StdMeshers/StdMeshers_Regular_1D.cxx b/src/StdMeshers/StdMeshers_Regular_1D.cxx index d3d92f9ea..c3eb48483 100644 --- a/src/StdMeshers/StdMeshers_Regular_1D.cxx +++ b/src/StdMeshers/StdMeshers_Regular_1D.cxx @@ -510,7 +510,7 @@ bool StdMeshers_Regular_1D::Compute(SMESH_Mesh & aMesh, const TopoDS_Shape & aSh // quardatic mesh required? SMESH_HypoFilter filter( SMESH_HypoFilter::HasName( "QuadraticMesh" )); - bool isQuadraticMesh = aMesh->GetHypothesis( aShape, filter, true ); + bool QuadMode = aMesh.GetHypothesis( aShape, filter, true ); const TopoDS_Edge & EE = TopoDS::Edge(aShape); TopoDS_Edge E = TopoDS::Edge(EE.Oriented(TopAbs_FORWARD)); @@ -533,15 +533,13 @@ bool StdMeshers_Regular_1D::Compute(SMESH_Mesh & aMesh, const TopoDS_Shape & aSh ASSERT(!VLast.IsNull()); lid=aMesh.GetSubMesh(VLast)->GetSubMeshDS()->GetNodes(); - if (!lid->more()) - { + if (!lid->more()) { MESSAGE (" NO NODE BUILT ON VERTEX "); return false; } const SMDS_MeshNode * idLast = lid->next(); - if (!Curve.IsNull()) - { + if (!Curve.IsNull()) { list< double > params; bool reversed = false; if ( !_mainEdge.IsNull() ) @@ -558,9 +556,14 @@ bool StdMeshers_Regular_1D::Compute(SMESH_Mesh & aMesh, const TopoDS_Shape & aSh // only internal nodes receive an edge position with param on curve const SMDS_MeshNode * idPrev = idFirst; + double parPrev = f; + double parLast = l; + if(reversed) { + parPrev = l; + parLast = f; + } - for (list::iterator itU = params.begin(); itU != params.end(); itU++) - { + for (list::iterator itU = params.begin(); itU != params.end(); itU++) { double param = *itU; gp_Pnt P = Curve->Value(param); @@ -568,15 +571,37 @@ bool StdMeshers_Regular_1D::Compute(SMESH_Mesh & aMesh, const TopoDS_Shape & aSh SMDS_MeshNode * node = meshDS->AddNode(P.X(), P.Y(), P.Z()); meshDS->SetNodeOnEdge(node, shapeID, param); - SMDS_MeshEdge * edge = meshDS->AddEdge(idPrev, node); - meshDS->SetMeshElementOnShape(edge, shapeID); + if(QuadMode) { + // create medium node + double prm = ( parPrev + param )/2; + gp_Pnt PM = Curve->Value(prm); + SMDS_MeshNode * NM = meshDS->AddNode(PM.X(), PM.Y(), PM.Z()); + meshDS->SetNodeOnEdge(NM, shapeID, prm); + SMDS_MeshEdge * edge = meshDS->AddEdge(idPrev, node, NM); + meshDS->SetMeshElementOnShape(edge, shapeID); + } + else { + SMDS_MeshEdge * edge = meshDS->AddEdge(idPrev, node); + meshDS->SetMeshElementOnShape(edge, shapeID); + } + idPrev = node; + parPrev = param; + } + if(QuadMode) { + double prm = ( parPrev + parLast )/2; + gp_Pnt PM = Curve->Value(prm); + SMDS_MeshNode * NM = meshDS->AddNode(PM.X(), PM.Y(), PM.Z()); + meshDS->SetNodeOnEdge(NM, shapeID, prm); + SMDS_MeshEdge * edge = meshDS->AddEdge(idPrev, idLast, NM); + meshDS->SetMeshElementOnShape(edge, shapeID); + } + else { + SMDS_MeshEdge* edge = meshDS->AddEdge(idPrev, idLast); + meshDS->SetMeshElementOnShape(edge, shapeID); } - SMDS_MeshEdge* edge = meshDS->AddEdge(idPrev, idLast); - meshDS->SetMeshElementOnShape(edge, shapeID); } - else - { + else { // Edge is a degenerated Edge : We put n = 5 points on the edge. int NbPoints = 5; BRep_Tool::Range(E, f, l); @@ -588,18 +613,38 @@ bool StdMeshers_Regular_1D::Compute(SMESH_Mesh & aMesh, const TopoDS_Shape & aSh gp_Pnt P = BRep_Tool::Pnt(V1); const SMDS_MeshNode * idPrev = idFirst; - for (int i = 2; i < NbPoints; i++) - { + for (int i = 2; i < NbPoints; i++) { double param = f + (i - 1) * du; SMDS_MeshNode * node = meshDS->AddNode(P.X(), P.Y(), P.Z()); + if(QuadMode) { + // create medium node + double prm = param - du/2.; + gp_Pnt PM = Curve->Value(prm); + SMDS_MeshNode * NM = meshDS->AddNode(PM.X(), PM.Y(), PM.Z()); + meshDS->SetNodeOnEdge(NM, shapeID, prm); + SMDS_MeshEdge * edge = meshDS->AddEdge(idPrev, node, NM); + meshDS->SetMeshElementOnShape(edge, shapeID); + } + else { + SMDS_MeshEdge * edge = meshDS->AddEdge(idPrev, node); + meshDS->SetMeshElementOnShape(edge, shapeID); + } meshDS->SetNodeOnEdge(node, shapeID, param); - - SMDS_MeshEdge * edge = meshDS->AddEdge(idPrev, node); - meshDS->SetMeshElementOnShape(edge, shapeID); idPrev = node; } - SMDS_MeshEdge * edge = meshDS->AddEdge(idPrev, idLast); - meshDS->SetMeshElementOnShape(edge, shapeID); + if(QuadMode) { + // create medium node + double prm = l - du/2.; + gp_Pnt PM = Curve->Value(prm); + SMDS_MeshNode * NM = meshDS->AddNode(PM.X(), PM.Y(), PM.Z()); + meshDS->SetNodeOnEdge(NM, shapeID, prm); + SMDS_MeshEdge * edge = meshDS->AddEdge(idPrev, idLast, NM); + meshDS->SetMeshElementOnShape(edge, shapeID); + } + else { + SMDS_MeshEdge * edge = meshDS->AddEdge(idPrev, idLast); + meshDS->SetMeshElementOnShape(edge, shapeID); + } } return true; }