Salome HOME
Merge branch 'master' into V7_5_BR
authorvsr <vsr@opencascade.com>
Fri, 7 Nov 2014 15:39:11 +0000 (18:39 +0300)
committervsr <vsr@opencascade.com>
Fri, 7 Nov 2014 15:39:11 +0000 (18:39 +0300)
15 files changed:
doc/salome/examples/CMakeLists.txt
doc/salome/examples/a3DmeshOnModified2Dmesh.py [new file with mode: 0644]
doc/salome/examples/prism_3d_algo.py
doc/salome/gui/SMESH/input/about_meshes.doc
doc/salome/gui/SMESH/input/basic_meshing_algos.doc
doc/salome/gui/SMESH/input/constructing_meshes.doc
doc/salome/gui/SMESH/input/modifying_meshes.doc
doc/salome/gui/SMESH/input/pattern_mapping.doc
doc/salome/gui/SMESH/input/tui_creating_meshes.doc
src/Controls/SMESH_Controls.cxx
src/SMESHGUI/SMESHGUI_GEOMGenUtils.cxx
src/SMESHGUI/SMESHGUI_GEOMGenUtils.h
src/SMESHGUI/SMESHGUI_HypothesesUtils.cxx
src/SMESHGUI/SMESHGUI_MeshOp.cxx
src/StdMeshers/StdMeshers_Quadrangle_2D.cxx

index 227764998bb0c1281ab364df15d4bbc745604b8b..7aa0636896d74818d7515d8e56d0f36ad144f9e8 100644 (file)
 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 #
 
