Salome HOME
0020222: Quandrangle_2D meshing fail
[modules/smesh.git] / src / StdMeshers / StdMeshers_Quadrangle_2D.cxx
index aa6b281654842906c46aeae75e3f4e7c07319dd7..8c507531c0b5aebc7e6e3fa45da2baa30279ffa8 100644 (file)
@@ -1,32 +1,30 @@
- //  SMESH SMESH : implementaion of SMESH idl descriptions
+//  Copyright (C) 2007-2008  CEA/DEN, EDF R&D, OPEN CASCADE
 //
-//  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
-//  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS 
-// 
-//  This library is free software; you can redistribute it and/or 
-//  modify it under the terms of the GNU Lesser General Public 
-//  License as published by the Free Software Foundation; either 
-//  version 2.1 of the License. 
-// 
-//  This library is distributed in the hope that it will be useful, 
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of 
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
-//  Lesser General Public License for more details. 
-// 
-//  You should have received a copy of the GNU Lesser General Public 
-//  License along with this library; if not, write to the Free Software 
-//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA 
-// 
-// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+//  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
 //
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License.
 //
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
 //
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+//  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+//  SMESH SMESH : implementaion of SMESH idl descriptions
 //  File   : StdMeshers_Quadrangle_2D.cxx
 //           Moved here from SMESH_Quadrangle_2D.cxx
 //  Author : Paul RASCLE, EDF
 //  Module : SMESH
-//  $Header$
-
+//
 #include "StdMeshers_Quadrangle_2D.hxx"
 
 #include "StdMeshers_FaceSide.hxx"
@@ -43,7 +41,6 @@
 #include "SMDS_EdgePosition.hxx"
 #include "SMDS_FacePosition.hxx"
 
-#include <BRepTools.hxx>
 #include <BRepTools_WireExplorer.hxx>
 #include <BRep_Tool.hxx>
 #include <Geom_Surface.hxx>
@@ -52,6 +49,7 @@
 #include <TColStd_SequenceOfReal.hxx>
 #include <TColgp_SequenceOfXY.hxx>
 #include <TopExp.hxx>
+#include <TopTools_ListIteratorOfListOfShape.hxx>
 #include <TopoDS.hxx>
 
 #include "utilities.h"
@@ -329,10 +327,7 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh,
           meshDS->SetMeshElementOnShape(face, geomFaceID);
         }
         else {
-          SMDS_MeshFace* face = myTool->AddFace(a, b, c);
-          meshDS->SetMeshElementOnShape(face, geomFaceID);
-          face = myTool->AddFace(a, c, d);
-          meshDS->SetMeshElementOnShape(face, geomFaceID);
+          SplitQuad(meshDS, geomFaceID, a, b, c, d);
         }
 
         // if node d is not at position g - make additional triangles
@@ -421,10 +416,7 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh,
             meshDS->SetMeshElementOnShape(face, geomFaceID);
           }
           else {
-            SMDS_MeshFace* face = myTool->AddFace(a, b, c);
-            meshDS->SetMeshElementOnShape(face, geomFaceID);
-            face = myTool->AddFace(a, c, d);
-            meshDS->SetMeshElementOnShape(face, geomFaceID);
+            SplitQuad(meshDS, geomFaceID, a, b, c, d);
           }
 
           if (near + 1 < g) { // if d not is at g - make additional triangles
@@ -499,10 +491,7 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh,
           meshDS->SetMeshElementOnShape(face, geomFaceID);
         }
         else {
-          SMDS_MeshFace* face = myTool->AddFace(a, b, c);
-          meshDS->SetMeshElementOnShape(face, geomFaceID);
-          face = myTool->AddFace(a, c, d);
-          meshDS->SetMeshElementOnShape(face, geomFaceID);
+          SplitQuad(meshDS, geomFaceID, a, b, c, d);
         }
 
         if (near - 1 > g) { // if d not is at g - make additional triangles
@@ -573,10 +562,7 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh,
             meshDS->SetMeshElementOnShape(face, geomFaceID);
           }
           else {
-            SMDS_MeshFace* face = myTool->AddFace(a, b, c);
-            meshDS->SetMeshElementOnShape(face, geomFaceID);
-            face = myTool->AddFace(a, c, d);
-            meshDS->SetMeshElementOnShape(face, geomFaceID);
+            SplitQuad(meshDS, geomFaceID, a, b, c, d);
           }
 
           if (near + 1 < g) { // if d not is at g - make additional triangles
@@ -601,6 +587,27 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh,
   return isOk;
 }
 
