From 36f660ae42e061693f9d7ec7b4f117643c31a9fe Mon Sep 17 00:00:00 2001 From: eap Date: Thu, 6 Nov 2014 20:11:51 +0300 Subject: [PATCH 1/3] 52568: Quadrangle (Mapping) differently meshes equal L-shaped faces. Take into account number of segments when selecting corners among multiple vertices --- src/StdMeshers/StdMeshers_Quadrangle_2D.cxx | 210 +++++++++++++++----- 1 file changed, 163 insertions(+), 47 deletions(-) diff --git a/src/StdMeshers/StdMeshers_Quadrangle_2D.cxx b/src/StdMeshers/StdMeshers_Quadrangle_2D.cxx index a9990e5e7..4d1321497 100644 --- a/src/StdMeshers/StdMeshers_Quadrangle_2D.cxx +++ b/src/StdMeshers/StdMeshers_Quadrangle_2D.cxx @@ -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 } - // move corners to make sides equal by length - int nbEqualV = equalVertices.size(); - int nbExcessV = nbEqualV - ( 1 + nbC[0] + nbC[1] ); - if ( nbExcessV > 0 ) + + const bool allCornersSame = ( nbC[0] == 3 ); + if ( allCornersSame && nbHalfDividers > 0 ) { - // calculate normalized length of each side enclosed between neighbor equalVertices - vector< double > curLengths; - 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 ) + // select two halfDivider's as corners + TGeoIndex hd1, hd2 = -1; + int iC2; + for ( iC2 = 0; iC2 < cornerInd.size() && hd2 < 0; ++iC2 ) { - curLengths.push_back( totalLen ); + 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 = equVerts.size(); + int nbExcessV = nbEqualV - ( 1 + nbC[0] + nbC[1] ); + if ( nbExcessV > 0 ) // there is nbExcessV vertices that can become corners + { + // calculate normalized length of each "side" enclosed between neighbor equVerts + vector< double > accuLength; + double totalLen = 0; + 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 ) ) + { + // 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; } From 131ded7390efc5172a382e6731b15d24b531963e Mon Sep 17 00:00:00 2001 From: eap Date: Fri, 7 Nov 2014 16:51:28 +0300 Subject: [PATCH 2/3] More info --- doc/salome/examples/CMakeLists.txt | 14 +++-- .../examples/a3DmeshOnModified2Dmesh.py | 62 +++++++++++++++++++ doc/salome/examples/prism_3d_algo.py | 11 +++- doc/salome/gui/SMESH/input/about_meshes.doc | 50 ++------------- .../gui/SMESH/input/basic_meshing_algos.doc | 4 +- .../gui/SMESH/input/constructing_meshes.doc | 24 ++++++- .../gui/SMESH/input/modifying_meshes.doc | 5 ++ .../gui/SMESH/input/pattern_mapping.doc | 33 ++++++---- .../gui/SMESH/input/tui_creating_meshes.doc | 5 ++ 9 files changed, 139 insertions(+), 69 deletions(-) create mode 100644 doc/salome/examples/a3DmeshOnModified2Dmesh.py diff --git a/doc/salome/examples/CMakeLists.txt b/doc/salome/examples/CMakeLists.txt index 227764998..7aa063689 100644 --- a/doc/salome/examples/CMakeLists.txt +++ b/doc/salome/examples/CMakeLists.txt @@ -17,8 +17,10 @@ # 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 index 000000000..7fcdcaca8 --- /dev/null +++ b/doc/salome/examples/a3DmeshOnModified2Dmesh.py @@ -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) diff --git a/doc/salome/examples/prism_3d_algo.py b/doc/salome/examples/prism_3d_algo.py index df18d0fcb..7be0a29d3 100644 --- a/doc/salome/examples/prism_3d_algo.py +++ b/doc/salome/examples/prism_3d_algo.py @@ -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) diff --git a/doc/salome/gui/SMESH/input/about_meshes.doc b/doc/salome/gui/SMESH/input/about_meshes.doc index 870e5c182..65201ac64 100644 --- a/doc/salome/gui/SMESH/input/about_meshes.doc +++ b/doc/salome/gui/SMESH/input/about_meshes.doc @@ -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. -

Connections

- -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: - - - -You can notice that there are two types of connections: \b inverse and -\b direct connections. - -

Inverse connections

- -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. - -

Direct connections