+# examples that cant be used for testing because they use external mesher plug-ins
 SET(BAD_TESTS
   3dmesh.py
+  a3DmeshOnModified2Dmesh.py
   creating_meshes_ex01.py
   creating_meshes_ex03.py
   creating_meshes_ex05.py
@@ -39,14 +41,14 @@ SET(BAD_TESTS
   quality_controls_ex20.py
   quality_controls_ex21.py
   quality_controls_ex22.py
-  viewing_meshes_ex01.py 
-)
+  viewing_meshes_ex01.py
+  )
 
 SET(GOOD_TESTS
-  cartesian_algo.py 
-  creating_meshes_ex02.py 
-  creating_meshes_ex04.py 
-  creating_meshes_ex06.py 
+  cartesian_algo.py
+  creating_meshes_ex02.py
+  creating_meshes_ex04.py
+  creating_meshes_ex06.py
   creating_meshes_ex07.py 
   creating_meshes_ex08.py 
   defining_hypotheses_ex01.py 
diff --git a/doc/salome/examples/a3DmeshOnModified2Dmesh.py b/doc/salome/examples/a3DmeshOnModified2Dmesh.py
new file mode 100644 (file)
index 0000000..7fcdcac
--- /dev/null
@@ -0,0 +1,62 @@
+import salome
+salome.salome_init()
+
+from salome.geom import geomBuilder
+geompy = geomBuilder.New(salome.myStudy)
+
+# This script demonstrates generation of 3D mesh basing on a modified 2D mesh
+#
+# Purpose is to get a tetrahedral mesh in a sphere cut by a cube.
+# The requirement is to have a surface mesh on the cube comprised of
+# triangles of exactly the same size arranged in a grid pattern.
+#
+# To fulfill this requirement we mesh the box using Quadrangle (Mapping)
+# meshing algorithm, split quadrangles into triangles and then generate
+# tetrahedrons.
+
+
+# Make the geometry
+
+Box_1    = geompy.MakeBox(-100,-100,-100, 100, 100, 100)
+Sphere_1 = geompy.MakeSphereR( 300 )
+Cut_1    = geompy.MakeCut(Sphere_1, Box_1, theName="Cut_1")
+# get a spherical face
+Sph_Face = geompy.ExtractShapes( Sphere_1, geompy.ShapeType["FACE"] )[0]
+
+# get the shape Sph_Face turned into during MakeCut()
+Sph_Face = geompy.GetInPlace(Cut_1, Sph_Face, isNewImplementation=True, theName="Sphere_1")
+
+
+# 1) Define a mesh with 1D and 2D meshers
+
+import  SMESH
+from salome.smesh import smeshBuilder
+smesh = smeshBuilder.New(salome.myStudy)
+
+Mesh_1 = smesh.Mesh(Cut_1)
+
+# "global" meshers (assigned to Cut_1) that will be used for the box
+Regular_1D = Mesh_1.Segment()
+Local_Length_1 = Regular_1D.LocalLength(20)
+Quadrangle_2D = Mesh_1.Quadrangle()
+
+# a "local" mesher (assigned to a sub-mesh on Sphere_1) to mesh the sphere
+algo_2D = Mesh_1.Triangle( smeshBuilder.NETGEN_1D2D, Sph_Face )
+algo_2D.SetMaxSize( 70. )
+algo_2D.SetFineness( smeshBuilder.Moderate )
+algo_2D.SetMinSize( 7. )
+
+# 2) Compute 2D mesh
+isDone = Mesh_1.Compute()
+
+# 3) Split quadrangles into triangles
+isDone = Mesh_1.SplitQuadObject( Mesh_1, Diag13=True )
+
+# 4) Define a 3D mesher
+Mesh_1.Tetrahedron()
+
+# 5) Compute 3D mesh
+Mesh_1.Compute()
+
+if salome.sg.hasDesktop():
+  salome.sg.updateObjBrowser(1)
index df18d0fcb511a98627d2294bfc85ae2af6ae8a65..7be0a29d3ddabad9cebf570f5da15e9166d06087 100644 (file)
@@ -1,9 +1,14 @@
 # Use 3D extrusion meshing algorithm
 
-import salome, smesh, SMESH, geompy
-
+import salome
 salome.salome_init()
-smesh.SetCurrentStudy( salome.myStudy )
+
+from salome.geom import geomBuilder
+geompy = geomBuilder.New(salome.myStudy)
+
+import SMESH
+from salome.smesh import smeshBuilder
+smesh =  smeshBuilder.New(salome.myStudy)
 
 OX = geompy.MakeVectorDXDYDZ(1,0,0)
 OY = geompy.MakeVectorDXDYDZ(0,1,0)
index 870e5c1825cdffb4185235ec4db026777ccf522a..65201ac6422e54c9a72469a622bcd5f3f6d8dc6a 100644 (file)
@@ -7,10 +7,12 @@ a set of entities with a simple topology.
 
 It is possible to \subpage constructing_meshes_page "construct meshes" 
 on the basis of geometrical shapes produced in the GEOM module.
-It is also possible to 
-\subpage constructing_submeshes_page "construct mesh on a part of the geometrical object", 
-for example, a face, with different meshing parameters or using
-another meshing algorithm.
+Construction of \subpage constructing_submeshes_page "sub-meshes"
+allows to mesh parts of the geometrical object, for example a face,
+with different meshing parameters or using another meshing algorithm
+than other parts.
+
+3D mesh can be generated basing on a 2D closed mesh.
 
 Several created meshes can be \subpage building_compounds_page "combined into another mesh".
 
@@ -62,44 +64,4 @@ described in the following way:
   coordinates of the corresponding vertex.</li>
 </ul>
 
-<br><h2>Connections</h2>
-
-Each mesh entity bounds 0 or more mesh entities of higher
-dimension. In the same way each mesh entity is bounded by 0 or more
-mesh entities of lower dimension:
-
-<ul>
-<li>A node bounds edges, faces and volumes</li>
-<li>An edge bounds faces, and volumes</li>
-<li>A face bounds volumes</li>
-<li>A volume is bounded by faces, edges and nodes</li>
-<li>A face is bounded by edges, and nodes</li>
-<li>An edge is bounded by nodes</li>
-</ul>
-
-You can notice that there are two types of connections: \b inverse and
-\b direct connections.
-
-<br><h2>Inverse connections</h2>
-
-This relationship has a particularity that the order of bounded
-entities has not a direct meaning. Also the number of bounded entities
-is not fixed.
-
-\b Example: The edges surrounding a node. The 3rd edge has no more
-sense that the 5th one.
-
-<br><h2>Direct connections</h2>
-
-This relationship has a particularity that the order of bounding
-entities is meaningful. The number of bounding entities is fixed and
-depends on the type of the entity (hexahedron, tetrahedron,?).
-
-\b Example: An edge is composed of two nodes. A face is composed of 3
-or 4 edges depending if we are dealing with triangles or quadrangles.
-
-The connections are not only restricted to entities of one dimension
-higher or lower. For example some algorithms may be interested to
-retrieve all the faces surrounding a node.
-
 */
index ee632b282113eb56970641ada4fda99b01a9a1ec..977b505dbad674d72220d8e33e9aaf5a4363c7bb 100644 (file)
@@ -52,15 +52,15 @@ geometrical objects.
 
 There is also a number of more specific algorithms:
 <ul>
+<li>\subpage prism_3d_algo_page "for meshing prismatic shapes"</li>
 <li>\subpage projection_algos_page "for meshing by projection of another mesh"</li>
 <li>\subpage import_algos_page "for meshing by importing elements from another mesh"</li>
 <li>\subpage radial_prism_algo_page "for meshing geometrical objects with cavities"</li>
-<li>\subpage segments_around_vertex_algo_page "for defining the local size of elements around a certain node"</li>
-<li>\subpage prism_3d_algo_page "for meshing prismatic shapes"</li>
 <li>\subpage radial_quadrangle_1D2D_algo_page "for meshing special 2d faces (circles and part of circles)"</li>
 <li>\subpage use_existing_page "Use Edges to be Created Manually" and 
 \ref use_existing_page "Use Faces to be Created Manually" algorithms can be
 used to create a 1D or a 2D mesh in a python script.</li>
+<li>\subpage segments_around_vertex_algo_page "for defining the local size of elements around a certain node"</li>
 </ul>
 
 \ref constructing_meshes_page "Constructing meshes" page describes in
index 232d4f524b006770d80f347e7900bf98699d3e74..5d26cae6c0f05ce1aa1e6dcd4e2f9dc631137c0a 100644 (file)
@@ -9,6 +9,7 @@
   <li> \ref preview_anchor "Previewing the mesh" (optional)</li>
   <li> \ref submesh_order_anchor "Changing sub-mesh priority" (optional)</li>
   <li> \ref compute_anchor "Computing the mesh"</li>
+  <li> \ref edit_anchor "Editing the mesh" (optional)</li>
 </ul>
 
 \anchor create_mesh_anchor
@@ -357,8 +358,29 @@ computation reporting. There are the following possibilities: always
 show the information box, show only if an error occurs or never. 
 By default, the information box is always shown after mesh computation operation.
 
-<br><br>
-
-
+<p><p>
+\anchor edit_anchor
+<h2>Editing the mesh</h2>
+
+It is possible to \ref modifying_meshes_page "edit the mesh" of
+lower dimension before generation of mesh of higher dimension.
+
+For example you can generate 2D mesh, modify it using e.g. 
+\ref pattern_mapping_page, and then generate 3D mesh basing on the
+modified 2D mesh. The workflow is following:
+- Define 1D and 2D meshing algorithms.
+- Compute the mesh. 2D mesh is generated.
+- Apply \ref pattern_mapping_page.
+- Define 3D meshing algorithms without modifying 1D and 2D algorithms
+and hypotheses.
+- Compute the mesh. 3D mesh is generated.
+
+\note Nodes and elements added \ref adding_nodes_and_elements_page
+"manually" can't be used in this workflow because the manually created
+entities are not attached to any geometry and thus (usually) can't be
+found by a mesher paving some geometry.
+
+<b>See Also</b> a sample TUI Script demonstrates the possibility of 
+\ref tui_editing_while_meshing "Intermediate edition while meshing"
 
 */
index 1bd0cc919b62f0b86a3c5ffee38822b0fa856ee8..f09ab21d47d03e7477f85efc37c810c38226a16b 100755 (executable)
@@ -51,6 +51,11 @@ or vice versa.</li>
 <li>\subpage cut_mesh_by_plane_page "Cut a tetrahedron mesh by a plane".</li>
 </ul>
 
+It is possible to \ref edit_anchor "modify the mesh" of lower
+dimension before generation of mesh of higher dimension.
+
+<p><br></p>
+
 \note It is possible to use the variables defined in the SALOME \b NoteBook
  to specify the numerical parameters used for modification of any object.
 
index ef7f8ba66a704be2910dfba199764ad1a3e4665f..969b9fc5e066a39b75acea62020432974a51864c 100644 (file)
@@ -14,7 +14,7 @@ The smp file contains 4 sections:
 
 -# The first line indicates the total number of pattern nodes (N).
 -# The next N lines describe nodes coordinates. Each line contains 2
-node coordinates for a 2D pattern or 3 node cordinates for a 3D pattern.
+node coordinates for a 2D pattern or 3 node coordinates for a 3D pattern.
 Note, that node coordinates of a 3D pattern can be defined only by relative values in range [0;1].
 -# The key-points line contains the indices of the nodes to be mapped on geometrical
 vertices (for a 2D pattern only). Index n refers to the node described 
@@ -89,7 +89,7 @@ An example of a simple 3D pattern smp file:
 
 <br><h2>Application of pattern mapping</h2>
 
-<em>To apply pattern mapping to a geometrical object:</em>
+<em>To apply pattern mapping to a geometrical object or mesh elements:</em>
 
 From the \b Modification menu choose the <b>Pattern Mapping</b> item or click 
 <em>"Pattern mapping"</em> button in the toolbar.
@@ -113,16 +113,17 @@ created manually or generated automatically from an existing mesh or submesh.</l
      boundaries of the pattern must also be equal to the number of vertices
      on internal boundaries of the face;</li>
 <li> \b Vertex to which the first key-point should be mapped;</li>
+</ul>
 Alternatively, it is possible to select <b>Refine selected mesh elements</b> 
-checkbox and apply the pattern to
+check-box and apply the pattern to <ul>
 <li> <b>Mesh Face</b> instead of a geometric Face</li>
 <li> and select \b Node instead of vertex.</li>
-
-Additionally it is possible to:
-<li> <b>Reverse the order of key-points</b> By default, the vertices of
-     a face are ordered counterclockwise.<li>
+</ul>
+Additionally it is possible to: <ul>
+<li> <b>Reverse the order of key-points</b>. By default, the vertices of
+     a face are ordered counterclockwise.</li>
 <li> Enable to <b> Create polygons near boundary</b> </li>
-<li> and <b>Create polyhedrons near boundary</b><li>  
+<li> and <b>Create polyhedrons near boundary</b></li>
 </ul>
 
 \n For a <b>3D pattern</b>
@@ -133,21 +134,27 @@ In this dialog you should specify:
 <ul>
 <li> \b Pattern, which can be loaded from .smp pattern file previously
 created manually or generated automatically from an existing mesh or submesh.</li>
-   <li> A 3D block (Solid) object;</li>
-   <li> Two vertices that specify the order of nodes in the resulting mesh.</li>
+<li> A 3D block (Solid) object.</li>
+<li> Two vertices that specify the order of nodes in the resulting
+  mesh.</li>
+</ul>
 Alternatively, it is possible to select <b>Refine selected mesh elements</b> 
 checkbox and apply the pattern to
+<ul>
 <li> One or several <b>Mesh volumes</b> instead of a geometric 3D
 object</li>
 <li> and select two /b Nodes instead of vertices.</li> 
+</ul>
 Additionally it is possible to:
+<ul>
 <li> Enable to <b> Create polygons near boundary</b> </li>
-<li> and <b>Create polyhedrons near boundary</b><li>
+<li> and <b>Create polyhedrons near boundary</b></li>
 </ul>
 
-\n Automatic Generation 
+<br>
+<h3> Automatic Generation </h3>
 
-To generate a pattern automatically from an existing mesh or submesh,
+To generate a pattern automatically from an existing mesh or sub-mesh,
 click \b New button.
 
 The following dialog box will appear:
index f1b12e4c41882ede90fe4b6e91c70341ba05fd58..984616457c7ff2b93f5bde86d206e9f2f0962671 100644 (file)
 <h2>Change priority of submeshes in Mesh</h2>
 \tui_script{creating_meshes_ex03.py}
 
+<br>
+\anchor tui_editing_while_meshing
+<h2>Intermediate edition while meshing</h2>
+\tui_script{a3DmeshOnModified2Dmesh.py}
+
 <br>
 \anchor tui_editing_mesh
 <h2>Editing a mesh</h2>
index dcb5d7b1a36351088d8139e80118e655925a5c71..6311da713a53cdff7413d67c76f886b75066d35a 100644 (file)
@@ -4251,11 +4251,11 @@ void BelongToGeom::init()
     myIsSubshape = IsSubShape(aMap, myShape);
   }
 
