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:
-
-
-- A node bounds edges, faces and volumes
-- An edge bounds faces, and volumes
-- A face bounds volumes
-- A volume is bounded by faces, edges and nodes
-- A face is bounded by edges, and nodes
-- An edge is bounded by nodes
-
-
-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:
+- \subpage prism_3d_algo_page "for meshing prismatic shapes"
- \subpage projection_algos_page "for meshing by projection of another mesh"
- \subpage import_algos_page "for meshing by importing elements from another mesh"
- \subpage radial_prism_algo_page "for meshing geometrical objects with cavities"
-- \subpage segments_around_vertex_algo_page "for defining the local size of elements around a certain node"
-- \subpage prism_3d_algo_page "for meshing prismatic shapes"
- \subpage radial_quadrangle_1D2D_algo_page "for meshing special 2d faces (circles and part of circles)"
- \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.
+- \subpage segments_around_vertex_algo_page "for defining the local size of elements around a certain node"
\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
- Mesh Face instead of a geometric Face
- and select \b Node instead of vertex.
-
-Additionally it is possible to:
-- Reverse the order of key-points By default, the vertices of
- a face are ordered counterclockwise.
-
+
+Additionally it is possible to:
+- Reverse the order of key-points. By default, the vertices of
+ a face are ordered counterclockwise.
- Enable to Create polygons near boundary
-- and Create polyhedrons near boundary
-
+
- and Create polyhedrons near boundary
\n For a 3D pattern
@@ -133,21 +134,27 @@ In this dialog you should specify:
- \b Pattern, which can be loaded from .smp pattern file previously
created manually or generated automatically from an existing mesh or submesh.
- - A 3D block (Solid) object;
- - Two vertices that specify the order of nodes in the resulting mesh.
+- A 3D block (Solid) object.
+- Two vertices that specify the order of nodes in the resulting
+ mesh.
+
Alternatively, it is possible to select Refine selected mesh elements
checkbox and apply the pattern to
+
- One or several Mesh volumes instead of a geometric 3D
object
- and select two /b Nodes instead of vertices.
+
Additionally it is possible to:
+
- Enable to Create polygons near boundary
-- and Create polyhedrons near boundary
-
+
- and Create polyhedrons near boundary
-\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
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 );
}
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;
}