+//================================================================================
+/*!
+ * \brief Return true if only two given edges meat at their common vertex
+ */
+//================================================================================
+
+static bool twoEdgesMeatAtVertex(const TopoDS_Edge& e1,
+                                 const TopoDS_Edge& e2,
+                                 SMESH_Mesh &       mesh)
+{
+  TopoDS_Vertex v;
+  if ( !TopExp::CommonVertex( e1, e2, v ))
+    return false;
+  TopTools_ListIteratorOfListOfShape ancestIt( mesh.GetAncestors( v ));
+  for ( ; ancestIt.More() ; ancestIt.Next() )
+    if ( ancestIt.Value().ShapeType() == TopAbs_EDGE )
+      if ( !e1.IsSame( ancestIt.Value() ) && !e2.IsSame( ancestIt.Value() ))
+        return false;
+  return true;
+}
+
 //=============================================================================
 /*!
  *  
@@ -657,6 +664,41 @@ FaceQuadStruct* StdMeshers_Quadrangle_2D::CheckNbEdges(SMESH_Mesh &         aMes
                                                     nbSides<TOP_SIDE, ignoreMediumNodes));
       ++nbSides;
     }
+    // issue 20222. Try to unite only edges shared by two same faces
+    if (nbSides < 4) {
+      // delete found sides
+      { FaceQuadStruct cleaner( *quad ); }
+      quad->side.clear();
+      quad->side.reserve(nbEdgesInWire.front());
+      nbSides = 0;
+
+      SMESH_Block::GetOrderedEdges (F, V, edges, nbEdgesInWire);
+      while ( !edges.empty()) {
+        sideEdges.clear();
+        sideEdges.splice( sideEdges.end(), edges, edges.begin());
+        bool sameSide = true;
+        while ( !edges.empty() && sameSide ) {
+          sameSide =
+            SMESH_Algo::IsContinuous( sideEdges.back(), edges.front() ) &&
+            twoEdgesMeatAtVertex( sideEdges.back(), edges.front(), aMesh );
+          if ( sameSide )
+            sideEdges.splice( sideEdges.end(), edges, edges.begin());
+        }
+        if ( nbSides == 0 ) { // go backward from the first edge
+          sameSide = true;
+          while ( !edges.empty() && sameSide ) {
+            sameSide =
+              SMESH_Algo::IsContinuous( sideEdges.front(), edges.back() ) &&
+              twoEdgesMeatAtVertex( sideEdges.front(), edges.back(), aMesh );
+            if ( sameSide )
+              sideEdges.splice( sideEdges.begin(), edges, --edges.end());
+          }
+        }
+        quad->side.push_back( new StdMeshers_FaceSide(F, sideEdges, &aMesh,
+                                                      nbSides<TOP_SIDE, ignoreMediumNodes));
+        ++nbSides;
+      }
+    }
   }
   if (nbSides != 4) {
 #ifdef _DEBUG_
@@ -925,7 +967,6 @@ static gp_UV CalcUV(double x0, double x1, double y0, double y1,
   return uv;
 }
 
-
 //=======================================================================
 //function : CalcUV2
 //purpose  : auxilary function for ComputeQuadPref
@@ -961,6 +1002,7 @@ static gp_UV CalcUV2(double x, double y,
   return uv;
 }
 
+
 //=======================================================================
 /*!
  * Create only quandrangle faces
@@ -1524,3 +1566,34 @@ bool StdMeshers_Quadrangle_2D::ComputeQuadPref (SMESH_Mesh &        aMesh,
   return isOk;
 }
 
+//=============================================================================
+/*! Split quadrangle in to 2 triangles by smallest diagonal
+ *   
+ */
+//=============================================================================
+void StdMeshers_Quadrangle_2D::SplitQuad(SMESHDS_Mesh *theMeshDS,
+                                    int theFaceID,
+                                    const SMDS_MeshNode* theNode1,
+                                    const SMDS_MeshNode* theNode2,
+                                    const SMDS_MeshNode* theNode3,
+                                    const SMDS_MeshNode* theNode4)
+{
+  gp_Pnt a(theNode1->X(),theNode1->Y(),theNode1->Z());
+  gp_Pnt b(theNode2->X(),theNode2->Y(),theNode2->Z());
+  gp_Pnt c(theNode3->X(),theNode3->Y(),theNode3->Z());
+  gp_Pnt d(theNode4->X(),theNode4->Y(),theNode4->Z());
+  SMDS_MeshFace* face;
+  if(a.Distance(c) > b.Distance(d)){
+    face = myTool->AddFace(theNode2, theNode4, theNode1);
+    theMeshDS->SetMeshElementOnShape(face, theFaceID );
+    face = myTool->AddFace(theNode2, theNode3, theNode4);
+    theMeshDS->SetMeshElementOnShape(face, theFaceID );
+
+  }
+  else{
+    face = myTool->AddFace(theNode1, theNode2 ,theNode3);
+    theMeshDS->SetMeshElementOnShape(face, theFaceID );
+    face = myTool->AddFace(theNode1, theNode3, theNode4);
+    theMeshDS->SetMeshElementOnShape(face, theFaceID );
+  }
+}