-  if (!myIsSubshape)
+  //if (!myIsSubshape) // to be always ready to check an element not bound to geometry
   {
     myElementsOnShapePtr.reset(new ElementsOnShape());
     myElementsOnShapePtr->SetTolerance(myTolerance);
-    myElementsOnShapePtr->SetAllNodes(true); // belong, while false means "lays on"
+    myElementsOnShapePtr->SetAllNodes(true); // "belong", while false means "lays on"
     myElementsOnShapePtr->SetMesh(myMeshDS);
     myElementsOnShapePtr->SetShape(myShape, myType);
   }
@@ -4296,36 +4296,43 @@ bool BelongToGeom::IsSatisfy (long theId)
   {
     if( const SMDS_MeshNode* aNode = myMeshDS->FindNode( theId ) )
     {
+      if ( aNode->getshapeId() < 1 )
+        return myElementsOnShapePtr->IsSatisfy(theId);
+
       const SMDS_PositionPtr& aPosition = aNode->GetPosition();
       SMDS_TypeOfPosition aTypeOfPosition = aPosition->GetTypeOfPosition();
       switch( aTypeOfPosition )
       {
-      case SMDS_TOP_VERTEX : return IsContains( myMeshDS,myShape,aNode,TopAbs_VERTEX );
-      case SMDS_TOP_EDGE   : return IsContains( myMeshDS,myShape,aNode,TopAbs_EDGE );
-      case SMDS_TOP_FACE   : return IsContains( myMeshDS,myShape,aNode,TopAbs_FACE );
-      case SMDS_TOP_3DSPACE: return IsContains( myMeshDS,myShape,aNode,TopAbs_SHELL );
+      case SMDS_TOP_VERTEX : return ( IsContains( myMeshDS,myShape,aNode,TopAbs_VERTEX ));
+      case SMDS_TOP_EDGE   : return ( IsContains( myMeshDS,myShape,aNode,TopAbs_EDGE ));
+      case SMDS_TOP_FACE   : return ( IsContains( myMeshDS,myShape,aNode,TopAbs_FACE ));
+      case SMDS_TOP_3DSPACE: return ( IsContains( myMeshDS,myShape,aNode,TopAbs_SOLID ) ||
+                                      IsContains( myMeshDS,myShape,aNode,TopAbs_SHELL ));
       }
     }
   }
   else
   {
-    if( const SMDS_MeshElement* anElem = myMeshDS->FindElement( theId ) )
+    if ( const SMDS_MeshElement* anElem = myMeshDS->FindElement( theId ))
     {
+      if ( anElem->getshapeId() < 1 )
+        return myElementsOnShapePtr->IsSatisfy(theId);
+
       if( myType == SMDSAbs_All )
       {
-        return IsContains( myMeshDS,myShape,anElem,TopAbs_EDGE ) ||
-               IsContains( myMeshDS,myShape,anElem,TopAbs_FACE ) ||
-               IsContains( myMeshDS,myShape,anElem,TopAbs_SHELL )||
-               IsContains( myMeshDS,myShape,anElem,TopAbs_SOLID );
+        return IsContains( myMeshDS,myShape,anElem,TopAbs_EDGE ) ||
+                 IsContains( myMeshDS,myShape,anElem,TopAbs_FACE ) ||
+                 IsContains( myMeshDS,myShape,anElem,TopAbs_SOLID )||
+                 IsContains( myMeshDS,myShape,anElem,TopAbs_SHELL ));
       }
       else if( myType == anElem->GetType() )
       {
         switch( myType )
         {
-        case SMDSAbs_Edge  : return IsContains( myMeshDS,myShape,anElem,TopAbs_EDGE );
-        case SMDSAbs_Face  : return IsContains( myMeshDS,myShape,anElem,TopAbs_FACE );
-        case SMDSAbs_Volume: return IsContains( myMeshDS,myShape,anElem,TopAbs_SHELL )||
-                                    IsContains( myMeshDS,myShape,anElem,TopAbs_SOLID );
+        case SMDSAbs_Edge  : return ( IsContains( myMeshDS,myShape,anElem,TopAbs_EDGE ));
+        case SMDSAbs_Face  : return ( IsContains( myMeshDS,myShape,anElem,TopAbs_FACE ));
+        case SMDSAbs_Volume: return ( IsContains( myMeshDS,myShape,anElem,TopAbs_SOLID )||
+                                      IsContains( myMeshDS,myShape,anElem,TopAbs_SHELL ));
         }
       }
     }
