22483: EDF 2772 SMESH: Define several 3D viscous layer hypotheses on the same Geometry

This commit is contained in:
eap 2014-08-21 15:15:12 +04:00
parent ce9a69a9b8
commit ae32dcd34f
47 changed files with 1517 additions and 611 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 32 KiB

BIN
doc/salome/gui/SMESH/images/createmesh-inv2.png Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 34 KiB

BIN
doc/salome/gui/SMESH/images/createmesh-inv3.png Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 33 KiB

BIN
doc/salome/gui/SMESH/images/image10.jpg Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -183,28 +183,48 @@ You can set the type of distribution for this hypothesis in the
<br><b>Equidistant Distribution</b> - all segments will have the same <br><b>Equidistant Distribution</b> - all segments will have the same
length, you define only the <b>Number of Segments</b>. length, you define only the <b>Number of Segments</b>.
<br><b>Scale Distribution</b> - length of segments gradually changes depending on the <b>Scale Factor</b>, which is a ratio of the first segment length to the last segment length. <br><b>Scale Distribution</b> - length of segments gradually changes
depending on the <b>Scale Factor</b>, which is a ratio of the first
segment length to the last segment length.<br>
Length of segments changes in geometric progression with the common
ratio (A) depending on the <b>Scale Factor</b> (S) and <b>Number of
Segments</b> (N) as follows: <code> A = S**(1/(N-1))</code>. For an
edge of length L, length of the first segment is
<code>L * (1 - A)/(1 - A**N)</code>.
\image html a-nbsegments2.png \image html a-nbsegments2.png
<br><b>Distribution with Table Density</b> - you input a number of
pairs <b>t - F(t)</b>, where \b t ranges from 0 to 1, and the module computes the
formula, which will rule the change of length of segments and shows
the curve in the plot. You can select the <b>Conversion mode</b> from
\b Exponent and <b>Cut negative</b>.
\image html distributionwithtabledensity.png
<br><b>Distribution with Analytic Density</b> - you input the formula, <br><b>Distribution with Analytic Density</b> - you input the formula,
which will rule the change of length of segments and the module shows which will rule the change of length of segments and the module shows
the curve in the plot. in the plot the density function curve in red and the node
distribution as blue crosses.
\image html distributionwithanalyticdensity.png \image html distributionwithanalyticdensity.png
<br>
\anchor analyticdensity_anchor
The node distribution is computed so that to have the density function
integral on the range between two nodes equal for all segments.
\image html analyticdensity.png
<br><b>Distribution with Table Density</b> - you input a number of
pairs <b>t - F(t)</b>, where \b t ranges from 0 to 1, and the module computes the
formula, which will rule the change of length of segments and shows
in the plot the density function curve in red and the node
distribution as blue crosses. The node distribution is computed the
same way as for
\ref analyticdensity_anchor "Distribution with Analytic Density". You
can select the <b>Conversion mode</b> from\b Exponent and <b>Cut
negative</b>.
\image html distributionwithtabledensity.png
<b>See Also</b> a sample TUI Script of a <b>See Also</b> a sample TUI Script of a
\ref tui_deflection_1d "Defining Number of Segments" hypothesis \ref tui_deflection_1d "Defining Number of Segments" hypothesis
operation. operation.
<br> <br>
\anchor start_and_end_length_anchor \anchor start_and_end_length_anchor
<h2>Start and End Length hypothesis</h2> <h2>Start and End Length hypothesis</h2>

View File

@ -93,7 +93,7 @@ computations.
and edges, just hide the mesh to avoid this. To avoid a long wait when a and edges, just hide the mesh to avoid this. To avoid a long wait when a
geometry with many faces (or edges) is displayed, the number of faces geometry with many faces (or edges) is displayed, the number of faces
(edges) shown at a time is limited by the value of "Sub-shapes (edges) shown at a time is limited by the value of "Sub-shapes
preview chunk size" preference (in Preferences/Mesh/General tab).<br> preview chunk size" preference (in Preferences/Mesh/General tab).
If faces/edges without layers are specified, the element layers are If faces/edges without layers are specified, the element layers are
not constructed on geometrical faces shared by several solids in 3D not constructed on geometrical faces shared by several solids in 3D
@ -106,6 +106,15 @@ computations.
possibly being internal faces/edges within the whole model. possibly being internal faces/edges within the whole model.
\image html viscous_layers_on_submesh.png 2D viscous layers constructed on boundary edges of a sub-mesh on a disk face. \image html viscous_layers_on_submesh.png 2D viscous layers constructed on boundary edges of a sub-mesh on a disk face.
If you use \b several hypotheses to define viscous layers on faces of
one solid, keep in mind the following. Each hypothesis defines a set
of faces with viscous layers (even if you specify faces without
layers). The sets of faces with viscous layers defined by several
hypotheses should not intersect, else the module won't add an
hypothesis that is incompatible with another one. <br>
Also you can't define different number of layers on adjacent faces
of a solid.<br>
This logic is also valid for the 2D hypothesis.
</li> </li>
</ul> </ul>

View File

@ -29,10 +29,14 @@
\image html createmesh-inv.png \image html createmesh-inv.png
<br> <br>
</li> </li>
<li>Select <b>Mesh Type</b> in the corresponding list from <b>Any, Hexahedral, Tetrahedral, Triangular </b> and \b Quadrilateral (there can be less items for lower dimensions). <li> To filter off irrelevant meshing algorithms, you can
select <b>Mesh Type</b> in the corresponding list from <b>Any,
Selection of a mesh type hides any algorithms that are not able to create elements of this type.</li> Hexahedral, Tetrahedral, Triangular </b> and \b Quadrilateral (there
can be less items for the geometry of lower dimensions).
Selection of a mesh type hides all meshing algorithms that can not
generate elements of this type.</li>
<li>Apply \subpage basic_meshing_algos_page "meshing algorithms" and <li>Apply \subpage basic_meshing_algos_page "meshing algorithms" and
\subpage about_hypo_page "hypotheses" which will be used to compute \subpage about_hypo_page "hypotheses" which will be used to compute
this mesh. this mesh.
@ -42,7 +46,8 @@
dimension of the CAD model (geometry) the algorithms listed on dimension of the CAD model (geometry) the algorithms listed on
this page affect and the maximal dimension of elements the algorithms this page affect and the maximal dimension of elements the algorithms
generate. For example, \b 3D page lists the algorithms that affect generate. For example, \b 3D page lists the algorithms that affect
3D geometrical objects (solids). 3D geometrical objects (solids) and generate 3D mesh elements
(tetrahedra, hexahedra etc.)
\note \note
- Some page(s) can be disabled if the source geometrical - Some page(s) can be disabled if the source geometrical
@ -65,7 +70,6 @@
it is "Mesh_1". Then select the geometrical object you wish to it is "Mesh_1". Then select the geometrical object you wish to
mesh in the Object Browser and click "Select" button near \b Geometry mesh in the Object Browser and click "Select" button near \b Geometry
field (if the name of the object has not yet appeared in \b Geometry field). field (if the name of the object has not yet appeared in \b Geometry field).
<center> <center>
\image html image120.png \image html image120.png
<em>"Select" button</em> <em>"Select" button</em>
@ -74,21 +78,22 @@
Now you can define 3D Algorithm and 3D Hypotheses, which will be Now you can define 3D Algorithm and 3D Hypotheses, which will be
applied to the solids of your geometrical object. Click the <em>"Add applied to the solids of your geometrical object. Click the <em>"Add
Hypothesis"</em> button to add a hypothesis. Hypothesis"</em> button to add a hypothesis.
<center> <center>
\image html image121.png \image html image121.png
<em>"Add Hypothesis" button</em> <em>"Add Hypothesis" button</em>
</center> </center>
Click the <em>"Plus"</em> button to enable adding more additional hypotheses.
Click the <em>"Edit Hypothesis"</em> button to change the values for the Click the <em>"Edit Hypothesis"</em> button to change the values for the
current hypothesis. current hypothesis.
<center> <center>
\image html image122.png \image html image122.png
<em>"Edit Hypothesis" button</em> <em>"Edit Hypothesis" button</em>
</center> </center>
Most 2D and 3D algorithms can work without hypotheses using default meshing parameters. Some algorithms do not require any hypotheses. After selection of an algorithm "Hypothesis" field of Most 2D and 3D algorithms can work without hypotheses using
default meshing parameters. Some algorithms do not require any
hypotheses. After selection of an algorithm "Hypothesis" field of
the dialog can contain: the dialog can contain:
<ul> <ul>
<li> <em>\<Default\></em> if the algorithm can work using default <li> <em>\<Default\></em> if the algorithm can work using default
@ -109,7 +114,10 @@
that any object has edges, even if their existence is not that any object has edges, even if their existence is not
apparent, for example, a sphere has 4 edges). Note that the apparent, for example, a sphere has 4 edges). Note that the
choice of hypotheses and lower dimension algorithms depends on choice of hypotheses and lower dimension algorithms depends on
the higher dimension algorithm. the higher dimension algorithm.
If you wish you can select different algorithms and/or hypotheses
for meshing some parts of your CAD model by \ref constructing_submeshes_page.
Some algorithms generate mesh of several dimensions, while others Some algorithms generate mesh of several dimensions, while others
produce mesh of only one dimension. In the latter case there must produce mesh of only one dimension. In the latter case there must
@ -128,8 +136,9 @@
It contains: It contains:
<ul> <ul>
<li>a mesh name (<em>Mesh_mechanic</em>);
<li>a reference to the geometrical object on the basis of <li>a reference to the geometrical object on the basis of
which the mesh has been constructed;</li> which the mesh has been constructed (\a mechanic);</li>
<li><b>Applied hypotheses</b> folder containing the references <li><b>Applied hypotheses</b> folder containing the references
to the hypotheses applied at the construction of the mesh;</li> to the hypotheses applied at the construction of the mesh;</li>
<li><b>Applied algorithms</b> folder containing the references <li><b>Applied algorithms</b> folder containing the references

View File

@ -2,7 +2,7 @@
\page constructing_submeshes_page Constructing sub-meshes \page constructing_submeshes_page Constructing sub-meshes
Sub-mesh is a mesh on a geometrical sub-object created with algorithms Sub-mesh is a mesh on a geometrical sub-object created with meshing algorithms
and/or hypotheses other than the algorithms and hypotheses assigned to and/or hypotheses other than the algorithms and hypotheses assigned to
the parent mesh on the parent geometrical object. the parent mesh on the parent geometrical object.
@ -52,7 +52,7 @@ The following dialog box will appear:
\par \par
It allows to define the \b Name, the parent \b Mesh and the \b It allows to define the \b Name, the parent \b Mesh and the \b
Geometry (e.g. a face if the parent mesh has been built on box) of the Geometry (e.g. a face if the parent mesh has been built on box) of the
sub-mesh. You can define algorithms and hypotheses in the same way as sub-mesh. You can select meshing algorithms and hypotheses in the same way as
in \ref constructing_meshes_page "Create mesh" menu. in \ref constructing_meshes_page "Create mesh" menu.
\par \par
@ -93,11 +93,13 @@ displayed as follows:
\par \par
It contains: It contains:
<ul> <ul>
<li>a reference to the geometrical object on the basis of which the sub-mesh has been constructed;</li> <li>a sub-mesh name (\a SubMeshFace1)
<li>a reference to the geometrical object on the basis of which the
sub-mesh has been constructed (<em>Cylindrical Face_1</em>);</li>
<li><b>Applied hypotheses</b> folder containing the references to the <li><b>Applied hypotheses</b> folder containing the references to the
hypotheses applied to the construction of the sub-mesh;</li> hypotheses selected at the construction of the sub-mesh;</li>
<li><b>Applied algorithms</b> folder containing the references to the <li><b>Applied algorithms</b> folder containing the references to the
algorithms applied to the construction of the sub-mesh.</li> algorithms selected at the construction of the sub-mesh.</li>
</ul> </ul>
<br><b>See Also</b> a sample TUI Script of a <br><b>See Also</b> a sample TUI Script of a

View File

@ -40,31 +40,26 @@ the following ways:
mesh. For this, turn on the <b>Select All</b> check box. In this mode mesh. For this, turn on the <b>Select All</b> check box. In this mode
all controls, which allow selecting the entities in other ways, are all controls, which allow selecting the entities in other ways, are
disabled.</li> disabled.</li>
<li>By applying the Filter. The <b>Set filter</b> button allows to
define the filter for selection of the elements for your group. See more
about filters on the
\ref selection_filter_library_page "Selection filter library" page.<br>
If the <b>Enable manual edition</b> check box is turned off, the
filter entirely defines the group contents. In this mode, the filter is
applied to all elements of the mesh. If there are no entities
corresponding to the filter, the \b Apply button is disabled.<br>
If the <b>Enable manual edition</b> check box is turned on, the defined
filter can be used to for selection of entities for the group.</li>
<li>By choosing entities manually with the mouse in the 3D Viewer. For <li>By choosing entities manually with the mouse in the 3D Viewer. For
this, turn on the <b>Enable manual edition</b> check box. You can this, turn on the <b>Enable manual edition</b> check box. You can
click on an element in the 3D viewer and it will be highlighted. After click on an element in the 3D viewer and it will be highlighted. After
that click the \b Add button and the ID of this element will be that click the \b Add button and the ID of this element will be
added to the list.</li> added to the list.<br>
<li>By adding entities from either a submesh or an existing The <b>Set filter</b> button allows to define the filter for
selection of the elements for your group. See more about filters on
the \ref selection_filter_library_page "Selection filter library"
page.</li>
<li>By adding entities from either a sub-mesh or an existing
group. For this, turn on the <b>Enable manual edition</b> check group. For this, turn on the <b>Enable manual edition</b> check
box. <b>Select from</b> set of fields allows to select a submesh or box. <b>Select from</b> set of fields allows to select a sub-mesh or
a group of the appropriate type.</li> a group of the appropriate type.</li>
</ul> </ul>
In the <b>manual edition</b> mode you can In the <b>manual edition</b> mode you can
<ul> <ul>
<li>click the \b Remove button to remove the selected elements from the list</li> <li>click the \b Remove button to remove the selected list items from
the list.</li>
<li>click the <b>Sort List</b> button to sort the list of IDs of <li>click the <b>Sort List</b> button to sort the list of IDs of
mesh elements.</li> mesh elements.</li>
</ul> </ul>
\image html creategroup.png \image html creategroup.png

View File

@ -2,11 +2,11 @@
\page editing_meshes_page Editing Meshes \page editing_meshes_page Editing Meshes
\n After you have created a mesh or submesh with definite applied \n After you have created a mesh or sub-mesh with definite applied
hypotheses and algorithms you can edit your mesh by \b assigning new meshing algorithms and hypotheses you can edit your mesh by \b assigning other
hypotheses and algorithms or \b unassigning the applied hypotheses and algorithms and/or hypotheses or \b unassigning the applied hypotheses and
algorithms. The editing proceeds in the same way as <b>Mesh algorithms. The editing proceeds in the same way as
Creation</b>. \ref create_mesh_anchor "Mesh Creation".
\image html createmesh-inv3.png \image html createmesh-inv3.png
@ -26,4 +26,4 @@ changes if we apply different algorithms to it.
<br><b>See Also</b> a sample TUI Script of an <br><b>See Also</b> a sample TUI Script of an
\ref tui_editing_mesh "Edit Mesh" operation. \ref tui_editing_mesh "Edit Mesh" operation.
*/ */

View File

@ -88,19 +88,19 @@ module SMESH
typedef sequence<log_block> log_array; typedef sequence<log_block> log_array;
struct PointStruct { double x; struct PointStruct { double x;
double y; double y;
double z; } ; double z; } ;
typedef sequence<PointStruct> nodes_array; typedef sequence<PointStruct> nodes_array;
struct DirStruct { PointStruct PS ; } ; // analog to OCCT gp_Vec struct DirStruct { PointStruct PS ; } ; // analog to OCCT gp_Vec
struct AxisStruct { double x; struct AxisStruct { double x;
double y; double y;
double z; double z;
double vx; double vx;
double vy; double vy;
double vz; } ; double vz; } ;
/*! /*!
* Node location on a shape * Node location on a shape
*/ */
@ -215,7 +215,8 @@ module SMESH
HYP_BAD_DIM, // bad dimension HYP_BAD_DIM, // bad dimension
HYP_BAD_SUBSHAPE, // shape is neither the main one, nor its sub-shape, nor a group HYP_BAD_SUBSHAPE, // shape is neither the main one, nor its sub-shape, nor a group
HYP_BAD_GEOMETRY, // geometry mismatches algorithm's expectation HYP_BAD_GEOMETRY, // geometry mismatches algorithm's expectation
HYP_NEED_SHAPE // algorithm can work on shape only HYP_NEED_SHAPE, // algorithm can work on shape only
HYP_INCOMPAT_HYPS // several additional hypotheses are incompatible one with other
}; };
/*! /*!
@ -389,7 +390,7 @@ module SMESH
* Create a group * Create a group
*/ */
SMESH_Group CreateGroup( in ElementType elem_type, SMESH_Group CreateGroup( in ElementType elem_type,
in string name ) in string name )
raises (SALOME::SALOME_Exception); raises (SALOME::SALOME_Exception);
/*! /*!
@ -508,31 +509,29 @@ module SMESH
raises (SALOME::SALOME_Exception); raises (SALOME::SALOME_Exception);
/*! /*!
* Add hypothesis to the mesh, under a particular Sub-shape * Add hypothesis to the mesh, under a particular sub-shape
* (or the main shape itself) * (or the main shape itself)
* The Add method is only used to prepare the build of the mesh and store * This method is only used to prepare the build of the mesh and store
* the algorithms and associated parameters. * the algorithms and associated parameters.
* Actual job of mesh the shape is done by MESH_Gen. * Actual job of meshing the shape is done by SMESH_Gen::Compute()
* @params * @params
* - aSubShape : sub-shape obtained by a shape explode in GEOM * - aSubObject : sub-shape obtained by a shape explode in GEOM
* (or main shape) * (or main shape)
* - anHyp : hypothesis object * - anHyp : an hypothesis object
* @return * @return
* - OK if the hypothesis is compatible with the sub-shape * - An enum item explaining what's up
* (and all previous hypothesis on the sub-shape) * - anErrorText: an optional textual description of a problem (if any)
* - NOK if the hypothesis is not compatible with the sub-shape
* (or one previous hypothesis on the sub-shape)
* raises exception if hypothesis has not been created
*/ */
Hypothesis_Status AddHypothesis(in GEOM::GEOM_Object aSubObject, Hypothesis_Status AddHypothesis(in GEOM::GEOM_Object aSubObject,
in SMESH_Hypothesis anHyp) in SMESH_Hypothesis anHyp,
out string anErrorText)
raises (SALOME::SALOME_Exception); raises (SALOME::SALOME_Exception);
/*! /*!
* Remove an hypothesis previouly added with AddHypothesis. * Remove an hypothesis previouly added with AddHypothesis.
*/ */
Hypothesis_Status RemoveHypothesis(in GEOM::GEOM_Object aSubObject, Hypothesis_Status RemoveHypothesis(in GEOM::GEOM_Object aSubObject,
in SMESH_Hypothesis anHyp) in SMESH_Hypothesis anHyp)
raises (SALOME::SALOME_Exception); raises (SALOME::SALOME_Exception);
/*! /*!

View File

@ -44,6 +44,8 @@ SET(SMESH_RESOURCES_FILES
mesh_hypo_segment.png mesh_hypo_segment.png
mesh_hypo_volume.png mesh_hypo_volume.png
mesh_hypo_edit.png mesh_hypo_edit.png
mesh_plus.png
mesh_minus.png
mesh_info.png mesh_info.png
advanced_mesh_info.png advanced_mesh_info.png
standard_mesh_info.png standard_mesh_info.png

BIN
resources/mesh_minus.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 529 B

BIN
resources/mesh_plus.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 598 B

View File

@ -138,6 +138,8 @@ class SMESH_EXPORT SMESH_Algo : public SMESH_Hypothesis
* \param aShape - the shape * \param aShape - the shape
* \param aStatus - check result * \param aStatus - check result
* \retval bool - true if hypothesis is well defined * \retval bool - true if hypothesis is well defined
*
* Textual description of a problem can be stored in _comment field.
*/ */
virtual bool CheckHypothesis(SMESH_Mesh& aMesh, virtual bool CheckHypothesis(SMESH_Mesh& aMesh,
const TopoDS_Shape& aShape, const TopoDS_Shape& aShape,

View File

@ -63,7 +63,8 @@ public:
HYP_BAD_DIM, // bad dimension HYP_BAD_DIM, // bad dimension
HYP_BAD_SUBSHAPE, // shape is neither the main one, nor its sub-shape, nor a group HYP_BAD_SUBSHAPE, // shape is neither the main one, nor its sub-shape, nor a group
HYP_BAD_GEOMETRY, // shape geometry mismatches algorithm's expectation HYP_BAD_GEOMETRY, // shape geometry mismatches algorithm's expectation
HYP_NEED_SHAPE // algorithm can work on shape only HYP_NEED_SHAPE, // algorithm can work on shape only
HYP_INCOMPAT_HYPS // several additional hypotheses are incompatible one with other
}; };
static bool IsStatusFatal(Hypothesis_Status theStatus) static bool IsStatusFatal(Hypothesis_Status theStatus)
{ return theStatus >= HYP_UNKNOWN_FATAL; } { return theStatus >= HYP_UNKNOWN_FATAL; }

View File

@ -601,12 +601,16 @@ SMESH_ComputeErrorPtr SMESH_Mesh::GMFToMesh(const char* theFileName,
//============================================================================= //=============================================================================
SMESH_Hypothesis::Hypothesis_Status SMESH_Hypothesis::Hypothesis_Status
SMESH_Mesh::AddHypothesis(const TopoDS_Shape & aSubShape, SMESH_Mesh::AddHypothesis(const TopoDS_Shape & aSubShape,
int anHypId ) throw(SALOME_Exception) int anHypId,
std::string* anError ) throw(SALOME_Exception)
{ {
Unexpect aCatch(SalomeException); Unexpect aCatch(SalomeException);
if(MYDEBUG) MESSAGE("SMESH_Mesh::AddHypothesis"); if(MYDEBUG) MESSAGE("SMESH_Mesh::AddHypothesis");
if ( anError )
anError->clear();
SMESH_subMesh *subMesh = GetSubMesh(aSubShape); SMESH_subMesh *subMesh = GetSubMesh(aSubShape);
if ( !subMesh || !subMesh->GetId()) if ( !subMesh || !subMesh->GetId())
return SMESH_Hypothesis::HYP_BAD_SUBSHAPE; return SMESH_Hypothesis::HYP_BAD_SUBSHAPE;
@ -631,23 +635,36 @@ SMESH_Hypothesis::Hypothesis_Status
} }
} }
// shape // shape
bool isAlgo = ( !anHyp->GetType() == SMESHDS_Hypothesis::PARAM_ALGO ); bool isAlgo = ( anHyp->GetType() != SMESHDS_Hypothesis::PARAM_ALGO );
int event = isAlgo ? SMESH_subMesh::ADD_ALGO : SMESH_subMesh::ADD_HYP; int event = isAlgo ? SMESH_subMesh::ADD_ALGO : SMESH_subMesh::ADD_HYP;
SMESH_Hypothesis::Hypothesis_Status ret = subMesh->AlgoStateEngine(event, anHyp); SMESH_Hypothesis::Hypothesis_Status ret = subMesh->AlgoStateEngine(event, anHyp);
if ( anError && SMESH_Hypothesis::IsStatusFatal(ret) && subMesh->GetComputeError() )
*anError = subMesh->GetComputeError()->myComment;
// sub-shapes // sub-shapes
if (!SMESH_Hypothesis::IsStatusFatal(ret) && if ( !SMESH_Hypothesis::IsStatusFatal(ret) &&
anHyp->GetDim() <= SMESH_Gen::GetShapeDim(aSubShape)) // is added on father anHyp->GetDim() <= SMESH_Gen::GetShapeDim(aSubShape)) // is added on father
{ {
event = isAlgo ? SMESH_subMesh::ADD_FATHER_ALGO : SMESH_subMesh::ADD_FATHER_HYP; event = isAlgo ? SMESH_subMesh::ADD_FATHER_ALGO : SMESH_subMesh::ADD_FATHER_HYP;
SMESH_Hypothesis::Hypothesis_Status ret2 = SMESH_Hypothesis::Hypothesis_Status ret2 =
subMesh->SubMeshesAlgoStateEngine(event, anHyp); subMesh->SubMeshesAlgoStateEngine(event, anHyp, /*exitOnFatal=*/true);
if (ret2 > ret) if (ret2 > ret)
{
ret = ret2; ret = ret2;
if ( SMESH_Hypothesis::IsStatusFatal( ret ))
{
if ( anError && subMesh->GetComputeError() )
*anError = subMesh->GetComputeError()->myComment;
// remove anHyp
event = isAlgo ? SMESH_subMesh::REMOVE_ALGO : SMESH_subMesh::REMOVE_HYP;
subMesh->AlgoStateEngine(event, anHyp);
}
}
// check concurent hypotheses on ancestors // check concurent hypotheses on ancestors
if (ret < SMESH_Hypothesis::HYP_CONCURENT && !isGlobalHyp ) if (ret < SMESH_Hypothesis::HYP_CONCURENT && !isGlobalHyp )
@ -892,16 +909,19 @@ int SMESH_Mesh::GetHypotheses(const SMESH_subMesh * aSubMesh,
const TopoDS_Shape & aSubShape = aSubMesh->GetSubShape(); const TopoDS_Shape & aSubShape = aSubMesh->GetSubShape();
const list<const SMESHDS_Hypothesis*>& hypList = _myMeshDS->GetHypothesis(aSubShape); const list<const SMESHDS_Hypothesis*>& hypList = _myMeshDS->GetHypothesis(aSubShape);
for ( hyp = hypList.begin(); hyp != hypList.end(); hyp++ ) for ( hyp = hypList.begin(); hyp != hypList.end(); hyp++ )
if ( aFilter.IsOk (cSMESH_Hyp( *hyp ), aSubShape) && {
( cSMESH_Hyp(*hyp)->IsAuxiliary() || !mainHypFound ) && const SMESH_Hypothesis* h = cSMESH_Hyp( *hyp );
hypTypes.insert( (*hyp)->GetName() ).second ) if (( aFilter.IsOk( h, aSubShape )) &&
( h->IsAuxiliary() || !mainHypFound ) &&
( h->IsAuxiliary() || hypTypes.insert( h->GetName() ).second ))
{ {
aHypList.push_back( *hyp ); aHypList.push_back( *hyp );
nbHyps++; nbHyps++;
if ( !cSMESH_Hyp(*hyp)->IsAuxiliary() ) if ( !h->IsAuxiliary() )
mainHypFound = true; mainHypFound = true;
if ( assignedTo ) assignedTo->push_back( aSubShape ); if ( assignedTo ) assignedTo->push_back( aSubShape );
} }
}
} }
// get hypos from ancestors of aSubShape // get hypos from ancestors of aSubShape
@ -918,16 +938,19 @@ int SMESH_Mesh::GetHypotheses(const SMESH_subMesh * aSubMesh,
const TopoDS_Shape& curSh = (*smIt)->GetSubShape(); const TopoDS_Shape& curSh = (*smIt)->GetSubShape();
const list<const SMESHDS_Hypothesis*>& hypList = _myMeshDS->GetHypothesis(curSh); const list<const SMESHDS_Hypothesis*>& hypList = _myMeshDS->GetHypothesis(curSh);
for ( hyp = hypList.begin(); hyp != hypList.end(); hyp++ ) for ( hyp = hypList.begin(); hyp != hypList.end(); hyp++ )
if (( aFilter.IsOk( cSMESH_Hyp( *hyp ), curSh )) && {
( cSMESH_Hyp(*hyp)->IsAuxiliary() || !mainHypFound ) && const SMESH_Hypothesis* h = cSMESH_Hyp( *hyp );
( hypTypes.insert( (*hyp)->GetName() ).second )) if (( aFilter.IsOk( h, curSh )) &&
( h->IsAuxiliary() || !mainHypFound ) &&
( h->IsAuxiliary() || hypTypes.insert( h->GetName() ).second ))
{ {
aHypList.push_back( *hyp ); aHypList.push_back( *hyp );
nbHyps++; nbHyps++;
if ( !cSMESH_Hyp(*hyp)->IsAuxiliary() ) if ( !h->IsAuxiliary() )
mainHypFound = true; mainHypFound = true;
if ( assignedTo ) assignedTo->push_back( curSh ); if ( assignedTo ) assignedTo->push_back( curSh );
} }
}
} }
} }
return nbHyps; return nbHyps;

View File