- -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. - */ diff --git a/doc/salome/gui/SMESH/input/basic_meshing_algos.doc b/doc/salome/gui/SMESH/input/basic_meshing_algos.doc index ee632b282..977b505db 100644 --- a/doc/salome/gui/SMESH/input/basic_meshing_algos.doc +++ b/doc/salome/gui/SMESH/input/basic_meshing_algos.doc @@ -52,15 +52,15 @@ geometrical objects. There is also a number of more specific algorithms: \ref constructing_meshes_page "Constructing meshes" page describes in diff --git a/doc/salome/gui/SMESH/input/constructing_meshes.doc b/doc/salome/gui/SMESH/input/constructing_meshes.doc index 232d4f524..5d26cae6c 100644 --- a/doc/salome/gui/SMESH/input/constructing_meshes.doc +++ b/doc/salome/gui/SMESH/input/constructing_meshes.doc @@ -9,6 +9,7 @@
  • \ref preview_anchor "Previewing the mesh" (optional)
  • \ref submesh_order_anchor "Changing sub-mesh priority" (optional)
  • \ref compute_anchor "Computing the mesh"
  • +
  • \ref edit_anchor "Editing the mesh" (optional)
  • \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. -

    +

    +\anchor edit_anchor +

    Editing the mesh

    +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. + +See Also a sample TUI Script demonstrates the possibility of +\ref tui_editing_while_meshing "Intermediate edition while meshing" */ diff --git a/doc/salome/gui/SMESH/input/modifying_meshes.doc b/doc/salome/gui/SMESH/input/modifying_meshes.doc index 1bd0cc919..f09ab21d4 100755 --- a/doc/salome/gui/SMESH/input/modifying_meshes.doc +++ b/doc/salome/gui/SMESH/input/modifying_meshes.doc @@ -51,6 +51,11 @@ or vice versa.
  • \subpage cut_mesh_by_plane_page "Cut a tetrahedron mesh by a plane".
  • +It is possible to \ref edit_anchor "modify the mesh" of lower +dimension before generation of mesh of higher dimension. + +


    + \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. diff --git a/doc/salome/gui/SMESH/input/pattern_mapping.doc b/doc/salome/gui/SMESH/input/pattern_mapping.doc index ef7f8ba66..969b9fc5e 100644 --- a/doc/salome/gui/SMESH/input/pattern_mapping.doc +++ b/doc/salome/gui/SMESH/input/pattern_mapping.doc @@ -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:

    Application of pattern mapping

    -To apply pattern mapping to a geometrical object: +To apply pattern mapping to a geometrical object or mesh elements: From the \b Modification menu choose the Pattern Mapping item or click "Pattern mapping" button in the toolbar. @@ -113,16 +113,17 @@ created manually or generated automatically from an existing mesh or submesh.
  • \b Vertex to which the first key-point should be mapped;
  • + Alternatively, it is possible to select Refine selected mesh elements -checkbox and apply the pattern to +check-box and apply the pattern to +Additionally it is possible to: \n For a 3D pattern @@ -133,21 +134,27 @@ In this dialog you should specify: Alternatively, it is possible to select Refine selected mesh elements checkbox and apply the pattern to + Additionally it is possible to: + -\n Automatic Generation +
    +

    Automatic Generation

    -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: diff --git a/doc/salome/gui/SMESH/input/tui_creating_meshes.doc b/doc/salome/gui/SMESH/input/tui_creating_meshes.doc index f1b12e4c4..984616457 100644 --- a/doc/salome/gui/SMESH/input/tui_creating_meshes.doc +++ b/doc/salome/gui/SMESH/input/tui_creating_meshes.doc @@ -18,6 +18,11 @@

    Change priority of submeshes in Mesh

    \tui_script{creating_meshes_ex03.py} +
    +\anchor tui_editing_while_meshing +

    Intermediate edition while meshing

    +\tui_script{a3DmeshOnModified2Dmesh.py} +
    \anchor tui_editing_mesh

    Editing a mesh

    From d6b7cb735f99cfc9d68fd3a44c0d4c456017f384 Mon Sep 17 00:00:00 2001 From: eap Date: Fri, 7 Nov 2014 18:07:13 +0300 Subject: [PATCH 3/3] Mesh edit dlg bug: algos are not filtered by shape at mesh edition More bug: "Belong to geom" filter does not find nodes bound to SOLID --- src/Controls/SMESH_Controls.cxx | 37 ++++++++++++++--------- src/SMESHGUI/SMESHGUI_GEOMGenUtils.cxx | 20 +++++++----- src/SMESHGUI/SMESHGUI_GEOMGenUtils.h | 2 +- src/SMESHGUI/SMESHGUI_HypothesesUtils.cxx | 4 +++ src/SMESHGUI/SMESHGUI_MeshOp.cxx | 9 +++--- 5 files changed, 44 insertions(+), 28 deletions(-) diff --git a/src/Controls/SMESH_Controls.cxx b/src/Controls/SMESH_Controls.cxx index dcb5d7b1a..6311da713 100644 --- a/src/Controls/SMESH_Controls.cxx +++ b/src/Controls/SMESH_Controls.cxx @@ -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 )); } } } diff --git a/src/SMESHGUI/SMESHGUI_GEOMGenUtils.cxx b/src/SMESHGUI/SMESHGUI_GEOMGenUtils.cxx index 88b181944..5453a6a1b 100644 --- a/src/SMESHGUI/SMESHGUI_GEOMGenUtils.cxx +++ b/src/SMESHGUI/SMESHGUI_GEOMGenUtils.cxx @@ -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 ) diff --git a/src/SMESHGUI/SMESHGUI_GEOMGenUtils.h b/src/SMESHGUI/SMESHGUI_GEOMGenUtils.h index f9cdeafd4..0aa10bd7a 100644 --- a/src/SMESHGUI/SMESHGUI_GEOMGenUtils.h +++ b/src/SMESHGUI/SMESHGUI_GEOMGenUtils.h @@ -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 ); diff --git a/src/SMESHGUI/SMESHGUI_HypothesesUtils.cxx b/src/SMESHGUI/SMESHGUI_HypothesesUtils.cxx index dc499bd73..fa29da180 100644 --- a/src/SMESHGUI/SMESHGUI_HypothesesUtils.cxx +++ b/src/SMESHGUI/SMESHGUI_HypothesesUtils.cxx @@ -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(), diff --git a/src/SMESHGUI/SMESHGUI_MeshOp.cxx b/src/SMESHGUI/SMESHGUI_MeshOp.cxx index 151328f9b..5f7f27ace 100644 --- a/src/SMESHGUI/SMESHGUI_MeshOp.cxx +++ b/src/SMESHGUI/SMESHGUI_MeshOp.cxx @@ -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 ); }