index 88b1819445cb5ace027fd75faba4cb4bead9bcc2..5453a6a1b758608d71a50e4b0eca7221532432ff 100644 (file)
@@ -82,20 +82,25 @@ namespace SMESH
     return GEOM::GEOM_Object::_nil();
   }
 
-  GEOM::GEOM_Object_ptr GetGeom (_PTR(SObject) theSO)
+  GEOM::GEOM_Object_var GetGeom (_PTR(SObject) theSO)
   {
+    GEOM::GEOM_Object_var aMeshShape;
     if (!theSO)
-      return GEOM::GEOM_Object::_nil();
+      return aMeshShape;
+
+    CORBA::Object_var obj = _CAST( SObject,theSO )->GetObject();
+    aMeshShape = GEOM::GEOM_Object::_narrow( obj );
+    if ( !aMeshShape->_is_nil() )
+      return aMeshShape;
 
     _PTR(Study) aStudy = SMESH::GetActiveStudyDocument();
     if (!aStudy)
-      return GEOM::GEOM_Object::_nil();
+      return aMeshShape;
 
     _PTR(ChildIterator) anIter (aStudy->NewChildIterator(theSO));
     for ( ; anIter->More(); anIter->Next()) {
       _PTR(SObject) aSObject = anIter->Value();
       _PTR(SObject) aRefSOClient;
-      GEOM::GEOM_Object_var aMeshShape;
 
       if (aSObject->ReferencedObject(aRefSOClient)) {
         SALOMEDS_SObject* aRefSO = _CAST(SObject,aRefSOClient);
@@ -104,11 +109,10 @@ namespace SMESH
         SALOMEDS_SObject* aSO = _CAST(SObject,aSObject);
         aMeshShape = GEOM::GEOM_Object::_narrow(aSO->GetObject());
       }
-
-      if (!aMeshShape->_is_nil())
-        return aMeshShape._retn();
+      if ( !aMeshShape->_is_nil() )
+        return aMeshShape;
     }
-    return GEOM::GEOM_Object::_nil();
+    return aMeshShape;
   }
 
   SMESHGUI_EXPORT char* GetGeomName( _PTR(SObject) smeshSO )