@ -126,7 +126,7 @@ public:
bool theMakeRequiredGroups = true ); bool theMakeRequiredGroups = true );
SMESH_Hypothesis::Hypothesis_Status SMESH_Hypothesis::Hypothesis_Status
AddHypothesis(const TopoDS_Shape & aSubShape, int anHypId) AddHypothesis(const TopoDS_Shape & aSubShape, int anHypId, std::string* error=0)
throw(SALOME_Exception); throw(SALOME_Exception);
SMESH_Hypothesis::Hypothesis_Status SMESH_Hypothesis::Hypothesis_Status

View File

@ -670,11 +670,17 @@ bool SMESH_subMesh::IsApplicableHypotesis(const SMESH_Hypothesis* theHypothesis,
return false; return false;
} }
//============================================================================= //================================================================================
/*! /*!
* * \brief Treats modification of hypotheses definition
* \param [in] event - what happens
* \param [in] anHyp - a hypothesis
* \return SMESH_Hypothesis::Hypothesis_Status - a treatment result.
*
* Optional description of a problematic situation (if any) can be retrieved
* via GetComputeError().
*/ */
//============================================================================= //================================================================================
SMESH_Hypothesis::Hypothesis_Status SMESH_Hypothesis::Hypothesis_Status
SMESH_subMesh::AlgoStateEngine(int event, SMESH_Hypothesis * anHyp) SMESH_subMesh::AlgoStateEngine(int event, SMESH_Hypothesis * anHyp)
@ -753,7 +759,7 @@ SMESH_Hypothesis::Hypothesis_Status
if ( ! CanAddHypothesis( anHyp )) // check dimension if ( ! CanAddHypothesis( anHyp )) // check dimension
return SMESH_Hypothesis::HYP_BAD_DIM; return SMESH_Hypothesis::HYP_BAD_DIM;
if ( /*!anHyp->IsAuxiliary() &&*/ getSimilarAttached( _subShape, anHyp ) ) if ( !anHyp->IsAuxiliary() && getSimilarAttached( _subShape, anHyp ) )
return SMESH_Hypothesis::HYP_ALREADY_EXIST; return SMESH_Hypothesis::HYP_ALREADY_EXIST;
if ( !meshDS->AddHypothesis(_subShape, anHyp)) if ( !meshDS->AddHypothesis(_subShape, anHyp))
@ -782,6 +788,9 @@ SMESH_Hypothesis::Hypothesis_Status
if (!isApplicableHyp) if (!isApplicableHyp)
return ret; // not applicable hypotheses do not change algo state return ret; // not applicable hypotheses do not change algo state
if (( algo = GetAlgo()))
algo->InitComputeError();
switch (_algoState) switch (_algoState)
{ {
@ -946,7 +955,7 @@ SMESH_Hypothesis::Hypothesis_Status
// ret should be fatal: anHyp was not added // ret should be fatal: anHyp was not added
ret = SMESH_Hypothesis::HYP_INCOMPATIBLE; ret = SMESH_Hypothesis::HYP_INCOMPATIBLE;
} }
else if (!_father->IsUsedHypothesis( anHyp, this )) else if (!_father->IsUsedHypothesis( anHyp, this ))
ret = SMESH_Hypothesis::HYP_INCOMPATIBLE; ret = SMESH_Hypothesis::HYP_INCOMPATIBLE;
if (SMESH_Hypothesis::IsStatusFatal( ret )) if (SMESH_Hypothesis::IsStatusFatal( ret ))
@ -1114,6 +1123,11 @@ SMESH_Hypothesis::Hypothesis_Status
} }
} }
if ( _algo ) { // get an error description set by _algo->CheckHypothesis()
_computeError = _algo->GetComputeError();
_algo->InitComputeError();
}
bool stateChange = ( _algoState != oldAlgoState ); bool stateChange = ( _algoState != oldAlgoState );
if ( stateChange && _algoState == HYP_OK ) // hyp becomes OK if ( stateChange && _algoState == HYP_OK ) // hyp becomes OK
@ -1141,8 +1155,8 @@ SMESH_Hypothesis::Hypothesis_Status
ComputeSubMeshStateEngine( CHECK_COMPUTE_STATE ); ComputeSubMeshStateEngine( CHECK_COMPUTE_STATE );
} }
if (stateChange || modifiedHyp) if ( stateChange || modifiedHyp )
ComputeStateEngine(MODIF_ALGO_STATE); ComputeStateEngine( MODIF_ALGO_STATE );
_realComputeCost = ( _algoState == HYP_OK ) ? computeCost() : 0; _realComputeCost = ( _algoState == HYP_OK ) ? computeCost() : 0;
@ -1213,14 +1227,24 @@ void SMESH_subMesh::setAlgoState(algo_state state)
_algoState = state; _algoState = state;
} }
//============================================================================= //================================================================================
/*! /*!
* \brief Send an event to sub-meshes
* \param [in] event - the event
* \param [in] anHyp - an hypothesis
* \param [in] exitOnFatal - to stop iteration on sub-meshes if a sub-mesh
* reports a fatal result
* \return SMESH_Hypothesis::Hypothesis_Status - the worst result
* *
* Optional description of a problematic situation (if any) can be retrieved
* via GetComputeError().
*/ */
//============================================================================= //================================================================================
SMESH_Hypothesis::Hypothesis_Status SMESH_Hypothesis::Hypothesis_Status
SMESH_subMesh::SubMeshesAlgoStateEngine(int event, SMESH_subMesh::SubMeshesAlgoStateEngine(int event,
SMESH_Hypothesis * anHyp) SMESH_Hypothesis * anHyp,
bool exitOnFatal)
{ {
SMESH_Hypothesis::Hypothesis_Status ret = SMESH_Hypothesis::HYP_OK; SMESH_Hypothesis::Hypothesis_Status ret = SMESH_Hypothesis::HYP_OK;
//EAP: a wire (dim==1) should notify edges (dim==1) //EAP: a wire (dim==1) should notify edges (dim==1)
@ -1229,10 +1253,16 @@ SMESH_Hypothesis::Hypothesis_Status
{ {
SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(false,false); SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(false,false);
while ( smIt->more() ) { while ( smIt->more() ) {
SMESH_Hypothesis::Hypothesis_Status ret2 = SMESH_subMesh* sm = smIt->next();
smIt->next()->AlgoStateEngine(event, anHyp); SMESH_Hypothesis::Hypothesis_Status ret2 = sm->AlgoStateEngine(event, anHyp);
if ( ret2 > ret ) if ( ret2 > ret )
{
ret = ret2; ret = ret2;
_computeError = sm->_computeError;
sm->_computeError.reset();
if ( exitOnFatal && SMESH_Hypothesis::IsStatusFatal( ret ))
break;
}
} }
} }
return ret; return ret;

View File

@ -218,10 +218,10 @@ public:
AlgoStateEngine(int event, SMESH_Hypothesis * anHyp); AlgoStateEngine(int event, SMESH_Hypothesis * anHyp);
SMESH_Hypothesis::Hypothesis_Status SMESH_Hypothesis::Hypothesis_Status
SubMeshesAlgoStateEngine(int event, SMESH_Hypothesis * anHyp); SubMeshesAlgoStateEngine(int event, SMESH_Hypothesis * anHyp, bool exitOnFatal=false);
algo_state GetAlgoState() const { return _algoState; } algo_state GetAlgoState() const { return _algoState; }
compute_state GetComputeState() const { return _computeState; }; compute_state GetComputeState() const { return _computeState; }
SMESH_ComputeErrorPtr& GetComputeError() { return _computeError; } SMESH_ComputeErrorPtr& GetComputeError() { return _computeError; }
void DumpAlgoState(bool isMain); void DumpAlgoState(bool isMain);

View File

@ -103,3 +103,14 @@ bool SMESHDS_Hypothesis::operator==(const SMESHDS_Hypothesis& other) const
((SMESHDS_Hypothesis*)&other)->SaveTo(otherSave); ((SMESHDS_Hypothesis*)&other)->SaveTo(otherSave);
return mySave.str() == otherSave.str(); return mySave.str() == otherSave.str();
} }
//================================================================================
/*!
* \brief Compare types of hypotheses
*/
//================================================================================
bool SMESHDS_Hypothesis::IsSameName( const SMESHDS_Hypothesis& other) const
{
return _name == other._name;
}

View File

@ -48,6 +48,7 @@ class SMESHDS_EXPORT SMESHDS_Hypothesis
virtual std::ostream & SaveTo(std::ostream & save)=0; virtual std::ostream & SaveTo(std::ostream & save)=0;
virtual std::istream & LoadFrom(std::istream & load)=0; virtual std::istream & LoadFrom(std::istream & load)=0;
bool IsSameName( const SMESHDS_Hypothesis& other) const;
virtual bool operator==(const SMESHDS_Hypothesis& other) const; virtual bool operator==(const SMESHDS_Hypothesis& other) const;
bool operator!=(const SMESHDS_Hypothesis& other) const { return !(*this==other); } bool operator!=(const SMESHDS_Hypothesis& other) const { return !(*this==other); }

View File

@ -91,21 +91,25 @@ namespace SMESH
QList<HypothesesSet*> myListOfHypothesesSets; QList<HypothesesSet*> myListOfHypothesesSets;
void processHypothesisStatus(const int theHypStatus, void processHypothesisStatus(const int theHypStatus,
SMESH::SMESH_Hypothesis_ptr theHyp, SMESH::SMESH_Hypothesis_ptr theHyp,
const bool theIsAddition) const bool theIsAddition,
const char* theError = 0)
{ {
if (theHypStatus > SMESH::HYP_OK) { if (theHypStatus > SMESH::HYP_OK) {
// get Hyp name // get Hyp name
QString aHypName ("NULL Hypothesis"); QString aHypName ("NULL Hypothesis");
if (!CORBA::is_nil(theHyp)) { if (!CORBA::is_nil(theHyp)) {
_PTR(SObject) Shyp = SMESH::FindSObject(theHyp); _PTR(SObject) Shyp = SMESH::FindSObject(theHyp);
if (Shyp) if (Shyp) {
// name in study // name in study
aHypName = Shyp->GetName().c_str(); aHypName = Shyp->GetName().c_str();
else }
else {
// label in xml file // label in xml file
aHypName = GetHypothesisData(theHyp->GetName())->Label; CORBA::String_var hypType = theHyp->GetName();
aHypName = GetHypothesisData( hypType.in() )->Label;
}
} }
// message // message
@ -116,12 +120,22 @@ namespace SMESH
else else
aMsg = (isFatal ? "SMESH_CANT_RM_HYP" : "SMESH_RM_HYP_WRN"); aMsg = (isFatal ? "SMESH_CANT_RM_HYP" : "SMESH_RM_HYP_WRN");
aMsg = QObject::tr(aMsg.toLatin1().data()).arg(aHypName) + aMsg = QObject::tr(aMsg.toLatin1().data()).arg(aHypName);
if ( theError && theError[0] )
{
aMsg += theError;
}
else
{
QObject::tr(QString("SMESH_HYP_%1").arg(theHypStatus).toLatin1().data()); QObject::tr(QString("SMESH_HYP_%1").arg(theHypStatus).toLatin1().data());
if ( theHypStatus == SMESH::HYP_HIDDEN_ALGO ) // PAL18501 if ( theHypStatus == SMESH::HYP_HIDDEN_ALGO ) { // PAL18501
aMsg = aMsg.arg( GetHypothesisData(theHyp->GetName())->Dim[0] ); CORBA::String_var hypType = theHyp->GetName();
if ( HypothesisData* hd = GetHypothesisData( hypType.in() ))
aMsg = aMsg.arg( hd->Dim[0] );
}
}
SUIT_MessageBox::warning(SMESHGUI::desktop(), SUIT_MessageBox::warning(SMESHGUI::desktop(),
QObject::tr("SMESH_WRN_WARNING"), QObject::tr("SMESH_WRN_WARNING"),
aMsg); aMsg);
@ -520,7 +534,8 @@ namespace SMESH
_PTR(SObject) SM = SMESH::FindSObject(aMesh); _PTR(SObject) SM = SMESH::FindSObject(aMesh);
GEOM::GEOM_Object_var aShapeObject = SMESH::GetShapeOnMeshOrSubMesh(SM); GEOM::GEOM_Object_var aShapeObject = SMESH::GetShapeOnMeshOrSubMesh(SM);
try { try {
res = aMesh->AddHypothesis(aShapeObject, aHyp); CORBA::String_var error;
res = aMesh->AddHypothesis(aShapeObject, aHyp, error.out());
if (res < SMESH::HYP_UNKNOWN_FATAL) { if (res < SMESH::HYP_UNKNOWN_FATAL) {
_PTR(SObject) aSH = SMESH::FindSObject(aHyp); _PTR(SObject) aSH = SMESH::FindSObject(aHyp);
if (SM && aSH) { if (SM && aSH) {
@ -529,7 +544,7 @@ namespace SMESH
} }
if (res > SMESH::HYP_OK) { if (res > SMESH::HYP_OK) {
wc.suspend(); wc.suspend();
processHypothesisStatus(res, aHyp, true); processHypothesisStatus(res, aHyp, true, error.in() );
wc.resume(); wc.resume();
} }
} }
@ -554,8 +569,10 @@ namespace SMESH
SMESH::SMESH_Mesh_var aMesh = aSubMesh->GetFather(); SMESH::SMESH_Mesh_var aMesh = aSubMesh->GetFather();
_PTR(SObject) SsubM = SMESH::FindSObject(aSubMesh); _PTR(SObject) SsubM = SMESH::FindSObject(aSubMesh);
GEOM::GEOM_Object_var aShapeObject = SMESH::GetShapeOnMeshOrSubMesh(SsubM); GEOM::GEOM_Object_var aShapeObject = SMESH::GetShapeOnMeshOrSubMesh(SsubM);
if (!aMesh->_is_nil() && SsubM && !aShapeObject->_is_nil()) { if (!aMesh->_is_nil() && SsubM && !aShapeObject->_is_nil())
res = aMesh->AddHypothesis(aShapeObject, aHyp); {
CORBA::String_var error;
res = aMesh->AddHypothesis( aShapeObject, aHyp, error.out() );
if (res < SMESH::HYP_UNKNOWN_FATAL) { if (res < SMESH::HYP_UNKNOWN_FATAL) {
_PTR(SObject) meshSO = SMESH::FindSObject(aMesh); _PTR(SObject) meshSO = SMESH::FindSObject(aMesh);
if (meshSO) if (meshSO)
@ -563,7 +580,7 @@ namespace SMESH
} }
if (res > SMESH::HYP_OK) { if (res > SMESH::HYP_OK) {
wc.suspend(); wc.suspend();
processHypothesisStatus(res, aHyp, true); processHypothesisStatus( res, aHyp, true, error.in() );
wc.resume(); wc.resume();
} }
} }

View File

@ -32,16 +32,19 @@
#include <SUIT_ResourceMgr.h> #include <SUIT_ResourceMgr.h>
// Qt includes // Qt includes
#include <QVBoxLayout>
#include <QGridLayout>
#include <QLabel>
#include <QTabWidget>
#include <QGroupBox>
#include <QToolButton>
#include <QComboBox> #include <QComboBox>
#include <QMenu>
#include <QCursor> #include <QCursor>
#include <QGridLayout>
#include <QGroupBox>
#include <QLabel>
#include <QListWidget>
#include <QMenu>
#include <QPushButton> #include <QPushButton>
#include <QTabWidget>
#include <QToolButton>
#include <QVBoxLayout>
#include <Standard_Integer.hxx>
#define SPACING 6 #define SPACING 6
#define MARGIN 11 #define MARGIN 11
@ -65,62 +68,81 @@ SMESHGUI_MeshTab::SMESHGUI_MeshTab( QWidget* theParent )
SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr(); SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr();
QIcon aCreateIcon( aResMgr->loadPixmap( "SMESH", tr( "ICON_HYPO" ) ) ); QIcon aCreateIcon( aResMgr->loadPixmap( "SMESH", tr( "ICON_HYPO" ) ) );
QIcon aEditIcon( aResMgr->loadPixmap( "SMESH", tr( "ICON_HYPO_EDIT" ) ) ); QIcon aEditIcon( aResMgr->loadPixmap( "SMESH", tr( "ICON_HYPO_EDIT" ) ) );
QIcon aPlusIcon( aResMgr->loadPixmap( "SMESH", tr( "ICON_PLUS" ) ) );
QIcon aMinusIcon( aResMgr->loadPixmap( "SMESH", tr( "ICON_MINUS" ) ) );
// Algorifm // Algorifm
QLabel* anAlgoLbl = new QLabel( tr( "ALGORITHM" ), this ); QLabel* anAlgoLbl = new QLabel( tr( "ALGORITHM" ), this );
myHyp[ Algo ] = new QComboBox( this ); myHypCombo[ Algo ] = new QComboBox( this );
// Hypothesis // Hypothesis
QLabel* aHypLbl = new QLabel( tr( "HYPOTHESIS" ), this ); QLabel* aHypLbl = new QLabel( tr( "HYPOTHESIS" ), this );
myHyp[ MainHyp ] = new QComboBox( this ); myHypCombo[ MainHyp ] = new QComboBox( this );
myHyp[ MainHyp ]->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ); myHypCombo[ MainHyp ]->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed );
myCreateHyp[ MainHyp ] = new QToolButton( this ); myCreateHypBtn[ MainHyp ] = new QToolButton( this );
myCreateHyp[ MainHyp ]->setIcon( aCreateIcon ); myCreateHypBtn[ MainHyp ]->setIcon( aCreateIcon );
myEditHyp[ MainHyp ] = new QToolButton( this ); myEditHypBtn[ MainHyp ] = new QToolButton( this );
myEditHyp[ MainHyp ]->setIcon( aEditIcon ); myEditHypBtn[ MainHyp ]->setIcon( aEditIcon );
// Line // Line
QFrame* aLine = new QFrame( this ); QFrame* aLine = new QFrame( this );
aLine->setFrameStyle( QFrame::HLine | QFrame::Sunken ); aLine->setFrameStyle( QFrame::HLine | QFrame::Sunken );
// Add. hypothesis // Add. hypothesis
QLabel* anAddHypLbl = new QLabel( tr( "ADD_HYPOTHESIS" ), this ); QLabel* anAddHypLbl = new QLabel( tr( "ADD_HYPOTHESIS" ), this );
myHyp[ AddHyp ] = new QComboBox( this ); myHypCombo[ AddHyp ] = new QComboBox( this );
myHyp[ AddHyp ]->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ); myHypCombo[ AddHyp ]->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed );
myCreateHyp[ AddHyp ] = new QToolButton( this ); myCreateHypBtn[ AddHyp ] = new QToolButton( this );
myCreateHyp[ AddHyp ]->setIcon( aCreateIcon ); myCreateHypBtn[ AddHyp ]->setIcon( aCreateIcon );
myEditHyp[ AddHyp ] = new QToolButton( this ); myEditHypBtn[ AddHyp ] = new QToolButton( this );
myEditHyp[ AddHyp ]->setIcon( aEditIcon ); myEditHypBtn[ AddHyp ]->setIcon( aEditIcon );
myEditHypBtn[ MoreAddHyp ] = new QToolButton( this );
myEditHypBtn[ MoreAddHyp ]->setIcon( aEditIcon );
myAddHypList = new QListWidget( this );
myMoreAddHypBtn = new QToolButton( this );
myMoreAddHypBtn->setIcon( aPlusIcon );
myLessAddHypBtn = new QToolButton( this );
myLessAddHypBtn->setIcon( aMinusIcon );
// Fill layout // Fill layout
QGridLayout* aLay = new QGridLayout( this ); QGridLayout* aLay = new QGridLayout( this );
aLay->setMargin( MARGIN ); aLay->setMargin( MARGIN );
aLay->setSpacing( SPACING ); aLay->setSpacing( SPACING );
aLay->addWidget( anAlgoLbl, 0, 0 ); aLay->addWidget( anAlgoLbl, 0, 0 );
aLay->addWidget( myHyp[ Algo ], 0, 1 ); aLay->addWidget( myHypCombo[ Algo ], 0, 1 );
aLay->addWidget( aHypLbl, 1, 0 ); aLay->addWidget( aHypLbl, 1, 0 );
aLay->addWidget( myHyp[ MainHyp ], 1, 1 ); aLay->addWidget( myHypCombo[ MainHyp ], 1, 1 );
aLay->addWidget( myCreateHyp[ MainHyp ], 1, 2 ); aLay->addWidget( myCreateHypBtn[ MainHyp ], 1, 2 );
aLay->addWidget( myEditHyp[ MainHyp ], 1, 3 ); aLay->addWidget( myEditHypBtn[ MainHyp ], 1, 3 );
aLay->addWidget( aLine, 2, 0, 1, 4 ); aLay->addWidget( aLine, 2, 0, 1, 4 );
aLay->addWidget( anAddHypLbl, 3, 0 ); aLay->addWidget( anAddHypLbl, 3, 0 );
aLay->addWidget( myHyp[ AddHyp ], 3, 1 ); aLay->addWidget( myHypCombo[ AddHyp ], 3, 1 );
aLay->addWidget( myCreateHyp[ AddHyp ], 3, 2 ); aLay->addWidget( myCreateHypBtn[ AddHyp ], 3, 2 );
aLay->addWidget( myEditHyp[ AddHyp ], 3, 3 ); aLay->addWidget( myEditHypBtn[ AddHyp ], 3, 3 );
aLay->addItem( new QSpacerItem( 0, 0, QSizePolicy::Fixed, QSizePolicy::Expanding ), 4, 0 ); aLay->addWidget( myAddHypList, 4, 1, 2, 1 );
aLay->addWidget( myMoreAddHypBtn, 4, 2 );
aLay->addWidget( myEditHypBtn[ MoreAddHyp ], 4, 3 );
aLay->addWidget( myLessAddHypBtn, 5, 2 );
aLay->addItem( new QSpacerItem( 0, 0, QSizePolicy::Fixed, QSizePolicy::Expanding ), 6, 0 );
// Connect signals and slots // Connect signals and slots
for ( int i = MainHyp; i <= AddHyp; i++ ) for ( int i = MainHyp; i <= AddHyp; i++ )
{ {
connect( myCreateHyp[ i ], SIGNAL( clicked() ) , SLOT( onCreateHyp() ) ); connect( myCreateHypBtn[ i ], SIGNAL( clicked() ) , SLOT( onCreateHyp() ) );
connect( myEditHyp[ i ] , SIGNAL( clicked() ) , SLOT( onEditHyp() ) ); connect( myEditHypBtn[ i ] , SIGNAL( clicked() ) , SLOT( onEditHyp() ) );
connect( myHyp[ i ] , SIGNAL( activated( int ) ), SLOT( onHyp( int ) ) ); connect( myHypCombo[ i ] , SIGNAL( activated( int ) ), SLOT( onHyp( int ) ) );
} }
connect( myHyp[ Algo ], SIGNAL( activated( int ) ), SLOT( onHyp( int ) ) ); connect( myHypCombo[ Algo ], SIGNAL( activated( int ) ), SLOT( onHyp( int ) ) );
connect( myAddHypList, SIGNAL( currentRowChanged( int ) ), SLOT( onHyp( int ) ) );
connect( myEditHypBtn[ MoreAddHyp ], SIGNAL( clicked() ), SLOT( onEditHyp() ) );
connect( myMoreAddHypBtn, SIGNAL( clicked() ), SLOT( onMoreAddHyp() ));
connect( myLessAddHypBtn, SIGNAL( clicked() ), SLOT( onLessAddHyp() ));
// Initialize controls // Initialize controls
setAvailableHyps( Algo, QStringList() ); setAvailableHyps( Algo, QStringList() );
setAvailableHyps( MainHyp, QStringList() ); setAvailableHyps( MainHyp, QStringList() );
setAvailableHyps( AddHyp, QStringList() ); setAvailableHyps( AddHyp, QStringList() );
@ -135,6 +157,49 @@ SMESHGUI_MeshTab::~SMESHGUI_MeshTab()
{ {
} }
//================================================================================
/*!
* \brief Adds an item in a control corresponding to \a type
* \param [in] txt - item text
* \param [in] type - HypType
* \param [in] index - index of item in a list of items
*/
//================================================================================
void SMESHGUI_MeshTab::addItem( const QString& txt, const int type, const int index )
{
if ( type <= AddHyp )
{
myHypCombo[ type ]->addItem( txt, QVariant( index ));
}
else
{
QListWidgetItem* item = new QListWidgetItem( txt, myAddHypList );
item->setData( Qt::UserRole, QVariant( index ));
}
}
//================================================================================
/*!
* \brief Returns index of hyp of a given type
*/
//================================================================================
int SMESHGUI_MeshTab::getCurrentIndex( const int type, const bool curByType ) const
{
if ( type <= AddHyp )
{
return myHypCombo[ type ]->itemData( myHypCombo[ type ]->currentIndex() ).toInt();
}
else
{
int row = curByType ? ( type - AddHyp - 1 ) : myAddHypList->currentRow();
if ( QListWidgetItem* item = myAddHypList->item( row ))
return item->data( Qt::UserRole ).toInt();
}
return -1;
}
//================================================================================ //================================================================================
/*! /*!
* \brief Sets available hypothesis or algorithms * \brief Sets available hypothesis or algorithms
@ -146,25 +211,26 @@ SMESHGUI_MeshTab::~SMESHGUI_MeshTab()
//================================================================================ //================================================================================
void SMESHGUI_MeshTab::setAvailableHyps( const int theId, const QStringList& theHyps ) void SMESHGUI_MeshTab::setAvailableHyps( const int theId, const QStringList& theHyps )
{ {
myAvailableHyps[ theId ] = theHyps; myAvailableHypTypes[ theId ] = theHyps;
bool enable = ! theHyps.isEmpty(); bool enable = ! theHyps.isEmpty();
if ( theId == Algo ) // fill list of algos if ( theId == Algo ) // fill list of algos
{ {
myHyp[ Algo ]->clear(); myHypCombo[ Algo ]->clear();
if ( enable ) if ( enable )
{ {
myHyp[ Algo ]->addItem( tr( "NONE" ) ); addItem( tr( "NONE"), Algo, 0 );
myHyp[ Algo ]->addItems( theHyps ); for ( int i = 0, nbHyp = theHyps.count(); i < nbHyp; ++i )
myHyp[ Algo ]->setCurrentIndex( 0 ); addItem( theHyps[i], Algo, i+1 );
myHypCombo[ Algo ]->setCurrentIndex( 0 );
} }
} }
else // enable buttons else // enable buttons
{ {
myCreateHyp[ theId ]->setEnabled( enable ); myCreateHypBtn[ theId ]->setEnabled( enable );
myEditHyp [ theId ]->setEnabled( false ); myEditHypBtn [ theId ]->setEnabled( false );
} }
myHyp[ theId ]->setEnabled( enable ); myHypCombo[ theId ]->setEnabled( enable );
} }
//================================================================================ //================================================================================
@ -172,7 +238,7 @@ void SMESHGUI_MeshTab::setAvailableHyps( const int theId, const QStringList& the
* \brief Sets existing hypothesis * \brief Sets existing hypothesis
* \param theId - identifier of hypothesis (main or additional, see HypType enumeration) * \param theId - identifier of hypothesis (main or additional, see HypType enumeration)
* \param theHyps - list of available hypothesis names * \param theHyps - list of available hypothesis names
* \param theDefaultAvlbl - \c true means that the algorithm can with w/o hypothesis * \param theDefaultAvlbl - \c true means that the algorithm can work w/o hypothesis
* with some default parameters * with some default parameters
* *
* Sets existing main or additional hypothesis for this tab * Sets existing main or additional hypothesis for this tab
@ -184,17 +250,25 @@ void SMESHGUI_MeshTab::setExistingHyps( const int theId,
{ {
if ( theId != Algo ) if ( theId != Algo )
{ {
bool enable = ! myAvailableHyps[ theId ].isEmpty(); bool enable = ! myAvailableHypTypes[ theId ].isEmpty();
myHyp[ theId ]->clear(); myHypCombo[ theId ]->clear();
if ( enable ) if ( enable )
{ {
QString none = tr( theDefaultAvlbl ? "DEFAULT" : ( theId == AddHyp ) ? "NONE" : "NONE" ); QString none = tr( theDefaultAvlbl ? "DEFAULT" : ( theId == AddHyp ) ? "NONE" : "NONE" );
myHyp[ theId ]->addItem( none ); addItem( none, theId, 0 );
myHyp[ theId ]->addItems( theHyps ); for ( int i = 0, nbHyp = theHyps.count(); i < nbHyp; ++i )
myHyp[ theId ]->setCurrentIndex( 0 ); addItem( theHyps[i], theId, i+1 );
myHypCombo[ theId ]->setCurrentIndex( 0 );
}
myHypCombo [ theId ]->setEnabled( enable );
myEditHypBtn[ theId ]->setEnabled( false );
if ( theId == AddHyp )
{
myAddHypList->clear();
myEditHypBtn[ MoreAddHyp ]->setEnabled( false );
myMoreAddHypBtn->setEnabled( false );
myLessAddHypBtn->setEnabled( false );
} }
myHyp [ theId ]->setEnabled( enable );
myEditHyp[ theId ]->setEnabled( false );
} }
} }
@ -210,46 +284,70 @@ void SMESHGUI_MeshTab::setExistingHyps( const int theId,
//================================================================================ //================================================================================
void SMESHGUI_MeshTab::addHyp( const int theId, const QString& theHyp ) void SMESHGUI_MeshTab::addHyp( const int theId, const QString& theHyp )
{ {
myHyp[ theId ]->addItem( theHyp ); int index = myHypCombo[ theId ]->count();
myHyp[ theId ]->setCurrentIndex( myHyp[ theId ]->count() - 1 ); if ( theId == AddHyp )
myEditHyp[ theId ]->setEnabled( true ); index += myAddHypList->count();
myHyp[ theId ]->setEnabled( true ); addItem( theHyp, theId, index );
myHypCombo[ theId ]->setCurrentIndex( myHypCombo[ theId ]->count() - 1 );
myEditHypBtn[ theId ]->setEnabled( true );
myHypCombo[ theId ]->setEnabled( true );
if ( theId == AddHyp )
myMoreAddHypBtn->setEnabled( true );
} }
//================================================================================ //================================================================================
/*! /*!
* \brief Renames hypothesis * \brief Renames hypothesis
* \param theId - identifier of hypothesis (main or additional, see HypType enumeration) * \param theId - identifier of hypothesis (main or additional, see HypType enumeration)
* \param theIndex - index of hypothesis to be renamed * \param theIndex - index of hypothesis to be renamed
* \param theNewName - new name of hypothesis to be renamed * \param theNewName - new name of hypothesis to be renamed
* *
* Renames hypothesis * Renames hypothesis
*/ */
//================================================================================ //================================================================================
void SMESHGUI_MeshTab::renameHyp( const int theId, // void SMESHGUI_MeshTab::renameHyp( const int theId,
const int theIndex, // const int theIndex,
const QString& theNewName ) // const QString& theNewName )
{ // {
if ( theIndex > 0 && theIndex < myHyp[ theId ]->count() ) // if ( theIndex > 0 && theIndex < myHypCombo[ theId ]->count() )
myHyp[ theId ]->setItemText( theIndex, theNewName ); // myHypCombo[ theId ]->setItemText( theIndex, theNewName );
} // }
//================================================================================ //================================================================================
/*! /*!
* \brief Sets current hypothesis * \brief Sets current hypothesis
* \param theId - identifier of hypothesis (main or additional, see HypType enumeration) * \param theId - identifier of hypothesis (main or additional, see HypType enumeration)
* \param theIndex - index of hypothesis to be set as current * \param theIndex - index of hypothesis to be set as current
* *
* Sets current hypothesis * Sets current hypothesis
*/ */
//================================================================================ //================================================================================
void SMESHGUI_MeshTab::setCurrentHyp( const int theId, const int theIndex ) void SMESHGUI_MeshTab::setCurrentHyp( const int theId, const int theIndex )
{ {
if ( theIndex >= 0 && theIndex < myHyp[ theId ]->count() ) if ( theId <= AddHyp )
{ {
myHyp[ theId ]->setCurrentIndex( theIndex ); if ( theIndex >= 0 && theIndex < myHypCombo[ theId ]->count() )
if ( myEditHyp[ theId ] ) {
myEditHyp[ theId ]->setEnabled( theIndex > 0 ); myHypCombo[ theId ]->setCurrentIndex( theIndex );
if ( myEditHypBtn[ theId ] )
myEditHypBtn[ theId ]->setEnabled( theIndex > 0 );
if ( theId == AddHyp )
myMoreAddHypBtn ->setEnabled( theIndex > 0 );
}
}
else // more than one additional hyp assigned
{
// move a hyp from myHypCombo[ AddHyp ] to myAddHypList
for ( int i = 1, nb = myHypCombo[ AddHyp ]->count(); i < nb; ++i )
{
int curIndex = myHypCombo[ AddHyp ]->itemData( i ).toInt();
if ( theIndex == curIndex )
{
addItem( myHypCombo[ AddHyp ]->itemText( i ), theId, theIndex );
myHypCombo[ AddHyp ]->removeItem( i );
break;
}
}
} }
} }
@ -260,11 +358,26 @@ void SMESHGUI_MeshTab::setCurrentHyp( const int theId, const int theIndex )
* \retval int - index of current hypothesis * \retval int - index of current hypothesis
* *
* Gets current hypothesis * Gets current hypothesis
* Use theId > AddHyp to get more than selected addetional hyps (see nbAddHypTypes()).
*/ */
//================================================================================ //================================================================================
int SMESHGUI_MeshTab::currentHyp( const int theId ) const int SMESHGUI_MeshTab::currentHyp( const int theId ) const
{ {
return myHyp[ theId ]->currentIndex(); return getCurrentIndex( theId, /*curByType=*/true );
}
//================================================================================
/*!
* \brief Returns nb of selected supplementary additional hypotheses
*
* Access to their indices is via currentHyp( AddHyp + i ) where i is within the
* range 0 <= i < this->nbAddHypTypes()
*/
//================================================================================
int SMESHGUI_MeshTab::nbAddHypTypes() const
{
return myAddHypList->count();
} }
//================================================================================ //================================================================================
@ -277,12 +390,12 @@ int SMESHGUI_MeshTab::currentHyp( const int theId ) const
//================================================================================ //================================================================================
void SMESHGUI_MeshTab::onCreateHyp() void SMESHGUI_MeshTab::onCreateHyp()
{ {
bool isMainHyp = sender() == myCreateHyp[ MainHyp ]; bool isMainHyp = ( sender() == myCreateHypBtn[ MainHyp ]);
QMenu aPopup( this ); QMenu aPopup( this );
QStringList aHypNames = isMainHyp ? QStringList aHypNames = isMainHyp ?
myAvailableHyps[ MainHyp ] : myAvailableHyps[ AddHyp ]; myAvailableHypTypes[ MainHyp ] : myAvailableHypTypes[ AddHyp ];
QList<QAction*> actions; QList<QAction*> actions;
for ( int i = 0, n = aHypNames.count(); i < n; i++ ) for ( int i = 0, n = aHypNames.count(); i < n; i++ )
@ -304,8 +417,12 @@ void SMESHGUI_MeshTab::onCreateHyp()
void SMESHGUI_MeshTab::onEditHyp() void SMESHGUI_MeshTab::onEditHyp()
{ {
const QObject* aSender = sender(); const QObject* aSender = sender();
int aHypType = aSender == myEditHyp[ MainHyp ] ? MainHyp : AddHyp; int aHypType = MainHyp;
emit editHyp( aHypType, myHyp[ aHypType ]->currentIndex() - 1 ); // - 1 because there is NONE on the top for ( ; aHypType <= MoreAddHyp; ++aHypType )
if ( aSender == myEditHypBtn[ aHypType ])
break;
emit editHyp( Min( aHypType, AddHyp ),
getCurrentIndex( aHypType ) - 1 ); // - 1 because there is NONE on the top
} }
//================================================================================ //================================================================================
@ -320,11 +437,66 @@ void SMESHGUI_MeshTab::onEditHyp()
void SMESHGUI_MeshTab::onHyp( int theIndex ) void SMESHGUI_MeshTab::onHyp( int theIndex )
{ {
const QObject* aSender = sender(); const QObject* aSender = sender();
if ( aSender == myHyp[ Algo ] ) if ( aSender == myHypCombo[ Algo ] )
{
emit selectAlgo( theIndex - 1 ); // - 1 because there is NONE on the top emit selectAlgo( theIndex - 1 ); // - 1 because there is NONE on the top
else { }
int anIndex = aSender == myHyp[ MainHyp ] ? MainHyp : AddHyp; else if ( aSender == myAddHypList )
myEditHyp[ anIndex ]->setEnabled( theIndex > 0 ); {
myEditHypBtn[ MoreAddHyp ]->setEnabled( theIndex >= 0 );
myLessAddHypBtn ->setEnabled( theIndex >= 0 );
}
else
{
int type = ( aSender == myHypCombo[ MainHyp ] ? MainHyp : AddHyp );
myEditHypBtn[ type ]->setEnabled( theIndex > 0 );
if ( type == AddHyp )
myMoreAddHypBtn ->setEnabled( theIndex > 0 );
}
}
//================================================================================
/*!
* \brief Adds a current additional hyp to myAddHypList
*
* SLOT called when myMoreAddHypBtn ("plus") clicked
*/
//================================================================================
void SMESHGUI_MeshTab::onMoreAddHyp()
{
int hypIndex = currentHyp( AddHyp );
if ( hypIndex > 0 )
{
// move a hyp from myHypCombo[ AddHyp ] to myAddHypList
int comboIndex = myHypCombo[ AddHyp ]->currentIndex();
addItem( myHypCombo[ AddHyp ]->itemText( comboIndex ), MoreAddHyp, hypIndex );
myHypCombo[ AddHyp ]->removeItem( comboIndex );
myHypCombo[ AddHyp ]->setCurrentIndex( 0 );
myMoreAddHypBtn->setEnabled( false );
myEditHypBtn[ AddHyp ]->setEnabled( false );
}
}
//================================================================================
/*!
* \brief Removes a current additional hyp from myAddHypList
*
* SLOT called when myLessAddHypBtn ("minus") clicked
*/
//================================================================================
void SMESHGUI_MeshTab::onLessAddHyp()
{
if ( QListWidgetItem * item = myAddHypList->currentItem() )
{
// move a hyp from myAddHypList to myHypCombo[ AddHyp ]
int hypIndex = item->data( Qt::UserRole ).toInt();
addItem( item->text(), AddHyp, hypIndex );
delete item;//myAddHypList->takeItem( myAddHypList->currentRow() );
} }
} }
@ -334,14 +506,14 @@ void SMESHGUI_MeshTab::onHyp( int theIndex )
* *
* Resets all tab fields * Resets all tab fields
*/ */
//================================================================================ //================================================================================
void SMESHGUI_MeshTab::reset() void SMESHGUI_MeshTab::reset()
{ {
for ( int i = Algo; i <= AddHyp; i++ ) for ( int i = Algo; i <= AddHyp; i++ )
{ {
myHyp[ i ]->setCurrentIndex( 0 ); myHypCombo[ i ]->setCurrentIndex( 0 );
if ( myEditHyp[ i ] ) if ( myEditHypBtn[ i ] )
myEditHyp[ i ]->setEnabled( false ); myEditHypBtn[ i ]->setEnabled( false );
} }
} }

View File

@ -38,11 +38,12 @@
#include <QMap> #include <QMap>
class SMESHGUI_MeshTab; class SMESHGUI_MeshTab;
class QTabWidget;
class QComboBox;
class QToolButton;
class QMenu;
class QAction; class QAction;
class QComboBox;
class QListWidget;
class QMenu;
class QTabWidget;
class QToolButton;
/*! /*!
* \brief Dialog for mech creation or editing * \brief Dialog for mech creation or editing
@ -89,7 +90,7 @@ private slots:
void onGeomSelectionButton( bool ); void onGeomSelectionButton( bool );
void onChangedMeshType( const int ); void onChangedMeshType( const int );
private: private:
QMap<int, SMESHGUI_MeshTab*> myTabs; QMap<int, SMESHGUI_MeshTab*> myTabs;
QTabWidget* myTabWg; QTabWidget* myTabWg;
QToolButton* myHypoSetButton; QToolButton* myHypoSetButton;
@ -98,23 +99,26 @@ private:
}; };
/*! /*!
* \brief Tab for tab widget containing controls for definition of * \brief Tab for tab widget containing controls for definition of
* algorithms and hypotheses * algorithms and hypotheses
*/ */
class SMESHGUI_EXPORT SMESHGUI_MeshTab : public QFrame class SMESHGUI_EXPORT SMESHGUI_MeshTab : public QFrame
{ {
Q_OBJECT Q_OBJECT
public: public:
/*! To differ main algorithms, hypotheses and additional ones*/ /*! To differ main algorithms, hypotheses and additional ones*/
enum HypType enum HypType
{ {
Algo = 0, //!< algorithms Algo = 0, //!< algorithms
MainHyp, //!< main hypothesis MainHyp, //!< main hypothesis
AddHyp //!< additional hypothesis AddHyp, //!< additional hypothesis
}; MoreAddHyp //! since several additional hypothesis are possible, the 2-nd, 3-d etc
// additional hypotheses are coded as being of HypType (AddHyp + 1), (AddHyp + 2) etc.
// Nb of HypType's after MainHyp is returned by SMESHGUI_MeshTab::nbAddHypTypes()
};
public: public:
SMESHGUI_MeshTab( QWidget* ); SMESHGUI_MeshTab( QWidget* );
virtual ~SMESHGUI_MeshTab(); virtual ~SMESHGUI_MeshTab();
@ -122,9 +126,10 @@ public:
void setAvailableHyps( const int, const QStringList& ); void setAvailableHyps( const int, const QStringList& );
void setExistingHyps( const int, const QStringList&, bool=false); void setExistingHyps( const int, const QStringList&, bool=false);
void addHyp( const int, const QString& ); void addHyp( const int, const QString& );
void renameHyp( const int, const int, const QString& ); //void renameHyp( const int, const int, const QString& );
void setCurrentHyp( const int, const int ); void setCurrentHyp( const int, const int );
int currentHyp( const int ) const; int currentHyp( const int ) const;
int nbAddHypTypes() const;
void reset(); void reset();
signals: signals:
@ -139,14 +144,24 @@ private slots:
void onCreateHyp(); void onCreateHyp();
void onEditHyp(); void onEditHyp();
void onHyp( int ); void onHyp( int );
void onMoreAddHyp();
private: void onLessAddHyp();
QMap<int, QComboBox*> myHyp;
QMap<int, QToolButton*> myCreateHyp; private:
QMap<int, QToolButton*> myEditHyp;
void addItem( const QString& txt, const int type, const int index );
QMap<int, QStringList> myAvailableHyps; int getCurrentIndex( const int type, const bool curByType=false) const;
QMap<int, QStringList> myExistingHyps;
QMap<int, QStringList> myAvailableHypTypes;
QMap<int, QComboBox*> myHypCombo;
QMap<int, QToolButton*> myCreateHypBtn;
QMap<int, QToolButton*> myEditHypBtn;
QToolButton* myMoreAddHypBtn;
QToolButton* myLessAddHypBtn;
QListWidget* myAddHypList; // 2-nd, etc. additional hyps
}; };
#endif // SMESHGUI_MESHDLG_H #endif // SMESHGUI_MESHDLG_H

View File

@ -610,8 +610,8 @@ void SMESHGUI_MeshOp::selectionDone()
myDlg->objectWg( SMESHGUI_MeshDlg::Geom, SMESHGUI_MeshDlg::Btn )->hide(); myDlg->objectWg( SMESHGUI_MeshDlg::Geom, SMESHGUI_MeshDlg::Btn )->hide();
myDlg->updateGeometry(); myDlg->updateGeometry();
myDlg->adjustSize(); myDlg->adjustSize();
readMesh();
myIsMesh = submeshVar->_is_nil(); myIsMesh = submeshVar->_is_nil();
readMesh();
} }
else else
myDlg->reset(); myDlg->reset();
@ -873,7 +873,11 @@ void SMESHGUI_MeshOp::availableHyps( const int theDim,
* \param theAlgoData - to select hypos able to be used by this algo (optional) * \param theAlgoData - to select hypos able to be used by this algo (optional)
* *
* Gets existing (i.e. already created) hypotheses or algorithm in accordance with * Gets existing (i.e. already created) hypotheses or algorithm in accordance with
* input parameters * input parameters.
*
* WARNING: when using this method to get hyps existing in Mesh component,
* call availableHyps() before in order to get only hyps of available types
* that was filtered by availableHyps()
*/ */
//================================================================================ //================================================================================
void SMESHGUI_MeshOp::existingHyps( const int theDim, void SMESHGUI_MeshOp::existingHyps( const int theDim,
@ -881,7 +885,7 @@ void SMESHGUI_MeshOp::existingHyps( const int theDim,
_PTR(SObject) theFather, _PTR(SObject) theFather,
QStringList& theHyps, QStringList& theHyps,
THypList& theHypList, THypList& theHypList,
HypothesisData* theAlgoData) HypothesisData* theAlgoData) const
{ {
// Clear hypoheses list // Clear hypoheses list
theHyps.clear(); theHyps.clear();
@ -890,20 +894,21 @@ void SMESHGUI_MeshOp::existingHyps( const int theDim,
if ( !theFather ) if ( !theFather )
return; return;
const bool isAux = ( theHypType == AddHyp );
_PTR(SObject) aHypRoot; _PTR(SObject) aHypRoot;
_PTR(GenericAttribute) anAttr; _PTR(GenericAttribute) anAttr;
_PTR(AttributeName) aName; _PTR(AttributeName) aName;
_PTR(AttributeIOR) anIOR; _PTR(AttributeIOR) anIOR;
bool isMesh = !_CAST( SComponent, theFather ); const bool isMesh = !_CAST( SComponent, theFather );
int aPart = -1; int aPart = -1;
if ( isMesh ) if ( isMesh )
aPart = theHypType == Algo ? SMESH::Tag_RefOnAppliedAlgorithms : SMESH::Tag_RefOnAppliedHypothesis; aPart = theHypType == Algo ? SMESH::Tag_RefOnAppliedAlgorithms : SMESH::Tag_RefOnAppliedHypothesis;
else else
aPart = theHypType == Algo ? SMESH::Tag_AlgorithmsRoot : SMESH::Tag_HypothesisRoot; aPart = theHypType == Algo ? SMESH::Tag_AlgorithmsRoot : SMESH::Tag_HypothesisRoot;
const bool isAux = ( theHypType == AddHyp );
const bool allHyps = ( !isMesh && theHypType != Algo && theDim > -1);
if ( theFather->FindSubObject( aPart, aHypRoot ) ) if ( theFather->FindSubObject( aPart, aHypRoot ) )
{ {
_PTR(ChildIterator) anIter = _PTR(ChildIterator) anIter =
@ -931,9 +936,10 @@ void SMESHGUI_MeshOp::existingHyps( const int theDim,
CORBA::String_var hypType = aHypVar->GetName(); CORBA::String_var hypType = aHypVar->GetName();
HypothesisData* aData = SMESH::GetHypothesisData( hypType.in() ); HypothesisData* aData = SMESH::GetHypothesisData( hypType.in() );
if ( !aData) continue; if ( !aData) continue;
if ( ( theDim == -1 || aData->Dim.contains( theDim ) ) && if (( theDim == -1 || aData->Dim.contains( theDim ) ) &&
( isCompatible ( theAlgoData, aData, theHypType )) && ( isCompatible ( theAlgoData, aData, theHypType )) &&
( theHypType == Algo || isAux == aData->IsAuxOrNeedHyp )) ( theHypType == Algo || isAux == aData->IsAuxOrNeedHyp ) &&
( !allHyps || myAvailableHypData[theDim][theHypType].count(aData) ))
{ {
std::string aHypName = aName->Value(); std::string aHypName = aName->Value();
theHyps.append( aHypName.c_str() ); theHyps.append( aHypName.c_str() );
@ -1173,6 +1179,8 @@ void SMESHGUI_MeshOp::createHypothesis(const int theDim,
myDim = theDim; myDim = theDim;
myType = theType; myType = theType;
// get a unique hyp name
QStringList aHypNames; QStringList aHypNames;
TDim2Type2HypList::const_iterator aDimIter = myExistingHyps.begin(); TDim2Type2HypList::const_iterator aDimIter = myExistingHyps.begin();
for ( ; aDimIter != myExistingHyps.end(); aDimIter++) { for ( ; aDimIter != myExistingHyps.end(); aDimIter++) {
@ -1481,13 +1489,14 @@ void SMESHGUI_MeshOp::onAlgoSelected( const int theIndex,
{ {
if ( !isAccessibleDim( dim )) if ( !isAccessibleDim( dim ))
continue; continue;
for ( int type = MainHyp; type < NbHypTypes; type++ ) for ( int dlgType = MainHyp; dlgType < nbDlgHypTypes(dim); dlgType++ )
{ {
const int type = Min( dlgType, AddHyp );
myAvailableHypData[ dim ][ type ].clear(); myAvailableHypData[ dim ][ type ].clear();
QStringList anAvailable, anExisting; QStringList anAvailable, anExisting;
HypothesisData* curAlgo = algoByDim[ dim ]; HypothesisData* curAlgo = algoByDim[ dim ];
int hypIndex = currentHyp( dim, type ); int hypIndex = currentHyp( dim, dlgType );
SMESH::SMESH_Hypothesis_var curHyp; SMESH::SMESH_Hypothesis_var curHyp;
if ( hypIndex >= 0 && hypIndex < myExistingHyps[ dim ][ type ].count() ) if ( hypIndex >= 0 && hypIndex < myExistingHyps[ dim ][ type ].count() )
@ -1521,8 +1530,8 @@ void SMESHGUI_MeshOp::onAlgoSelected( const int theIndex,
if ( !isCompatible( curAlgo, hypData, type )) if ( !isCompatible( curAlgo, hypData, type ))
curHyp = SMESH::SMESH_Hypothesis::_nil(); curHyp = SMESH::SMESH_Hypothesis::_nil();
} }
existingHyps( dim, type, pObj, anExisting, myExistingHyps[ dim ][ type ], curAlgo);
availableHyps( dim, type, anAvailable, myAvailableHypData[ dim ][ type ], curAlgo); availableHyps( dim, type, anAvailable, myAvailableHypData[ dim ][ type ], curAlgo);
existingHyps( dim, type, pObj, anExisting, myExistingHyps[ dim ][ type ], curAlgo);
defaulHypAvlbl = (type == MainHyp && !curAlgo->IsAuxOrNeedHyp ); defaulHypAvlbl = (type == MainHyp && !curAlgo->IsAuxOrNeedHyp );
} }
// set list of hypotheses // set list of hypotheses
@ -1701,14 +1710,19 @@ bool SMESHGUI_MeshOp::createMesh( QString& theMess, QStringList& theEntryList )
SMESH::SetName( aMeshSO, myDlg->objectText( SMESHGUI_MeshDlg::Obj ) ); SMESH::SetName( aMeshSO, myDlg->objectText( SMESHGUI_MeshDlg::Obj ) );
} }
for ( int aDim = SMESH::DIM_0D; aDim <= SMESH::DIM_3D; aDim++ ) { for ( int aDim = SMESH::DIM_0D; aDim <= SMESH::DIM_3D; aDim++ )
{
if ( !isAccessibleDim( aDim )) continue; if ( !isAccessibleDim( aDim )) continue;
// assign hypotheses // assign hypotheses
for ( int aHypType = MainHyp; aHypType <= AddHyp; aHypType++ ) { for ( int dlgType = MainHyp; dlgType < nbDlgHypTypes(aDim); dlgType++ )
int aHypIndex = currentHyp( aDim, aHypType ); {
if ( aHypIndex >= 0 && aHypIndex < myExistingHyps[ aDim ][ aHypType ].count() ) { const int aHypIndex = currentHyp( aDim, dlgType );
SMESH::SMESH_Hypothesis_var aHypVar = myExistingHyps[ aDim ][ aHypType ][ aHypIndex ].first; const int aHypType = Min( dlgType, AddHyp );
if ( aHypIndex >= 0 && aHypIndex < myExistingHyps[ aDim ][ aHypType ].count() )
{
SMESH::SMESH_Hypothesis_var aHypVar =
myExistingHyps[ aDim ][ aHypType ][ aHypIndex ].first;
if ( !aHypVar->_is_nil() ) if ( !aHypVar->_is_nil() )
SMESH::AddHypothesisOnMesh( aMeshVar, aHypVar ); SMESH::AddHypothesisOnMesh( aMeshVar, aHypVar );
} }
@ -1838,9 +1852,10 @@ bool SMESHGUI_MeshOp::createSubMesh( QString& theMess, QStringList& theEntryList
if ( !anAlgoVar->_is_nil() ) if ( !anAlgoVar->_is_nil() )
SMESH::AddHypothesisOnSubMesh( aSubMeshVar, anAlgoVar ); SMESH::AddHypothesisOnSubMesh( aSubMeshVar, anAlgoVar );
// assign hypotheses // assign hypotheses
for ( int aHypType = MainHyp; aHypType <= AddHyp; aHypType++ ) for ( int dlgType = MainHyp; dlgType < nbDlgHypTypes(aDim); dlgType++ )
{ {
int aHypIndex = currentHyp( aDim, aHypType ); const int aHypIndex = currentHyp( aDim, dlgType );
const int aHypType = Min( dlgType, AddHyp );
if ( aHypIndex >= 0 && aHypIndex < myExistingHyps[ aDim ][ aHypType ].count() ) if ( aHypIndex >= 0 && aHypIndex < myExistingHyps[ aDim ][ aHypType ].count() )
{ {
SMESH::SMESH_Hypothesis_var aHypVar = SMESH::SMESH_Hypothesis_var aHypVar =
@ -1876,6 +1891,36 @@ int SMESHGUI_MeshOp::currentHyp( const int theDim, const int theHypType ) const
return myDlg->tab( theDim )->currentHyp( theHypType ) - 1; return myDlg->tab( theDim )->currentHyp( theHypType ) - 1;
} }
//================================================================================
/*!
* \brief Checks if a hypothesis is selected
*/
//================================================================================
bool SMESHGUI_MeshOp::isSelectedHyp( int theDim, int theHypType, int theIndex) const
{
if ( theHypType < AddHyp ) // only one hyp can be selected
return currentHyp( theDim, theHypType ) == theIndex;
for ( int dlgHypType = AddHyp; dlgHypType < nbDlgHypTypes( theDim ); ++dlgHypType )
if ( currentHyp( theDim, dlgHypType ) == theIndex )
return true;
return false;
}
//================================================================================
/*!
* \brief Returns nb of HypType's taking into account possible several
* selected additional hypotheses which are coded as additional HypType's.
*/
//================================================================================
int SMESHGUI_MeshOp::nbDlgHypTypes( const int dim ) const
{
return NbHypTypes + myDlg->tab( dim )->nbAddHypTypes();
}
//================================================================================ //================================================================================
/*! /*!
* \brief Returns true if hypotheses of given dim can be assigned * \brief Returns true if hypotheses of given dim can be assigned
@ -2074,11 +2119,11 @@ void SMESHGUI_MeshOp::readMesh()
SMESH::SMESH_Hypothesis_var aVar = myObjHyps[ dim ][ Algo ].first().first; SMESH::SMESH_Hypothesis_var aVar = myObjHyps[ dim ][ Algo ].first().first;
HypothesisData* algoData = SMESH::GetHypothesisData( aVar->GetName() ); HypothesisData* algoData = SMESH::GetHypothesisData( aVar->GetName() );
aHypIndex = myAvailableHypData[ dim ][ Algo ].indexOf ( algoData ); aHypIndex = myAvailableHypData[ dim ][ Algo ].indexOf ( algoData );
// if ( aHypIndex < 0 && algoData ) { // if ( aHypIndex < 0 && algoData ) {
// // assigned algo is incompatible with other algorithms // // assigned algo is incompatible with other algorithms
// myAvailableHypData[ dim ][ Algo ].push_back( algoData ); // myAvailableHypData[ dim ][ Algo ].push_back( algoData );
// aHypIndex = myAvailableHypData[ dim ][ hypType ].count() - 1; // aHypIndex = myAvailableHypData[ dim ][ hypType ].count() - 1;
// } // }
algoFound = ( aHypIndex > -1 ); algoFound = ( aHypIndex > -1 );
} }
setCurrentHyp( dim, Algo, aHypIndex ); setCurrentHyp( dim, Algo, aHypIndex );
@ -2095,23 +2140,26 @@ void SMESHGUI_MeshOp::readMesh()
{ {
// get hypotheses // get hypotheses
existingHyps( dim, hypType, pObj, anExisting, myObjHyps[ dim ][ hypType ] ); existingHyps( dim, hypType, pObj, anExisting, myObjHyps[ dim ][ hypType ] );
// find index of requered hypothesis among existing ones for this dimension and type for ( int i = 0, nb = myObjHyps[ dim ][ hypType ].count(); i < nb; ++i )
int aHypIndex = -1; {
if ( myObjHyps[ dim ][ hypType ].count() > 0 ) { // find index of required hypothesis among existing ones for this dimension and type
aHypIndex = find( myObjHyps[ dim ][ hypType ].first().first, int aHypIndex = find( myObjHyps[ dim ][ hypType ][ i ].first,
myExistingHyps[ dim ][ hypType ] ); myExistingHyps[ dim ][ hypType ] );
if ( aHypIndex < 0 ) { if ( aHypIndex < 0 ) {
// assigned hypothesis is incompatible with the algorithm // assigned hypothesis is incompatible with the algorithm
if ( currentHyp( dim, Algo ) < 0 ) if ( currentHyp( dim, Algo ) < 0 )
{ // none algo selected; it is edition for sure, of submesh maybe { // none algo selected; it is edition for sure, of submesh maybe
hypWithoutAlgo = true; hypWithoutAlgo = true;
myExistingHyps[ dim ][ hypType ].push_back( myObjHyps[ dim ][ hypType ].first() ); myExistingHyps[ dim ][ hypType ].push_back( myObjHyps[ dim ][ hypType ][ i ] );
anExisting.push_back( myObjHyps[ dim ][ hypType ][ i ].second );
aHypIndex = myExistingHyps[ dim ][ hypType ].count() - 1; aHypIndex = myExistingHyps[ dim ][ hypType ].count() - 1;
myDlg->tab( dim )->setExistingHyps( hypType, anExisting ); myDlg->tab( dim )->setExistingHyps( hypType, anExisting );
} }
} }
setCurrentHyp( dim, hypType + i, aHypIndex );
if ( hypType == MainHyp ) break; // only one main hyp allowed
} }
setCurrentHyp( dim, hypType, aHypIndex );
} }
} }
// make available other hyps of same type as one without algo // make available other hyps of same type as one without algo
@ -2122,8 +2170,8 @@ void SMESHGUI_MeshOp::readMesh()
//================================================================================ //================================================================================
/*! /*!
* \brief Gets name of object * \brief Gets name of object
* \param theSO - SObject * \param theSO - SObject
* \retval QString - name of object * \retval QString - name of object
* *
* Gets name of object * Gets name of object
*/ */
@ -2249,37 +2297,38 @@ bool SMESHGUI_MeshOp::editMeshOrSubMesh( QString& theMess )
myObjHyps[ dim ][ Algo ].append( THypItem( anAlgoVar, aName) ); myObjHyps[ dim ][ Algo ].append( THypItem( anAlgoVar, aName) );
} }
// assign hypotheses // remove deselected hypotheses
for ( int hypType = MainHyp; hypType <= AddHyp; hypType++ ) for ( int hypType = MainHyp; hypType <= AddHyp; hypType++ )
{ {
int aNewHypIndex = currentHyp( dim, hypType ); for ( int i = 0, nb = myObjHyps[ dim ][ hypType ].count(); i < nb; ++i )
int anOldHypIndex = -1;
// remove old hypotheses
if ( myObjHyps[ dim ][ hypType ].count() > 0 )
{ {
anOldHypIndex = find( myObjHyps[ dim ][ hypType ].first().first, SMESH::SMESH_Hypothesis_var hyp = myObjHyps[ dim ][ hypType ][ i ].first;
myExistingHyps[ dim ][ hypType ] ); int hypIndex = this->find( hyp, myExistingHyps[ dim ][ hypType ]);
if ( aNewHypIndex != anOldHypIndex || // different hyps if ( !isSelectedHyp( dim, hypType, hypIndex ) && !hyp->_is_nil() )
anOldHypIndex == -1 ) // hyps of different algos
{ {
SMESH::RemoveHypothesisOrAlgorithmOnMesh SMESH::RemoveHypothesisOrAlgorithmOnMesh( pObj, hyp );
( pObj, myObjHyps[ dim ][ hypType ].first().first );
myObjHyps[ dim ][ hypType ].clear();
} }
} }
}
// assign new hypotheses // assign newly selected hypotheses
if ( aNewHypIndex != anOldHypIndex && aNewHypIndex > -1 ) for ( int dlgType = MainHyp; dlgType < nbDlgHypTypes(dim); dlgType++ )
{
const int curIndex = currentHyp( dim, dlgType );
const int hypType = Min( dlgType, AddHyp );
if ( curIndex >= 0 && curIndex < myExistingHyps[ dim ][ hypType ].count() )
{ {
if ( isMesh ) SMESH::SMESH_Hypothesis_var hyp = myExistingHyps[ dim ][ hypType ][ curIndex ].first;
SMESH::AddHypothesisOnMesh
(aMeshVar, myExistingHyps[ dim ][ hypType ][ aNewHypIndex ].first ); bool isAssigned = ( this->find( hyp, myObjHyps[ dim ][ hypType ]) >= 0 );
else if ( !aSubMeshVar->_is_nil() ) if ( !isAssigned )
SMESH::AddHypothesisOnSubMesh {
( aSubMeshVar, myExistingHyps[ dim ][ hypType ][ aNewHypIndex ].first ); if ( isMesh )
SMESH::AddHypothesisOnMesh (aMeshVar, hyp );
else if ( !aSubMeshVar->_is_nil() )
SMESH::AddHypothesisOnSubMesh ( aSubMeshVar, hyp );
}
} }
// reread all hypotheses of mesh if necessary // reread all hypotheses of mesh
QStringList anExisting; QStringList anExisting;
existingHyps( dim, hypType, pObj, anExisting, myObjHyps[ dim ][ hypType ] ); existingHyps( dim, hypType, pObj, anExisting, myObjHyps[ dim ][ hypType ] );
} }

View File

@ -96,12 +96,12 @@ private:
QStringList&, QStringList&,
THypDataList&, THypDataList&,
HypothesisData* = 0 ) const; HypothesisData* = 0 ) const;
static void existingHyps( const int, void existingHyps( const int,
const int, const int,
_PTR(SObject), _PTR(SObject),
QStringList&, QStringList&,
THypList&, THypList&,
HypothesisData* = 0 ); HypothesisData* = 0 ) const;
HypothesisData* hypData( const int, HypothesisData* hypData( const int,
const int, const int,
const int ); // access to myAvailableHypData const int ); // access to myAvailableHypData
@ -117,6 +117,8 @@ private:
bool askUser=false); bool askUser=false);
int currentHyp( const int, const int ) const; int currentHyp( const int, const int ) const;
bool isSelectedHyp( int, int, int ) const;
int nbDlgHypTypes( const int ) const;
bool isAccessibleDim( const int ) const; bool isAccessibleDim( const int ) const;
void setCurrentHyp( const int, const int, const int ); void setCurrentHyp( const int, const int, const int );
void setDefaultName( const QString& prefix="" ) const; void setDefaultName( const QString& prefix="" ) const;
@ -135,7 +137,9 @@ private:
void createMeshTypeList( QStringList& ); void createMeshTypeList( QStringList& );
void setAvailableMeshType( const QStringList& ); void setAvailableMeshType( const QStringList& );
void setFilteredAlgoData( const int, const int ); void setFilteredAlgoData( const int, const int );
private: private:
SMESHGUI_MeshDlg* myDlg; SMESHGUI_MeshDlg* myDlg;
SMESHGUI_ShapeByMeshOp* myShapeByMeshOp; SMESHGUI_ShapeByMeshOp* myShapeByMeshOp;
bool myToCreate; bool myToCreate;

View File

@ -299,6 +299,14 @@
<source>ICON_HYPO_EDIT</source> <source>ICON_HYPO_EDIT</source>
<translation>mesh_hypo_edit.png</translation> <translation>mesh_hypo_edit.png</translation>
</message> </message>
<message>
<source>ICON_PLUS</source>
<translation>mesh_plus.png</translation>
</message>
<message>
<source>ICON_MINUS</source>
<translation>mesh_minus.png</translation>
</message>
<message> <message>
<source>ICON_INTERSECT</source> <source>ICON_INTERSECT</source>
<translation>mesh_intersectGroups.png</translation> <translation>mesh_intersectGroups.png</translation>

View File

@ -549,6 +549,7 @@ SMESH::Hypothesis_Status SMESH_Mesh_i::ConvertHypothesisStatus
RETURNCASE( HYP_BAD_SUBSHAPE ); RETURNCASE( HYP_BAD_SUBSHAPE );
RETURNCASE( HYP_BAD_GEOMETRY ); RETURNCASE( HYP_BAD_GEOMETRY );
RETURNCASE( HYP_NEED_SHAPE ); RETURNCASE( HYP_NEED_SHAPE );
RETURNCASE( HYP_INCOMPAT_HYPS );
default:; default:;
} }
return SMESH::HYP_UNKNOWN_FATAL; return SMESH::HYP_UNKNOWN_FATAL;
@ -564,33 +565,31 @@ SMESH::Hypothesis_Status SMESH_Mesh_i::ConvertHypothesisStatus
*/ */
//============================================================================= //=============================================================================
SMESH::Hypothesis_Status SMESH_Mesh_i::AddHypothesis(GEOM::GEOM_Object_ptr aSubShapeObject, SMESH::Hypothesis_Status
SMESH::SMESH_Hypothesis_ptr anHyp) SMESH_Mesh_i::AddHypothesis(GEOM::GEOM_Object_ptr aSubShape,
SMESH::SMESH_Hypothesis_ptr anHyp,
CORBA::String_out anErrorText)
throw(SALOME::SALOME_Exception) throw(SALOME::SALOME_Exception)
{ {
Unexpect aCatch(SALOME_SalomeException); Unexpect aCatch(SALOME_SalomeException);
if ( _preMeshInfo ) if ( _preMeshInfo )
_preMeshInfo->ForgetOrLoad(); _preMeshInfo->ForgetOrLoad();
SMESH_Hypothesis::Hypothesis_Status status = addHypothesis( aSubShapeObject, anHyp ); std::string error;
SMESH_Hypothesis::Hypothesis_Status status = addHypothesis( aSubShape, anHyp, &error );
anErrorText = error.c_str();
SMESH::SMESH_Mesh_var mesh( _this() ); SMESH::SMESH_Mesh_var mesh( _this() );
if ( !SMESH_Hypothesis::IsStatusFatal(status) ) if ( !SMESH_Hypothesis::IsStatusFatal(status) )
{ {
SALOMEDS::Study_var study = _gen_i->GetCurrentStudy(); SALOMEDS::Study_var study = _gen_i->GetCurrentStudy();
_gen_i->AddHypothesisToShape( study, mesh, aSubShapeObject, anHyp ); _gen_i->AddHypothesisToShape( study, mesh, aSubShape, anHyp );
} }
if(MYDEBUG) MESSAGE( " AddHypothesis(): status = " << status ); if(MYDEBUG) MESSAGE( " AddHypothesis(): status = " << status );
// Update Python script // Update Python script
//if(_impl->HasShapeToMesh()) TPythonDump() << "status = " << mesh << ".AddHypothesis( "
{ << aSubShape << ", " << anHyp << " )";
TPythonDump() << "status = " << mesh << ".AddHypothesis( "
<< aSubShapeObject << ", " << anHyp << " )";
}
// else {
// TPythonDump() << "status = " << mesh << ".AddHypothesis( "<< anHyp << " )";
// }
return ConvertHypothesisStatus(status); return ConvertHypothesisStatus(status);
} }
@ -602,12 +601,13 @@ SMESH::Hypothesis_Status SMESH_Mesh_i::AddHypothesis(GEOM::GEOM_Object_ptr
//============================================================================= //=============================================================================
SMESH_Hypothesis::Hypothesis_Status SMESH_Hypothesis::Hypothesis_Status
SMESH_Mesh_i::addHypothesis(GEOM::GEOM_Object_ptr aSubShapeObject, SMESH_Mesh_i::addHypothesis(GEOM::GEOM_Object_ptr aSubShape,
SMESH::SMESH_Hypothesis_ptr anHyp) SMESH::SMESH_Hypothesis_ptr anHyp,
std::string* anErrorText)
{ {
if(MYDEBUG) MESSAGE("addHypothesis"); if(MYDEBUG) MESSAGE("addHypothesis");
if (CORBA::is_nil( aSubShapeObject ) && HasShapeToMesh()) if (CORBA::is_nil( aSubShape ) && HasShapeToMesh())
THROW_SALOME_CORBA_EXCEPTION("bad Sub-shape reference",SALOME::BAD_PARAM); THROW_SALOME_CORBA_EXCEPTION("bad Sub-shape reference",SALOME::BAD_PARAM);
if (CORBA::is_nil( anHyp )) if (CORBA::is_nil( anHyp ))
@ -619,22 +619,28 @@ SMESH_Mesh_i::addHypothesis(GEOM::GEOM_Object_ptr aSubShapeObject,
TopoDS_Shape myLocSubShape; TopoDS_Shape myLocSubShape;
//use PseudoShape in case if mesh has no shape //use PseudoShape in case if mesh has no shape
if(HasShapeToMesh()) if(HasShapeToMesh())
myLocSubShape = _gen_i->GeomObjectToShape( aSubShapeObject); myLocSubShape = _gen_i->GeomObjectToShape( aSubShape);
else else
myLocSubShape = _impl->GetShapeToMesh(); myLocSubShape = _impl->GetShapeToMesh();
const int hypId = anHyp->GetId(); const int hypId = anHyp->GetId();
status = _impl->AddHypothesis(myLocSubShape, hypId); std::string error;
if ( !SMESH_Hypothesis::IsStatusFatal(status) ) { status = _impl->AddHypothesis( myLocSubShape, hypId, &error );
if ( !SMESH_Hypothesis::IsStatusFatal(status) )
{
_mapHypo[hypId] = SMESH::SMESH_Hypothesis::_duplicate( anHyp ); _mapHypo[hypId] = SMESH::SMESH_Hypothesis::_duplicate( anHyp );
anHyp->Register(); anHyp->Register();
// assure there is a corresponding submesh // assure there is a corresponding submesh
if ( !_impl->IsMainShape( myLocSubShape )) { if ( !_impl->IsMainShape( myLocSubShape )) {
int shapeId = _impl->GetMeshDS()->ShapeToIndex( myLocSubShape ); int shapeId = _impl->GetMeshDS()->ShapeToIndex( myLocSubShape );
if ( _mapSubMesh_i.find( shapeId ) == _mapSubMesh_i.end() ) if ( _mapSubMesh_i.find( shapeId ) == _mapSubMesh_i.end() )
SMESH::SMESH_subMesh_var( createSubMesh( aSubShapeObject )); SMESH::SMESH_subMesh_var( createSubMesh( aSubShape ));
} }
} }
else if ( anErrorText )
{
*anErrorText = error;
}
} }
catch(SALOME_Exception & S_ex) catch(SALOME_Exception & S_ex)
{ {
@ -649,7 +655,7 @@ SMESH_Mesh_i::addHypothesis(GEOM::GEOM_Object_ptr aSubShapeObject,
*/ */
//============================================================================= //=============================================================================
SMESH::Hypothesis_Status SMESH_Mesh_i::RemoveHypothesis(GEOM::GEOM_Object_ptr aSubShapeObject, SMESH::Hypothesis_Status SMESH_Mesh_i::RemoveHypothesis(GEOM::GEOM_Object_ptr aSubShape,
SMESH::SMESH_Hypothesis_ptr anHyp) SMESH::SMESH_Hypothesis_ptr anHyp)
throw(SALOME::SALOME_Exception) throw(SALOME::SALOME_Exception)
{ {
@ -657,18 +663,18 @@ SMESH::Hypothesis_Status SMESH_Mesh_i::RemoveHypothesis(GEOM::GEOM_Object_ptr aS
if ( _preMeshInfo ) if ( _preMeshInfo )
_preMeshInfo->ForgetOrLoad(); _preMeshInfo->ForgetOrLoad();
SMESH_Hypothesis::Hypothesis_Status status = removeHypothesis( aSubShapeObject, anHyp ); SMESH_Hypothesis::Hypothesis_Status status = removeHypothesis( aSubShape, anHyp );
SMESH::SMESH_Mesh_var mesh = _this(); SMESH::SMESH_Mesh_var mesh = _this();
if ( !SMESH_Hypothesis::IsStatusFatal(status) ) if ( !SMESH_Hypothesis::IsStatusFatal(status) )
{ {
SALOMEDS::Study_var study = _gen_i->GetCurrentStudy(); SALOMEDS::Study_var study = _gen_i->GetCurrentStudy();
_gen_i->RemoveHypothesisFromShape( study, mesh, aSubShapeObject, anHyp ); _gen_i->RemoveHypothesisFromShape( study, mesh, aSubShape, anHyp );
} }
// Update Python script // Update Python script
if(_impl->HasShapeToMesh()) if(_impl->HasShapeToMesh())
TPythonDump() << "status = " << mesh << ".RemoveHypothesis( " TPythonDump() << "status = " << mesh << ".RemoveHypothesis( "
<< aSubShapeObject << ", " << anHyp << " )"; << aSubShape << ", " << anHyp << " )";
else else
TPythonDump() << "status = " << mesh << ".RemoveHypothesis( " TPythonDump() << "status = " << mesh << ".RemoveHypothesis( "
<< anHyp << " )"; << anHyp << " )";
@ -683,12 +689,12 @@ SMESH::Hypothesis_Status SMESH_Mesh_i::RemoveHypothesis(GEOM::GEOM_Object_ptr aS
//============================================================================= //=============================================================================
SMESH_Hypothesis::Hypothesis_Status SMESH_Hypothesis::Hypothesis_Status
SMESH_Mesh_i::removeHypothesis(GEOM::GEOM_Object_ptr aSubShapeObject, SMESH_Mesh_i::removeHypothesis(GEOM::GEOM_Object_ptr aSubShape,
SMESH::SMESH_Hypothesis_ptr anHyp) SMESH::SMESH_Hypothesis_ptr anHyp)
{ {
if(MYDEBUG) MESSAGE("removeHypothesis()"); if(MYDEBUG) MESSAGE("removeHypothesis()");
if (CORBA::is_nil( aSubShapeObject ) && HasShapeToMesh()) if (CORBA::is_nil( aSubShape ) && HasShapeToMesh())
THROW_SALOME_CORBA_EXCEPTION("bad Sub-shape reference", SALOME::BAD_PARAM); THROW_SALOME_CORBA_EXCEPTION("bad Sub-shape reference", SALOME::BAD_PARAM);
if (CORBA::is_nil( anHyp )) if (CORBA::is_nil( anHyp ))
@ -700,7 +706,7 @@ SMESH_Mesh_i::removeHypothesis(GEOM::GEOM_Object_ptr aSubShapeObject,
TopoDS_Shape myLocSubShape; TopoDS_Shape myLocSubShape;
//use PseudoShape in case if mesh has no shape //use PseudoShape in case if mesh has no shape
if( _impl->HasShapeToMesh() ) if( _impl->HasShapeToMesh() )
myLocSubShape = _gen_i->GeomObjectToShape( aSubShapeObject ); myLocSubShape = _gen_i->GeomObjectToShape( aSubShape );
else else
myLocSubShape = _impl->GetShapeToMesh(); myLocSubShape = _impl->GetShapeToMesh();
@ -726,18 +732,18 @@ SMESH_Mesh_i::removeHypothesis(GEOM::GEOM_Object_ptr aSubShapeObject,
//============================================================================= //=============================================================================
SMESH::ListOfHypothesis * SMESH::ListOfHypothesis *
SMESH_Mesh_i::GetHypothesisList(GEOM::GEOM_Object_ptr aSubShapeObject) SMESH_Mesh_i::GetHypothesisList(GEOM::GEOM_Object_ptr aSubShape)
throw(SALOME::SALOME_Exception) throw(SALOME::SALOME_Exception)
{ {
Unexpect aCatch(SALOME_SalomeException); Unexpect aCatch(SALOME_SalomeException);
if (MYDEBUG) MESSAGE("GetHypothesisList"); if (MYDEBUG) MESSAGE("GetHypothesisList");
if (_impl->HasShapeToMesh() && CORBA::is_nil(aSubShapeObject)) if (_impl->HasShapeToMesh() && CORBA::is_nil(aSubShape))
THROW_SALOME_CORBA_EXCEPTION("bad Sub-shape reference", SALOME::BAD_PARAM); THROW_SALOME_CORBA_EXCEPTION("bad Sub-shape reference", SALOME::BAD_PARAM);
SMESH::ListOfHypothesis_var aList = new SMESH::ListOfHypothesis(); SMESH::ListOfHypothesis_var aList = new SMESH::ListOfHypothesis();
try { try {
TopoDS_Shape myLocSubShape = _gen_i->GeomObjectToShape(aSubShapeObject); TopoDS_Shape myLocSubShape = _gen_i->GeomObjectToShape(aSubShape);
if ( myLocSubShape.IsNull() && !_impl->HasShapeToMesh() ) if ( myLocSubShape.IsNull() && !_impl->HasShapeToMesh() )
myLocSubShape = _impl->GetShapeToMesh(); myLocSubShape = _impl->GetShapeToMesh();
const list<const SMESHDS_Hypothesis*>& aLocalList = _impl->GetHypothesisList( myLocSubShape ); const list<const SMESHDS_Hypothesis*>& aLocalList = _impl->GetHypothesisList( myLocSubShape );
@ -803,18 +809,18 @@ SMESH::submesh_array* SMESH_Mesh_i::GetSubMeshes() throw (SALOME::SALOME_Excepti
*/ */
//============================================================================= //=============================================================================
SMESH::SMESH_subMesh_ptr SMESH_Mesh_i::GetSubMesh(GEOM::GEOM_Object_ptr aSubShapeObject, SMESH::SMESH_subMesh_ptr SMESH_Mesh_i::GetSubMesh(GEOM::GEOM_Object_ptr aSubShape,
const char* theName ) const char* theName )
throw(SALOME::SALOME_Exception) throw(SALOME::SALOME_Exception)
{ {
Unexpect aCatch(SALOME_SalomeException); Unexpect aCatch(SALOME_SalomeException);
if (CORBA::is_nil(aSubShapeObject)) if (CORBA::is_nil(aSubShape))
THROW_SALOME_CORBA_EXCEPTION("bad Sub-shape reference", SALOME::BAD_PARAM); THROW_SALOME_CORBA_EXCEPTION("bad Sub-shape reference", SALOME::BAD_PARAM);
SMESH::SMESH_subMesh_var subMesh; SMESH::SMESH_subMesh_var subMesh;
SMESH::SMESH_Mesh_var aMesh = _this(); SMESH::SMESH_Mesh_var aMesh = _this();
try { try {
TopoDS_Shape myLocSubShape = _gen_i->GeomObjectToShape(aSubShapeObject); TopoDS_Shape myLocSubShape = _gen_i->GeomObjectToShape(aSubShape);
//Get or Create the SMESH_subMesh object implementation //Get or Create the SMESH_subMesh object implementation
@ -830,16 +836,16 @@ SMESH::SMESH_subMesh_ptr SMESH_Mesh_i::GetSubMesh(GEOM::GEOM_Object_ptr aSubShap
// create a new subMesh object servant if there is none for the shape // create a new subMesh object servant if there is none for the shape
if ( subMesh->_is_nil() ) if ( subMesh->_is_nil() )
subMesh = createSubMesh( aSubShapeObject ); subMesh = createSubMesh( aSubShape );
if ( _gen_i->CanPublishInStudy( subMesh )) if ( _gen_i->CanPublishInStudy( subMesh ))
{ {
SALOMEDS::Study_var study = _gen_i->GetCurrentStudy(); SALOMEDS::Study_var study = _gen_i->GetCurrentStudy();
SALOMEDS::SObject_wrap aSO = SALOMEDS::SObject_wrap aSO =
_gen_i->PublishSubMesh( study, aMesh, subMesh, aSubShapeObject, theName ); _gen_i->PublishSubMesh( study, aMesh, subMesh, aSubShape, theName );
if ( !aSO->_is_nil()) { if ( !aSO->_is_nil()) {
// Update Python script // Update Python script
TPythonDump() << aSO << " = " << aMesh << ".GetSubMesh( " TPythonDump() << aSO << " = " << aMesh << ".GetSubMesh( "
<< aSubShapeObject << ", '" << theName << "' )"; << aSubShape << ", '" << theName << "' )";
} }
} }
} }
@ -863,7 +869,7 @@ void SMESH_Mesh_i::RemoveSubMesh( SMESH::SMESH_subMesh_ptr theSubMesh )
if ( theSubMesh->_is_nil() ) if ( theSubMesh->_is_nil() )
return; return;
GEOM::GEOM_Object_var aSubShapeObject; GEOM::GEOM_Object_var aSubShape;
SALOMEDS::Study_var aStudy = _gen_i->GetCurrentStudy(); SALOMEDS::Study_var aStudy = _gen_i->GetCurrentStudy();
if ( !aStudy->_is_nil() ) { if ( !aStudy->_is_nil() ) {
// Remove submesh's SObject // Remove submesh's SObject
@ -875,10 +881,10 @@ void SMESH_Mesh_i::RemoveSubMesh( SMESH::SMESH_subMesh_ptr theSubMesh )
anObj->ReferencedObject( aRef.inout() )) anObj->ReferencedObject( aRef.inout() ))
{ {
CORBA::Object_var obj = aRef->GetObject(); CORBA::Object_var obj = aRef->GetObject();
aSubShapeObject = GEOM::GEOM_Object::_narrow( obj ); aSubShape = GEOM::GEOM_Object::_narrow( obj );
} }
// if ( aSubShapeObject->_is_nil() ) // not published shape (IPAL13617) // if ( aSubShape->_is_nil() ) // not published shape (IPAL13617)
// aSubShapeObject = theSubMesh->GetSubShape(); // aSubShape = theSubMesh->GetSubShape();
SALOMEDS::StudyBuilder_var builder = aStudy->NewBuilder(); SALOMEDS::StudyBuilder_var builder = aStudy->NewBuilder();
builder->RemoveObjectWithChildren( anSO ); builder->RemoveObjectWithChildren( anSO );
@ -888,7 +894,7 @@ void SMESH_Mesh_i::RemoveSubMesh( SMESH::SMESH_subMesh_ptr theSubMesh )
} }
} }
if ( removeSubMesh( theSubMesh, aSubShapeObject.in() )) if ( removeSubMesh( theSubMesh, aSubShape.in() ))
if ( _preMeshInfo ) if ( _preMeshInfo )
_preMeshInfo->ForgetOrLoad(); _preMeshInfo->ForgetOrLoad();

View File

@ -86,21 +86,22 @@ public:
void ClearSubMesh(CORBA::Long ShapeID) void ClearSubMesh(CORBA::Long ShapeID)
throw (SALOME::SALOME_Exception); throw (SALOME::SALOME_Exception);
SMESH::Hypothesis_Status AddHypothesis(GEOM::GEOM_Object_ptr aSubShapeObject, SMESH::Hypothesis_Status AddHypothesis(GEOM::GEOM_Object_ptr aSubShape,
SMESH::SMESH_Hypothesis_ptr anHyp) SMESH::SMESH_Hypothesis_ptr anHyp,
CORBA::String_out anErrorText)
throw (SALOME::SALOME_Exception); throw (SALOME::SALOME_Exception);
SMESH::Hypothesis_Status RemoveHypothesis(GEOM::GEOM_Object_ptr aSubShapeObject, SMESH::Hypothesis_Status RemoveHypothesis(GEOM::GEOM_Object_ptr aSubShape,
SMESH::SMESH_Hypothesis_ptr anHyp) SMESH::SMESH_Hypothesis_ptr anHyp)
throw (SALOME::SALOME_Exception); throw (SALOME::SALOME_Exception);
SMESH::ListOfHypothesis* GetHypothesisList(GEOM::GEOM_Object_ptr aSubShapeObject) SMESH::ListOfHypothesis* GetHypothesisList(GEOM::GEOM_Object_ptr aSubShape)
throw (SALOME::SALOME_Exception); throw (SALOME::SALOME_Exception);
SMESH::submesh_array* GetSubMeshes() SMESH::submesh_array* GetSubMeshes()
throw (SALOME::SALOME_Exception); throw (SALOME::SALOME_Exception);
SMESH::SMESH_subMesh_ptr GetSubMesh(GEOM::GEOM_Object_ptr aSubShapeObject, const char* theName) SMESH::SMESH_subMesh_ptr GetSubMesh(GEOM::GEOM_Object_ptr aSubShape, const char* theName)
throw (SALOME::SALOME_Exception); throw (SALOME::SALOME_Exception);
void RemoveSubMesh( SMESH::SMESH_subMesh_ptr theSubMesh ) void RemoveSubMesh( SMESH::SMESH_subMesh_ptr theSubMesh )
@ -404,10 +405,11 @@ public:
// Internal methods not available through CORBA // Internal methods not available through CORBA
// They are called by corresponding interface methods // They are called by corresponding interface methods
SMESH_Hypothesis::Hypothesis_Status addHypothesis(GEOM::GEOM_Object_ptr aSubShapeObject, SMESH_Hypothesis::Hypothesis_Status addHypothesis(GEOM::GEOM_Object_ptr aSubShape,
SMESH::SMESH_Hypothesis_ptr anHyp); SMESH::SMESH_Hypothesis_ptr anHyp,
std::string* anErrorText=0);
SMESH_Hypothesis::Hypothesis_Status removeHypothesis(GEOM::GEOM_Object_ptr aSubShapeObject, SMESH_Hypothesis::Hypothesis_Status removeHypothesis(GEOM::GEOM_Object_ptr aSubShape,
SMESH::SMESH_Hypothesis_ptr anHyp); SMESH::SMESH_Hypothesis_ptr anHyp);
static SMESH::Hypothesis_Status static SMESH::Hypothesis_Status

View File

@ -207,12 +207,15 @@ def GetName(obj):
raise RuntimeError, "Null or invalid object" raise RuntimeError, "Null or invalid object"
## Prints error message if a hypothesis was not assigned. ## Prints error message if a hypothesis was not assigned.
def TreatHypoStatus(status, hypName, geomName, isAlgo): def TreatHypoStatus(status, hypName, geomName, isAlgo, mesh):
if isAlgo: if isAlgo:
hypType = "algorithm" hypType = "algorithm"
else: else:
hypType = "hypothesis" hypType = "hypothesis"
pass pass
reason = ""
if hasattr( status, "__getitem__" ):
status,reason = status[0],status[1]
if status == HYP_UNKNOWN_FATAL : if status == HYP_UNKNOWN_FATAL :
reason = "for unknown reason" reason = "for unknown reason"
elif status == HYP_INCOMPATIBLE : elif status == HYP_INCOMPATIBLE :
@ -235,17 +238,24 @@ def TreatHypoStatus(status, hypName, geomName, isAlgo):
elif status == HYP_HIDING_ALGO: elif status == HYP_HIDING_ALGO:
reason = "it hides algorithms of lower dimensions by generating elements of all dimensions" reason = "it hides algorithms of lower dimensions by generating elements of all dimensions"
elif status == HYP_NEED_SHAPE: elif status == HYP_NEED_SHAPE:
reason = "Algorithm can't work without shape" reason = "algorithm can't work without shape"
elif status == HYP_INCOMPAT_HYPS:
pass
else: else:
return return
hypName = '"' + hypName + '"' where = geomName
geomName= '"' + geomName+ '"' if where:
if status < HYP_UNKNOWN_FATAL and not geomName =='""': where = '"%s"' % geomName
print hypName, "was assigned to", geomName,"but", reason if mesh:
elif not geomName == '""': meshName = GetName( mesh )
print hypName, "was not assigned to",geomName,":", reason if meshName and meshName != NO_NAME:
where = '"%s" in "%s"' % ( geomName, meshName )
if status < HYP_UNKNOWN_FATAL and where:
print '"%s" was assigned to %s but %s' %( hypName, where, reason )
elif where:
print '"%s" was not assigned to %s : %s' %( hypName, where, reason )
else: else:
print hypName, "was not assigned:", reason print '"%s" was not assigned : %s' %( hypName, reason )
pass pass
## Private method. Add geom (sub-shape of the main shape) into the study if not yet there ## Private method. Add geom (sub-shape of the main shape) into the study if not yet there
@ -1592,7 +1602,7 @@ class Mesh:
if geom: if geom:
geom_name = geom.GetName() geom_name = geom.GetName()
isAlgo = hyp._narrow( SMESH_Algo ) isAlgo = hyp._narrow( SMESH_Algo )
TreatHypoStatus( status, hyp_name, geom_name, isAlgo ) TreatHypoStatus( status, hyp_name, geom_name, isAlgo, self )
return status return status
## Return True if an algorithm of hypothesis is assigned to a given shape ## Return True if an algorithm of hypothesis is assigned to a given shape
@ -1878,7 +1888,7 @@ class Mesh:
# @param UnaryOp FT_LogicalNOT or FT_Undefined # @param UnaryOp FT_LogicalNOT or FT_Undefined
# @param Tolerance the tolerance used by FT_BelongToGeom, FT_BelongToSurface, # @param Tolerance the tolerance used by FT_BelongToGeom, FT_BelongToSurface,
# FT_LyingOnGeom, FT_CoplanarFaces criteria # FT_LyingOnGeom, FT_CoplanarFaces criteria
# @return SMESH_Group # @return SMESH_GroupOnFilter
# @ingroup l2_grps_create # @ingroup l2_grps_create
def MakeGroup(self, def MakeGroup(self,
groupName, groupName,
@ -1895,7 +1905,7 @@ class Mesh:
## Creates a mesh group by the given criterion ## Creates a mesh group by the given criterion
# @param groupName the name of the mesh group # @param groupName the name of the mesh group
# @param Criterion the instance of Criterion class # @param Criterion the instance of Criterion class
# @return SMESH_Group # @return SMESH_GroupOnFilter
# @ingroup l2_grps_create # @ingroup l2_grps_create
def MakeGroupByCriterion(self, groupName, Criterion): def MakeGroupByCriterion(self, groupName, Criterion):
aFilterMgr = self.smeshpyD.CreateFilterManager() aFilterMgr = self.smeshpyD.CreateFilterManager()
@ -1910,7 +1920,7 @@ class Mesh:
## Creates a mesh group by the given criteria (list of criteria) ## Creates a mesh group by the given criteria (list of criteria)
# @param groupName the name of the mesh group # @param groupName the name of the mesh group
# @param theCriteria the list of criteria # @param theCriteria the list of criteria
# @return SMESH_Group # @return SMESH_GroupOnFilter
# @ingroup l2_grps_create # @ingroup l2_grps_create
def MakeGroupByCriteria(self, groupName, theCriteria): def MakeGroupByCriteria(self, groupName, theCriteria):
aFilterMgr = self.smeshpyD.CreateFilterManager() aFilterMgr = self.smeshpyD.CreateFilterManager()
@ -1923,12 +1933,13 @@ class Mesh:
## Creates a mesh group by the given filter ## Creates a mesh group by the given filter
# @param groupName the name of the mesh group # @param groupName the name of the mesh group
# @param theFilter the instance of Filter class # @param theFilter the instance of Filter class
# @return SMESH_Group # @return SMESH_GroupOnFilter
# @ingroup l2_grps_create # @ingroup l2_grps_create
def MakeGroupByFilter(self, groupName, theFilter): def MakeGroupByFilter(self, groupName, theFilter):
group = self.CreateEmptyGroup(theFilter.GetElementType(), groupName) #group = self.CreateEmptyGroup(theFilter.GetElementType(), groupName)
theFilter.SetMesh( self.mesh ) #theFilter.SetMesh( self.mesh )
group.AddFrom( theFilter ) #group.AddFrom( theFilter )
group = self.GroupOnFilter( theFilter.GetElementType(), groupName, theFilter )
return group return group
## Removes a group ## Removes a group

View File

@ -214,7 +214,7 @@ class Mesh_Algorithm:
## Private method ## Private method
def Hypothesis (self, hyp, args=[], so="libStdMeshersEngine.so", def Hypothesis (self, hyp, args=[], so="libStdMeshersEngine.so",
UseExisting=0, CompareMethod=""): UseExisting=0, CompareMethod="", toAdd=True):
from salome.smesh.smeshBuilder import TreatHypoStatus, GetName from salome.smesh.smeshBuilder import TreatHypoStatus, GetName
hypo = None hypo = None
if UseExisting: if UseExisting:
@ -243,8 +243,9 @@ class Mesh_Algorithm:
geomName="" geomName=""
if self.geom: if self.geom:
geomName = GetName(self.geom) geomName = GetName(self.geom)
status = self.mesh.mesh.AddHypothesis(self.geom, hypo) if toAdd:
TreatHypoStatus( status, GetName(hypo), geomName, 0 ) status = self.mesh.mesh.AddHypothesis(self.geom, hypo)
TreatHypoStatus( status, GetName(hypo), geomName, 0, self.mesh )
return hypo return hypo
## Returns entry of the shape to mesh in the study ## Returns entry of the shape to mesh in the study
@ -275,11 +276,13 @@ class Mesh_Algorithm:
if faces and isinstance( faces[0], geomBuilder.GEOM._objref_GEOM_Object ): if faces and isinstance( faces[0], geomBuilder.GEOM._objref_GEOM_Object ):
faces = [ self.mesh.geompyD.GetSubShapeID(self.mesh.geom, f) for f in faces ] faces = [ self.mesh.geompyD.GetSubShapeID(self.mesh.geom, f) for f in faces ]
hyp = self.Hypothesis("ViscousLayers", hyp = self.Hypothesis("ViscousLayers",
[thickness, numberOfLayers, stretchFactor, faces]) [thickness, numberOfLayers, stretchFactor, faces, isFacesToIgnore],
toAdd=False)
hyp.SetTotalThickness(thickness) hyp.SetTotalThickness(thickness)
hyp.SetNumberLayers(numberOfLayers) hyp.SetNumberLayers(numberOfLayers)
hyp.SetStretchFactor(stretchFactor) hyp.SetStretchFactor(stretchFactor)
hyp.SetFaces(faces, isFacesToIgnore) hyp.SetFaces(faces, isFacesToIgnore)
self.mesh.AddHypothesis( hyp, self.geom )
return hyp return hyp
## Defines "ViscousLayers2D" hypothesis to give parameters of layers of quadrilateral ## Defines "ViscousLayers2D" hypothesis to give parameters of layers of quadrilateral
@ -303,12 +306,13 @@ class Mesh_Algorithm:
if edges and isinstance( edges[0], geomBuilder.GEOM._objref_GEOM_Object ): if edges and isinstance( edges[0], geomBuilder.GEOM._objref_GEOM_Object ):
edges = [ self.mesh.geompyD.GetSubShapeID(self.mesh.geom, f) for f in edges ] edges = [ self.mesh.geompyD.GetSubShapeID(self.mesh.geom, f) for f in edges ]
hyp = self.Hypothesis("ViscousLayers2D", hyp = self.Hypothesis("ViscousLayers2D",
[thickness, numberOfLayers, stretchFactor, [thickness, numberOfLayers, stretchFactor, edges, isEdgesToIgnore],
edges, isEdgesToIgnore]) toAdd=False)
hyp.SetTotalThickness(thickness) hyp.SetTotalThickness(thickness)
hyp.SetNumberLayers(numberOfLayers) hyp.SetNumberLayers(numberOfLayers)
hyp.SetStretchFactor(stretchFactor) hyp.SetStretchFactor(stretchFactor)
hyp.SetEdges(edges, isEdgesToIgnore) hyp.SetEdges(edges, isEdgesToIgnore)
self.mesh.AddHypothesis( hyp, self.geom )
return hyp return hyp
## Transform a list of either edges or tuples (edge, 1st_vertex_of_edge) ## Transform a list of either edges or tuples (edge, 1st_vertex_of_edge)

View File

@ -1012,7 +1012,8 @@ TSideVector StdMeshers_FaceSide::GetFaceWires(const TopoDS_Face& theFace,
SMESH_Mesh & theMesh, SMESH_Mesh & theMesh,
const bool theIgnoreMediumNodes, const bool theIgnoreMediumNodes,
TError & theError, TError & theError,
SMESH_ProxyMesh::Ptr theProxyMesh) SMESH_ProxyMesh::Ptr theProxyMesh,
const bool theCheckVertexNodes)
{ {
list< TopoDS_Edge > edges, internalEdges; list< TopoDS_Edge > edges, internalEdges;
list< int > nbEdgesInWires; list< int > nbEdgesInWires;
@ -1037,17 +1038,18 @@ TSideVector StdMeshers_FaceSide::GetFaceWires(const TopoDS_Face& theFace,
// as StdMeshers_FaceSide::GetUVPtStruct() requires // as StdMeshers_FaceSide::GetUVPtStruct() requires
if ( wireEdges.front().Orientation() != TopAbs_INTERNAL ) // Issue 0020676 if ( wireEdges.front().Orientation() != TopAbs_INTERNAL ) // Issue 0020676
{ {
while ( !SMESH_Algo::VertexNode( TopExp::FirstVertex( wireEdges.front(), true), if ( theCheckVertexNodes )
theMesh.GetMeshDS())) while ( !SMESH_Algo::VertexNode( TopExp::FirstVertex( wireEdges.front(), true),
{ theMesh.GetMeshDS()))
wireEdges.splice(wireEdges.end(), wireEdges, {
wireEdges.begin(), ++wireEdges.begin()); wireEdges.splice(wireEdges.end(), wireEdges,
if ( from->IsSame( wireEdges.front() )) { wireEdges.begin(), ++wireEdges.begin());
theError = TError if ( from->IsSame( wireEdges.front() )) {
( new SMESH_ComputeError(COMPERR_BAD_INPUT_MESH,"No nodes on vertices")); theError = TError
return TSideVector(0); ( new SMESH_ComputeError(COMPERR_BAD_INPUT_MESH,"No nodes on vertices"));
return TSideVector(0);
}
} }
}
} }
else if ( *nbE > 1 ) // Issue 0020676 (Face_pb_netgen.brep) - several internal edges in a wire else if ( *nbE > 1 ) // Issue 0020676 (Face_pb_netgen.brep) - several internal edges in a wire
{ {

View File

@ -141,7 +141,8 @@ public:
SMESH_Mesh & theMesh, SMESH_Mesh & theMesh,
const bool theIgnoreMediumNodes, const bool theIgnoreMediumNodes,
TError & theError, TError & theError,
SMESH_ProxyMesh::Ptr theProxyMesh = SMESH_ProxyMesh::Ptr()); SMESH_ProxyMesh::Ptr theProxyMesh = SMESH_ProxyMesh::Ptr(),
const bool theCheckVertexNodes=true);
/*! /*!
* \brief Change orientation of side geometry * \brief Change orientation of side geometry
*/ */

View File

@ -124,23 +124,17 @@ bool StdMeshers_Hexa_3D::CheckHypothesis
return true; return true;
} }
// only StdMeshers_ViscousLayers can be used
aStatus = HYP_OK; aStatus = HYP_OK;
for ( ; h != hyps.end(); ++h ) for ( ; h != hyps.end(); ++h )
{ {
string hypName = (*h)->GetName(); if ( !(_viscousLayersHyp = dynamic_cast< const StdMeshers_ViscousLayers*> ( *h )))
if ( find( _compatibleHypothesis.begin(),_compatibleHypothesis.end(),hypName ) break;
!= _compatibleHypothesis.end() )
{
_viscousLayersHyp = dynamic_cast< const StdMeshers_ViscousLayers*> ( *h );
}
else
{
aStatus = HYP_INCOMPATIBLE;
}
} }
if ( !_viscousLayersHyp ) if ( !_viscousLayersHyp )
aStatus = HYP_INCOMPATIBLE; aStatus = HYP_INCOMPATIBLE;
else
error( _viscousLayersHyp->CheckHypothesis( aMesh, aShape, aStatus ));
return aStatus == HYP_OK; return aStatus == HYP_OK;
} }

View File

@ -122,6 +122,9 @@ bool StdMeshers_MEFISTO_2D::CheckHypothesis
_edgeLength = 0; _edgeLength = 0;
_maxElementArea = 0; _maxElementArea = 0;
if ( !error( StdMeshers_ViscousLayers2D::CheckHypothesis( aMesh, aShape, aStatus )))
return false;
list <const SMESHDS_Hypothesis * >::const_iterator itl; list <const SMESHDS_Hypothesis * >::const_iterator itl;
const SMESHDS_Hypothesis *theHyp; const SMESHDS_Hypothesis *theHyp;

View File

@ -114,7 +114,17 @@ TopoDS_Edge StdMeshers_Propagation::GetPropagationSource(SMESH_Mesh& the
return PropagationMgr::GetSource( theMesh.GetSubMeshContaining( theEdge ), return PropagationMgr::GetSource( theMesh.GetSubMeshContaining( theEdge ),
isPropagOfDistribution); isPropagOfDistribution);
} }
const SMESH_HypoFilter& StdMeshers_Propagation::GetFilter()
{
static SMESH_HypoFilter propagHypFilter;
if ( propagHypFilter.IsEmpty() )
{
propagHypFilter.
Init( SMESH_HypoFilter::HasName( StdMeshers_Propagation::GetName ())).
Or ( SMESH_HypoFilter::HasName( StdMeshers_PropagOfDistribution::GetName ()));
}
return propagHypFilter;
}
//============================================================================= //=============================================================================
//============================================================================= //=============================================================================
// PROPAGATION MANAGEMENT // PROPAGATION MANAGEMENT
@ -226,14 +236,8 @@ namespace {
*/ */
const SMESH_Hypothesis* getProagationHyp (SMESH_subMesh* theSubMesh) const SMESH_Hypothesis* getProagationHyp (SMESH_subMesh* theSubMesh)
{ {
static SMESH_HypoFilter propagHypFilter; return theSubMesh->GetFather()->GetHypothesis
if ( propagHypFilter.IsEmpty() ) ( theSubMesh, StdMeshers_Propagation::GetFilter(), true );
{
propagHypFilter.
Init( SMESH_HypoFilter::HasName( StdMeshers_Propagation::GetName ())).
Or ( SMESH_HypoFilter::HasName( StdMeshers_PropagOfDistribution::GetName ()));
}
return theSubMesh->GetFather()->GetHypothesis( theSubMesh, propagHypFilter, true );
} }
//================================================================================ //================================================================================
/*! /*!

View File

@ -35,6 +35,7 @@
#include <TopoDS_Edge.hxx> #include <TopoDS_Edge.hxx>
class SMESH_HypoFilter;
// ======================================================================= // =======================================================================
/*! /*!
@ -42,7 +43,7 @@
*/ */
// ======================================================================= // =======================================================================
class STDMESHERS_EXPORT StdMeshers_Propagation:public SMESH_Hypothesis class STDMESHERS_EXPORT StdMeshers_Propagation : public SMESH_Hypothesis
{ {
public: public:
StdMeshers_Propagation(int hypId, int studyId, SMESH_Gen * gen); StdMeshers_Propagation(int hypId, int studyId, SMESH_Gen * gen);
@ -53,6 +54,12 @@ class STDMESHERS_EXPORT StdMeshers_Propagation:public SMESH_Hypothesis
static std::string GetName (); static std::string GetName ();
/*!
* \brief Returns a filter selecting both StdMeshers_Propagation and
* StdMeshers_PropagOfDistribution hypotheses
*/
static const SMESH_HypoFilter& GetFilter();
/*! /*!
* \brief Set EventListener managing propagation of hypotheses * \brief Set EventListener managing propagation of hypotheses
* \param subMesh - edge submesh to set event listener on * \param subMesh - edge submesh to set event listener on

View File

@ -199,7 +199,9 @@ bool StdMeshers_Quadrangle_2D::CheckHypothesis
} }
} }
return isOk; error( StdMeshers_ViscousLayers2D::CheckHypothesis( aMesh, aShape, aStatus ));
return aStatus == HYP_OK;
} }
//============================================================================= //=============================================================================

View File

@ -112,7 +112,7 @@ StdMeshers_Regular_1D::~StdMeshers_Regular_1D()
//============================================================================= //=============================================================================
/*! /*!
* *
*/ */
//============================================================================= //=============================================================================
@ -127,13 +127,18 @@ bool StdMeshers_Regular_1D::CheckHypothesis( SMESH_Mesh& aMesh,
const list <const SMESHDS_Hypothesis * > & hyps = const list <const SMESHDS_Hypothesis * > & hyps =
GetUsedHypothesis(aMesh, aShape, /*ignoreAuxiliaryHyps=*/false); GetUsedHypothesis(aMesh, aShape, /*ignoreAuxiliaryHyps=*/false);
const SMESH_HypoFilter & propagFilter = StdMeshers_Propagation::GetFilter();
// find non-auxiliary hypothesis // find non-auxiliary hypothesis
const SMESHDS_Hypothesis *theHyp = 0; const SMESHDS_Hypothesis *theHyp = 0;
set< string > propagTypes;
list <const SMESHDS_Hypothesis * >::const_iterator h = hyps.begin(); list <const SMESHDS_Hypothesis * >::const_iterator h = hyps.begin();
for ( ; h != hyps.end(); ++h ) { for ( ; h != hyps.end(); ++h ) {
if ( static_cast<const SMESH_Hypothesis*>(*h)->IsAuxiliary() ) { if ( static_cast<const SMESH_Hypothesis*>(*h)->IsAuxiliary() ) {
if ( strcmp( "QuadraticMesh", (*h)->GetName() ) == 0 ) if ( strcmp( "QuadraticMesh", (*h)->GetName() ) == 0 )
_quadraticMesh = true; _quadraticMesh = true;
if ( propagFilter.IsOk( static_cast< const SMESH_Hypothesis*>( *h ), aShape ))
propagTypes.insert( (*h)->GetName() );
} }
else { else {
if ( !theHyp ) if ( !theHyp )
@ -293,11 +298,48 @@ bool StdMeshers_Regular_1D::CheckHypothesis( SMESH_Mesh& aMesh,
ASSERT(_adaptiveHyp); ASSERT(_adaptiveHyp);
_hypType = ADAPTIVE; _hypType = ADAPTIVE;
_onlyUnaryInput = false; _onlyUnaryInput = false;
aStatus = SMESH_Hypothesis::HYP_OK;
} }
else else
{
aStatus = SMESH_Hypothesis::HYP_INCOMPATIBLE; aStatus = SMESH_Hypothesis::HYP_INCOMPATIBLE;
}
return ( _hypType != NONE ); if ( propagTypes.size() > 1 && aStatus == HYP_OK )
{
// detect concurrent Propagation hyps
_usedHypList.clear();
list< TopoDS_Shape > assignedTo;
if ( aMesh.GetHypotheses( aShape, propagFilter, _usedHypList, true, &assignedTo ) > 1 )
{
// find most simple shape and a hyp on it
int simpleShape = TopAbs_COMPOUND;
const SMESHDS_Hypothesis* localHyp = 0;
list< TopoDS_Shape >::iterator shape = assignedTo.begin();
list< const SMESHDS_Hypothesis *>::iterator hyp = _usedHypList.begin();
for ( ; shape != assignedTo.end(); ++shape )
if ( shape->ShapeType() > simpleShape )
{
simpleShape = shape->ShapeType();
localHyp = (*hyp);
}
// check if there a different hyp on simpleShape
shape = assignedTo.begin();
hyp = _usedHypList.begin();
for ( ; hyp != _usedHypList.end(); ++hyp, ++shape )
if ( shape->ShapeType() == simpleShape &&
!localHyp->IsSameName( **hyp ))
{
aStatus = HYP_INCOMPAT_HYPS;
return error( SMESH_Comment("Hypotheses of both \"")
<< StdMeshers_Propagation::GetName() << "\" and \""
<< StdMeshers_PropagOfDistribution::GetName()
<< "\" types can't be applied to the same edge");
}
}
}
return ( aStatus == SMESH_Hypothesis::HYP_OK );
} }
static bool computeParamByFunc(Adaptor3d_Curve& C3d, double first, double last, static bool computeParamByFunc(Adaptor3d_Curve& C3d, double first, double last,

View File

@ -355,6 +355,7 @@ namespace VISCOUS_3D
bool IsOnEdge() const { return _2neibors; } bool IsOnEdge() const { return _2neibors; }
gp_XYZ Copy( _LayerEdge& other, SMESH_MesherHelper& helper ); gp_XYZ Copy( _LayerEdge& other, SMESH_MesherHelper& helper );
void SetCosin( double cosin ); void SetCosin( double cosin );
int NbSteps() const { return _pos.size() - 1; } // nb inlation steps
}; };
struct _LayerEdgeCmp struct _LayerEdgeCmp
{ {
@ -414,6 +415,36 @@ namespace VISCOUS_3D
bool CheckPrisms() const; bool CheckPrisms() const;
}; };
//--------------------------------------------------------------------------------
/*!
* \brief Layers parameters got by averaging several hypotheses
*/
struct AverageHyp
{
AverageHyp( const StdMeshers_ViscousLayers* hyp = 0 )
:_nbLayers(0), _nbHyps(0), _thickness(0), _stretchFactor(0)
{
Add( hyp );
}
void Add( const StdMeshers_ViscousLayers* hyp )
{
if ( hyp )
{
_nbHyps++;
_nbLayers = hyp->GetNumberLayers();
//_thickness += hyp->GetTotalThickness();
_thickness = Max( _thickness, hyp->GetTotalThickness() );
_stretchFactor += hyp->GetStretchFactor();
}
}
double GetTotalThickness() const { return _thickness; /*_nbHyps ? _thickness / _nbHyps : 0;*/ }
double GetStretchFactor() const { return _nbHyps ? _stretchFactor / _nbHyps : 0; }
int GetNumberLayers() const { return _nbLayers; }
private:
int _nbLayers, _nbHyps;
double _thickness, _stretchFactor;
};
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
typedef map< const SMDS_MeshNode*, _LayerEdge*, TIDCompare > TNode2Edge; typedef map< const SMDS_MeshNode*, _LayerEdge*, TIDCompare > TNode2Edge;
@ -424,12 +455,15 @@ namespace VISCOUS_3D
*/ */
struct _SolidData struct _SolidData
{ {
typedef const StdMeshers_ViscousLayers* THyp;
TopoDS_Shape _solid; TopoDS_Shape _solid;
const StdMeshers_ViscousLayers* _hyp; TGeomID _index; // SOLID id
TopoDS_Shape _hypShape;
_MeshOfSolid* _proxyMesh; _MeshOfSolid* _proxyMesh;
set<TGeomID> _reversedFaceIds; list< THyp > _hyps;
set<TGeomID> _ignoreFaceIds; // WOL FACEs and FACEs of other SOLIDS list< TopoDS_Shape > _hypShapes;
map< TGeomID, THyp > _face2hyp; // filled if _hyps.size() > 1
set< TGeomID > _reversedFaceIds;
set< TGeomID > _ignoreFaceIds; // WOL FACEs and FACEs of other SOLIDs
double _stepSize, _stepSizeCoeff, _geomSize; double _stepSize, _stepSizeCoeff, _geomSize;
const SMDS_MeshNode* _stepSizeNodes[2]; const SMDS_MeshNode* _stepSizeNodes[2];
@ -439,7 +473,7 @@ namespace VISCOUS_3D
// map to find _n2eMap of another _SolidData by a shrink shape shared by two _SolidData's // map to find _n2eMap of another _SolidData by a shrink shape shared by two _SolidData's
map< TGeomID, TNode2Edge* > _s2neMap; map< TGeomID, TNode2Edge* > _s2neMap;
// edges of _n2eMap. We keep same data in two containers because // edges of _n2eMap. We keep same data in two containers because
// iteration over the map is 5 time longer than over the vector // iteration over the map is 5 times longer than over the vector
vector< _LayerEdge* > _edges; vector< _LayerEdge* > _edges;
// key: an id of shape (EDGE or VERTEX) shared by a FACE with // key: an id of shape (EDGE or VERTEX) shared by a FACE with
@ -462,15 +496,16 @@ namespace VISCOUS_3D
vector< int > _endEdgeOnShape; vector< int > _endEdgeOnShape;
int _nbShapesToSmooth; int _nbShapesToSmooth;
// data of averaged StdMeshers_ViscousLayers parameters for each shape with _LayerEdge's
vector< AverageHyp > _hypOnShape;
double _maxThickness; // of all _hyps
double _minThickness; // of all _hyps
double _epsilon; // precision for SegTriaInter() double _epsilon; // precision for SegTriaInter()
TGeomID _index; // SOLID id, for debug _SolidData(const TopoDS_Shape& s=TopoDS_Shape(),
_MeshOfSolid* m=0)
_SolidData(const TopoDS_Shape& s=TopoDS_Shape(), :_solid(s), _proxyMesh(m) {}
const StdMeshers_ViscousLayers* h=0,
const TopoDS_Shape& hs=TopoDS_Shape(),
_MeshOfSolid* m=0)
:_solid(s), _hyp(h), _hypShape(hs), _proxyMesh(m) {}
~_SolidData(); ~_SolidData();
Handle(Geom_Curve) CurveForSmooth( const TopoDS_Edge& E, Handle(Geom_Curve) CurveForSmooth( const TopoDS_Edge& E,
@ -496,7 +531,7 @@ namespace VISCOUS_3D
iEnd = _endEdgeOnShape[ end ]; iEnd = _endEdgeOnShape[ end ];
} }
bool GetShapeEdges(const TGeomID shapeID, size_t& edgeEnd, int* iBeg=0, int* iEnd=0 ) const; bool GetShapeEdges(const TGeomID shapeID, size_t& iEdgeEnd, int* iBeg=0, int* iEnd=0 ) const;
void AddShapesToSmooth( const set< TGeomID >& shapeIDs ); void AddShapesToSmooth( const set< TGeomID >& shapeIDs );
}; };
@ -563,6 +598,9 @@ namespace VISCOUS_3D
// does it's job // does it's job
SMESH_ComputeErrorPtr Compute(SMESH_Mesh& mesh, SMESH_ComputeErrorPtr Compute(SMESH_Mesh& mesh,
const TopoDS_Shape& shape); const TopoDS_Shape& shape);
// check validity of hypotheses
SMESH_ComputeErrorPtr CheckHypotheses( SMESH_Mesh& mesh,
const TopoDS_Shape& shape );
// restore event listeners used to clear an inferior dim sub-mesh modified by viscous layers // restore event listeners used to clear an inferior dim sub-mesh modified by viscous layers
void RestoreListeners(); void RestoreListeners();
@ -573,7 +611,11 @@ namespace VISCOUS_3D
private: private:
bool findSolidsWithLayers(); bool findSolidsWithLayers();
bool findFacesWithLayers(); bool findFacesWithLayers(const bool onlyWith=false);
void getIgnoreFaces(const TopoDS_Shape& solid,
const StdMeshers_ViscousLayers* hyp,
const TopoDS_Shape& hypShape,
set<TGeomID>& ignoreFaces);
bool makeLayer(_SolidData& data); bool makeLayer(_SolidData& data);
bool setEdgeData(_LayerEdge& edge, const set<TGeomID>& subIds, bool setEdgeData(_LayerEdge& edge, const set<TGeomID>& subIds,
SMESH_MesherHelper& helper, _SolidData& data); SMESH_MesherHelper& helper, _SolidData& data);
@ -832,6 +874,27 @@ bool StdMeshers_ViscousLayers::SetParametersByMesh(const SMESH_Mesh* theMesh,
{ {
// TODO // TODO
return false; return false;
} // --------------------------------------------------------------------------------
SMESH_ComputeErrorPtr
StdMeshers_ViscousLayers::CheckHypothesis(SMESH_Mesh& theMesh,
const TopoDS_Shape& theShape,
SMESH_Hypothesis::Hypothesis_Status& theStatus)
{
VISCOUS_3D::_ViscousBuilder bulder;
SMESH_ComputeErrorPtr err = bulder.CheckHypotheses( theMesh, theShape );
if ( err && !err->IsOK() )
theStatus = SMESH_Hypothesis::HYP_INCOMPAT_HYPS;
else
theStatus = SMESH_Hypothesis::HYP_OK;
return err;
}
// --------------------------------------------------------------------------------
bool StdMeshers_ViscousLayers::IsShapeWithLayers(int shapeIndex) const
{
bool isIn =
( std::find( _shapeIds.begin(), _shapeIds.end(), shapeIndex ) != _shapeIds.end() );
return IsToIgnoreShapes() ? !isIn : isIn;
} }
// END StdMeshers_ViscousLayers hypothesis // END StdMeshers_ViscousLayers hypothesis
//================================================================================ //================================================================================
@ -1313,6 +1376,34 @@ SMESH_ComputeErrorPtr _ViscousBuilder::Compute(SMESH_Mesh& theMesh,
return _error; return _error;
} }
//================================================================================
/*!
* \brief Check validity of hypotheses
*/
//================================================================================
SMESH_ComputeErrorPtr _ViscousBuilder::CheckHypotheses( SMESH_Mesh& mesh,
const TopoDS_Shape& shape )
{
_mesh = & mesh;
if ( _ViscousListener::GetSolidMesh( _mesh, shape, /*toCreate=*/false))
return SMESH_ComputeErrorPtr(); // everything already computed
findSolidsWithLayers();
bool ok = findFacesWithLayers();
// remove _MeshOfSolid's of _SolidData's
for ( size_t i = 0; i < _sdVec.size(); ++i )
_ViscousListener::RemoveSolidMesh( _mesh, _sdVec[i]._solid );
if ( !ok )
return _error;
return SMESH_ComputeErrorPtr();
}
//================================================================================ //================================================================================
/*! /*!
* \brief Finds SOLIDs to compute using viscous layers. Fills _sdVec * \brief Finds SOLIDs to compute using viscous layers. Fills _sdVec
@ -1336,22 +1427,28 @@ bool _ViscousBuilder::findSolidsWithLayers()
// TODO: check if algo is hidden // TODO: check if algo is hidden
const list <const SMESHDS_Hypothesis *> & allHyps = const list <const SMESHDS_Hypothesis *> & allHyps =
algo->GetUsedHypothesis(*_mesh, allSolids(i), /*ignoreAuxiliary=*/false); algo->GetUsedHypothesis(*_mesh, allSolids(i), /*ignoreAuxiliary=*/false);
_SolidData* soData = 0;
list< const SMESHDS_Hypothesis *>::const_iterator hyp = allHyps.begin(); list< const SMESHDS_Hypothesis *>::const_iterator hyp = allHyps.begin();
const StdMeshers_ViscousLayers* viscHyp = 0; const StdMeshers_ViscousLayers* viscHyp = 0;
for ( ; hyp != allHyps.end() && !viscHyp; ++hyp ) for ( ; hyp != allHyps.end(); ++hyp )
viscHyp = dynamic_cast<const StdMeshers_ViscousLayers*>( *hyp ); if ( viscHyp = dynamic_cast<const StdMeshers_ViscousLayers*>( *hyp ))
if ( viscHyp ) {
{ TopoDS_Shape hypShape;
TopoDS_Shape hypShape; filter.Init( filter.Is( viscHyp ));
filter.Init( filter.Is( viscHyp )); _mesh->GetHypothesis( allSolids(i), filter, true, &hypShape );
_mesh->GetHypothesis( allSolids(i), filter, true, &hypShape );
_MeshOfSolid* proxyMesh = _ViscousListener::GetSolidMesh( _mesh, if ( !soData )
allSolids(i), {
/*toCreate=*/true); _MeshOfSolid* proxyMesh = _ViscousListener::GetSolidMesh( _mesh,
_sdVec.push_back( _SolidData( allSolids(i), viscHyp, hypShape, proxyMesh )); allSolids(i),
_sdVec.back()._index = getMeshDS()->ShapeToIndex( allSolids(i)); /*toCreate=*/true);
} _sdVec.push_back( _SolidData( allSolids(i), proxyMesh ));
soData = & _sdVec.back();
soData->_index = getMeshDS()->ShapeToIndex( allSolids(i));
}
soData->_hyps.push_back( viscHyp );
soData->_hypShapes.push_back( hypShape );
}
} }
if ( _sdVec.empty() ) if ( _sdVec.empty() )
return error return error
@ -1366,7 +1463,7 @@ bool _ViscousBuilder::findSolidsWithLayers()
*/ */
//================================================================================ //================================================================================
bool _ViscousBuilder::findFacesWithLayers() bool _ViscousBuilder::findFacesWithLayers(const bool onlyWith)
{ {
SMESH_MesherHelper helper( *_mesh ); SMESH_MesherHelper helper( *_mesh );
TopExp_Explorer exp; TopExp_Explorer exp;
@ -1377,56 +1474,99 @@ bool _ViscousBuilder::findFacesWithLayers()
{ {
solids.Add( _sdVec[i]._solid ); solids.Add( _sdVec[i]._solid );
vector<TGeomID> ids = _sdVec[i]._hyp->GetBndShapes(); // get faces to ignore defined by each hyp
if ( _sdVec[i]._hyp->IsToIgnoreShapes() ) // FACEs to ignore are given typedef const StdMeshers_ViscousLayers* THyp;
typedef std::pair< set<TGeomID>, THyp > TFacesOfHyp;
list< TFacesOfHyp > ignoreFacesOfHyps;
list< THyp >::iterator hyp = _sdVec[i]._hyps.begin();
list< TopoDS_Shape >::iterator hypShape = _sdVec[i]._hypShapes.begin();
for ( ; hyp != _sdVec[i]._hyps.end(); ++hyp, ++hypShape )
{ {
for ( size_t ii = 0; ii < ids.size(); ++ii ) ignoreFacesOfHyps.push_back( TFacesOfHyp( set<TGeomID>(), *hyp ));
{ getIgnoreFaces( _sdVec[i]._solid, *hyp, *hypShape, ignoreFacesOfHyps.back().first );
const TopoDS_Shape& s = getMeshDS()->IndexToShape( ids[ii] );
if ( !s.IsNull() && s.ShapeType() == TopAbs_FACE )
_sdVec[i]._ignoreFaceIds.insert( ids[ii] );
}
}
else // FACEs with layers are given
{
exp.Init( _sdVec[i]._solid, TopAbs_FACE );
for ( ; exp.More(); exp.Next() )
{
TGeomID faceInd = getMeshDS()->ShapeToIndex( exp.Current() );
if ( find( ids.begin(), ids.end(), faceInd ) == ids.end() )
_sdVec[i]._ignoreFaceIds.insert( faceInd );
}
} }
// ignore internal FACEs if inlets and outlets are specified // fill _SolidData::_face2hyp and check compatibility of hypotheses
const int nbHyps = _sdVec[i]._hyps.size();
if ( nbHyps > 1 )
{ {
TopTools_IndexedDataMapOfShapeListOfShape solidsOfFace; // check if two hypotheses define different parameters for the same FACE
if ( _sdVec[i]._hyp->IsToIgnoreShapes() ) list< TFacesOfHyp >::iterator igFacesOfHyp;
TopExp::MapShapesAndAncestors( _sdVec[i]._hypShape, for ( exp.Init( _sdVec[i]._solid, TopAbs_FACE ); exp.More(); exp.Next() )
TopAbs_FACE, TopAbs_SOLID, solidsOfFace); {
const TGeomID faceID = getMeshDS()->ShapeToIndex( exp.Current() );
THyp hyp = 0;
igFacesOfHyp = ignoreFacesOfHyps.begin();
for ( ; igFacesOfHyp != ignoreFacesOfHyps.end(); ++igFacesOfHyp )
if ( ! igFacesOfHyp->first.count( faceID ))
{
if ( hyp )
return error(SMESH_Comment("Several hypotheses define "
"Viscous Layers on the face #") << faceID );
hyp = igFacesOfHyp->second;
}
if ( hyp )
_sdVec[i]._face2hyp.insert( make_pair( faceID, hyp ));
else
_sdVec[i]._ignoreFaceIds.insert( faceID );
}
// check if two hypotheses define different number of viscous layers for
// adjacent faces of a solid
set< int > nbLayersSet;
igFacesOfHyp = ignoreFacesOfHyps.begin();
for ( ; igFacesOfHyp != ignoreFacesOfHyps.end(); ++igFacesOfHyp )
{
nbLayersSet.insert( igFacesOfHyp->second->GetNumberLayers() );
}
if ( nbLayersSet.size() > 1 )
{
for ( exp.Init( _sdVec[i]._solid, TopAbs_EDGE ); exp.More(); exp.Next() )
{
PShapeIteratorPtr fIt = helper.GetAncestors( exp.Current(), *_mesh, TopAbs_FACE );
THyp hyp1 = 0, hyp2 = 0;
while( const TopoDS_Shape* face = fIt->next() )
{
const TGeomID faceID = getMeshDS()->ShapeToIndex( *face );
map< TGeomID, THyp >::iterator f2h = _sdVec[i]._face2hyp.find( faceID );
if ( f2h != _sdVec[i]._face2hyp.end() )
{
( hyp1 ? hyp2 : hyp1 ) = f2h->second;
}
}
if ( hyp1 && hyp2 &&
hyp1->GetNumberLayers() != hyp2->GetNumberLayers() )
{
return error("Two hypotheses define different number of "
"viscous layers on adjacent faces");
}
}
}
} // if ( nbHyps > 1 )
else
{
_sdVec[i]._ignoreFaceIds.swap( ignoreFacesOfHyps.back().first );
}
// fill _SolidData::_reversedFaceIds
{
exp.Init( _sdVec[i]._solid.Oriented( TopAbs_FORWARD ), TopAbs_FACE ); exp.Init( _sdVec[i]._solid.Oriented( TopAbs_FORWARD ), TopAbs_FACE );
for ( ; exp.More(); exp.Next() ) for ( ; exp.More(); exp.Next() )
{ {
const TopoDS_Face& face = TopoDS::Face( exp.Current() ); const TopoDS_Face& face = TopoDS::Face( exp.Current() );
if ( helper.NbAncestors( face, *_mesh, TopAbs_SOLID ) < 2 ) const TGeomID faceID = getMeshDS()->ShapeToIndex( face );
continue; if ( //!sdVec[i]._ignoreFaceIds.count( faceID ) && ???????
helper.NbAncestors( face, *_mesh, TopAbs_SOLID ) > 1 &&
const TGeomID faceInd = getMeshDS()->ShapeToIndex( face ); helper.IsReversedSubMesh( face ))
if ( _sdVec[i]._hyp->IsToIgnoreShapes() )
{ {
int nbSolids = solidsOfFace.FindFromKey( face ).Extent(); _sdVec[i]._reversedFaceIds.insert( faceID );
if ( nbSolids > 1 )
_sdVec[i]._ignoreFaceIds.insert( faceInd );
}
if ( helper.IsReversedSubMesh( face ))
{
_sdVec[i]._reversedFaceIds.insert( faceInd );
} }
} }
} }
} } // loop on _sdVec
if ( onlyWith ) // is called to check hypotheses compatibility only
return true;
// Find faces to shrink mesh on (solution 2 in issue 0020832); // Find faces to shrink mesh on (solution 2 in issue 0020832);
TopTools_IndexedMapOfShape shapes; TopTools_IndexedMapOfShape shapes;
@ -1642,6 +1782,60 @@ bool _ViscousBuilder::findFacesWithLayers()
return true; return true;
} }
//================================================================================
/*!
* \brief Finds FACEs w/o layers for a given SOLID by an hypothesis
*/
//================================================================================
void _ViscousBuilder::getIgnoreFaces(const TopoDS_Shape& solid,
const StdMeshers_ViscousLayers* hyp,
const TopoDS_Shape& hypShape,
set<TGeomID>& ignoreFaceIds)
{
TopExp_Explorer exp;
vector<TGeomID> ids = hyp->GetBndShapes();
if ( hyp->IsToIgnoreShapes() ) // FACEs to ignore are given
{
for ( size_t ii = 0; ii < ids.size(); ++ii )
{
const TopoDS_Shape& s = getMeshDS()->IndexToShape( ids[ii] );
if ( !s.IsNull() && s.ShapeType() == TopAbs_FACE )
ignoreFaceIds.insert( ids[ii] );
}
}
else // FACEs with layers are given
{
exp.Init( solid, TopAbs_FACE );
for ( ; exp.More(); exp.Next() )
{
TGeomID faceInd = getMeshDS()->ShapeToIndex( exp.Current() );
if ( find( ids.begin(), ids.end(), faceInd ) == ids.end() )
ignoreFaceIds.insert( faceInd );
}
}
// ignore internal FACEs if inlets and outlets are specified
if ( hyp->IsToIgnoreShapes() )
{
TopTools_IndexedDataMapOfShapeListOfShape solidsOfFace;
TopExp::MapShapesAndAncestors( hypShape,
TopAbs_FACE, TopAbs_SOLID, solidsOfFace);
for ( exp.Init( solid, TopAbs_FACE ); exp.More(); exp.Next() )
{
const TopoDS_Face& face = TopoDS::Face( exp.Current() );
if ( SMESH_MesherHelper::NbAncestors( face, *_mesh, TopAbs_SOLID ) < 2 )
continue;
int nbSolids = solidsOfFace.FindFromKey( face ).Extent();
if ( nbSolids > 1 )
ignoreFaceIds.insert( getMeshDS()->ShapeToIndex( face ));
}
}
}
//================================================================================ //================================================================================
/*! /*!
* \brief Create the inner surface of the viscous layer and prepare data for infation * \brief Create the inner surface of the viscous layer and prepare data for infation
@ -1940,7 +2134,6 @@ void _ViscousBuilder::limitStepSize( _SolidData& data, const double minSize )
void _ViscousBuilder::limitStepSizeByCurvature( _SolidData& data ) void _ViscousBuilder::limitStepSizeByCurvature( _SolidData& data )
{ {
const int nbTestPnt = 5; // on a FACE sub-shape const int nbTestPnt = 5; // on a FACE sub-shape
const double minCurvature = 0.9 / data._hyp->GetTotalThickness();
BRepLProp_SLProps surfProp( 2, 1e-6 ); BRepLProp_SLProps surfProp( 2, 1e-6 );
SMESH_MesherHelper helper( *_mesh ); SMESH_MesherHelper helper( *_mesh );
@ -1975,8 +2168,9 @@ void _ViscousBuilder::limitStepSizeByCurvature( _SolidData& data )
else else
continue; continue;
// check concavity and curvature and limit data._stepSize // check concavity and curvature and limit data._stepSize
const double minCurvature = 0.9 / data._hypOnShape[ edgesEnd ].GetTotalThickness();
int nbLEdges = iEnd - iBeg; int nbLEdges = iEnd - iBeg;
int iStep = Max( 1, nbLEdges / nbTestPnt ); int iStep = Max( 1, nbLEdges / nbTestPnt );
for ( ; iBeg < iEnd; iBeg += iStep ) for ( ; iBeg < iEnd; iBeg += iStep )
{ {
gp_XY uv = helper.GetNodeUV( F, data._edges[ iBeg ]->_nodes[0] ); gp_XY uv = helper.GetNodeUV( F, data._edges[ iBeg ]->_nodes[0] );
@ -2069,7 +2263,16 @@ bool _ViscousBuilder::sortEdges( _SolidData& data,
{ {
// define allowed thickness // define allowed thickness
computeGeomSize( data ); // compute data._geomSize computeGeomSize( data ); // compute data._geomSize
const double tgtThick = Min( 0.5 * data._geomSize, data._hyp->GetTotalThickness() );
data._maxThickness = 0;
data._minThickness = 1e100;
list< const StdMeshers_ViscousLayers* >::iterator hyp = data._hyps.begin();
for ( ; hyp != data._hyps.end(); ++hyp )
{
data._maxThickness = Max( data._maxThickness, (*hyp)->GetTotalThickness() );
data._minThickness = Min( data._minThickness, (*hyp)->GetTotalThickness() );
}
const double tgtThick = /*Min( 0.5 * data._geomSize, */data._maxThickness;
// Find shapes needing smoothing; such a shape has _LayerEdge._normal on it's // Find shapes needing smoothing; such a shape has _LayerEdge._normal on it's
// boundry inclined to the shape at a sharp angle // boundry inclined to the shape at a sharp angle
@ -2200,6 +2403,45 @@ bool _ViscousBuilder::sortEdges( _SolidData& data,
//eVec.clear(); //eVec.clear();
} }
// compute average StdMeshers_ViscousLayers parameters for each shape
data._hypOnShape.clear();
if ( data._hyps.size() == 1 )
{
data._hypOnShape.resize( data._endEdgeOnShape.size(), AverageHyp( data._hyps.back() ));
}
else
{
data._hypOnShape.resize( data._endEdgeOnShape.size() );
map< TGeomID, const StdMeshers_ViscousLayers* >::iterator f2hyp;
for ( size_t i = 0; i < data._endEdgeOnShape.size(); ++i )
{
int iEnd = data._endEdgeOnShape[i];
_LayerEdge* LE = data._edges[ iEnd-1 ];
TGeomID iShape = LE->_nodes[0]->getshapeId();
const TopoDS_Shape& S = getMeshDS()->IndexToShape( iShape );
if ( S.ShapeType() == TopAbs_FACE )
{
if (( f2hyp = data._face2hyp.find( iShape )) != data._face2hyp.end() )
{
data._hypOnShape[ i ].Add( f2hyp->second );
}
}
else
{
PShapeIteratorPtr fIt = SMESH_MesherHelper::GetAncestors( S, *_mesh, TopAbs_FACE );
while ( const TopoDS_Shape* face = fIt->next() )
{
TGeomID faceID = getMeshDS()->ShapeToIndex( *face );
if (( f2hyp = data._face2hyp.find( faceID )) != data._face2hyp.end() )
{
data._hypOnShape[ i ].Add( f2hyp->second );
}
}
}
}
}
return ok; return ok;
} }
@ -2912,9 +3154,9 @@ bool _ViscousBuilder::inflate(_SolidData& data)
if ( data._stepSize > 0.3 * data._geomSize ) if ( data._stepSize > 0.3 * data._geomSize )
limitStepSize( data, 0.3 * data._geomSize ); limitStepSize( data, 0.3 * data._geomSize );
const double tgtThick = data._hyp->GetTotalThickness(); const double tgtThick = data._maxThickness;
if ( data._stepSize > tgtThick ) if ( data._stepSize > data._minThickness )
limitStepSize( data, tgtThick ); limitStepSize( data, data._minThickness );
if ( data._stepSize < 1. ) if ( data._stepSize < 1. )
data._epsilon = data._stepSize * 1e-7; data._epsilon = data._stepSize * 1e-7;
@ -2923,21 +3165,26 @@ bool _ViscousBuilder::inflate(_SolidData& data)
double avgThick = 0, curThick = 0, distToIntersection = Precision::Infinite(); double avgThick = 0, curThick = 0, distToIntersection = Precision::Infinite();
int nbSteps = 0, nbRepeats = 0; int nbSteps = 0, nbRepeats = 0;
while ( 1.01 * avgThick < tgtThick ) int iBeg, iEnd, iS;
while ( avgThick < 0.99 )
{ {
// new target length // new target length
curThick += data._stepSize; curThick += data._stepSize;
if ( curThick > tgtThick ) if ( curThick > tgtThick )
{ {
curThick = tgtThick + ( tgtThick-avgThick ) * nbRepeats; curThick = tgtThick + tgtThick*( 1.-avgThick ) * nbRepeats;
nbRepeats++; nbRepeats++;
} }
// Elongate _LayerEdge's // Elongate _LayerEdge's
dumpFunction(SMESH_Comment("inflate")<<data._index<<"_step"<<nbSteps); // debug dumpFunction(SMESH_Comment("inflate")<<data._index<<"_step"<<nbSteps); // debug
for ( size_t i = 0; i < data._edges.size(); ++i ) for ( iBeg = 0, iS = 0; iS < data._endEdgeOnShape.size(); ++iS )
{ {
data._edges[i]->SetNewLength( curThick, helper ); const double shapeCurThick = Min( curThick, data._hypOnShape[ iS ].GetTotalThickness() );
for ( iEnd = data._endEdgeOnShape[ iS ]; iBeg < iEnd; ++iBeg )
{
data._edges[iBeg]->SetNewLength( shapeCurThick, helper );
}
} }
dumpFunctionEnd(); dumpFunctionEnd();
@ -2962,16 +3209,22 @@ bool _ViscousBuilder::inflate(_SolidData& data)
// Evaluate achieved thickness // Evaluate achieved thickness
avgThick = 0; avgThick = 0;
for ( size_t i = 0; i < data._edges.size(); ++i ) for ( iBeg = 0, iS = 0; iS < data._endEdgeOnShape.size(); ++iS )
avgThick += data._edges[i]->_len; {
const double shapeTgtThick = data._hypOnShape[ iS ].GetTotalThickness();
for ( iEnd = data._endEdgeOnShape[ iS ]; iBeg < iEnd; ++iBeg )
{
avgThick += Min( 1., data._edges[iBeg]->_len / shapeTgtThick );
}
}
avgThick /= data._edges.size(); avgThick /= data._edges.size();
debugMsg( "-- Thickness " << avgThick << " reached" ); debugMsg( "-- Thickness " << avgThick*100 << "% reached" );
if ( distToIntersection < avgThick*1.5 ) if ( distToIntersection < tgtThick*avgThick*1.5 )
{ {
debugMsg( "-- Stop inflation since " debugMsg( "-- Stop inflation since "
<< " distToIntersection( "<<distToIntersection<<" ) < avgThick( " << " distToIntersection( "<<distToIntersection<<" ) < avgThick( "
<< avgThick << " ) * 1.5" ); << tgtThick*avgThick << " ) * 1.5" );
break; break;
} }
// new step size // new step size
@ -2980,12 +3233,12 @@ bool _ViscousBuilder::inflate(_SolidData& data)
data._stepSize = data._stepSizeCoeff * data._stepSize = data._stepSizeCoeff *
SMESH_TNodeXYZ(data._stepSizeNodes[0]).Distance(data._stepSizeNodes[1]); SMESH_TNodeXYZ(data._stepSizeNodes[0]).Distance(data._stepSizeNodes[1]);
} // while ( 1.01 * avgThick < tgtThick ) } // while ( avgThick < 0.99 )
if (nbSteps == 0 ) if (nbSteps == 0 )
return error("failed at the very first inflation step", data._index); return error("failed at the very first inflation step", data._index);
if ( 1.01 * avgThick < tgtThick ) if ( avgThick < 0.99 )
if ( SMESH_subMesh* sm = _mesh->GetSubMeshContaining( data._index )) if ( SMESH_subMesh* sm = _mesh->GetSubMeshContaining( data._index ))
{ {
SMESH_ComputeErrorPtr& smError = sm->GetComputeError(); SMESH_ComputeErrorPtr& smError = sm->GetComputeError();
@ -2994,14 +3247,13 @@ bool _ViscousBuilder::inflate(_SolidData& data)
( new SMESH_ComputeError (COMPERR_WARNING, ( new SMESH_ComputeError (COMPERR_WARNING,
SMESH_Comment("Thickness ") << tgtThick << SMESH_Comment("Thickness ") << tgtThick <<
" of viscous layers not reached," " of viscous layers not reached,"
" average reached thickness is " << avgThick )); " average reached thickness is " << avgThick*100 << "%."));
} }
// Restore position of src nodes moved by infaltion on _noShrinkShapes // Restore position of src nodes moved by infaltion on _noShrinkShapes
dumpFunction(SMESH_Comment("restoNoShrink_So")<<data._index); // debug dumpFunction(SMESH_Comment("restoNoShrink_So")<<data._index); // debug
int iBeg, iEnd = 0; for ( iEnd = iS = 0; iS < data._endEdgeOnShape.size(); ++iS )
for ( int iS = 0; iS < data._endEdgeOnShape.size(); ++iS )
{ {
iBeg = iEnd; iBeg = iEnd;
iEnd = data._endEdgeOnShape[ iS ]; iEnd = data._endEdgeOnShape[ iS ];
@ -3041,6 +3293,16 @@ bool _ViscousBuilder::smoothAndCheck(_SolidData& data,
iBeg = iEnd; iBeg = iEnd;
iEnd = data._endEdgeOnShape[ iS ]; iEnd = data._endEdgeOnShape[ iS ];
// bool toSmooth = false;
// for ( int i = iBeg; i < iEnd; ++i )
// toSmooth = data._edges[ iBeg ]->NbSteps() >= nbSteps+1;
// if ( !toSmooth )
// {
// if ( iS+1 == data._nbShapesToSmooth )
// data._nbShapesToSmooth--;
// continue; // target length reached some steps before
// }
if ( !data._edges[ iBeg ]->_sWOL.IsNull() && if ( !data._edges[ iBeg ]->_sWOL.IsNull() &&
data._edges[ iBeg ]->_sWOL.ShapeType() == TopAbs_FACE ) data._edges[ iBeg ]->_sWOL.ShapeType() == TopAbs_FACE )
{ {
@ -3089,10 +3351,10 @@ bool _ViscousBuilder::smoothAndCheck(_SolidData& data,
badNb = 0; badNb = 0;
moved = false; moved = false;
if ( step % 2 ) if ( step % 2 )
for ( int i = iBeg; i < iEnd; ++i ) for ( int i = iBeg; i < iEnd; ++i ) // iterate forward
moved |= data._edges[i]->Smooth(badNb); moved |= data._edges[i]->Smooth(badNb);
else else
for ( int i = iEnd-1; i >= iBeg; --i ) for ( int i = iEnd-1; i >= iBeg; --i ) // iterate backward
moved |= data._edges[i]->Smooth(badNb); moved |= data._edges[i]->Smooth(badNb);
improved = ( badNb < oldBadNb ); improved = ( badNb < oldBadNb );
@ -3330,14 +3592,14 @@ void _SolidData::SortOnEdge( const TopoDS_Edge& E,
//================================================================================ //================================================================================
bool _SolidData::GetShapeEdges(const TGeomID shapeID, bool _SolidData::GetShapeEdges(const TGeomID shapeID,
size_t & edgesEnd, size_t & iEdgesEnd,
int* iBeg, int* iBeg,
int* iEnd ) const int* iEnd ) const
{ {
int beg = 0, end = 0; int beg = 0, end = 0;
for ( edgesEnd = 0; edgesEnd < _endEdgeOnShape.size(); ++edgesEnd ) for ( iEdgesEnd = 0; iEdgesEnd < _endEdgeOnShape.size(); ++iEdgesEnd )
{ {
end = _endEdgeOnShape[ edgesEnd ]; end = _endEdgeOnShape[ iEdgesEnd ];
TGeomID sID = _edges[ beg ]->_nodes[0]->getshapeId(); TGeomID sID = _edges[ beg ]->_nodes[0]->getshapeId();
if ( sID == shapeID ) if ( sID == shapeID )
{ {
@ -4699,7 +4961,7 @@ void _LayerEdge::SetNewLength( double len, SMESH_MesherHelper& helper )
{ {
if ( _len - len > -1e-6 ) if ( _len - len > -1e-6 )
{ {
_pos.push_back( _pos.back() ); //_pos.push_back( _pos.back() );
return; return;
} }
@ -4809,6 +5071,8 @@ bool _ViscousBuilder::refine(_SolidData& data)
// Create intermediate nodes on each _LayerEdge // Create intermediate nodes on each _LayerEdge
int iS = 0, iEnd = data._endEdgeOnShape[ iS ];
for ( size_t i = 0; i < data._edges.size(); ++i ) for ( size_t i = 0; i < data._edges.size(); ++i )
{ {
_LayerEdge& edge = *data._edges[i]; _LayerEdge& edge = *data._edges[i];
@ -4816,6 +5080,11 @@ bool _ViscousBuilder::refine(_SolidData& data)
if ( edge._nodes.size() < 2 ) if ( edge._nodes.size() < 2 )
continue; // on _noShrinkShapes continue; // on _noShrinkShapes
// get parameters of layers for the edge
if ( i == iEnd )
iEnd = data._endEdgeOnShape[ ++iS ];
const AverageHyp& hyp = data._hypOnShape[ iS ];
// get accumulated length of segments // get accumulated length of segments
vector< double > segLen( edge._pos.size() ); vector< double > segLen( edge._pos.size() );
segLen[0] = 0.0; segLen[0] = 0.0;
@ -4826,7 +5095,7 @@ bool _ViscousBuilder::refine(_SolidData& data)
const SMDS_MeshNode* tgtNode = edge._nodes.back(); const SMDS_MeshNode* tgtNode = edge._nodes.back();
if ( edge._nodes.size() == 2 ) if ( edge._nodes.size() == 2 )
{ {
edge._nodes.resize( data._hyp->GetNumberLayers() + 1, 0 ); edge._nodes.resize( hyp.GetNumberLayers() + 1, 0 );
edge._nodes[1] = 0; edge._nodes[1] = 0;
edge._nodes.back() = tgtNode; edge._nodes.back() = tgtNode;
} }
@ -4875,8 +5144,8 @@ bool _ViscousBuilder::refine(_SolidData& data)
// calculate height of the first layer // calculate height of the first layer
double h0; double h0;
const double T = segLen.back(); //data._hyp.GetTotalThickness(); const double T = segLen.back(); //data._hyp.GetTotalThickness();
const double f = data._hyp->GetStretchFactor(); const double f = hyp.GetStretchFactor();
const int N = data._hyp->GetNumberLayers(); const int N = hyp.GetNumberLayers();
const double fPowN = pow( f, N ); const double fPowN = pow( f, N );
if ( fPowN - 1 <= numeric_limits<double>::min() ) if ( fPowN - 1 <= numeric_limits<double>::min() )
h0 = T / N; h0 = T / N;
@ -4995,10 +5264,12 @@ bool _ViscousBuilder::refine(_SolidData& data)
TopExp_Explorer exp( data._solid, TopAbs_FACE ); TopExp_Explorer exp( data._solid, TopAbs_FACE );
for ( ; exp.More(); exp.Next() ) for ( ; exp.More(); exp.Next() )
{ {
if ( data._ignoreFaceIds.count( getMeshDS()->ShapeToIndex( exp.Current() ))) const TGeomID faceID = getMeshDS()->ShapeToIndex( exp.Current() );
if ( data._ignoreFaceIds.count( faceID ))
continue; continue;
SMESHDS_SubMesh* fSubM = getMeshDS()->MeshElements( exp.Current() ); const bool isReversedFace = data._reversedFaceIds.count( faceID );
SMDS_ElemIteratorPtr fIt = fSubM->GetElements(); SMESHDS_SubMesh* fSubM = getMeshDS()->MeshElements( exp.Current() );
SMDS_ElemIteratorPtr fIt = fSubM->GetElements();
while ( fIt->more() ) while ( fIt->more() )
{ {
const SMDS_MeshElement* face = fIt->next(); const SMDS_MeshElement* face = fIt->next();
@ -5011,14 +5282,15 @@ bool _ViscousBuilder::refine(_SolidData& data)
for ( int iN = 0; iN < nbNodes; ++iN ) for ( int iN = 0; iN < nbNodes; ++iN )
{ {
const SMDS_MeshNode* n = nIt->next(); const SMDS_MeshNode* n = nIt->next();
nnVec[ iN ] = & data._n2eMap[ n ]->_nodes; const int i = isReversedFace ? nbNodes-1-iN : iN;
if ( nnVec[ iN ]->size() < 2 ) nnVec[ i ] = & data._n2eMap[ n ]->_nodes;
if ( nnVec[ i ]->size() < 2 )
degenEdgeInd.insert( iN ); degenEdgeInd.insert( iN );
else else
nbZ = nnVec[ iN ]->size(); nbZ = nnVec[ i ]->size();
if ( helper.HasDegeneratedEdges() ) if ( helper.HasDegeneratedEdges() )
nnSet.insert( nnVec[ iN ]); nnSet.insert( nnVec[ i ]);
} }
if ( nbZ == 0 ) if ( nbZ == 0 )
continue; continue;

View File

@ -28,6 +28,7 @@
#include "SMESH_Hypothesis.hxx" #include "SMESH_Hypothesis.hxx"
#include "SMESH_ProxyMesh.hxx" #include "SMESH_ProxyMesh.hxx"
#include "SMESH_ComputeError.hxx"
#include <vector> #include <vector>
@ -39,7 +40,7 @@ class STDMESHERS_EXPORT StdMeshers_ViscousLayers : public SMESH_Hypothesis
public: public:
StdMeshers_ViscousLayers(int hypId, int studyId, SMESH_Gen* gen); StdMeshers_ViscousLayers(int hypId, int studyId, SMESH_Gen* gen);
// Set boundary shapes, faces in 3D, edges in 2D, either to exclude from // Set boundary shapes (faces in 3D, edges in 2D) either to exclude from
// treatment or to make the Viscous Layers on // treatment or to make the Viscous Layers on
void SetBndShapes(const std::vector<int>& shapeIds, bool toIgnore); void SetBndShapes(const std::vector<int>& shapeIds, bool toIgnore);
std::vector<int> GetBndShapes() const { return _shapeIds; } std::vector<int> GetBndShapes() const { return _shapeIds; }
@ -63,6 +64,15 @@ public:
const TopoDS_Shape& theShape, const TopoDS_Shape& theShape,
const bool toMakeN2NMap=false) const; const bool toMakeN2NMap=false) const;
// Checks compatibility of assigned StdMeshers_ViscousLayers hypotheses
static SMESH_ComputeErrorPtr
CheckHypothesis(SMESH_Mesh& aMesh,
const TopoDS_Shape& aShape,
SMESH_Hypothesis::Hypothesis_Status& aStatus);
// Checks if viscous layers should be constructed on a shape
bool IsShapeWithLayers(int shapeIndex) const;
virtual std::ostream & SaveTo(std::ostream & save); virtual std::ostream & SaveTo(std::ostream & save);
virtual std::istream & LoadFrom(std::istream & load); virtual std::istream & LoadFrom(std::istream & load);

View File

@ -256,6 +256,7 @@ namespace VISCOUS_2D
_PolyLine* _rightLine; _PolyLine* _rightLine;
int _firstPntInd; // index in vector<UVPtStruct> of _wire int _firstPntInd; // index in vector<UVPtStruct> of _wire
int _lastPntInd; int _lastPntInd;
int _index; // index in _ViscousBuilder2D::_polyLineVec
vector< _LayerEdge > _lEdges; /* _lEdges[0] is usually is not treated vector< _LayerEdge > _lEdges; /* _lEdges[0] is usually is not treated
as it is equal to the last one of the _leftLine */ as it is equal to the last one of the _leftLine */
@ -325,6 +326,7 @@ namespace VISCOUS_2D
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
typedef map< const SMDS_MeshNode*, _LayerEdge*, TIDCompare > TNode2Edge; typedef map< const SMDS_MeshNode*, _LayerEdge*, TIDCompare > TNode2Edge;
typedef StdMeshers_ViscousLayers2D THypVL;
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
/*! /*!
@ -335,14 +337,17 @@ namespace VISCOUS_2D
public: public:
_ViscousBuilder2D(SMESH_Mesh& theMesh, _ViscousBuilder2D(SMESH_Mesh& theMesh,
const TopoDS_Face& theFace, const TopoDS_Face& theFace,
const StdMeshers_ViscousLayers2D* theHyp); vector< const THypVL* > & theHyp,
vector< TopoDS_Shape > & theHypShapes);
SMESH_ComputeErrorPtr GetError() const { return _error; } SMESH_ComputeErrorPtr GetError() const { return _error; }
// does it's job // does it's job
SMESH_ProxyMesh::Ptr Compute(const TopoDS_Shape& theShapeHypAssignedTo); SMESH_ProxyMesh::Ptr Compute();
private: private:
bool findEdgesWithLayers(const TopoDS_Shape& theShapeHypAssignedTo); friend class ::StdMeshers_ViscousLayers2D;
bool findEdgesWithLayers();
bool makePolyLines(); bool makePolyLines();
bool inflate(); bool inflate();
bool fixCollisions(); bool fixCollisions();
@ -362,9 +367,13 @@ namespace VISCOUS_2D
GeomAPI_ProjectPointOnSurf* faceProj); GeomAPI_ProjectPointOnSurf* faceProj);
void adjustCommonEdge( _PolyLine& LL, _PolyLine& LR ); void adjustCommonEdge( _PolyLine& LL, _PolyLine& LR );
void calcLayersHeight(const double totalThick, void calcLayersHeight(const double totalThick,
vector<double>& heights); vector<double>& heights,
const THypVL* hyp);
bool removeMeshFaces(const TopoDS_Shape& face); bool removeMeshFaces(const TopoDS_Shape& face);
const THypVL* getLineHypothesis(int iPL);
double getLineThickness (int iPL);
bool error( const string& text ); bool error( const string& text );
SMESHDS_Mesh* getMeshDS() { return _mesh->GetMeshDS(); } SMESHDS_Mesh* getMeshDS() { return _mesh->GetMeshDS(); }
_ProxyMeshOfFace* getProxyMesh(); _ProxyMeshOfFace* getProxyMesh();
@ -377,7 +386,8 @@ namespace VISCOUS_2D
// input data // input data
SMESH_Mesh* _mesh; SMESH_Mesh* _mesh;
TopoDS_Face _face; TopoDS_Face _face;
const StdMeshers_ViscousLayers2D* _hyp; vector< const THypVL* > _hyps;
vector< TopoDS_Shape > _hypShapes;
// result data // result data
SMESH_ProxyMesh::Ptr _proxyMesh; SMESH_ProxyMesh::Ptr _proxyMesh;
@ -388,11 +398,12 @@ namespace VISCOUS_2D
SMESH_MesherHelper _helper; SMESH_MesherHelper _helper;
TSideVector _faceSideVec; // wires (StdMeshers_FaceSide) of _face TSideVector _faceSideVec; // wires (StdMeshers_FaceSide) of _face
vector<_PolyLine> _polyLineVec; // fronts to advance vector<_PolyLine> _polyLineVec; // fronts to advance
vector< const THypVL* > _hypOfEdge; // a hyp per an EDGE of _faceSideVec
bool _is2DIsotropic; // is same U and V resoulution of _face bool _is2DIsotropic; // is same U and V resoulution of _face
vector<TopoDS_Face> _clearedFaces; // FACEs whose mesh was removed by shrink() vector<TopoDS_Face> _clearedFaces; // FACEs whose mesh was removed by shrink()
double _fPowN; // to compute thickness of layers //double _fPowN; // to compute thickness of layers
double _thickness; // required or possible layers thickness double _maxThickness; // max possible layers thickness
// sub-shapes of _face // sub-shapes of _face
set<TGeomID> _ignoreShapeIds; // ids of EDGEs w/o layers set<TGeomID> _ignoreShapeIds; // ids of EDGEs w/o layers
@ -409,15 +420,32 @@ namespace VISCOUS_2D
/*! /*!
* \brief Returns StdMeshers_ViscousLayers2D for the FACE * \brief Returns StdMeshers_ViscousLayers2D for the FACE
*/ */
const StdMeshers_ViscousLayers2D* findHyp(SMESH_Mesh& theMesh, bool findHyps(SMESH_Mesh& theMesh,
const TopoDS_Face& theFace, const TopoDS_Face& theFace,
TopoDS_Shape* assignedTo=0) vector< const StdMeshers_ViscousLayers2D* > & theHyps,
vector< TopoDS_Shape > & theAssignedTo)
{ {
theHyps.clear();
theAssignedTo.clear();
SMESH_HypoFilter hypFilter SMESH_HypoFilter hypFilter
( SMESH_HypoFilter::HasName( StdMeshers_ViscousLayers2D::GetHypType() )); ( SMESH_HypoFilter::HasName( StdMeshers_ViscousLayers2D::GetHypType() ));
const SMESH_Hypothesis * hyp = list< const SMESHDS_Hypothesis * > hypList;
theMesh.GetHypothesis( theFace, hypFilter, /*ancestors=*/true, assignedTo ); list< TopoDS_Shape > hypShapes;
return dynamic_cast< const StdMeshers_ViscousLayers2D* > ( hyp ); int nbHyps = theMesh.GetHypotheses
( theFace, hypFilter, hypList, /*ancestors=*/true, &hypShapes );
if ( nbHyps )
{
theHyps.reserve( nbHyps );
theAssignedTo.reserve( nbHyps );
list< const SMESHDS_Hypothesis * >::iterator hyp = hypList.begin();
list< TopoDS_Shape >::iterator shape = hypShapes.begin();
for ( ; hyp != hypList.end(); ++hyp, ++shape )
{
theHyps.push_back( static_cast< const StdMeshers_ViscousLayers2D* > ( *hyp ));
theAssignedTo.push_back( *shape );
}
}
return nbHyps;
} }
//================================================================================ //================================================================================
@ -436,7 +464,7 @@ namespace VISCOUS_2D
const SMESHDS_Mesh* theMesh, const SMESHDS_Mesh* theMesh,
set< int > & theEdgeIds) set< int > & theEdgeIds)
{ {
int nbToEdgesIgnore = 0; int nbEdgesToIgnore = 0;
vector<TGeomID> ids = theHyp->GetBndShapes(); vector<TGeomID> ids = theHyp->GetBndShapes();
if ( theHyp->IsToIgnoreShapes() ) // EDGEs to ignore are given if ( theHyp->IsToIgnoreShapes() ) // EDGEs to ignore are given
{ {
@ -448,20 +476,20 @@ namespace VISCOUS_2D
SMESH_MesherHelper::IsSubShape( E, theFace )) SMESH_MesherHelper::IsSubShape( E, theFace ))
{ {
theEdgeIds.insert( ids[i] ); theEdgeIds.insert( ids[i] );
++nbToEdgesIgnore; ++nbEdgesToIgnore;
} }
} }
} }
else // EDGEs to make the Viscous Layers on are given else // EDGEs to make the Viscous Layers on are given
{ {
TopExp_Explorer E( theFace, TopAbs_EDGE ); TopExp_Explorer E( theFace, TopAbs_EDGE );
for ( ; E.More(); E.Next(), ++nbToEdgesIgnore ) for ( ; E.More(); E.Next(), ++nbEdgesToIgnore )
theEdgeIds.insert( theMesh->ShapeToIndex( E.Current() )); theEdgeIds.insert( theMesh->ShapeToIndex( E.Current() ));
for ( size_t i = 0; i < ids.size(); ++i ) for ( size_t i = 0; i < ids.size(); ++i )
nbToEdgesIgnore -= theEdgeIds.erase( ids[i] ); nbEdgesToIgnore -= theEdgeIds.erase( ids[i] );
} }
return nbToEdgesIgnore; return nbEdgesToIgnore;
} }
} // namespace VISCOUS_2D } // namespace VISCOUS_2D
@ -489,12 +517,12 @@ StdMeshers_ViscousLayers2D::Compute(SMESH_Mesh& theMesh,
{ {
SMESH_ProxyMesh::Ptr pm; SMESH_ProxyMesh::Ptr pm;
TopoDS_Shape hypAssignedTo; vector< const StdMeshers_ViscousLayers2D* > hyps;
const StdMeshers_ViscousLayers2D* vlHyp = VISCOUS_2D::findHyp( theMesh, theFace, &hypAssignedTo ); vector< TopoDS_Shape > hypShapes;
if ( vlHyp ) if ( VISCOUS_2D::findHyps( theMesh, theFace, hyps, hypShapes ))
{ {
VISCOUS_2D::_ViscousBuilder2D builder( theMesh, theFace, vlHyp ); VISCOUS_2D::_ViscousBuilder2D builder( theMesh, theFace, hyps, hypShapes );
pm = builder.Compute( hypAssignedTo ); pm = builder.Compute();
SMESH_ComputeErrorPtr error = builder.GetError(); SMESH_ComputeErrorPtr error = builder.GetError();
if ( error && !error->IsOK() ) if ( error && !error->IsOK() )
theMesh.GetSubMesh( theFace )->GetComputeError() = error; theMesh.GetSubMesh( theFace )->GetComputeError() = error;
@ -510,6 +538,38 @@ StdMeshers_ViscousLayers2D::Compute(SMESH_Mesh& theMesh,
return pm; return pm;
} }
// -------------------------------------------------------------------------------- // --------------------------------------------------------------------------------
SMESH_ComputeErrorPtr
StdMeshers_ViscousLayers2D::CheckHypothesis(SMESH_Mesh& theMesh,
const TopoDS_Shape& theShape,
SMESH_Hypothesis::Hypothesis_Status& theStatus)
{
SMESH_ComputeErrorPtr error = SMESH_ComputeError::New(COMPERR_OK);
theStatus = SMESH_Hypothesis::HYP_OK;
TopExp_Explorer exp( theShape, TopAbs_FACE );
for ( ; exp.More() && theStatus == SMESH_Hypothesis::HYP_OK; exp.Next() )
{
const TopoDS_Face& face = TopoDS::Face( exp.Current() );
vector< const StdMeshers_ViscousLayers2D* > hyps;
vector< TopoDS_Shape > hypShapes;
if ( VISCOUS_2D::findHyps( theMesh, face, hyps, hypShapes ))
{
VISCOUS_2D::_ViscousBuilder2D builder( theMesh, face, hyps, hypShapes );
builder._faceSideVec =
StdMeshers_FaceSide::GetFaceWires( face, theMesh, true, error,
SMESH_ProxyMesh::Ptr(),
/*theCheckVertexNodes=*/false);
if ( error->IsOK() && !builder.findEdgesWithLayers())
{
error = builder.GetError();
if ( error && !error->IsOK() )
theStatus = SMESH_Hypothesis::HYP_INCOMPAT_HYPS;
}
}
}
return error;
}
// --------------------------------------------------------------------------------
void StdMeshers_ViscousLayers2D::RestoreListeners() const void StdMeshers_ViscousLayers2D::RestoreListeners() const
{ {
StudyContextStruct* sc = _gen->GetStudyContext( _studyId ); StudyContextStruct* sc = _gen->GetStudyContext( _studyId );
@ -547,19 +607,22 @@ using namespace VISCOUS_2D;
*/ */
//================================================================================ //================================================================================
_ViscousBuilder2D::_ViscousBuilder2D(SMESH_Mesh& theMesh, _ViscousBuilder2D::_ViscousBuilder2D(SMESH_Mesh& theMesh,
const TopoDS_Face& theFace, const TopoDS_Face& theFace,
const StdMeshers_ViscousLayers2D* theHyp): vector< const THypVL* > & theHyps,
_mesh( &theMesh ), _face( theFace ), _hyp( theHyp ), _helper( theMesh ) vector< TopoDS_Shape > & theAssignedTo):
_mesh( &theMesh ), _face( theFace ), _helper( theMesh )
{ {
_hyps.swap( theHyps );
_hypShapes.swap( theAssignedTo );
_helper.SetSubShape( _face ); _helper.SetSubShape( _face );
_helper.SetElementsOnShape( true ); _helper.SetElementsOnShape( true );
_face.Orientation( TopAbs_FORWARD ); // 2D logic works only in this case _face.Orientation( TopAbs_FORWARD ); // 2D logic works only in this case
_surface = BRep_Tool::Surface( _face ); _surface = BRep_Tool::Surface( _face );
if ( _hyp ) _error = SMESH_ComputeError::New(COMPERR_OK);
_fPowN = pow( _hyp->GetStretchFactor(), _hyp->GetNumberLayers() );
_nbLE = 0; _nbLE = 0;
} }
@ -593,14 +656,14 @@ bool _ViscousBuilder2D::error(const string& text )
*/ */
//================================================================================ //================================================================================
SMESH_ProxyMesh::Ptr _ViscousBuilder2D::Compute(const TopoDS_Shape& theShapeHypAssignedTo) SMESH_ProxyMesh::Ptr _ViscousBuilder2D::Compute()
{ {
_error = SMESH_ComputeError::New(COMPERR_OK); _faceSideVec = StdMeshers_FaceSide::GetFaceWires( _face, *_mesh, true, _error);
_faceSideVec = StdMeshers_FaceSide::GetFaceWires( _face, *_mesh, true, _error );
if ( !_error->IsOK() ) if ( !_error->IsOK() )
return _proxyMesh; return _proxyMesh;
if ( !findEdgesWithLayers(theShapeHypAssignedTo) ) // analysis of a shape if ( !findEdgesWithLayers() ) // analysis of a shape
return _proxyMesh; return _proxyMesh;
if ( ! makePolyLines() ) // creation of fronts if ( ! makePolyLines() ) // creation of fronts
@ -629,21 +692,79 @@ SMESH_ProxyMesh::Ptr _ViscousBuilder2D::Compute(const TopoDS_Shape& theShapeHypA
*/ */
//================================================================================ //================================================================================
bool _ViscousBuilder2D::findEdgesWithLayers(const TopoDS_Shape& theShapeHypAssignedTo) bool _ViscousBuilder2D::findEdgesWithLayers()
{ {
// collect all EDGEs to ignore defined by hyp // collect all EDGEs to ignore defined by _hyps
int nbMyEdgesIgnored = getEdgesToIgnore( _hyp, _face, getMeshDS(), _ignoreShapeIds ); typedef std::pair< set<TGeomID>, const THypVL* > TEdgesOfHyp;
vector< TEdgesOfHyp > ignoreEdgesOfHyp( _hyps.size() );
for ( size_t i = 0; i < _hyps.size(); ++i )
{
ignoreEdgesOfHyp[i].second = _hyps[i];
getEdgesToIgnore( _hyps[i], _face, getMeshDS(), ignoreEdgesOfHyp[i].first );
}
// get all shared EDGEs // get all shared EDGEs
TopTools_MapOfShape sharedEdges; TopTools_MapOfShape sharedEdges;
TopTools_IndexedMapOfShape hypFaces; // faces with VL hyps
for ( size_t i = 0; i < _hypShapes.size(); ++i )
TopExp::MapShapes( _hypShapes[i], TopAbs_FACE, hypFaces );
TopTools_IndexedDataMapOfShapeListOfShape facesOfEdgeMap; TopTools_IndexedDataMapOfShapeListOfShape facesOfEdgeMap;
TopExp::MapShapesAndAncestors( theShapeHypAssignedTo, for ( int iF = 1; iF <= hypFaces.Extent(); ++iF )
TopAbs_EDGE, TopAbs_FACE, facesOfEdgeMap); TopExp::MapShapesAndAncestors( hypFaces(iF), TopAbs_EDGE, TopAbs_FACE, facesOfEdgeMap);
for ( int iE = 1; iE <= facesOfEdgeMap.Extent(); ++iE ) for ( int iE = 1; iE <= facesOfEdgeMap.Extent(); ++iE )
if ( facesOfEdgeMap( iE ).Extent() > 1 ) if ( facesOfEdgeMap( iE ).Extent() > 1 )
sharedEdges.Add( facesOfEdgeMap.FindKey( iE )); sharedEdges.Add( facesOfEdgeMap.FindKey( iE ));
// check all EDGEs of the _face // fill _hypOfEdge
if ( _hyps.size() > 1 )
{
// check if two hypotheses define different parameters for the same EDGE
for ( size_t iWire = 0; iWire < _faceSideVec.size(); ++iWire )
{
StdMeshers_FaceSidePtr wire = _faceSideVec[ iWire ];
for ( int iE = 0; iE < wire->NbEdges(); ++iE )
{
const THypVL* hyp = 0;
const TGeomID edgeID = wire->EdgeID( iE );
if ( !sharedEdges.Contains( wire->Edge( iE )))
{
for ( size_t i = 0; i < ignoreEdgesOfHyp.size(); ++i )
if ( ! ignoreEdgesOfHyp[i].first.count( edgeID ))
{
if ( hyp )
return error(SMESH_Comment("Several hypotheses define "
"Viscous Layers on the edge #") << edgeID );
hyp = ignoreEdgesOfHyp[i].second;
}
}
_hypOfEdge.push_back( hyp );
if ( !hyp )
_ignoreShapeIds.insert( edgeID );
}
// check if two hypotheses define different number of viscous layers for
// adjacent EDGEs
const THypVL *hyp, *prevHyp = _hypOfEdge.back();
size_t iH = _hypOfEdge.size() - wire->NbEdges();
for ( ; iH < _hypOfEdge.size(); ++iH )
{
hyp = _hypOfEdge[ iH ];
if ( hyp && prevHyp &&
hyp->GetNumberLayers() != prevHyp->GetNumberLayers() )
{
return error("Two hypotheses define different number of "
"viscous layers on adjacent edges");
}
prevHyp = hyp;
}
}
}
else if ( _hyps.size() == 1 )
{
_ignoreShapeIds.swap( ignoreEdgesOfHyp[0].first );
}
// check all EDGEs of the _face to fill _ignoreShapeIds and _noShrinkVert
int totalNbEdges = 0; int totalNbEdges = 0;
for ( size_t iWire = 0; iWire < _faceSideVec.size(); ++iWire ) for ( size_t iWire = 0; iWire < _faceSideVec.size(); ++iWire )
{ {
@ -674,9 +795,9 @@ bool _ViscousBuilder2D::findEdgesWithLayers(const TopoDS_Shape& theShapeHypAssig
for ( ; hyp != allHyps.end() && !viscHyp; ++hyp ) for ( ; hyp != allHyps.end() && !viscHyp; ++hyp )
viscHyp = dynamic_cast<const StdMeshers_ViscousLayers2D*>( *hyp ); viscHyp = dynamic_cast<const StdMeshers_ViscousLayers2D*>( *hyp );
set<TGeomID> neighbourIgnoreEdges; // set<TGeomID> neighbourIgnoreEdges;
if (viscHyp) // if (viscHyp)
getEdgesToIgnore( viscHyp, neighbourFace, getMeshDS(), neighbourIgnoreEdges ); // getEdgesToIgnore( viscHyp, neighbourFace, getMeshDS(), neighbourIgnoreEdges );
for ( int iV = 0; iV < 2; ++iV ) for ( int iV = 0; iV < 2; ++iV )
{ {
@ -688,12 +809,22 @@ bool _ViscousBuilder2D::findEdgesWithLayers(const TopoDS_Shape& theShapeHypAssig
PShapeIteratorPtr edgeIt = _helper.GetAncestors( vertex, *_mesh, TopAbs_EDGE ); PShapeIteratorPtr edgeIt = _helper.GetAncestors( vertex, *_mesh, TopAbs_EDGE );
while ( const TopoDS_Shape* edge = edgeIt->next() ) while ( const TopoDS_Shape* edge = edgeIt->next() )
if ( !edge->IsSame( wire->Edge( iE )) && if ( !edge->IsSame( wire->Edge( iE )) &&
_helper.IsSubShape( *edge, neighbourFace ) && _helper.IsSubShape( *edge, neighbourFace ))
( neighbourIgnoreEdges.count( getMeshDS()->ShapeToIndex( *edge )) ||
sharedEdges.Contains( *edge )))
{ {
_noShrinkVert.insert( getMeshDS()->ShapeToIndex( vertex )); const TGeomID neighbourID = getMeshDS()->ShapeToIndex( *edge );
break; bool hasVL = !sharedEdges.Contains( *edge );
if ( hasVL )
{
hasVL = false;
for ( hyp = allHyps.begin(); hyp != allHyps.end() && !hasVL; ++hyp )
if ( viscHyp = dynamic_cast<const THypVL*>( *hyp ))
hasVL = viscHyp->IsShapeWithLayers( neighbourID );
}
if ( !hasVL )
{
_noShrinkVert.insert( getMeshDS()->ShapeToIndex( vertex ));
break;
}
} }
} }
} }
@ -702,18 +833,20 @@ bool _ViscousBuilder2D::findEdgesWithLayers(const TopoDS_Shape& theShapeHypAssig
} }
} }
int nbMyEdgesIgnored = _ignoreShapeIds.size();
// add VERTEXes w/o layers to _ignoreShapeIds (this is used by toShrinkForAdjacent()) // add VERTEXes w/o layers to _ignoreShapeIds (this is used by toShrinkForAdjacent())
for ( size_t iWire = 0; iWire < _faceSideVec.size(); ++iWire ) // for ( size_t iWire = 0; iWire < _faceSideVec.size(); ++iWire )
{ // {
StdMeshers_FaceSidePtr wire = _faceSideVec[ iWire ]; // StdMeshers_FaceSidePtr wire = _faceSideVec[ iWire ];
for ( int iE = 0; iE < wire->NbEdges(); ++iE ) // for ( int iE = 0; iE < wire->NbEdges(); ++iE )
{ // {
TGeomID edge1 = wire->EdgeID( iE ); // TGeomID edge1 = wire->EdgeID( iE );
TGeomID edge2 = wire->EdgeID( iE+1 ); // TGeomID edge2 = wire->EdgeID( iE+1 );
if ( _ignoreShapeIds.count( edge1 ) && _ignoreShapeIds.count( edge2 )) // if ( _ignoreShapeIds.count( edge1 ) && _ignoreShapeIds.count( edge2 ))
_ignoreShapeIds.insert( getMeshDS()->ShapeToIndex( wire->LastVertex( iE ))); // _ignoreShapeIds.insert( getMeshDS()->ShapeToIndex( wire->LastVertex( iE )));
} // }
} // }
return ( nbMyEdgesIgnored < totalNbEdges ); return ( nbMyEdgesIgnored < totalNbEdges );
} }
@ -772,6 +905,7 @@ bool _ViscousBuilder2D::makePolyLines()
for ( int iE = 0; iE < wire->NbEdges(); ++iE ) for ( int iE = 0; iE < wire->NbEdges(); ++iE )
{ {
_PolyLine& L = _polyLineVec[ iPoLine++ ]; _PolyLine& L = _polyLineVec[ iPoLine++ ];
L._index = iPoLine-1;
L._wire = wire.get(); L._wire = wire.get();
L._edgeInd = iE; L._edgeInd = iE;
L._advancable = !_ignoreShapeIds.count( wire->EdgeID( iE )); L._advancable = !_ignoreShapeIds.count( wire->EdgeID( iE ));
@ -846,13 +980,16 @@ bool _ViscousBuilder2D::makePolyLines()
// Evaluate max possible _thickness if required layers thickness seems too high // Evaluate max possible _thickness if required layers thickness seems too high
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
_thickness = _hyp->GetTotalThickness(); _maxThickness = _hyps[0]->GetTotalThickness();
for ( size_t iH = 1; iH < _hyps.size(); ++iH )
_maxThickness = Max( _maxThickness, _hyps[iH]->GetTotalThickness() );
_SegmentTree::box_type faceBndBox2D; _SegmentTree::box_type faceBndBox2D;
for ( iPoLine = 0; iPoLine < _polyLineVec.size(); ++iPoLine ) for ( iPoLine = 0; iPoLine < _polyLineVec.size(); ++iPoLine )
faceBndBox2D.Add( *_polyLineVec[ iPoLine]._segTree->getBox() ); faceBndBox2D.Add( *_polyLineVec[ iPoLine]._segTree->getBox() );
double boxTol = 1e-3 * sqrt( faceBndBox2D.SquareExtent() ); const double boxTol = 1e-3 * sqrt( faceBndBox2D.SquareExtent() );
//
if ( _thickness * maxLen2dTo3dRatio > sqrt( faceBndBox2D.SquareExtent() ) / 10 ) if ( _maxThickness * maxLen2dTo3dRatio > sqrt( faceBndBox2D.SquareExtent() ) / 10 )
{ {
vector< const _Segment* > foundSegs; vector< const _Segment* > foundSegs;
double maxPossibleThick = 0; double maxPossibleThick = 0;
@ -885,7 +1022,7 @@ bool _ViscousBuilder2D::makePolyLines()
} }
} }
if ( maxPossibleThick > 0. ) if ( maxPossibleThick > 0. )
_thickness = Min( _hyp->GetTotalThickness(), maxPossibleThick ); _maxThickness = Min( _maxThickness, maxPossibleThick );
} }
// Adjust _LayerEdge's at _PolyLine's extremities // Adjust _LayerEdge's at _PolyLine's extremities
@ -930,13 +1067,14 @@ bool _ViscousBuilder2D::makePolyLines()
for ( iPoLine = 0; iPoLine < _polyLineVec.size(); ++iPoLine ) for ( iPoLine = 0; iPoLine < _polyLineVec.size(); ++iPoLine )
{ {
lineBoxes[ iPoLine ] = *_polyLineVec[ iPoLine ]._segTree->getBox(); lineBoxes[ iPoLine ] = *_polyLineVec[ iPoLine ]._segTree->getBox();
lineBoxes[ iPoLine ].Enlarge( maxLen2dTo3dRatio * _thickness * lineBoxes[ iPoLine ].Enlarge( maxLen2dTo3dRatio * getLineThickness( iPoLine ) *
( _polyLineVec[ iPoLine ]._advancable ? 2. : 1.2 )); ( _polyLineVec[ iPoLine ]._advancable ? 2. : 1.2 ));
} }
// _reachableLines // _reachableLines
for ( iPoLine = 0; iPoLine < _polyLineVec.size(); ++iPoLine ) for ( iPoLine = 0; iPoLine < _polyLineVec.size(); ++iPoLine )
{ {
_PolyLine& L1 = _polyLineVec[ iPoLine ]; _PolyLine& L1 = _polyLineVec[ iPoLine ];
const double thick1 = getLineThickness( iPoLine );
for ( size_t iL2 = 0; iL2 < _polyLineVec.size(); ++iL2 ) for ( size_t iL2 = 0; iL2 < _polyLineVec.size(); ++iL2 )
{ {
_PolyLine& L2 = _polyLineVec[ iL2 ]; _PolyLine& L2 = _polyLineVec[ iL2 ];
@ -950,7 +1088,7 @@ bool _ViscousBuilder2D::makePolyLines()
{ {
_LayerEdge& LE = L1._lEdges[iLE]; _LayerEdge& LE = L1._lEdges[iLE];
if ( !lineBoxes[ iL2 ].IsOut ( LE._uvOut, if ( !lineBoxes[ iL2 ].IsOut ( LE._uvOut,
LE._uvOut + LE._normal2D *_thickness * LE._len2dTo3dRatio )) LE._uvOut + LE._normal2D * thick1 * LE._len2dTo3dRatio ))
{ {
L1._reachableLines.push_back( & L2 ); L1._reachableLines.push_back( & L2 );
break; break;
@ -1024,9 +1162,9 @@ void _ViscousBuilder2D::adjustCommonEdge( _PolyLine& LL, _PolyLine& LR )
// during inflate(). // during inflate().
// //
// find max length of the VERTEX-based _LayerEdge whose direction is normAvg // find max length of the VERTEX-based _LayerEdge whose direction is normAvg
double maxLen2D = _thickness * EL._len2dTo3dRatio; double maxLen2D = _maxThickness * EL._len2dTo3dRatio;
const gp_XY& pCommOut = ER._uvOut; const gp_XY& pCommOut = ER._uvOut;
gp_XY pCommIn = pCommOut + normAvg * maxLen2D; gp_XY pCommIn = pCommOut + normAvg * maxLen2D;
_Segment segCommon( pCommOut, pCommIn ); _Segment segCommon( pCommOut, pCommIn );
_SegmentIntersection intersection; _SegmentIntersection intersection;
vector< const _Segment* > foundSegs; vector< const _Segment* > foundSegs;
@ -1067,7 +1205,7 @@ void _ViscousBuilder2D::adjustCommonEdge( _PolyLine& LL, _PolyLine& LR )
_SegmentIntersection lastIntersection; _SegmentIntersection lastIntersection;
for ( ; iLE < L._lEdges.size(); ++iLE, eIt += dIt ) for ( ; iLE < L._lEdges.size(); ++iLE, eIt += dIt )
{ {
gp_XY uvIn = eIt->_uvOut + eIt->_normal2D * _thickness * eIt->_len2dTo3dRatio; gp_XY uvIn = eIt->_uvOut + eIt->_normal2D * _maxThickness * eIt->_len2dTo3dRatio;
_Segment segOfEdge( eIt->_uvOut, uvIn ); _Segment segOfEdge( eIt->_uvOut, uvIn );
if ( !intersection.Compute( segCommon, segOfEdge )) if ( !intersection.Compute( segCommon, segOfEdge ))
break; break;
@ -1148,7 +1286,7 @@ void _ViscousBuilder2D::setLayerEdgeData( _LayerEdge& lEdge,
gp_Vec faceNorm = du ^ dv; gp_Vec faceNorm = du ^ dv;
gp_Vec normal = faceNorm ^ tangent; gp_Vec normal = faceNorm ^ tangent;
normal.Normalize(); normal.Normalize();
p = pOut.XYZ() + normal.XYZ() * /*1e-2 * */_hyp->GetTotalThickness() / _hyp->GetNumberLayers(); p = pOut.XYZ() + normal.XYZ() * /*1e-2 * */_hyps[0]->GetTotalThickness() / _hyps[0]->GetNumberLayers();
faceProj->Perform( p ); faceProj->Perform( p );
if ( !faceProj->IsDone() || faceProj->NbPoints() < 1 ) if ( !faceProj->IsDone() || faceProj->NbPoints() < 1 )
return setLayerEdgeData( lEdge, u, pcurve, curve, p, reverse, NULL ); return setLayerEdgeData( lEdge, u, pcurve, curve, p, reverse, NULL );
@ -1205,7 +1343,7 @@ bool _ViscousBuilder2D::inflate()
{ {
// Limit size of inflation step by geometry size found by // Limit size of inflation step by geometry size found by
// itersecting _LayerEdge's with _Segment's // itersecting _LayerEdge's with _Segment's
double minSize = _thickness, maxSize = 0; double minSize = _maxThickness, maxSize = 0;
vector< const _Segment* > foundSegs; vector< const _Segment* > foundSegs;
_SegmentIntersection intersection; _SegmentIntersection intersection;
for ( size_t iL1 = 0; iL1 < _polyLineVec.size(); ++iL1 ) for ( size_t iL1 = 0; iL1 < _polyLineVec.size(); ++iL1 )
@ -1233,29 +1371,30 @@ bool _ViscousBuilder2D::inflate()
} }
} }
if ( minSize > maxSize ) // no collisions possible if ( minSize > maxSize ) // no collisions possible
maxSize = _thickness; maxSize = _maxThickness;
#ifdef __myDEBUG #ifdef __myDEBUG
cout << "-- minSize = " << minSize << ", maxSize = " << maxSize << endl; cout << "-- minSize = " << minSize << ", maxSize = " << maxSize << endl;
#endif #endif
double curThick = 0, stepSize = minSize; double curThick = 0, stepSize = minSize;
int nbSteps = 0; int nbSteps = 0;
if ( maxSize > _thickness ) if ( maxSize > _maxThickness )
maxSize = _thickness; maxSize = _maxThickness;
while ( curThick < maxSize ) while ( curThick < maxSize )
{ {
curThick += stepSize * 1.25; curThick += stepSize * 1.25;
if ( curThick > _thickness ) if ( curThick > _maxThickness )
curThick = _thickness; curThick = _maxThickness;
// Elongate _LayerEdge's // Elongate _LayerEdge's
for ( size_t iL = 0; iL < _polyLineVec.size(); ++iL ) for ( size_t iL = 0; iL < _polyLineVec.size(); ++iL )
{ {
_PolyLine& L = _polyLineVec[ iL ]; _PolyLine& L = _polyLineVec[ iL ];
if ( !L._advancable ) continue; if ( !L._advancable ) continue;
const double lineThick = Min( curThick, getLineThickness( iL ));
bool lenChange = false; bool lenChange = false;
for ( size_t iLE = L.FirstLEdge(); iLE < L._lEdges.size(); ++iLE ) for ( size_t iLE = L.FirstLEdge(); iLE < L._lEdges.size(); ++iLE )
lenChange |= L._lEdges[iLE].SetNewLength( curThick ); lenChange |= L._lEdges[iLE].SetNewLength( lineThick );
// for ( int k=0; k<L._segments.size(); ++k) // for ( int k=0; k<L._segments.size(); ++k)
// cout << "( " << L._segments[k].p1().X() << ", " <<L._segments[k].p1().Y() << " ) " // cout << "( " << L._segments[k].p1().X() << ", " <<L._segments[k].p1().Y() << " ) "
// << "( " << L._segments[k].p2().X() << ", " <<L._segments[k].p2().Y() << " ) " // << "( " << L._segments[k].p2().X() << ", " <<L._segments[k].p2().Y() << " ) "
@ -1270,7 +1409,7 @@ bool _ViscousBuilder2D::inflate()
{ {
break; // no more inflating possible break; // no more inflating possible
} }
stepSize = Max( stepSize , _thickness / 10. ); stepSize = Max( stepSize , _maxThickness / 10. );
nbSteps++; nbSteps++;
} }
@ -1533,26 +1672,28 @@ bool _ViscousBuilder2D::shrink()
int iPFrom = L._firstPntInd, iPTo = L._lastPntInd; int iPFrom = L._firstPntInd, iPTo = L._lastPntInd;
if ( isShrinkableL ) if ( isShrinkableL )
{ {
const THypVL* hyp = getLineHypothesis( L._leftLine->_index );
vector<gp_XY>& uvVec = L._lEdges.front()._uvRefined; vector<gp_XY>& uvVec = L._lEdges.front()._uvRefined;
for ( int i = 0; i < _hyp->GetNumberLayers(); ++i ) { for ( int i = 0; i < hyp->GetNumberLayers(); ++i ) {
const UVPtStruct& uvPt = points[ iPFrom + i + 1 ]; const UVPtStruct& uvPt = points[ iPFrom + i + 1 ];
L._leftNodes.push_back( uvPt.node ); L._leftNodes.push_back( uvPt.node );
uvVec.push_back ( pcurve->Value( uvPt.param ).XY() ); uvVec.push_back ( pcurve->Value( uvPt.param ).XY() );
} }
iPFrom += hyp->GetNumberLayers();
} }
if ( isShrinkableR ) if ( isShrinkableR )
{ {
const THypVL* hyp = getLineHypothesis( L._rightLine->_index );
vector<gp_XY>& uvVec = L._lEdges.back()._uvRefined; vector<gp_XY>& uvVec = L._lEdges.back()._uvRefined;
for ( int i = 0; i < _hyp->GetNumberLayers(); ++i ) { for ( int i = 0; i < hyp->GetNumberLayers(); ++i ) {
const UVPtStruct& uvPt = points[ iPTo - i - 1 ]; const UVPtStruct& uvPt = points[ iPTo - i - 1 ];
L._rightNodes.push_back( uvPt.node ); L._rightNodes.push_back( uvPt.node );
uvVec.push_back ( pcurve->Value( uvPt.param ).XY() ); uvVec.push_back ( pcurve->Value( uvPt.param ).XY() );
} }
iPTo -= hyp->GetNumberLayers();
} }
// make proxy sub-mesh data of present nodes // make proxy sub-mesh data of present nodes
// //
if ( isShrinkableL ) iPFrom += _hyp->GetNumberLayers();
if ( isShrinkableR ) iPTo -= _hyp->GetNumberLayers();
UVPtStructVec nodeDataVec( & points[ iPFrom ], & points[ iPTo + 1 ]); UVPtStructVec nodeDataVec( & points[ iPFrom ], & points[ iPTo + 1 ]);
double normSize = nodeDataVec.back().normParam - nodeDataVec.front().normParam; double normSize = nodeDataVec.back().normParam - nodeDataVec.front().normParam;
@ -1723,14 +1864,14 @@ bool _ViscousBuilder2D::shrink()
( isR ? L._leftLine->_lEdges.back() : L._rightLine->_lEdges.front() ); ( isR ? L._leftLine->_lEdges.back() : L._rightLine->_lEdges.front() );
length2D = neighborLE._length2D; length2D = neighborLE._length2D;
if ( length2D == 0 ) if ( length2D == 0 )
length2D = _thickness * nearLE._len2dTo3dRatio; length2D = _maxThickness * nearLE._len2dTo3dRatio;
} }
} }
// move u to the internal boundary of layers // move u to the internal boundary of layers
// u --> u // u --> u
// x-x-x-x-----x-----x---- // x-x-x-x-----x-----x----
double maxLen3D = Min( _thickness, edgeLen / ( 1 + nbAdvancable )); double maxLen3D = Min( _maxThickness, edgeLen / ( 1 + nbAdvancable ));
double maxLen2D = maxLen3D * nearLE._len2dTo3dRatio; double maxLen2D = maxLen3D * nearLE._len2dTo3dRatio;
if ( !length2D ) length2D = length1D / len1dTo2dRatio; if ( !length2D ) length2D = length1D / len1dTo2dRatio;
if ( Abs( length2D ) > maxLen2D ) if ( Abs( length2D ) > maxLen2D )
@ -1746,7 +1887,8 @@ bool _ViscousBuilder2D::shrink()
// compute params of layers on L // compute params of layers on L
vector<double> heights; vector<double> heights;
calcLayersHeight( u - u0, heights ); const THypVL* hyp = getLineHypothesis( L2->_index );
calcLayersHeight( u - u0, heights, hyp );
// //
vector< double > params( heights.size() ); vector< double > params( heights.size() );
for ( size_t i = 0; i < params.size(); ++i ) for ( size_t i = 0; i < params.size(); ++i )
@ -1756,13 +1898,13 @@ bool _ViscousBuilder2D::shrink()
// x-x-x-x--- // x-x-x-x---
vector< const SMDS_MeshNode* >& layersNode = isR ? L._rightNodes : L._leftNodes; vector< const SMDS_MeshNode* >& layersNode = isR ? L._rightNodes : L._leftNodes;
vector<gp_XY>& nodeUV = ( isR ? L._lEdges.back() : L._lEdges[0] )._uvRefined; vector<gp_XY>& nodeUV = ( isR ? L._lEdges.back() : L._lEdges[0] )._uvRefined;
nodeUV.resize ( _hyp->GetNumberLayers() ); nodeUV.resize ( hyp->GetNumberLayers() );
layersNode.resize( _hyp->GetNumberLayers() ); layersNode.resize( hyp->GetNumberLayers() );
const SMDS_MeshNode* vertexNode = nodeDataVec[ iPEnd ].node; const SMDS_MeshNode* vertexNode = nodeDataVec[ iPEnd ].node;
const SMDS_MeshNode * prevNode = vertexNode; const SMDS_MeshNode * prevNode = vertexNode;
for ( size_t i = 0; i < params.size(); ++i ) for ( size_t i = 0; i < params.size(); ++i )
{ {
gp_Pnt p = curve.Value( params[i] ); const gp_Pnt p = curve.Value( params[i] );
layersNode[ i ] = helper.AddNode( p.X(), p.Y(), p.Z(), /*id=*/0, params[i] ); layersNode[ i ] = helper.AddNode( p.X(), p.Y(), p.Z(), /*id=*/0, params[i] );
nodeUV [ i ] = pcurve->Value( params[i] ).XY(); nodeUV [ i ] = pcurve->Value( params[i] ).XY();
helper.AddEdge( prevNode, layersNode[ i ] ); helper.AddEdge( prevNode, layersNode[ i ] );
@ -1773,7 +1915,7 @@ bool _ViscousBuilder2D::shrink()
if ( !L2->_advancable ) if ( !L2->_advancable )
{ {
isRShrinkedForAdjacent = isR; isRShrinkedForAdjacent = isR;
nodeDataForAdjacent.resize( _hyp->GetNumberLayers() ); nodeDataForAdjacent.resize( hyp->GetNumberLayers() );
size_t iFrw = 0, iRev = nodeDataForAdjacent.size()-1, *i = isR ? &iRev : &iFrw; size_t iFrw = 0, iRev = nodeDataForAdjacent.size()-1, *i = isR ? &iRev : &iFrw;
nodeDataForAdjacent[ *i ] = points[ isR ? L._lastPntInd : L._firstPntInd ]; nodeDataForAdjacent[ *i ] = points[ isR ? L._lastPntInd : L._firstPntInd ];
@ -1890,11 +2032,11 @@ bool _ViscousBuilder2D::shrink()
{ {
// refine the not shared _LayerEdge // refine the not shared _LayerEdge
vector<double> layersHeight; vector<double> layersHeight;
calcLayersHeight( LE2._length2D, layersHeight ); calcLayersHeight( LE2._length2D, layersHeight, getLineHypothesis( L2._index ));
vector<gp_XY>& nodeUV2 = LE2._uvRefined; vector<gp_XY>& nodeUV2 = LE2._uvRefined;
nodeUV2.resize ( _hyp->GetNumberLayers() ); nodeUV2.resize ( layersHeight.size() );
layerNodes2.resize( _hyp->GetNumberLayers() ); layerNodes2.resize( layersHeight.size() );
for ( size_t i = 0; i < layersHeight.size(); ++i ) for ( size_t i = 0; i < layersHeight.size(); ++i )
{ {
gp_XY uv = LE2._uvOut + LE2._normal2D * layersHeight[i]; gp_XY uv = LE2._uvOut + LE2._normal2D * layersHeight[i];
@ -1952,12 +2094,13 @@ bool _ViscousBuilder2D::toShrinkForAdjacent( const TopoDS_Face& adjFace,
if ( _noShrinkVert.count( getMeshDS()->ShapeToIndex( V )) || adjFace.IsNull() ) if ( _noShrinkVert.count( getMeshDS()->ShapeToIndex( V )) || adjFace.IsNull() )
return false; return false;
TopoDS_Shape hypAssignedTo; vector< const StdMeshers_ViscousLayers2D* > hyps;
if ( const StdMeshers_ViscousLayers2D* vlHyp = findHyp( *_mesh, adjFace, &hypAssignedTo )) vector< TopoDS_Shape > hypShapes;
if ( VISCOUS_2D::findHyps( *_mesh, adjFace, hyps, hypShapes ))
{ {
VISCOUS_2D::_ViscousBuilder2D builder( *_mesh, adjFace, vlHyp ); VISCOUS_2D::_ViscousBuilder2D builder( *_mesh, adjFace, hyps, hypShapes );
builder._faceSideVec = StdMeshers_FaceSide::GetFaceWires( adjFace, *_mesh, true, _error ); builder._faceSideVec = StdMeshers_FaceSide::GetFaceWires( adjFace, *_mesh, true, _error );
builder.findEdgesWithLayers( hypAssignedTo ); builder.findEdgesWithLayers();
PShapeIteratorPtr edgeIt = _helper.GetAncestors( V, *_mesh, TopAbs_EDGE ); PShapeIteratorPtr edgeIt = _helper.GetAncestors( V, *_mesh, TopAbs_EDGE );
while ( const TopoDS_Shape* edgeAtV = edgeIt->next() ) while ( const TopoDS_Shape* edgeAtV = edgeIt->next() )
@ -2180,7 +2323,8 @@ bool _ViscousBuilder2D::refine()
} }
// normalized height of layers // normalized height of layers
calcLayersHeight( 1., layersHeight ); const THypVL* hyp = getLineHypothesis( iL );
calcLayersHeight( 1., layersHeight, hyp);
// Create layers of faces // Create layers of faces
@ -2192,11 +2336,11 @@ bool _ViscousBuilder2D::refine()
for ( int i = L._firstPntInd; i <= L._lastPntInd; ++i ) for ( int i = L._firstPntInd; i <= L._lastPntInd; ++i )
outerNodes[ i-L._firstPntInd ] = points[i].node; outerNodes[ i-L._firstPntInd ] = points[i].node;
L._leftNodes .reserve( _hyp->GetNumberLayers() ); L._leftNodes .reserve( hyp->GetNumberLayers() );
L._rightNodes.reserve( _hyp->GetNumberLayers() ); L._rightNodes.reserve( hyp->GetNumberLayers() );
int cur = 0, prev = -1; // to take into account orientation of _face int cur = 0, prev = -1; // to take into account orientation of _face
if ( isReverse ) std::swap( cur, prev ); if ( isReverse ) std::swap( cur, prev );
for ( int iF = 0; iF < _hyp->GetNumberLayers(); ++iF ) // loop on layers of faces for ( int iF = 0; iF < hyp->GetNumberLayers(); ++iF ) // loop on layers of faces
{ {
// create innerNodes of a current layer // create innerNodes of a current layer
for ( size_t i = iN0; i < iNE; ++i ) for ( size_t i = iN0; i < iNE; ++i )
@ -2358,6 +2502,30 @@ bool _ViscousBuilder2D::removeMeshFaces(const TopoDS_Shape& face)
return thereWereElems; return thereWereElems;
} }
//================================================================================
/*!
* \brief Returns a hypothesis for a _PolyLine
*/
//================================================================================
const StdMeshers_ViscousLayers2D* _ViscousBuilder2D::getLineHypothesis(int iPL)
{
return iPL < (int)_hypOfEdge.size() ? _hypOfEdge[ iPL ] : _hyps[0];
}
//================================================================================
/*!
* \brief Returns a layers thickness for a _PolyLine
*/
//================================================================================
double _ViscousBuilder2D::getLineThickness(int iPL)
{
if ( const StdMeshers_ViscousLayers2D* h = getLineHypothesis( iPL ))
return Min( _maxThickness, h->GetTotalThickness() );
return _maxThickness;
}
//================================================================================ //================================================================================
/*! /*!
* \brief Creates a _ProxyMeshOfFace and store it in a sub-mesh of FACE * \brief Creates a _ProxyMeshOfFace and store it in a sub-mesh of FACE
@ -2384,21 +2552,23 @@ _ProxyMeshOfFace* _ViscousBuilder2D::getProxyMesh()
//================================================================================ //================================================================================
void _ViscousBuilder2D::calcLayersHeight(const double totalThick, void _ViscousBuilder2D::calcLayersHeight(const double totalThick,
vector<double>& heights) vector<double>& heights,
const THypVL* hyp)
{ {
heights.resize( _hyp->GetNumberLayers() ); const double fPowN = pow( hyp->GetStretchFactor(), hyp->GetNumberLayers() );
heights.resize( hyp->GetNumberLayers() );
double h0; double h0;
if ( _fPowN - 1 <= numeric_limits<double>::min() ) if ( fPowN - 1 <= numeric_limits<double>::min() )
h0 = totalThick / _hyp->GetNumberLayers(); h0 = totalThick / hyp->GetNumberLayers();
else else
h0 = totalThick * ( _hyp->GetStretchFactor() - 1 )/( _fPowN - 1 ); h0 = totalThick * ( hyp->GetStretchFactor() - 1 )/( fPowN - 1 );
double hSum = 0, hi = h0; double hSum = 0, hi = h0;
for ( int i = 0; i < _hyp->GetNumberLayers(); ++i ) for ( int i = 0; i < hyp->GetNumberLayers(); ++i )
{ {
hSum += hi; hSum += hi;
heights[ i ] = hSum; heights[ i ] = hSum;
hi *= _hyp->GetStretchFactor(); hi *= hyp->GetStretchFactor();
} }
} }

View File

@ -35,9 +35,10 @@ class STDMESHERS_EXPORT StdMeshers_ViscousLayers2D : public StdMeshers_ViscousLa
{ {
public: public:
StdMeshers_ViscousLayers2D(int hypId, int studyId, SMESH_Gen* gen); StdMeshers_ViscousLayers2D(int hypId, int studyId, SMESH_Gen* gen);
/*!
// Computes temporary 2D mesh to be used by 2D algorithm. * \brief Computes temporary 2D mesh to be used by 2D algorithm.
// Return SMESH_ProxyMesh for the given FACE, or NULL in case of error * Return SMESH_ProxyMesh for the given FACE, or NULL in case of error
*/
static SMESH_ProxyMesh::Ptr Compute(SMESH_Mesh& theMesh, static SMESH_ProxyMesh::Ptr Compute(SMESH_Mesh& theMesh,
const TopoDS_Face& theShape); const TopoDS_Face& theShape);
/*! /*!
@ -46,13 +47,19 @@ public:
*/ */
void RestoreListeners() const; void RestoreListeners() const;
/*!
* \brief Checks compatibility of assigned StdMeshers_ViscousLayers2D hypotheses
*/
static SMESH_ComputeErrorPtr CheckHypothesis(SMESH_Mesh& aMesh,
const TopoDS_Shape& aShape,
Hypothesis_Status& aStatus);
/*! /*!
* \brief Initialize my parameter values by the mesh built on the geometry * \brief Initialize my parameter values by the mesh built on the geometry
* \param theMesh - the built mesh * \param theMesh - the built mesh
* \param theShape - the geometry of interest * \param theShape - the geometry of interest
* \retval bool - true if parameter values have been successfully defined * \retval bool - true if parameter values have been successfully defined
* *
* Just return false as this hypothesis does not have parameters values * Just return false as this hypothesis does not have parameters values
*/ */
virtual bool SetParametersByMesh(const SMESH_Mesh* theMesh, const TopoDS_Shape& theShape); virtual bool SetParametersByMesh(const SMESH_Mesh* theMesh, const TopoDS_Shape& theShape);