index f9cdeafd40acc430f0a58f0b3cc8d5d48ee8492c..0aa10bd7a9bb493a9a431f867eefffab9dca2190 100644 (file)
@@ -47,7 +47,7 @@ namespace SMESH
 
   SMESHGUI_EXPORT GEOM::GEOM_Object_var GetShapeOnMeshOrSubMesh( _PTR(SObject), bool* isMesh=0 );
 
-  SMESHGUI_EXPORT GEOM::GEOM_Object_ptr GetGeom( _PTR(SObject) );
+  SMESHGUI_EXPORT GEOM::GEOM_Object_var GetGeom( _PTR(SObject) );
 
   SMESHGUI_EXPORT char* GetGeomName( _PTR(SObject) smeshSO );
 
index dc499bd7381fe9e7db3feb31fc0cad754090bebe..fa29da180e0efe8ed73680d34caa0e020d9e08f2 100644 (file)
@@ -511,10 +511,14 @@ namespace SMESH
 
     return SMESH::SMESH_Hypothesis::_nil();
   }
+
   bool IsApplicable(const QString&        aHypType,
                     GEOM::GEOM_Object_ptr theGeomObject,
                     const bool            toCheckAll)
   {
+    if ( getenv("NO_LIMIT_ALGO_BY_SHAPE")) // allow a workaround for a case if
+      return true;                         // IsApplicable() returns false due to a bug
+
     HypothesisData* aHypData = GetHypothesisData(aHypType);
     QString aServLib = aHypData->ServerLibName;
     return SMESHGUI::GetSMESHGen()->IsApplicable( aHypType.toLatin1().data(),
index 151328f9bc524b40fbc381f5287ba8a3076ae156..5f7f27ace455a3b5c2c4893fa5b58bab326576bb 100644 (file)
@@ -247,8 +247,9 @@ void SMESHGUI_MeshOp::startOperation()
     myDlg->activateObject( myIsMesh ? SMESHGUI_MeshDlg::Geom : SMESHGUI_MeshDlg::Mesh );
   }
   else
+  {
     myDlg->activateObject( SMESHGUI_MeshDlg::Obj );
-
+  }
   myDlg->setCurrentTab( SMESH::DIM_3D );
 
   QStringList TypeMeshList;
@@ -2614,11 +2615,11 @@ void SMESHGUI_MeshOp::setFilteredAlgoData( const int theTabIndex, const int theI
 
   bool toCheckIsApplicableToAll = !myIsMesh;
   GEOM::GEOM_Object_var aGeomVar;
-  QString anEntry = myDlg->selectedObject( SMESHGUI_MeshDlg::Geom );
+  QString anEntry =
+    myDlg->selectedObject( myToCreate ? SMESHGUI_MeshDlg::Geom : SMESHGUI_MeshDlg::Obj );
   if ( _PTR(SObject) so = studyDS()->FindObjectID( anEntry.toLatin1().data() ))
   {
-    CORBA::Object_var obj = _CAST( SObject,so )->GetObject();
-    aGeomVar = GEOM::GEOM_Object::_narrow( obj );
+    aGeomVar = SMESH::GetGeom( so );
     if ( !aGeomVar->_is_nil() && toCheckIsApplicableToAll )
       toCheckIsApplicableToAll = ( aGeomVar->GetType() == GEOM_GROUP );
   }
index a9990e5e7e7aaf475b764d56ac9e684aa8f92205..4d1321497a6d08eb6ad1fe25b8c4b43227dc3647 100644 (file)
@@ -4280,16 +4280,17 @@ int StdMeshers_Quadrangle_2D::getCorners(const TopoDS_Face&          theFace,
     vMap.Add( (*a2v).second );
 
   // check if there are possible variations in choosing corners
-  bool isThereVariants = false;
+  bool haveVariants = false;
   if ( vertexByAngle.size() > nbCorners )
   {
     double lostAngle = a2v->first;
     double lastAngle = ( --a2v, a2v->first );
-    isThereVariants  = ( lostAngle * 1.1 >= lastAngle );
+    haveVariants  = ( lostAngle * 1.1 >= lastAngle );
   }
 
+  const double angleTol = 5.* M_PI/180;
   myCheckOri = ( vertexByAngle.size() > nbCorners ||
-                 vertexByAngle.begin()->first < 5.* M_PI/180 );
+                 vertexByAngle.begin()->first < angleTol );
 
   // make theWire begin from a corner vertex or triaVertex
   if ( nbCorners == 3 )
@@ -4306,9 +4307,10 @@ int StdMeshers_Quadrangle_2D::getCorners(const TopoDS_Face&          theFace,
   vector< double >      angles;
   vector< TopoDS_Edge > edgeVec;
   vector< int >         cornerInd, nbSeg;
-  angles.reserve( vertexByAngle.size() );
+  int nbSegTot = 0;
+  angles .reserve( vertexByAngle.size() );
   edgeVec.reserve( vertexByAngle.size() );
-  nbSeg.reserve( vertexByAngle.size() );
+  nbSeg  .reserve( vertexByAngle.size() );
   cornerInd.reserve( nbCorners );
   for ( edge = theWire.begin(); edge != theWire.end(); ++edge )
   {
@@ -4321,105 +4323,219 @@ int StdMeshers_Quadrangle_2D::getCorners(const TopoDS_Face&          theFace,
       theVertices.push_back( v );
       cornerInd.push_back( angles.size() );
     }
-    angles.push_back( angleByVertex.IsBound( v ) ? angleByVertex( v ) : -M_PI );
+    angles .push_back( angleByVertex.IsBound( v ) ? angleByVertex( v ) : -M_PI );
     edgeVec.push_back( *edge );
-    if ( theConsiderMesh && isThereVariants )
+    if ( theConsiderMesh && haveVariants )
     {
       if ( SMESHDS_SubMesh* sm = helper.GetMeshDS()->MeshElements( *edge ))
         nbSeg.push_back( sm->NbNodes() + 1 );
       else
         nbSeg.push_back( 0 );
+      nbSegTot += nbSeg.back();
     }
   }
 
-  // refine the result vector - make sides elual by length if
+  // refine the result vector - make sides equal by length if
   // there are several equal angles
-  if ( isThereVariants )
+  if ( haveVariants )
   {
     if ( nbCorners == 3 )
       angles[0] = 2 * M_PI; // not to move the base triangle VERTEX
 
-    set< int > refinedCorners;
+    // here we refer to VERTEX'es and EDGEs by indices in angles and edgeVec vectors
+    typedef int TGeoIndex;
+
+    // for each vertex find a vertex till which there are nbSegHalf segments
+    const int nbSegHalf = ( nbSegTot % 2 || nbCorners == 3 ) ? 0 : nbSegTot / 2;
+    vector< TGeoIndex > halfDivider( angles.size(), -1 );
+    int nbHalfDividers = 0;
+    if ( nbSegHalf )
+    {
+      // get min angle of corners
+      double minAngle = 10.;
+      for ( size_t iC = 0; iC < cornerInd.size(); ++iC )
+        minAngle = Min( minAngle, angles[ cornerInd[ iC ]]);
+
+      // find halfDivider's
+      for ( TGeoIndex iV1 = 0; iV1 < TGeoIndex( angles.size() ); ++iV1 )
+      {
+        int nbSegs = 0;
+        TGeoIndex iV2 = iV1;
+        do {
+          nbSegs += nbSeg[ iV2 ];
+          iV2 = helper.WrapIndex( iV2 + 1, nbSeg.size() );
+        } while ( nbSegs < nbSegHalf );
+
+        if ( nbSegs == nbSegHalf &&
+             angles[ iV1 ] + angleTol >= minAngle &&
+             angles[ iV2 ] + angleTol >= minAngle )
+        {
+          halfDivider[ iV1 ] = iV2;
+          ++nbHalfDividers;
+        }
+      }
+    }
+
+    set< TGeoIndex > refinedCorners, treatedCorners;
     for ( size_t iC = 0; iC < cornerInd.size(); ++iC )
     {
-      int iV = cornerInd[iC];
-      if ( !refinedCorners.insert( iV ).second )
+      TGeoIndex iV = cornerInd[iC];
+      if ( !treatedCorners.insert( iV ).second )
         continue;
-      list< int > equalVertices;
-      equalVertices.push_back( iV );
+      list< TGeoIndex > equVerts; // inds of vertices that can become corners
+      equVerts.push_back( iV );
       int nbC[2] = { 0, 0 };
       // find equal angles backward and forward from the iV-th corner vertex
       for ( int isFwd = 0; isFwd < 2; ++isFwd )
       {
-        int     dV = isFwd ? +1 : -1;
-        int iCNext = helper.WrapIndex( iC + dV, cornerInd.size() );
-        int iVNext = helper.WrapIndex( iV + dV, angles.size() );
+        int           dV = isFwd ? +1 : -1;
+        int       iCNext = helper.WrapIndex( iC + dV, cornerInd.size() );
+        TGeoIndex iVNext = helper.WrapIndex( iV + dV, angles.size() );
         while ( iVNext != iV )
         {
-          bool equal = Abs( angles[iV] - angles[iVNext] ) < 0.1 * angles[iV];
+          bool equal = Abs( angles[iV] - angles[iVNext] ) < angleTol;
           if ( equal )
-            equalVertices.insert( isFwd ? equalVertices.end() : equalVertices.begin(), iVNext );
+            equVerts.insert( isFwd ? equVerts.end() : equVerts.begin(), iVNext );
           if ( iVNext == cornerInd[ iCNext ])
           {
             if ( !equal )
+            {
+              if ( angles[iV] < angles[iVNext] )
+                refinedCorners.insert( iVNext );
               break;
+            }
             nbC[ isFwd ]++;
-            refinedCorners.insert( cornerInd[ iCNext ] );
+            treatedCorners.insert( cornerInd[ iCNext ] );
             iCNext = helper.WrapIndex( iCNext + dV, cornerInd.size() );
           }
           iVNext = helper.WrapIndex( iVNext + dV, angles.size() );
         }
+        if ( iVNext == iV )
+          break; // all angles equal
       }
+
+      const bool allCornersSame = ( nbC[0] == 3 );
+      if ( allCornersSame && nbHalfDividers > 0 )
+      {
+        // select two halfDivider's as corners
+        TGeoIndex hd1, hd2 = -1;
+        int iC2;
+        for ( iC2 = 0; iC2 < cornerInd.size() && hd2 < 0; ++iC2 )
+        {
+          hd1 = cornerInd[ iC2 ];
+          hd2 = halfDivider[ hd1 ];
+          if ( std::find( equVerts.begin(), equVerts.end(), hd2 ) == equVerts.end() )
+            hd2 = -1; // hd2-th vertex can't become a corner
+          else
+            break;
+        }
+        if ( hd2 >= 0 )
+        {
+          angles[ hd1 ] = 2 * M_PI; // make hd1-th vertex no more "equal"
+          angles[ hd2 ] = 2 * M_PI;
+          refinedCorners.insert( hd1 );
+          refinedCorners.insert( hd2 );
+          treatedCorners = refinedCorners;
+          // update cornerInd
+          equVerts.push_front( equVerts.back() );
+          equVerts.push_back( equVerts.front() );
+          list< TGeoIndex >::iterator hdPos =
+            std::find( equVerts.begin(), equVerts.end(), hd2 );
+          if ( hdPos == equVerts.end() ) break;
+          cornerInd[ helper.WrapIndex( iC2 + 0, cornerInd.size()) ] = hd1;
+          cornerInd[ helper.WrapIndex( iC2 + 1, cornerInd.size()) ] = *( --hdPos );
+          cornerInd[ helper.WrapIndex( iC2 + 2, cornerInd.size()) ] = hd2;
+          cornerInd[ helper.WrapIndex( iC2 + 3, cornerInd.size()) ] = *( ++hdPos, ++hdPos );
+
+          theVertices[ 0 ] = helper.IthVertex( 0, edgeVec[ cornerInd[0] ]);
+          theVertices[ 1 ] = helper.IthVertex( 0, edgeVec[ cornerInd[1] ]);
+          theVertices[ 2 ] = helper.IthVertex( 0, edgeVec[ cornerInd[2] ]);
+          theVertices[ 3 ] = helper.IthVertex( 0, edgeVec[ cornerInd[3] ]);
+          iC = -1;
+          continue;
+        }
+      }
+
       // move corners to make sides equal by length
-      int nbEqualV  = equalVertices.size();
+      int nbEqualV  = equVerts.size();
       int nbExcessV = nbEqualV - ( 1 + nbC[0] + nbC[1] );
-      if ( nbExcessV > 0 )
+      if ( nbExcessV > 0 ) // there is nbExcessV vertices that can become corners
       {
-        // calculate normalized length of each side enclosed between neighbor equalVertices
-        vector< double > curLengths;
+        // calculate normalized length of each "side" enclosed between neighbor equVerts
+        vector< double > accuLength;
         double totalLen = 0;
-        vector< int > evVec( equalVertices.begin(), equalVertices.end() );
-        int   iEV = 0;
-        int    iE = cornerInd[ helper.WrapIndex( iC - nbC[0] - 1, cornerInd.size() )];
-        int iEEnd = cornerInd[ helper.WrapIndex( iC + nbC[1] + 1, cornerInd.size() )];
-        while ( curLengths.size() < nbEqualV + 1 )
+        vector< TGeoIndex > evVec( equVerts.begin(), equVerts.end() );
+        int          iEV = 0;
+        TGeoIndex    iE = cornerInd[ helper.WrapIndex( iC - nbC[0] - 1, cornerInd.size() )];
+        TGeoIndex iEEnd = cornerInd[ helper.WrapIndex( iC + nbC[1] + 1, cornerInd.size() )];
+        while ( accuLength.size() < nbEqualV + int( !allCornersSame ) )
         {
-          curLengths.push_back( totalLen );
+          // accumulate length of edges before iEV-th equal vertex
+          accuLength.push_back( totalLen );
           do {
-            curLengths.back() += SMESH_Algo::EdgeLength( edgeVec[ iE ]);
+            accuLength.back() += SMESH_Algo::EdgeLength( edgeVec[ iE ]);
             iE = helper.WrapIndex( iE + 1, edgeVec.size());
-            if ( iEV < evVec.size() && iE == evVec[ iEV++ ] )
-              break;
+            if ( iEV < evVec.size() && iE == evVec[ iEV ] ) {
+              iEV++;
+              break; // equal vertex reached
+            }
           }
           while( iE != iEEnd );
-          totalLen = curLengths.back();
+          totalLen = accuLength.back();
         }
-        curLengths.resize( equalVertices.size() );
-        for ( size_t iS = 0; iS < curLengths.size(); ++iS )
-          curLengths[ iS ] /= totalLen;
+        accuLength.resize( equVerts.size() );
+        for ( size_t iS = 0; iS < accuLength.size(); ++iS )
+          accuLength[ iS ] /= totalLen;
 
-        // find equalVertices most close to the ideal sub-division of all sides
+        // find equVerts most close to the ideal sub-division of all sides
         int iBestEV = 0;
         int iCorner = helper.WrapIndex( iC - nbC[0], cornerInd.size() );
-        int nbSides = 2 + nbC[0] + nbC[1];
+        int nbSides = Min( nbCorners, 2 + nbC[0] + nbC[1] );
         for ( int iS = 1; iS < nbSides; ++iS, ++iBestEV )
         {
           double idealLen = iS / double( nbSides );
-          double d, bestDist = 1.;
-          for ( iEV = iBestEV; iEV < curLengths.size(); ++iEV )
-            if (( d = Abs( idealLen - curLengths[ iEV ])) < bestDist )
+          double d, bestDist = 2.;
+          for ( iEV = iBestEV; iEV < accuLength.size(); ++iEV )
+          {
+            d = Abs( idealLen - accuLength[ iEV ]);
+
+            // take into account presence of a coresponding halfDivider
+            const double cornerWgt = 0.5  / nbSides;
+            const double vertexWgt = 0.25 / nbSides;
+            TGeoIndex hd = halfDivider[ evVec[ iEV ]];
+            if ( hd < 0 )
+              d += vertexWgt;
+            else if( refinedCorners.count( hd ))
+              d -= cornerWgt;
+            else
+              d -= vertexWgt;
+
+            // choose vertex with the best d
+            if ( d < bestDist )
             {
               bestDist = d;
               iBestEV  = iEV;
             }
+          }
           if ( iBestEV > iS-1 + nbExcessV )
             iBestEV = iS-1 + nbExcessV;
           theVertices[ iCorner ] = helper.IthVertex( 0, edgeVec[ evVec[ iBestEV ]]);
+          refinedCorners.insert( evVec[ iBestEV ]);
           iCorner = helper.WrapIndex( iCorner + 1, cornerInd.size() );
         }
+
+      } // if ( nbExcessV > 0 )
+      else
+      {
+        refinedCorners.insert( cornerInd[ iC ]);
       }
-    }
-  }
+    } // loop on cornerInd
+
+    // make theWire begin from the cornerInd[0]-th EDGE
+    while ( !theWire.front().IsSame( edgeVec[ cornerInd[0] ]))
+      theWire.splice( theWire.begin(), theWire, --theWire.end() );
+
+  } // if ( haveVariants )
 
   return nbCorners;
 }