diff --git a/doc/salome/examples/defining_hypotheses_ex01.py b/doc/salome/examples/defining_hypotheses_ex01.py
index 4bb75c56b..1d5d281c8 100644
--- a/doc/salome/examples/defining_hypotheses_ex01.py
+++ b/doc/salome/examples/defining_hypotheses_ex01.py
@@ -1,12 +1,11 @@
-# Arithmetic 1D
+# Arithmetic 1D and Geometric Progression
import salome
salome.salome_init()
-import GEOM
+
from salome.geom import geomBuilder
geompy = geomBuilder.New(salome.myStudy)
-import SMESH, SALOMEDS
from salome.smesh import smeshBuilder
smesh = smeshBuilder.New(salome.myStudy)
@@ -21,12 +20,20 @@ hexa = smesh.Mesh(box, "Box : hexahedrical mesh")
algo1D = hexa.Segment()
# optionally reverse node distribution on certain edges
-allEdges = geompy.SubShapeAllSortedIDs( box, geompy.ShapeType["EDGE"])
+allEdges = geompy.SubShapeAllSorted( box, geompy.ShapeType["EDGE"])
reversedEdges = [ allEdges[0], allEdges[4] ]
# define "Arithmetic1D" hypothesis to cut all edges in several segments with increasing arithmetic length
algo1D.Arithmetic1D(1, 4, reversedEdges)
+# define "Geometric Progression" hypothesis on one edge to cut this edge in segments with length increasing by 20% starting from 1
+gpAlgo = hexa.Segment( allEdges[1] )
+gpAlgo.GeometricProgression( 1, 1.2 )
+
+# propagate distribution of nodes computed using "Geometric Progression" to parallel edges
+gpAlgo.PropagationOfDistribution()
+
+
# create a quadrangle 2D algorithm for faces
hexa.Quadrangle()
diff --git a/doc/salome/examples/defining_hypotheses_ex08.py b/doc/salome/examples/defining_hypotheses_ex08.py
index 34fcbc377..3c877f3da 100644
--- a/doc/salome/examples/defining_hypotheses_ex08.py
+++ b/doc/salome/examples/defining_hypotheses_ex08.py
@@ -11,7 +11,8 @@ from salome.smesh import smeshBuilder
smesh = smeshBuilder.New(salome.myStudy)
# create a box
-box = geompy.MakeBoxDXDYDZ(10., 10., 10.)
+base = geompy.MakeSketcher("Sketcher:F 0 0:TT 10 0:TT 20 10:TT 0 10:WF", theName="F")
+box = geompy.MakePrismDXDYDZ( base, 0,0,10 )
geompy.addToStudy(box, "Box")
# get one edge of the box to put local hypothesis on
@@ -20,7 +21,7 @@ EdgeX = geompy.GetEdgeNearPoint(box, p5)
geompy.addToStudyInFather(box, EdgeX, "Edge [0,0,0 - 10,0,0]")
# create a hexahedral mesh on the box
-hexa = smesh.Mesh(box, "Box : hexahedrical mesh")
+hexa = smesh.Mesh(box, "Propagation of hypothesis")
# set global algorithms and hypotheses
algo1D = hexa.Segment()
@@ -28,15 +29,37 @@ hexa.Quadrangle()
hexa.Hexahedron()
algo1D.NumberOfSegments(4)
-# create a sub-mesh with local 1D hypothesis and propagation
+# create a sub-mesh with local 1D hypothesis and "Propagation of 1D Hypothesis"
algo_local = hexa.Segment(EdgeX)
# define "Arithmetic1D" hypothesis to cut an edge in several segments with increasing length
algo_local.Arithmetic1D(1, 4)
-# define "Propagation" hypothesis that propagates all other 1D hypotheses
-# from all edges on the opposite side of a face in case of quadrangular faces
+# define "Propagation" hypothesis that propagates "Arithmetic1D" hypothesis
+# from 'EdgeX' on opposite sides of all quadilateral faces
algo_local.Propagation()
-# compute the mesh
+# compute the mesh which contains prisms
hexa.Compute()
+
+
+# create another mesh on the box
+mesh = smesh.Mesh(box, "Propagation of distribution of nodes")
+
+# set global algorithms and hypotheses
+algo1D = mesh.Segment()
+mesh.Quadrangle()
+mesh.Hexahedron()
+algo1D.NumberOfSegments(4)
+
+# create a sub-mesh with local 1D hypothesis and "Propagation of Node Distribution"
+algo_local = mesh.Segment(EdgeX)
+algo_local.Arithmetic1D(1, 4)
+
+# define "Propagation Of Distribution" hypothesis that propagates
+# distribution of nodes generated by "Arithmetic1D" hypothesis
+# from 'EdgeX' on opposite sides of all quadilateral faces
+algo_local.PropagationOfDistribution()
+
+# compute the mesh which contains hexahedra only
+mesh.Compute()
diff --git a/doc/salome/gui/SMESH/images/a-geometric1d.png b/doc/salome/gui/SMESH/images/a-geometric1d.png
new file mode 100644
index 000000000..a60be94a4
Binary files /dev/null and b/doc/salome/gui/SMESH/images/a-geometric1d.png differ
diff --git a/doc/salome/gui/SMESH/images/viscous_layers_hyp.png b/doc/salome/gui/SMESH/images/viscous_layers_hyp.png
index 9c9930317..717819138 100644
Binary files a/doc/salome/gui/SMESH/images/viscous_layers_hyp.png and b/doc/salome/gui/SMESH/images/viscous_layers_hyp.png differ
diff --git a/doc/salome/gui/SMESH/input/1d_meshing_hypo.doc b/doc/salome/gui/SMESH/input/1d_meshing_hypo.doc
index 470fe0c4d..b992bc8e2 100644
--- a/doc/salome/gui/SMESH/input/1d_meshing_hypo.doc
+++ b/doc/salome/gui/SMESH/input/1d_meshing_hypo.doc
@@ -6,6 +6,7 @@
\ref adaptive_1d_anchor "Adaptive"
\ref arithmetic_1d_anchor "Arithmetic 1D"
+\ref geometric_1d_anchor "Geometric Progression"
\ref average_length_anchor "Local Length"
\ref max_length_anchor "Max Size"
\ref deflection_1d_anchor "Deflection 1D"
@@ -55,7 +56,30 @@ picking them in the 3D viewer or by selecting the edges or groups of edges in th
\image html b-ithmetic1d.png "Arithmetic 1D hypothesis - the size of mesh elements gradually increases"
See Also a sample TUI Script of a
-\ref tui_1d_arithmetic "Defining Arithmetic 1D hypothesis" operation.
+\ref tui_1d_arithmetic "Defining Arithmetic 1D and Geometric Progression hypothesis" operation.
+
+
+\anchor geometric_1d_anchor
+Geometric Progression hypothesis
+
+Geometric Progression hypothesis allows to split edges into
+segments with a length that changes in geometric progression (Lk =
+Lk-1 * d) beginning from a given starting length and with a given
+common ratio.
+
+The direction of the splitting is defined by the orientation of the
+underlying geometrical edge. "Reverse Edges" list box allows to
+specify the edges for which the splitting should be made in the
+direction opposing to their orientation. This list box is enabled only
+if the geometry object is selected for the meshing. In this case the
+user can select edges to be reversed either directly picking them in
+the 3D viewer or by selecting the edges or groups of edges in the
+Object Browser.
+
+\image html a-geometric1d.png
+
+See Also a sample TUI Script of a
+\ref tui_1d_arithmetic "Defining Arithmetic 1D and Geometric Progression hypothesis" operation.
\anchor deflection_1d_anchor
diff --git a/doc/salome/gui/SMESH/input/about_hypo.doc b/doc/salome/gui/SMESH/input/about_hypo.doc
index 09768cc7c..65d5c7ad0 100644
--- a/doc/salome/gui/SMESH/input/about_hypo.doc
+++ b/doc/salome/gui/SMESH/input/about_hypo.doc
@@ -20,6 +20,7 @@ In \b MESH there are the following Basic Hypotheses:
\ref max_length_anchor "Max Size"
\ref adaptive_1d_anchor "Adaptive"
\ref arithmetic_1d_anchor "Arithmetic 1D"
+\ref geometric_1d_anchor "Geometric 1D"
\ref start_and_end_length_anchor "Start and end length"
\ref deflection_1d_anchor "Deflection 1D"
\ref automatic_length_anchor "Automatic Length"
@@ -41,6 +42,7 @@ There also exist
with other hypotheses:
\ref propagation_anchor "Propagation of 1D Hypothesis on opposite edges"
+\ref propagofdistribution_anchor "Propagation of Node Distribution on Opposite Edges"
\ref viscous_layers_anchor "Viscous layers"
\ref quadratic_mesh_anchor "Quadratic mesh"
\ref non_conform_allowed_anchor "Non conform mesh allowed"
diff --git a/doc/salome/gui/SMESH/input/additional_hypo.doc b/doc/salome/gui/SMESH/input/additional_hypo.doc
index 938c7870e..adccc49aa 100644
--- a/doc/salome/gui/SMESH/input/additional_hypo.doc
+++ b/doc/salome/gui/SMESH/input/additional_hypo.doc
@@ -38,6 +38,19 @@ has been locally defined on the opposite edge.
See Also a sample TUI Script of a
\ref tui_propagation "Propagation hypothesis" operation
+\anchor propagofdistribution_anchor
+Propagation of Node Distribution on Opposite Edges
+
+Propagation of Node Distribution on Opposite Edges allows to propagate
+distribution of nodes onto an opposite edge. If a local hypothesis and
+propagation are defined on an edge of a quadrangular face, the
+opposite edge will have the same number of nodes and the same
+relations between segment lengths, unless another hypothesis
+has been locally defined on the opposite edge.
+
+See Also a sample TUI Script of a
+\ref tui_propagation "Propagation hypothesis" operation
+
\anchor quadrangle_preference_anchor
Quadrangle Preference
@@ -68,29 +81,29 @@ computations.
Number of layers - defines the number of element layers.
Stretch factor - defines the growth factor of element height
from the mesh boundary inwards.
-Specified Edges are - defines how the shapes specified by
+Specified Faces/Edges are - defines how the shapes specified by
the next parameter are used.
-Faces without layers and Edges with/without layers -
- in the 3D case it defines geometrical faces on which element layers
- should not be constructed; in the 2D case it defines geometrical edges
- on which element layers either should be or should not be
- constructed, depending on the value of the previous parameter
- (Specified Edges are ).
+ Faces/Edges with/without layers -
+ defines geometrical faces or edges on which element layers
+ either should be or should not be constructed, depending on the
+ value of the previous parameter (Specified Faces/Edges are ).
+ Faces (or edges) can be selected either in the Object Browser or in
+ the VTK Viewer.
\note A mesh shown in the 3D Viewer can prevent selection of faces
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
(edges) shown at a time is limited by the value of "Sub-shapes
preview chunk size" preference (in Preferences/Mesh/General tab).
- Whatever shapes are specified by this
- parameter, the element layers are not constructed on geometrical
- faces shared by several solids in 3D case and edges shared by
- several faces in 2D case. In other words the element layers can be
- constructed on boundary faces and edges, and are not constructed on
- internal faces and edges. There is an exception to this rule in 2D
- case: if "Viscous Layers 2D" hypothesis is assigned to a sub-mesh,
- the element layers can be constructed on boundary edges of the shape
- of this sub-mesh.
+ If faces/edges without layers are specified, the element layers are
+ not constructed on geometrical faces shared by several solids in 3D
+ case and edges shared by several faces in 2D case. In other words,
+ in this mode the element layers can be constructed on boundary faces
+ and edges only, and are not constructed on internal faces and
+ edges. There is an exception to this rule: if a hypothesis is
+ assigned to a sub-mesh, the element layers can be constructed on
+ boundary faces/edges of the shape of this sub-mesh, at same time
+ 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.
@@ -101,5 +114,4 @@ computations.
See also a sample TUI script of a \ref tui_viscous_layers
"Viscous layers construction".
-
*/
diff --git a/doc/salome/gui/SMESH/input/tui_defining_hypotheses.doc b/doc/salome/gui/SMESH/input/tui_defining_hypotheses.doc
index 333017d77..863bf76e7 100644
--- a/doc/salome/gui/SMESH/input/tui_defining_hypotheses.doc
+++ b/doc/salome/gui/SMESH/input/tui_defining_hypotheses.doc
@@ -9,6 +9,7 @@ This page provides example codes of \ref tui_defining_meshing_algos
\ref tui_1d_adaptive "Adaptive 1D" hypothesis
\ref tui_1d_arithmetic "Arithmetic 1D" hypothesis
+ \ref tui_1d_arithmetic "Geometric Progression" hypothesis
\ref tui_deflection_1d "Deflection 1D and Number of Segments" hypotheses
\ref tui_start_and_end_length "Start and End Length" hypotheses
\ref tui_average_length "Local Length"
@@ -44,7 +45,7 @@ This page provides example codes of \ref tui_defining_meshing_algos
\anchor tui_1d_arithmetic
-Arithmetic 1D
+Arithmetic 1D and Geometric Progression
\tui_script{defining_hypotheses_ex01.py}
diff --git a/idl/SMESH_BasicHypothesis.idl b/idl/SMESH_BasicHypothesis.idl
index 798475b30..186b06681 100644
--- a/idl/SMESH_BasicHypothesis.idl
+++ b/idl/SMESH_BasicHypothesis.idl
@@ -127,10 +127,36 @@ module StdMeshers
double GetFineness();
};
+ /*!
+ * Common inteface of 1D hypotheses that can be reversed
+ */
+ interface Reversible1D
+ {
+ /*!
+ * Set list of edges to reverse
+ */
+ void SetReversedEdges( in SMESH::long_array list );
+
+ /*!
+ * Returns list of edges to reverse
+ */
+ SMESH::long_array GetReversedEdges();
+
+ /*!
+ * Set entry of the main object
+ */
+ void SetObjectEntry( in string entry );
+
+ /*!
+ * Get the entry of the main object
+ */
+ string GetObjectEntry();
+ };
+
/*!
* StdMeshers_NumberOfSegments: interface of "Nb. Segments" hypothesis
*/
- interface StdMeshers_NumberOfSegments : SMESH::SMESH_Hypothesis
+ interface StdMeshers_NumberOfSegments : SMESH::SMESH_Hypothesis, Reversible1D
{
/*!
* Builds and returns point distribution according to passed density function
@@ -209,32 +235,12 @@ module StdMeshers
*/
long ConversionMode()
raises (SALOME::SALOME_Exception);
-
- /*!
- * Set list of edges to reverse
- */
- void SetReversedEdges( in SMESH::long_array list );
-
- /*!
- * Returns list of edges to reverse
- */
- SMESH::long_array GetReversedEdges();
-
- /*!
- * Set entry of the main object
- */
- void SetObjectEntry( in string entry );
-
- /*!
- * Get the entry of the main object
- */
- string GetObjectEntry();
};
/*!
* StdMeshers_Arithmetic1D: interface of "Arithmetic 1D" hypothesis
*/
- interface StdMeshers_Arithmetic1D : SMESH::SMESH_Hypothesis
+ interface StdMeshers_Arithmetic1D : SMESH::SMESH_Hypothesis, Reversible1D
{
/*!
* Sets or parameter value
@@ -260,26 +266,36 @@ module StdMeshers
* Returns or parameter value
*/
double GetLength(in boolean isStartLength);
-
+
+ };
+
+ /*!
+ * StdMeshers_Arithmetic1D: interface of "Geometric 1D" hypothesis
+ */
+ interface StdMeshers_Geometric1D : SMESH::SMESH_Hypothesis, Reversible1D
+ {
/*!
- * Set list of edges to reverse
+ * Sets length of the first segment
*/
- void SetReversedEdges( in SMESH::long_array list );
-
+ void SetStartLength(in double length)
+ raises (SALOME::SALOME_Exception);
+
/*!
- * Returns list of edges to reverse
+ * Sets value of Common Ratio
*/
- SMESH::long_array GetReversedEdges();
-
+ void SetCommonRatio(in double factor)
+ raises (SALOME::SALOME_Exception);
+
/*!
- * Set entry of the main object
+ * Returns length of the first segment
*/
- void SetObjectEntry( in string entry );
-
+ double GetStartLength();
+
/*!
- * Get the entry of the main object
+ * Returns value of Common Ratio
*/
- string GetObjectEntry();
+ double GetCommonRatio();
+
};
/*!
@@ -319,7 +335,7 @@ module StdMeshers
/*!
* StdMeshers_StartEndLength: interface of "Start and End Length" hypothesis
*/
- interface StdMeshers_StartEndLength : SMESH::SMESH_Hypothesis
+ interface StdMeshers_StartEndLength : SMESH::SMESH_Hypothesis, Reversible1D
{
/*!
* Sets or parameter value
@@ -346,25 +362,6 @@ module StdMeshers
*/
double GetLength(in boolean isStartLength);
- /*!
- * Set list of edges to reverse
- */
- void SetReversedEdges( in SMESH::long_array list );
-
- /*!
- * Returns list of edges to reverse
- */
- SMESH::long_array GetReversedEdges();
-
- /*!
- * Set entry of the main object
- */
- void SetObjectEntry( in string entry );
-
- /*!
- * Get the entry of the main object
- */
- string GetObjectEntry();
};
@@ -388,7 +385,7 @@ module StdMeshers
/*!
* StdMeshers_FixedPoints1D: interface of "Fixed points 1D" hypothesis
*/
- interface StdMeshers_FixedPoints1D : SMESH::SMESH_Hypothesis
+ interface StdMeshers_FixedPoints1D : SMESH::SMESH_Hypothesis, Reversible1D
{
/*!
* Sets some points on edge using parameter on curve from 0 to 1
@@ -410,26 +407,7 @@ module StdMeshers
* Returns list of numbers of segments
*/
SMESH::long_array GetNbSegments();
-
- /*!
- * Set list of edges to reverse
- */
- void SetReversedEdges( in SMESH::long_array list );
-
- /*!
- * Returns list of edges to reverse
- */
- SMESH::long_array GetReversedEdges();
-
- /*!
- * Set entry of the main object
- */
- void SetObjectEntry( in string entry );
-
- /*!
- * Get the entry of the main object
- */
- string GetObjectEntry();
+
};
/*!
@@ -483,7 +461,8 @@ module StdMeshers
};
/*!
- * StdMeshers_Propagation: interface of "Propagation" hypothesis.
+ * StdMeshers_Propagation: interface of "Propagation of 1D Hyp. on
+ * Opposite Edges" hypothesis.
* Presence of this hypothesis on any edge propagates any other 1D
* hypothesis from this edge on all edges, opposite to it.
* It concerns only edges of quadrangle faces.
@@ -492,6 +471,17 @@ module StdMeshers
{
};
+ /*!
+ * StdMeshers_Propagation: interface of "Propagation of Node
+ * Distribution on Opposite Edges" hypothesis.
+ * Presence of this hypothesis on any edge propagates distribution of nodes
+ * from this edge on all edges, opposite to it.
+ * It concerns only edges of quadrangle faces.
+ */
+ interface StdMeshers_PropagOfDistribution : SMESH::SMESH_Hypothesis
+ {
+ };
+
/*!
* StdMeshers_QuadranglePreference: interface of "QuadranglePreference" hypothesis.
* This hypothesis is used by StdMeshers_Quadrangle_2D algorithm.
@@ -807,6 +797,22 @@ module StdMeshers
* Get the type of quadrangulation
*/
QuadType GetQuadType();
+
+ /*!
+ * Set positions of enforced nodes
+ */
+ void SetEnforcedNodes(in GEOM::ListOfGO vertices, in SMESH::nodes_array points)
+ raises (SALOME::SALOME_Exception);
+
+ /*!
+ * Returns positions of enforced nodes
+ */
+ void GetEnforcedNodes(out GEOM::ListOfGO vertices, out SMESH::nodes_array points);
+
+ /*!
+ * Returns entries of shapes defining enforced nodes
+ */
+ SMESH::string_array GetEnfVertices();
};
/*!
@@ -865,6 +871,14 @@ module StdMeshers
void SetIgnoreFaces(in SMESH::long_array faceIDs) raises (SALOME::SALOME_Exception);
SMESH::long_array GetIgnoreFaces();
+ /*!
+ * Set faces either to exclude from treatment or to make the Viscous Layers on.
+ */
+ void SetFaces(in SMESH::long_array faceIDs,
+ in boolean toIgnore) raises (SALOME::SALOME_Exception);
+ SMESH::long_array GetFaces();
+ boolean GetIsToIgnoreFaces();
+
/*!
* Set total thickness of layers of prisms
*/
@@ -936,7 +950,7 @@ module StdMeshers
/*!
* Set size threshold. A polyhedral cell got by cutting an initial
* hexahedron by geometry boundary is considered small and is removed if
- * it's size is \athreshold times less than the size of the initial hexahedron.
+ * it's size is \a threshold times less than the size of the initial hexahedron.
* threshold must be > 1.0
*/
void SetSizeThreshold(in double threshold) raises (SALOME::SALOME_Exception);
@@ -971,6 +985,13 @@ module StdMeshers
void GetGridSpacing(out SMESH::string_array spaceFunctions,
out SMESH::double_array internalPoints,
in short axis) raises (SALOME::SALOME_Exception);
+ /*!
+ * Enables implementation of geometrical edges into the mesh. If this feature
+ * is disabled, sharp edges of the shape are lost ("smoothed") in the mesh if
+ * they don't coincide with the grid lines
+ */
+ void SetToAddEdges(in boolean toAdd);
+ boolean GetToAddEdges();
/*!
* \brief Computes node coordinates by spacing functions
@@ -978,13 +999,15 @@ module StdMeshers
* \param x1 - upper coordinate
* \param spaceFuns - space functions
* \param points - internal points
- * \param coords - the computed coordinates
+ * \param axisName - e.g. "X"
+ * \return the computed coordinates
*/
SMESH::double_array ComputeCoordinates(in double x0,
in double x1,
in SMESH::string_array spaceFuns,
in SMESH::double_array points,
- in string axisName ) raises (SALOME::SALOME_Exception);
+ in string axisName )
+ raises (SALOME::SALOME_Exception);
};
/*!
diff --git a/idl/SMESH_Mesh.idl b/idl/SMESH_Mesh.idl
index fb85b15af..ff60e68ad 100644
--- a/idl/SMESH_Mesh.idl
+++ b/idl/SMESH_Mesh.idl
@@ -925,6 +925,11 @@ module SMESH
*/
long_array GetElemFaceNodes(in long elemId, in short faceIndex);
+ /*!
+ * Returns three components of normal of given mesh face (or an empty array in KO case)
+ */
+ double_array GetFaceNormal(in long faceId);
+
/*!
* Returns an element based on all given nodes.
*/
diff --git a/resources/StdMeshers.xml.in b/resources/StdMeshers.xml.in
index d80b4e7d9..d6f6527b6 100644
--- a/resources/StdMeshers.xml.in
+++ b/resources/StdMeshers.xml.in
@@ -55,6 +55,11 @@
icon-id ="mesh_hypo_length.png"
dim ="1"/>
+
+
+
+
@@ -215,12 +226,14 @@
LocalLength=LocalLength(SetLength(1),,SetPrecision(1))
MaxLength=MaxSize(SetLength(1))
Arithmetic1D=Arithmetic1D(SetStartLength(),SetEndLength(),SetReversedEdges())
+ GeometricProgression=GeometricProgression(SetStartLength(),SetCommonRatio(),SetReversedEdges())
StartEndLength=StartEndLength(SetStartLength(),SetEndLength(),SetReversedEdges())
Deflection1D=Deflection1D(SetDeflection())
Adaptive1D=Adaptive(SetMinSize(),SetMaxSize(),SetDeflection())
AutomaticLength=AutomaticLength(SetFineness())
FixedPoints1D=FixedPoints1D(SetPoints(),SetNbSegments(),SetReversedEdges())
Propagation=Propagation()
+ PropagOfDistribution=PropagationOfDistribution()
QuadraticMesh=QuadraticMesh()
@@ -228,8 +241,8 @@
@@ -238,12 +251,14 @@
LocalLength=LocalLength(SetLength(), ,SetPrecision())
MaxLength=MaxSize(SetLength())
Arithmetic1D=Arithmetic1D(SetStartLength(),SetEndLength(),SetReversedEdges())
+ GeometricProgression=GeometricProgression(SetStartLength(),SetCommonRatio(),SetReversedEdges())
StartEndLength=StartEndLength(SetStartLength(),SetEndLength(),SetReversedEdges())
Deflection1D=Deflection1D(SetDeflection())
Adaptive1D=Adaptive(SetMinSize(),SetMaxSize(),SetDeflection())
AutomaticLength=AutomaticLength(SetFineness())
FixedPoints1D=FixedPoints1D(SetPoints(),SetNbSegments(),SetReversedEdges())
Propagation=Propagation()
+ PropagOfDistribution=PropagationOfDistribution()
QuadraticMesh=QuadraticMesh()
@@ -292,6 +307,7 @@
label-id ="Hexahedron (i,j,k)"
icon-id ="mesh_algo_hexa.png"
input ="QUAD"
+ output ="HEXA,PENTA"
need-geom="false"
opt-hypos="ViscousLayers"
dim ="3">
@@ -379,6 +395,7 @@
label-id="3D Extrusion"
icon-id ="mesh_algo_hexa.png"
input ="QUAD,TRIA"
+ output ="HEXA,PENTA,OCTA,POLYHEDRON"
dim ="3">
Prism_3D=Prism()
@@ -390,6 +407,7 @@
icon-id ="mesh_algo_hexa.png"
hypos ="NumberOfLayers, LayerDistribution"
input ="QUAD,TRIA"
+ output ="HEXA,PENTA,OCTA,POLYHEDRON"
dim ="3">
RadialPrism_3D=Prism('RadialPrism_3D')
@@ -424,7 +442,7 @@
icon-id ="mesh_algo_quad.png"
hypos ="NumberOfLayers2D, LayerDistribution2D"
input ="EDGE"
- output ="QUAD,TRIA"
+ output ="QUAD"
dim ="2">
RadialQuadrangle_1D2D=Quadrangle(algo=smeshBuilder.RADIAL_QUAD)
@@ -437,6 +455,7 @@
icon-id ="mesh_algo_hexa.png"
hypos ="CartesianParameters3D"
support-submeshes="false"
+ output ="HEXA"
dim ="3">
Cartesian_3D=BodyFitted()
diff --git a/src/SMESH/SMESH_Algo.cxx b/src/SMESH/SMESH_Algo.cxx
index 19a1e4b09..8beda034e 100644
--- a/src/SMESH/SMESH_Algo.cxx
+++ b/src/SMESH/SMESH_Algo.cxx
@@ -410,7 +410,7 @@ bool SMESH_Algo::GetSortedNodesOnEdge(const SMESHDS_Mesh* theM
return false;
SMESHDS_SubMesh * eSubMesh = theMesh->MeshElements( theEdge );
- if ( !eSubMesh || !eSubMesh->GetElements()->more() )
+ if ( !eSubMesh || ( eSubMesh->NbElements()==0 && eSubMesh->NbNodes() == 0))
return false; // edge is not meshed
int nbNodes = 0;
diff --git a/src/SMESH/SMESH_MesherHelper.cxx b/src/SMESH/SMESH_MesherHelper.cxx
index b7d8759e9..06f247009 100644
--- a/src/SMESH/SMESH_MesherHelper.cxx
+++ b/src/SMESH/SMESH_MesherHelper.cxx
@@ -896,7 +896,7 @@ bool SMESH_MesherHelper::CheckNodeU(const TopoDS_Edge& E,
const bool force,
double distXYZ[4]) const
{
- int shapeID = n->getshapeId();
+ int shapeID = n->getshapeId();
bool infinit = Precision::IsInfinite( u );
if ( force || toCheckPosOnShape( shapeID ) || infinit )
{
diff --git a/src/SMESH/SMESH_Pattern.cxx b/src/SMESH/SMESH_Pattern.cxx
index 63e6f365f..5d0f5e536 100644
--- a/src/SMESH/SMESH_Pattern.cxx
+++ b/src/SMESH/SMESH_Pattern.cxx
@@ -2641,10 +2641,10 @@ bool SMESH_Pattern::Apply (const SMDS_MeshFace* theFace,
list< const SMDS_MeshNode* > nodes;
list< const SMDS_MeshNode* >::iterator n = nodes.end();
- SMDS_ElemIteratorPtr noIt = theFace->nodesIterator();
+ SMDS_NodeIteratorPtr noIt = theFace->nodeIterator();
int iSub = 0;
while ( noIt->more() && iSub < nbFaceNodes ) {
- const SMDS_MeshNode* node = smdsNode( noIt->next() );
+ const SMDS_MeshNode* node = noIt->next();
nodes.push_back( node );
if ( iSub++ == theNodeIndexOnKeyPoint1 )
n = --nodes.end();
@@ -2661,7 +2661,7 @@ bool SMESH_Pattern::Apply (const SMDS_MeshFace* theFace,
list< gp_XYZ > xyzList;
myOrderedNodes.resize( nbFaceNodes );
for ( iSub = 0, n = nodes.begin(); n != nodes.end(); ++n ) {
- xyzList.push_back( gp_XYZ( (*n)->X(), (*n)->Y(), (*n)->Z() ));
+ xyzList.push_back( SMESH_TNodeXYZ( *n ));
myOrderedNodes[ iSub++] = *n;
}
@@ -2963,11 +2963,6 @@ bool SMESH_Pattern::Apply (SMESH_Mesh* theMesh,
myXYZ.resize( myPoints.size() * theFaces.size(), undefinedXYZ() );
myElements.reserve( theFaces.size() );
- // to find point index
- map< TPoint*, int > pointIndex;
- for ( int i = 0; i < myPoints.size(); i++ )
- pointIndex.insert( make_pair( & myPoints[ i ], i ));
-
int ind1 = 0; // lowest point index for a face
// meshed geometry
@@ -3019,7 +3014,7 @@ bool SMESH_Pattern::Apply (SMESH_Mesh* theMesh,
{
list< TPoint* > & linkPoints = getShapePoints( eID++ );
const SMDS_MeshNode* n1 = myOrderedNodes[ i ];
- const SMDS_MeshNode* n2 = myOrderedNodes[ i + 1 == nbNodes ? 0 : i + 1 ];
+ const SMDS_MeshNode* n2 = myOrderedNodes[( i+1 ) % nbNodes ];
// make a link and a node set
TNodeSet linkSet, node1Set;
linkSet.insert( n1 );
@@ -3028,7 +3023,7 @@ bool SMESH_Pattern::Apply (SMESH_Mesh* theMesh,
list< TPoint* >::iterator p = linkPoints.begin();
{
// map the first link point to n1
- int nId = pointIndex[ *p ] + ind1;
+ int nId = ( *p - &myPoints[0] ) + ind1;
myXYZIdToNodeMap[ nId ] = n1;
list< list< int > >& groups = myIdsOnBoundary[ node1Set ];
groups.push_back(list< int > ());
@@ -3040,7 +3035,7 @@ bool SMESH_Pattern::Apply (SMESH_Mesh* theMesh,
list< int >& indList = groups.back();
// add points to the map excluding the end points
for ( p++; *p != linkPoints.back(); p++ )
- indList.push_back( pointIndex[ *p ] + ind1 );
+ indList.push_back( ( *p - &myPoints[0] ) + ind1 );
}
ind1 += myPoints.size();
}
@@ -3443,7 +3438,7 @@ void SMESH_Pattern::mergePoints (const bool uniteGroups)
Bnd_Box box;
TNodeSet::const_iterator n = nodes.begin();
for ( ; n != nodes.end(); ++n )
- box.Add( gp_Pnt( (*n)->X(), (*n)->Y(), (*n)->Z() ));
+ box.Add( gp_Pnt( SMESH_TNodeXYZ( *n )));
double x, y, z, X, Y, Z;
box.Get( x, y, z, X, Y, Z );
gp_Pnt p( x, y, z ), P( X, Y, Z );
@@ -3454,7 +3449,7 @@ void SMESH_Pattern::mergePoints (const bool uniteGroups)
bool unite = ( uniteGroups && nodes.size() == 2 );
map< double, int > distIndMap;
const SMDS_MeshNode* node = *nodes.begin();
- gp_Pnt P( node->X(), node->Y(), node->Z() );
+ gp_Pnt P = SMESH_TNodeXYZ( node );
// compare points, replace indices
@@ -3928,32 +3923,142 @@ bool SMESH_Pattern::MakeMesh(SMESH_Mesh* theMesh,
myXYZ[ i ].Y(),
myXYZ[ i ].Z());
}
- }
+ if ( theMesh->HasShapeToMesh() )
+ {
+ // set nodes on EDGEs (IMP 22368)
+ SMESH_MesherHelper helper( *theMesh );
+ helper.ToFixNodeParameters( true );
+ map< TNodeSet, list< list< int > > >::iterator idListIt = myIdsOnBoundary.begin();
+ for ( ; idListIt != myIdsOnBoundary.end(); idListIt++ )
+ {
+ list >& groups = idListIt->second;
+ const TNodeSet& nodes = idListIt->first;
+ if ( nodes.size() != 2 )
+ continue; // not a link
+ const SMDS_MeshNode* n1 = *nodes.begin();
+ const SMDS_MeshNode* n2 = *nodes.rbegin();
+ TopoDS_Shape S1 = helper.GetSubShapeByNode( n1, aMeshDS );
+ TopoDS_Shape S2 = helper.GetSubShapeByNode( n2, aMeshDS );
+ if ( S1.IsNull() || S1.ShapeType() < TopAbs_EDGE ||
+ S2.IsNull() || S2.ShapeType() < TopAbs_EDGE )
+ continue;
+ TopoDS_Shape S;
+ if ( S1.ShapeType() == TopAbs_EDGE )
+ {
+ if ( S1 == S2 || helper.IsSubShape( S2, S1 ))
+ S = S1;
+ }
+ else if ( S2.ShapeType() == TopAbs_EDGE )
+ {
+ if ( helper.IsSubShape( S1, S2 ))
+ S = S2;
+ }
+ else
+ {
+ S = helper.GetCommonAncestor( S1, S2, *theMesh, TopAbs_EDGE );
+ }
+ if ( S.IsNull() )
+ continue;
+ const TopoDS_Edge & E = TopoDS::Edge( S );
+ helper.SetSubShape( E );
+ list >::iterator g = groups.begin();
+ for ( ; g != groups.end(); ++g )
+ {
+ list< int >& ids = *g;
+ list< int >::iterator id = ids.begin();
+ for ( ; id != ids.end(); ++id )
+ if ( nodesVector[ *id ] && nodesVector[ *id ]->getshapeId() < 1 )
+ {
+ double u = 1e100;
+ aMeshDS->SetNodeOnEdge( nodesVector[ *id ], E, u );
+ helper.CheckNodeU( E, nodesVector[ *id ], u, 1e-7, true );
+ }
+ }
+ }
+ }
+ } // if ( onMeshElements )
+
else
{
nodesVector.resize( myPoints.size(), 0 );
- // to find point index
- map< TPoint*, int > pointIndex;
- for ( int i = 0; i < myPoints.size(); i++ )
- pointIndex.insert( make_pair( & myPoints[ i ], i ));
+ // find existing nodes on EDGEs and VERTEXes (IMP 22368)
+ map< int, list< TPoint* > >::iterator idPointIt = myShapeIDToPointsMap.begin();
+ if ( !myShapeIDMap.IsEmpty() && aMeshDS->NbNodes() > 0 )
+
+ for ( ; idPointIt != myShapeIDToPointsMap.end(); idPointIt++ )
+ {
+ const TopoDS_Shape& S = myShapeIDMap( idPointIt->first );
+ list< TPoint* > & points = idPointIt->second;
+ if ( points.empty() )
+ continue;
+
+ switch ( S.ShapeType() )
+ {
+ case TopAbs_VERTEX:
+ {
+ int pIndex = points.back() - &myPoints[0];
+ if ( !nodesVector[ pIndex ] )
+ nodesVector[ pIndex ] = SMESH_Algo::VertexNode( TopoDS::Vertex( S ), aMeshDS );
+ break;
+ }
+ case TopAbs_EDGE:
+ {
+ const TopoDS_Edge& edge = TopoDS::Edge( S );
+ map< double, const SMDS_MeshNode* > paramsOfNodes;
+ if ( !SMESH_Algo::GetSortedNodesOnEdge( aMeshDS, edge,
+ /*ignoreMediumNodes=*/false,
+ paramsOfNodes )
+ || paramsOfNodes.size() < 3 )
+ break;
+ // points on VERTEXes are included with wrong myU
+ list< TPoint* >::reverse_iterator pItR = ++points.rbegin();
+ list< TPoint* >::iterator pItF = ++points.begin();
+ const bool isForward = ( (*pItF)->myU < (*pItR)->myU );
+ map< double, const SMDS_MeshNode* >::iterator u2n = ++paramsOfNodes.begin();
+ map< double, const SMDS_MeshNode* >::iterator u2nEnd = --paramsOfNodes.end();
+ TPoint* p;
+ while ( u2n != u2nEnd && pItF != points.end() )
+ {
+ const double u = u2n->first;
+ const SMDS_MeshNode* n = u2n->second;
+ const double tol = ( (++u2n)->first - u ) / 20;
+ do
+ {
+ p = ( isForward ? *pItF : *pItR );
+ if ( Abs( u - p->myU ) < tol )
+ {
+ int pIndex = p - &myPoints[0];
+ if ( !nodesVector [ pIndex ] )
+ nodesVector [ pIndex ] = n;
+ ++pItF;
+ ++pItR;
+ break;
+ }
+ }
+ while ( p->myU < u && ( ++pItF, ++pItR != points.rend() ));
+ }
+ break;
+ }
+ default:;
+ }
+ } // end of "find existing nodes on EDGEs and VERTEXes"
// loop on sub-shapes of myShape: create nodes
- map< int, list< TPoint* > >::iterator idPointIt = myShapeIDToPointsMap.begin();
+ idPointIt = myShapeIDToPointsMap.begin();
for ( ; idPointIt != myShapeIDToPointsMap.end(); idPointIt++ )
{
TopoDS_Shape S;
- //SMESHDS_SubMesh * subMeshDS = 0;
if ( !myShapeIDMap.IsEmpty() ) {
S = myShapeIDMap( idPointIt->first );
- //subMeshDS = aMeshDS->MeshElements( S );
}
list< TPoint* > & points = idPointIt->second;
list< TPoint* >::iterator pIt = points.begin();
for ( ; pIt != points.end(); pIt++ )
{
TPoint* point = *pIt;
- int pIndex = pointIndex[ point ];
+ //int pIndex = pointIndex[ point ];
+ int pIndex = point - &myPoints[0];
if ( nodesVector [ pIndex ] )
continue;
SMDS_MeshNode* node = aMeshDS->AddNode (point->myXYZ.X(),
@@ -4148,8 +4253,9 @@ void SMESH_Pattern::createElements(SMESH_Mesh* theMes
SMDS_ElemIteratorPtr noIt = elem->nodesIterator();
while ( noIt->more() ) {
SMDS_MeshNode* node = const_cast(smdsNode( noIt->next() ));
- if (!node->getshapeId() &&
- shellNodes.find( node ) == shellNodes.end() ) {
+ if ( node->getshapeId() < 1 &&
+ shellNodes.find( node ) == shellNodes.end() )
+ {
if ( S.ShapeType() == TopAbs_FACE )
aMeshDS->SetNodeOnFace( node, shapeID,
Precision::Infinite(),// <- it's a sign that UV is not set
diff --git a/src/SMESH/SMESH_Pattern.hxx b/src/SMESH/SMESH_Pattern.hxx
index b2606e463..b57624c2d 100644
--- a/src/SMESH/SMESH_Pattern.hxx
+++ b/src/SMESH/SMESH_Pattern.hxx
@@ -356,7 +356,7 @@ private:
// all functions assure that shapes are indexed so that first go
// ordered vertices, then ordered edge, then faces and maybe a shell
TopTools_IndexedMapOfOrientedShape myShapeIDMap;
- std::map< int, std::list< TPoint* > > myShapeIDToPointsMap;
+ std::map< int, std::list< TPoint*> > myShapeIDToPointsMap;
// for the 2d case:
// nb of key-points in each of pattern boundaries
diff --git a/src/SMESHGUI/SMESHGUI_Hypotheses.cxx b/src/SMESHGUI/SMESHGUI_Hypotheses.cxx
index fa9add8e0..e8ebeea25 100644
--- a/src/SMESHGUI/SMESHGUI_Hypotheses.cxx
+++ b/src/SMESHGUI/SMESHGUI_Hypotheses.cxx
@@ -551,6 +551,8 @@ QString SMESHGUI_GenericHypothesisCreator::helpPage() const
aHelpFileName = "a1d_meshing_hypo_page.html#max_length_anchor";
else if ( aHypType == "Arithmetic1D")
aHelpFileName = "a1d_meshing_hypo_page.html#arithmetic_1d_anchor";
+ else if ( aHypType == "GeometricProgression")
+ aHelpFileName = "a1d_meshing_hypo_page.html#geometric_1d_anchor";
else if ( aHypType == "FixedPoints1D")
aHelpFileName = "a1d_meshing_hypo_page.html#fixed_points_1d_anchor";
else if ( aHypType == "MaxElementArea")
diff --git a/src/SMESHGUI/SMESHGUI_HypothesesUtils.cxx b/src/SMESHGUI/SMESHGUI_HypothesesUtils.cxx
index 2d45966ed..58003954a 100644
--- a/src/SMESHGUI/SMESHGUI_HypothesesUtils.cxx
+++ b/src/SMESHGUI/SMESHGUI_HypothesesUtils.cxx
@@ -296,24 +296,45 @@ namespace SMESH
}
- QStringList GetHypothesesSets(int maxDim)
+ QStringList GetHypothesesSets(int maxDim, const QString& MeshType)
{
QStringList aSetNameList;
// Init list of available hypotheses, if needed
InitAvailableHypotheses();
-
QList::iterator hypoSet;
- for ( hypoSet = myListOfHypothesesSets.begin();
+ for ( hypoSet = myListOfHypothesesSets.begin();
hypoSet != myListOfHypothesesSets.end();
++hypoSet ) {
HypothesesSet* aSet = *hypoSet;
- if ( aSet &&
- ( aSet->count( true ) || aSet->count( false )) &&
- aSet->maxDim() <= maxDim)
+ bool isAvailable = false;
+ if ( !MeshType.isEmpty() )
{
- aSetNameList.append( mangledHypoSetName( aSet ));
+ if ( aSet->maxDim() != maxDim)
+ continue;
+ aSet->init( true );
+ while ( aSet->next(), aSet->more() )
+ {
+ if ( HypothesisData* hypData = SMESH::GetHypothesisData( aSet->current() ) )
+ {
+ QStringList::const_iterator inElemType = hypData->OutputTypes.begin();
+ for ( ; inElemType != hypData->OutputTypes.end(); inElemType++ )
+ {
+ if ( *inElemType == MeshType ){
+ isAvailable = true;
+ break;
+ }
+ }
+ }
+ if ( isAvailable ) break;
+ }
}
+ else if ( aSet && ( aSet->count( true ) || aSet->count( false )) &&
+ aSet->maxDim() <= maxDim)
+ {
+ isAvailable = true;
+ }
+ if ( isAvailable ) aSetNameList.append( mangledHypoSetName( aSet ));
}
aSetNameList.removeDuplicates();
aSetNameList.sort();
diff --git a/src/SMESHGUI/SMESHGUI_HypothesesUtils.h b/src/SMESHGUI/SMESHGUI_HypothesesUtils.h
index a2c12f595..333418b31 100644
--- a/src/SMESHGUI/SMESHGUI_HypothesesUtils.h
+++ b/src/SMESHGUI/SMESHGUI_HypothesesUtils.h
@@ -71,7 +71,7 @@ namespace SMESH
const bool = false,
const bool = true);
SMESHGUI_EXPORT
- QStringList GetHypothesesSets( int maxDim );
+ QStringList GetHypothesesSets( int, const QString& );
SMESHGUI_EXPORT
HypothesesSet* GetHypothesesSet( const QString& );
diff --git a/src/SMESHGUI/SMESHGUI_MeshDlg.cxx b/src/SMESHGUI/SMESHGUI_MeshDlg.cxx
index 4b030bbc0..94d9ce681 100644
--- a/src/SMESHGUI/SMESHGUI_MeshDlg.cxx
+++ b/src/SMESHGUI/SMESHGUI_MeshDlg.cxx
@@ -364,6 +364,9 @@ SMESHGUI_MeshDlg::SMESHGUI_MeshDlg( const bool theToCreate, const bool theIsMesh
// geometry
createObject( tr( "GEOMETRY" ), mainFrame(), Geom );
myGeomPopup = 0;
+ // mesh type
+ QLabel* anMeshTypeLbl = new QLabel( tr( "MESH_TYPE" ), this );
+ myMeshType = new QComboBox( this );
// Create tab widget
@@ -398,10 +401,16 @@ SMESHGUI_MeshDlg::SMESHGUI_MeshDlg( const bool theToCreate, const bool theIsMesh
aLay->addWidget( objectWg( Geom, Label ), 2, 0 );
aLay->addWidget( objectWg( Geom, Btn ), 2, 1 );
aLay->addWidget( objectWg( Geom, Control ), 2, 2 );
- aLay->addWidget( myTabWg, 4, 0, 1, 3 );
- aLay->addWidget( myHypoSetButton, 5, 0, 1, 3 );
+ aLay->addWidget( anMeshTypeLbl, 3, 0 );
+ aLay->addWidget( myMeshType, 3, 2 );
+ aLay->addWidget( myTabWg, 5, 0, 1, 3 );
+ aLay->addWidget( myHypoSetButton, 6, 0, 1, 3 );
aLay->setRowMinimumHeight( 3, 20 );
+ myMeshType->clear();
+
+ // Connect signals and slots
+ connect( myMeshType, SIGNAL( activated( int ) ), SLOT( onChangedMeshType( int ) ) );
// Disable controls if necessary
setObjectShown( Mesh, false );
if ( theToCreate )
@@ -615,3 +624,36 @@ int SMESHGUI_MeshDlg::getActiveObject()
return i;
return -1;
}
+//================================================================================
+/*!
+ * \brief Sets available types of mesh
+ * \param theTypeMesh - list of available types of mesh
+ */
+//================================================================================
+void SMESHGUI_MeshDlg::setAvailableMeshType( const QStringList& theTypeMesh )
+{
+ myMeshType->clear();
+ myMeshType->addItems(theTypeMesh);
+}
+//================================================================================
+/*!
+ * \brief Emits selectMeshType( const int, const int ) signal
+ *
+ * SLOT is called when a combo box "mesh type" is selected.
+ */
+//================================================================================
+void SMESHGUI_MeshDlg::onChangedMeshType( const int isIndex )
+{
+ emit selectMeshType( Dim3D - myTabWg->currentIndex(), isIndex );
+}
+//================================================================================
+/*!
+ * \brief Get current index types of mesh
+ */
+//================================================================================
+int SMESHGUI_MeshDlg::currentMeshType( )
+{
+ return myMeshType->currentIndex( );
+}
+
+
diff --git a/src/SMESHGUI/SMESHGUI_MeshDlg.h b/src/SMESHGUI/SMESHGUI_MeshDlg.h
index 6ba8e6cb9..08f11ff6f 100644
--- a/src/SMESHGUI/SMESHGUI_MeshDlg.h
+++ b/src/SMESHGUI/SMESHGUI_MeshDlg.h
@@ -74,21 +74,26 @@ public:
void enableTab(const int);
bool isTabEnabled(const int) const;
int getActiveObject();
+ void setAvailableMeshType(const QStringList& );
+ int currentMeshType();
signals:
void hypoSet( const QString& );
void geomSelectionByMesh( bool );
+ void selectMeshType( const int, const int );
private slots:
void onHypoSetPopup( QAction* );
void onGeomPopup( QAction* );
void onGeomSelectionButton( bool );
+ void onChangedMeshType( const int );
private:
QMap myTabs;
QTabWidget* myTabWg;
QToolButton* myHypoSetButton;
QMenu* myGeomPopup;
+ QComboBox* myMeshType;
};
/*!
diff --git a/src/SMESHGUI/SMESHGUI_MeshOp.cxx b/src/SMESHGUI/SMESHGUI_MeshOp.cxx
index 62a5c4b74..eb0a30ed7 100644
--- a/src/SMESHGUI/SMESHGUI_MeshOp.cxx
+++ b/src/SMESHGUI/SMESHGUI_MeshOp.cxx
@@ -95,6 +95,7 @@ SMESHGUI_MeshOp::SMESHGUI_MeshOp( const bool theToCreate, const bool theIsMesh )
if ( GeometryGUI::GetGeomGen()->_is_nil() )// check that GEOM_Gen exists
GeometryGUI::InitGeomGen();
myIsOnGeometry = true;
+ myMaxShapeDim = -1;
}
//================================================================================
@@ -211,14 +212,13 @@ void SMESHGUI_MeshOp::startOperation()
}
connect( myDlg, SIGNAL( hypoSet( const QString& )), SLOT( onHypoSet( const QString& )));
connect( myDlg, SIGNAL( geomSelectionByMesh( bool )), SLOT( onGeomSelectionByMesh( bool )));
-
+ connect( myDlg, SIGNAL( selectMeshType( const int, const int ) ), SLOT( onAlgoSetByMeshType( const int, const int)));
if ( myToCreate )
if ( myIsMesh ) myHelpFileName = "constructing_meshes_page.html";
else myHelpFileName = "constructing_submeshes_page.html";
else myHelpFileName = "editing_meshes_page.html";
}
SMESHGUI_SelectionOp::startOperation();
-
// iterate through dimensions and get available algoritms, set them to the dialog
_PTR(SComponent) aFather = SMESH::GetActiveStudyDocument()->FindComponent( "SMESH" );
for ( int i = SMESH::DIM_0D; i <= SMESH::DIM_3D; i++ )
@@ -245,6 +245,11 @@ void SMESHGUI_MeshOp::startOperation()
myDlg->activateObject( SMESHGUI_MeshDlg::Obj );
myDlg->setCurrentTab( SMESH::DIM_3D );
+
+ QStringList TypeMeshList;
+ createMeshTypeList( TypeMeshList );
+ setAvailableMeshType( TypeMeshList );
+
myDlg->show();
myDlg->setGeomPopupEnabled(false);
selectionDone();
@@ -582,7 +587,8 @@ void SMESHGUI_MeshOp::selectionDone()
onAlgoSelected(-1, i);
}
myDlg->setMaxHypoDim( shapeDim );
- myDlg->setHypoSets( SMESH::GetHypothesesSets( shapeDim ));
+ myMaxShapeDim = shapeDim;
+ myDlg->setHypoSets( SMESH::GetHypothesesSets( shapeDim, "" ));
if (!myToCreate) // edition: read hypotheses
{
@@ -669,12 +675,16 @@ void SMESHGUI_MeshOp::selectionDone()
for (int i = SMESH::DIM_0D;i < SMESH::DIM_3D; ++i) {
myDlg->disableTab(i);
}
+ myMaxShapeDim = -1;
//Hide labels and fields (Mesh ang Geometry)
myDlg->setObjectShown( SMESHGUI_MeshDlg::Mesh, false );
myDlg->setObjectShown( SMESHGUI_MeshDlg::Geom, false );
myDlg->adjustSize();
readMesh();
}
+ QStringList TypeMeshList;
+ createMeshTypeList( TypeMeshList );
+ setAvailableMeshType( TypeMeshList );
}
catch ( const SALOME::SALOME_Exception& S_ex )
{
@@ -1380,7 +1390,19 @@ void SMESHGUI_MeshOp::onAlgoSelected( const int theIndex,
availableHyps( aDim, Algo, anAvailable, myAvailableHypData[ aDim ][ Algo ]);
myDlg->tab( aDim )->setAvailableHyps( Algo, anAvailable );
}
-
+ // check that tab enable, if algorithm building needed algo is one less than dimension
+ if ( algoData && myIsOnGeometry && !algoData->InputTypes.isEmpty() &&
+ ( aDim > SMESH::DIM_0D ) && !isAccessibleDim( aDim - 1 ) ){
+ myDlg->enableTab( aDim - 1 );
+ }
+ if ( (myDlg->currentMeshType() != MT_ANY) &&
+ (( !algoData && ( aDim > SMESH::DIM_0D ) && isAccessibleDim( aDim - 1 )) ||
+ ( algoData && myIsOnGeometry && algoData->InputTypes.isEmpty() &&
+ ( aDim > SMESH::DIM_0D ) && isAccessibleDim( aDim - 1 ) ) ) ){
+ for (int i = aDim - 1; i >= SMESH::DIM_0D; i--){
+ if ( isAccessibleDim( i ) ) myDlg->disableTab( i );
+ }
+ }
// check that algorithms of other dimentions are compatible with
// the selected one
@@ -2343,3 +2365,193 @@ void SMESHGUI_MeshOp::selectObject( _PTR(SObject) theSObj ) const
sm->setSelectedObjects( anIOList, false );
}
}
+//================================================================================
+/*!
+ * \brief Create available list types of mesh
+ * \param theTypeMesh - Output list of available types of mesh
+ */
+//================================================================================
+void SMESHGUI_MeshOp::createMeshTypeList( QStringList& theTypeMesh)
+{
+ theTypeMesh.clear();
+ theTypeMesh.append( tr( "MT_ANY" ) );
+ if ( myIsOnGeometry && ( myMaxShapeDim >= 2 || myMaxShapeDim == -1 ) )
+ {
+ theTypeMesh.append( tr( "MT_TRIANGULAR" ) );
+ theTypeMesh.append( tr( "MT_QUADRILATERAL" ) );
+ }
+ if ( myIsOnGeometry && ( myMaxShapeDim == 3 || myMaxShapeDim == -1 ) )
+ {
+ theTypeMesh.append( tr( "MT_TETRAHEDRAL" ) );
+ theTypeMesh.append( tr( "MT_HEXAHEDRAL" ) );
+ }
+
+}
+//================================================================================
+/*!
+ * \brief Set available types of mesh
+ * \param theTypeMesh - List of available types of mesh
+ */
+//================================================================================
+void SMESHGUI_MeshOp::setAvailableMeshType( const QStringList& theTypeMesh )
+{
+ myDlg->setAvailableMeshType( theTypeMesh );
+}
+
+//================================================================================
+/*!
+ * \brief SLOT. Is called when the user select type of mesh
+ * \param theTabIndex - Index of current active tab
+ * \param theIndex - Index of current type of mesh
+ */
+//================================================================================
+void SMESHGUI_MeshOp::onAlgoSetByMeshType( const int theTabIndex, const int theIndex)
+{
+ int aDim;
+ if ( !myIsOnGeometry ) return;
+ THypDataList anAvailableAlgsData;
+ QStringList anAvailableAlgs;
+ QString anCompareType = "ANY";
+ bool isAvailableChoiceAlgo = false;
+ int anCurrentAvailableAlgo = 0;
+ bool isNone = true;
+ switch ( theIndex ) {
+ case MT_ANY:
+ {
+ for ( int dim = SMESH::DIM_2D; dim <= SMESH::DIM_3D; dim++ )
+ {
+ isNone = currentHyp( dim, Algo ) < 0;
+ isAvailableChoiceAlgo = false;
+ // retrieves a list of available algorithms from resources
+ availableHyps( dim, Algo, anAvailableAlgs, anAvailableAlgsData );
+ //return current algo in current tab
+ if ( !isNone && !myAvailableHypData[dim][Algo].empty() ){
+ for (int i = 0 ; i < anAvailableAlgsData.count(); i++)
+ {
+ HypothesisData* algoAny = anAvailableAlgsData.at(i);
+ HypothesisData* algoCur = myAvailableHypData[dim][Algo].at( currentHyp( dim, Algo ) );
+ QString tem = algoAny->Label;
+ if ( algoAny->Label == algoCur->Label ){
+ isAvailableChoiceAlgo = true;
+ anCurrentAvailableAlgo = i;
+ break;
+ }
+ }
+ }
+ else if ( !isNone ){
+ isAvailableChoiceAlgo = true;
+ anCurrentAvailableAlgo = currentHyp( dim, Algo );
+ }
+ //set new algorithm list and select the current algorithm
+ myAvailableHypData[dim][Algo] = anAvailableAlgsData;
+ myDlg->tab( dim )->setAvailableHyps( Algo, anAvailableAlgs );
+ if ( isAvailableChoiceAlgo )
+ setCurrentHyp( dim, Algo, anCurrentAvailableAlgo );
+ }
+ int aMaxShapeDim = ( myMaxShapeDim == -1 ) ? SMESH::DIM_3D : myMaxShapeDim;
+ for ( int i = SMESH::DIM_0D; i <= aMaxShapeDim; i++ ) {
+ myDlg->enableTab( i );
+ }
+ myDlg->setCurrentTab( theTabIndex );
+ myDlg->setHypoSets( SMESH::GetHypothesesSets( aMaxShapeDim, "" ) );
+ }
+ break;
+ case MT_TRIANGULAR:{
+ aDim = SMESH::DIM_2D;
+ anCompareType = "TRIA";
+ }
+ break;
+ case MT_QUADRILATERAL:{
+ aDim = SMESH::DIM_2D;
+ anCompareType = "QUAD";
+ }
+ break;
+ case MT_TETRAHEDRAL:{
+ aDim = SMESH::DIM_3D;
+ anCompareType = "TETRA";
+ }
+ break;
+ case MT_HEXAHEDRAL:{
+ aDim = SMESH::DIM_3D;
+ anCompareType = "HEXA";
+ }
+ break;
+ default:;
+ }
+ if ( anCompareType != "ANY" )
+ {
+ QString anCurrentAlgo;
+ bool isReqDisBound = true;
+ isNone = currentHyp( aDim, Algo ) < 0;
+ // retrieves a list of available algorithms from resources
+ availableHyps( aDim, Algo, anAvailableAlgs, anAvailableAlgsData );
+ // finding algorithm which is selected
+ if ( !isNone && !myAvailableHypData[aDim][Algo].empty() &&
+ myAvailableHypData[aDim][Algo].count() != anAvailableAlgsData.count() ){
+ anCurrentAlgo = myAvailableHypData[aDim][Algo].at( currentHyp( aDim, Algo ) )->Label;
+ isReqDisBound = myAvailableHypData[aDim][Algo].at( currentHyp( aDim, Algo ) )->InputTypes.isEmpty();
+ }
+ else if ( !isNone ){
+ anCurrentAlgo = anAvailableAlgsData.at( currentHyp( aDim, Algo ) )->Label;
+ isReqDisBound = anAvailableAlgsData.at( currentHyp( aDim, Algo ) )->InputTypes.isEmpty();
+ }
+ anAvailableAlgs.clear();
+ myAvailableHypData[aDim][Algo].clear();
+ // finding and adding algorithm depending on the type mesh
+ for ( int i = 0 ; i < anAvailableAlgsData.count(); i++ )
+ {
+ HypothesisData* algoIn = anAvailableAlgsData.at( i );
+ bool isAvailableAlgo = ( algoIn->OutputTypes.count() == 0 );
+ QStringList::const_iterator inElemType = algoIn->OutputTypes.begin();
+ for ( ; inElemType != algoIn->OutputTypes.end(); inElemType++ )
+ {
+ if ( *inElemType == anCompareType ){
+ isAvailableAlgo = true;
+ break;
+ }
+ }
+ if ( isAvailableAlgo || algoIn->OutputTypes.count()==0 ){
+ anAvailableAlgs.append( algoIn->Label );
+ myAvailableHypData[aDim][Algo].append( algoIn );
+ }
+ //algorithm will be active, if the chosen algorithm available in the current mesh type
+ if ( !isNone && isAvailableAlgo && algoIn->Label == anCurrentAlgo ){
+ isAvailableChoiceAlgo = true;
+ anCurrentAvailableAlgo = anAvailableAlgs.count() - 1 ;
+ }
+ }
+ //set new algorithm list and select the current algorithm
+ myDlg->tab( aDim )->setAvailableHyps( Algo, anAvailableAlgs );
+ if ( isAvailableChoiceAlgo )
+ setCurrentHyp( aDim, Algo, anCurrentAvailableAlgo );
+ int aMaxShapeDim = ( myMaxShapeDim == -1 ) ? SMESH::DIM_3D : myMaxShapeDim;
+ if ( isNone || isReqDisBound || !isAvailableChoiceAlgo ) {
+ for ( int i = SMESH::DIM_0D; i <= aMaxShapeDim; i++ ) {
+ if ( aDim != i ) {
+ myDlg->disableTab( i );
+ setCurrentHyp(i, Algo, -1);
+ }
+ }
+ }
+ else if ( !isNone ){
+ if ( aDim == SMESH::DIM_2D){
+ myDlg->disableTab( SMESH::DIM_3D );
+ setCurrentHyp( SMESH::DIM_3D, Algo, -1);
+ }
+ for ( int i = aMaxShapeDim; i > SMESH::DIM_0D; i-- )
+ {
+ isReqDisBound = ( currentHyp( i, Algo ) < 0 ) ? true : myAvailableHypData[i][Algo].at( currentHyp( i, Algo ) )->InputTypes.isEmpty();
+ if ( aMaxShapeDim != i && isReqDisBound) {
+ for (int j = i - 1; j >= SMESH::DIM_0D; j--){
+ myDlg->disableTab( j );
+ setCurrentHyp( j , Algo, -1 );
+ }
+ break;
+ }
+ }
+ }
+ myDlg->setHypoSets( SMESH::GetHypothesesSets( aDim, anCompareType ) );
+ myDlg->enableTab( aDim );
+ myDlg->setCurrentTab( aDim );
+ }
+}
diff --git a/src/SMESHGUI/SMESHGUI_MeshOp.h b/src/SMESHGUI/SMESHGUI_MeshOp.h
index 91c39ed72..5f5688267 100644
--- a/src/SMESHGUI/SMESHGUI_MeshOp.h
+++ b/src/SMESHGUI/SMESHGUI_MeshOp.h
@@ -48,6 +48,7 @@ class SMESHGUI_EXPORT SMESHGUI_MeshOp : public SMESHGUI_SelectionOp
public:
enum HypType{ Algo = 0, MainHyp, AddHyp, NbHypTypes };
+ enum MeshType{ MT_ANY = 0, MT_TRIANGULAR, MT_QUADRILATERAL, MT_TETRAHEDRAL, MT_HEXAHEDRAL };
typedef std::pair THypItem;
typedef QList< THypItem > THypList;
@@ -83,6 +84,7 @@ protected slots:
void processSet();
void onHypoCreated( int );
void onHypoEdited( int );
+ void onAlgoSetByMeshType( const int, const int );
private:
typedef QList THypDataList; // typedef: list of hypothesis data
@@ -125,7 +127,8 @@ private:
char* isSubmeshIgnored() const;
_PTR(SObject) getSubmeshByGeom() const;
void selectObject( _PTR(SObject) ) const;
-
+ void createMeshTypeList( QStringList& );
+ void setAvailableMeshType( const QStringList& );
private:
SMESHGUI_MeshDlg* myDlg;
SMESHGUI_ShapeByMeshOp* myShapeByMeshOp;
@@ -136,13 +139,12 @@ private:
TDim2Type2HypList myExistingHyps; //!< all hypothesis of SMESH module
TDim2Type2HypList myObjHyps; //!< hypothesis assigned to the current
// edited mesh/sub-mesh
-
// hypdata corresponding to hypotheses present in myDlg
THypDataList myAvailableHypData[4][NbHypTypes];
bool myIgnoreAlgoSelection;
HypothesesSet* myHypoSet;
- int myDim, myType;
+ int myDim, myType, myMaxShapeDim;
QString myObjectToSelect;
};
diff --git a/src/SMESHGUI/SMESH_msg_en.ts b/src/SMESHGUI/SMESH_msg_en.ts
index 174bcf165..df41ace14 100644
--- a/src/SMESHGUI/SMESH_msg_en.ts
+++ b/src/SMESHGUI/SMESH_msg_en.ts
@@ -5977,6 +5977,10 @@ Please specify them and try again
MESH
Mesh
+
+ MESH_TYPE
+ Mesh type
+
NAME
Name
@@ -6032,6 +6036,26 @@ Please specify it and try again
MESH_IS_NULL
Mesh is null
+
+ MT_ANY
+ Any
+
+
+ MT_HEXAHEDRAL
+ Hexahedral
+
+
+ MT_TETRAHEDRAL
+ Tetrahedral
+
+
+ MT_TRIANGULAR
+ Triangular
+
+
+ MT_QUADRILATERAL
+ Quadrilaterial
+
NAME_OF_MESH_IS_EMPTY
Name of mesh is empty
diff --git a/src/SMESHGUI/SMESH_msg_fr.ts b/src/SMESHGUI/SMESH_msg_fr.ts
index 749b17e7e..b8ddd3e1b 100755
--- a/src/SMESHGUI/SMESH_msg_fr.ts
+++ b/src/SMESHGUI/SMESH_msg_fr.ts
@@ -5971,6 +5971,10 @@ Indiquez-les et essayez de nouveau
MESH
Maillage
+
+ MESH_TYPE
+ Mesh type
+
NAME
Nom
@@ -6026,6 +6030,26 @@ Spécifiez-le et essayez de nouveau
MESH_IS_NULL
Le maillage est nul
+
+ MT_ANY
+ Any
+
+
+ MT_HEXAHEDRAL
+ Hexahedral
+
+
+ MT_TETRAHEDRAL
+ Tetrahedral
+
+
+ MT_TRIANGULAR
+ Triangular
+
+
+ MT_QUADRILATERAL
+ Quadrilaterial
+
NAME_OF_MESH_IS_EMPTY
Le nom du maillage est vide
diff --git a/src/SMESHUtils/SMESH_Block.cxx b/src/SMESHUtils/SMESH_Block.cxx
index 7d2ed2a71..fd40175d8 100644
--- a/src/SMESHUtils/SMESH_Block.cxx
+++ b/src/SMESHUtils/SMESH_Block.cxx
@@ -26,6 +26,11 @@
//
#include "SMESH_Block.hxx"
+#include "SMDS_MeshNode.hxx"
+#include "SMDS_MeshVolume.hxx"
+#include "SMDS_VolumeTool.hxx"
+#include "SMESH_MeshAlgos.hxx"
+
#include
#include
#include
@@ -56,10 +61,7 @@
#include
#include
-#include "SMDS_MeshNode.hxx"
-#include "SMDS_MeshVolume.hxx"
-#include "SMDS_VolumeTool.hxx"
-#include "utilities.h"
+#include
#include
#include
@@ -309,24 +311,15 @@ gp_XYZ SMESH_Block::TFace::Point( const gp_XYZ& theParams ) const
namespace
{
+ inline
bool isPntInTria( const gp_XY& p, const gp_XY& t0, const gp_XY& t1, const gp_XY& t2 )
{
- const double // matrix 2x2
- T11 = t0.X()-t2.X(), T12 = t1.X()-t2.X(),
- T21 = t0.Y()-t2.Y(), T22 = t1.Y()-t2.Y();
- const double Tdet = T11*T22 - T12*T21; // matrix determinant
- if ( Abs( Tdet ) < std::numeric_limits::min() )
- return false;
- // matrix inverse
- const double t11 = T22, t12 = -T12, t21 = -T21, t22 = T11;
- // vector
- const double r11 = p.X()-t2.X(), r12 = p.Y()-t2.Y();
- // barycentric coordinates: mutiply matrix by vector
- const double bc0 = (t11 * r11 + t12 * r12)/Tdet;
- const double bc1 = (t21 * r11 + t22 * r12)/Tdet;
+ double bc0, bc1;
+ SMESH_MeshAlgos::GetBarycentricCoords( p, t0, t1, t2, bc0, bc1 );
return ( bc0 >= 0. && bc1 >= 0. && bc0 + bc1 <= 1. );
}
+ inline
bool isPntInQuad( const gp_XY& p,
const gp_XY& q0, const gp_XY& q1, const gp_XY& q2, const gp_XY& q3 )
{
diff --git a/src/SMESHUtils/SMESH_Block.hxx b/src/SMESHUtils/SMESH_Block.hxx
index a2fcd0a1a..4fc690137 100644
--- a/src/SMESHUtils/SMESH_Block.hxx
+++ b/src/SMESHUtils/SMESH_Block.hxx
@@ -68,20 +68,19 @@ class SMESHUtils_EXPORT SMESH_Block: public math_FunctionSetWithDerivatives
// ----------------------------
ID_NONE = 0,
- ID_V000 = 1, ID_V100, ID_V010, ID_V110, ID_V001, ID_V101, ID_V011, ID_V111,
+ ID_V000 = 1, ID_V100, ID_V010, ID_V110, ID_V001, ID_V101, ID_V011, ID_V111, // 1-8
- ID_Ex00, ID_Ex10, ID_Ex01, ID_Ex11,
- ID_E0y0, ID_E1y0, ID_E0y1, ID_E1y1,
- ID_E00z, ID_E10z, ID_E01z, ID_E11z,
+ ID_Ex00, ID_Ex10, ID_Ex01, ID_Ex11, // 9-12
+ ID_E0y0, ID_E1y0, ID_E0y1, ID_E1y1, // 13-16
+ ID_E00z, ID_E10z, ID_E01z, ID_E11z, // 17-20
- ID_Fxy0, ID_Fxy1, ID_Fx0z, ID_Fx1z, ID_F0yz, ID_F1yz,
+ ID_Fxy0, ID_Fxy1, ID_Fx0z, ID_Fx1z, ID_F0yz, ID_F1yz, // 21-26
- ID_Shell
- };
- enum { // to use TShapeID for indexing certain type subshapes
+ ID_Shell, // 27
+
+ // to use TShapeID for indexing certain type subshapes
ID_FirstV = ID_V000, ID_FirstE = ID_Ex00, ID_FirstF = ID_Fxy0
-
};
@@ -285,7 +284,7 @@ public:
std::list< int > & theNbEdgesInWires,
TopoDS_Vertex theFirstVertex=TopoDS_Vertex(),
const bool theShapeAnalysisAlgo=false);
- // Return nb wires and a list of oredered edges.
+ // Return nb wires and a list of ordered edges.
// It is used to assign indices to subshapes.
// theFirstVertex may be NULL.
// Always try to set a seam edge first
diff --git a/src/SMESHUtils/SMESH_MeshAlgos.cxx b/src/SMESHUtils/SMESH_MeshAlgos.cxx
index 45acf33b1..2ecd29a90 100644
--- a/src/SMESHUtils/SMESH_MeshAlgos.cxx
+++ b/src/SMESHUtils/SMESH_MeshAlgos.cxx
@@ -1386,6 +1386,39 @@ double SMESH_MeshAlgos::GetDistance( const SMDS_MeshFace* face,
return badDistance;
}
+//================================================================================
+/*!
+ * \brief Returns barycentric coordinates of a point within a triangle.
+ * A not returned bc2 = 1. - bc0 - bc1.
+ * The point lies within the triangle if ( bc0 >= 0 && bc1 >= 0 && bc0+bc1 <= 1 )
+ */
+//================================================================================
+
+void SMESH_MeshAlgos::GetBarycentricCoords( const gp_XY& p,
+ const gp_XY& t0,
+ const gp_XY& t1,
+ const gp_XY& t2,
+ double & bc0,
+ double & bc1)
+{
+ const double // matrix 2x2
+ T11 = t0.X()-t2.X(), T12 = t1.X()-t2.X(),
+ T21 = t0.Y()-t2.Y(), T22 = t1.Y()-t2.Y();
+ const double Tdet = T11*T22 - T12*T21; // matrix determinant
+ if ( Abs( Tdet ) < std::numeric_limits::min() )
+ {
+ bc0 = bc1 = 2.;
+ return;
+ }
+ // matrix inverse
+ const double t11 = T22, t12 = -T12, t21 = -T21, t22 = T11;
+ // vector
+ const double r11 = p.X()-t2.X(), r12 = p.Y()-t2.Y();
+ // barycentric coordinates: mutiply matrix by vector
+ bc0 = (t11 * r11 + t12 * r12)/Tdet;
+ bc1 = (t21 * r11 + t22 * r12)/Tdet;
+}
+
//=======================================================================
//function : FindFaceInSet
//purpose : Return a face having linked nodes n1 and n2 and which is
diff --git a/src/SMESHUtils/SMESH_MeshAlgos.hxx b/src/SMESHUtils/SMESH_MeshAlgos.hxx
index a02ba10dd..dc4d8fcb4 100644
--- a/src/SMESHUtils/SMESH_MeshAlgos.hxx
+++ b/src/SMESHUtils/SMESH_MeshAlgos.hxx
@@ -97,9 +97,16 @@ namespace SMESH_MeshAlgos
/*!
* \brief Return true if the point is IN or ON of the element
*/
- SMESHUtils_EXPORT bool IsOut( const SMDS_MeshElement* element, const gp_Pnt& point, double tol );
+ SMESHUtils_EXPORT
+ bool IsOut( const SMDS_MeshElement* element, const gp_Pnt& point, double tol );
- SMESHUtils_EXPORT double GetDistance( const SMDS_MeshFace* face, const gp_Pnt& point );
+ SMESHUtils_EXPORT
+ double GetDistance( const SMDS_MeshFace* face, const gp_Pnt& point );
+
+ SMESHUtils_EXPORT
+ void GetBarycentricCoords( const gp_XY& point,
+ const gp_XY& t0, const gp_XY& t1, const gp_XY& t2,
+ double & bc0, double & bc1);
/*!
* Return a face having linked nodes n1 and n2 and which is
@@ -107,35 +114,40 @@ namespace SMESH_MeshAlgos
* - in elemSet provided that !elemSet.empty()
* i1 and i2 optionally returns indices of n1 and n2
*/
- SMESHUtils_EXPORT const SMDS_MeshElement*
- FindFaceInSet(const SMDS_MeshNode* n1,
- const SMDS_MeshNode* n2,
- const TIDSortedElemSet& elemSet,
- const TIDSortedElemSet& avoidSet,
- int* i1=0,
- int* i2=0);
+ SMESHUtils_EXPORT
+ const SMDS_MeshElement* FindFaceInSet(const SMDS_MeshNode* n1,
+ const SMDS_MeshNode* n2,
+ const TIDSortedElemSet& elemSet,
+ const TIDSortedElemSet& avoidSet,
+ int* i1=0,
+ int* i2=0);
/*!
* \brief Calculate normal of a mesh face
*/
- SMESHUtils_EXPORT bool FaceNormal(const SMDS_MeshElement* F, gp_XYZ& normal, bool normalized=true);
+ SMESHUtils_EXPORT
+ bool FaceNormal(const SMDS_MeshElement* F, gp_XYZ& normal, bool normalized=true);
/*!
* \brief Return nodes common to two elements
*/
- SMESHUtils_EXPORT std::vector< const SMDS_MeshNode*> GetCommonNodes(const SMDS_MeshElement* e1,
+ SMESHUtils_EXPORT
+ std::vector< const SMDS_MeshNode*> GetCommonNodes(const SMDS_MeshElement* e1,
const SMDS_MeshElement* e2);
/*!
* \brief Return SMESH_NodeSearcher. The caller is responsible for deleteing it
*/
- SMESHUtils_EXPORT SMESH_NodeSearcher* GetNodeSearcher( SMDS_Mesh& mesh );
+ SMESHUtils_EXPORT
+ SMESH_NodeSearcher* GetNodeSearcher( SMDS_Mesh& mesh );
/*!
* \brief Return SMESH_ElementSearcher. The caller is responsible for deleting it
*/
- SMESHUtils_EXPORT SMESH_ElementSearcher* GetElementSearcher( SMDS_Mesh& mesh );
- SMESHUtils_EXPORT SMESH_ElementSearcher* GetElementSearcher( SMDS_Mesh& mesh,
- SMDS_ElemIteratorPtr elemIt );
+ SMESHUtils_EXPORT
+ SMESH_ElementSearcher* GetElementSearcher( SMDS_Mesh& mesh );
+ SMESHUtils_EXPORT
+ SMESH_ElementSearcher* GetElementSearcher( SMDS_Mesh& mesh,
+ SMDS_ElemIteratorPtr elemIt );
}
#endif
diff --git a/src/SMESHUtils/SMESH_TypeDefs.hxx b/src/SMESHUtils/SMESH_TypeDefs.hxx
index 2555cc371..6e5bda2a5 100644
--- a/src/SMESHUtils/SMESH_TypeDefs.hxx
+++ b/src/SMESHUtils/SMESH_TypeDefs.hxx
@@ -29,9 +29,10 @@
#include "SMESH_Utils.hxx"
-#include
+#include "SMDS_MeshNode.hxx"
#include
+#include
#include
#include
@@ -42,7 +43,7 @@ typedef std::map, TIDCompare > TElemOfElemListMap;
typedef std::map, TIDCompare > TElemOfNodeListMap;
-typedef std::map TNodeNodeMap;
+typedef std::map TNodeNodeMap;
//!< Set of elements sorted by ID, to be used to assure predictability of edition
typedef std::set< const SMDS_MeshElement*, TIDCompare > TIDSortedElemSet;
@@ -50,8 +51,8 @@ typedef std::set< const SMDS_MeshNode*, TIDCompare > TIDSortedNodeSet;
typedef std::pair< const SMDS_MeshNode*, const SMDS_MeshNode* > NLink;
-struct faceQuadStruct; // defined in StdMeshers_Quadrangle_2D.hxx
-typedef boost::shared_ptr TFaceQuadStructPtr;
+struct FaceQuadStruct; // defined in StdMeshers_Quadrangle_2D.hxx
+typedef boost::shared_ptr TFaceQuadStructPtr;
namespace SMESHUtils
@@ -137,6 +138,10 @@ typedef struct uvPtStruct
double x, y; // 2d parameter, normalized [0,1]
const SMDS_MeshNode * node;
+ uvPtStruct(): node(NULL) {}
+
+ inline gp_XY UV() const { return gp_XY( u, v ); }
+
struct NodeAccessor // accessor to iterate on nodes in UVPtStructVec
{
static const SMDS_MeshNode* value(std::vector< uvPtStruct >::const_iterator it)
diff --git a/src/SMESH_I/SMESH_2smeshpy.cxx b/src/SMESH_I/SMESH_2smeshpy.cxx
index 929da0dcf..7a59ad87f 100644
--- a/src/SMESH_I/SMESH_2smeshpy.cxx
+++ b/src/SMESH_I/SMESH_2smeshpy.cxx
@@ -2075,6 +2075,7 @@ bool _pyMesh::NeedMeshAccess( const Handle(_pyCommand)& theCommand )
"GetSubMeshElementsId","GetSubMeshNodesId","GetSubMeshElementType","Dump","GetNodeXYZ",
"GetNodeInverseElements","GetShapeID","GetShapeIDForElem","GetElemNbNodes",
"GetElemNode","IsMediumNode","IsMediumNodeOfAnyElem","ElemNbEdges","ElemNbFaces",
+ "GetElemFaceNodes", "GetFaceNormal", "FindElementByNodes",
"IsPoly","IsQuadratic","BaryCenter","GetHypothesisList", "SetAutoColor", "GetAutoColor",
"Clear", "ConvertToStandalone", "GetMeshOrder", "SetMeshOrder"
,"" }; // <- mark of end
diff --git a/src/SMESH_I/SMESH_DumpPython.cxx b/src/SMESH_I/SMESH_DumpPython.cxx
index 43ffd029b..78d9bf959 100644
--- a/src/SMESH_I/SMESH_DumpPython.cxx
+++ b/src/SMESH_I/SMESH_DumpPython.cxx
@@ -240,13 +240,20 @@ namespace SMESH
template
void DumpArray(const TArray& theArray, TPythonDump & theStream)
{
- theStream << "[ ";
- for (int i = 1; i <= theArray.length(); i++) {
- theStream << theArray[i-1];
- if ( i < theArray.length() )
- theStream << ", ";
+ if ( theArray.length() == 0 )
+ {
+ theStream << "[]";
+ }
+ else
+ {
+ theStream << "[ ";
+ for (int i = 1; i <= theArray.length(); i++) {
+ theStream << theArray[i-1];
+ if ( i < theArray.length() )
+ theStream << ", ";
+ }
+ theStream << " ]";
}
- theStream << " ]";
}
TPythonDump&
@@ -263,6 +270,13 @@ namespace SMESH
return *this;
}
+ TPythonDump&
+ TPythonDump::operator<<(const SMESH::nodes_array& theArg)
+ {
+ DumpArray( theArg, *this );
+ return *this;
+ }
+
TPythonDump&
TPythonDump::operator<<(const SMESH::string_array& theArray)
{
@@ -517,6 +531,11 @@ namespace SMESH
DumpArray( *theList, *this );
return *this;
}
+ TPythonDump& TPythonDump::operator<<(const GEOM::ListOfGO& theList)
+ {
+ DumpArray( theList, *this );
+ return *this;
+ }
TPythonDump& TPythonDump::operator<<(const SMESH::ListOfIDSources& theList)
{
DumpArray( theList, *this );
diff --git a/src/SMESH_I/SMESH_Mesh_i.cxx b/src/SMESH_I/SMESH_Mesh_i.cxx
index 812d3c0cd..f6beb92d5 100644
--- a/src/SMESH_I/SMESH_Mesh_i.cxx
+++ b/src/SMESH_I/SMESH_Mesh_i.cxx
@@ -44,6 +44,7 @@
#include "SMESH_Gen_i.hxx"
#include "SMESH_Group.hxx"
#include "SMESH_Group_i.hxx"
+#include "SMESH_MeshAlgos.hxx"
#include "SMESH_MeshEditor.hxx"
#include "SMESH_MeshEditor_i.hxx"
#include "SMESH_MeshPartDS.hxx"
@@ -4023,6 +4024,32 @@ SMESH::long_array* SMESH_Mesh_i::GetElemFaceNodes(CORBA::Long elemId,
return aResult._retn();
}
+//=======================================================================
+//function : GetElemFaceNodes
+//purpose : Returns three components of normal of given mesh face.
+//=======================================================================
+
+SMESH::double_array* SMESH_Mesh_i::GetFaceNormal(CORBA::Long elemId)
+{
+ if ( _preMeshInfo )
+ _preMeshInfo->FullLoadFromFile();
+
+ SMESH::double_array_var aResult = new SMESH::double_array();
+
+ if ( SMESHDS_Mesh* mesh = _impl->GetMeshDS() )
+ {
+ gp_XYZ normal;
+ if ( SMESH_MeshAlgos::FaceNormal( mesh->FindElement(elemId), normal, /*normalized=*/true ))
+ {
+ aResult->length( 3 );
+ aResult[ 0 ] = normal.X();
+ aResult[ 1 ] = normal.Y();
+ aResult[ 2 ] = normal.Z();
+ }
+ }
+ return aResult._retn();
+}
+
//=======================================================================
//function : FindElementByNodes
//purpose : Returns an element based on all given nodes.
diff --git a/src/SMESH_I/SMESH_Mesh_i.hxx b/src/SMESH_I/SMESH_Mesh_i.hxx
index c52699bb2..2615bef48 100644
--- a/src/SMESH_I/SMESH_Mesh_i.hxx
+++ b/src/SMESH_I/SMESH_Mesh_i.hxx
@@ -532,6 +532,11 @@ public:
*/
SMESH::long_array* GetElemFaceNodes(CORBA::Long elemId, CORBA::Short faceIndex);
+ /*!
+ * Returns three components of normal of given mesh face (or an empty array in KO case)
+ */
+ SMESH::double_array* GetFaceNormal(CORBA::Long faceId);
+
/*!
* Returns an element based on all given nodes.
*/
diff --git a/src/SMESH_I/SMESH_PythonDump.hxx b/src/SMESH_I/SMESH_PythonDump.hxx
index 595e732fa..1f9d5a623 100644
--- a/src/SMESH_I/SMESH_PythonDump.hxx
+++ b/src/SMESH_I/SMESH_PythonDump.hxx
@@ -27,6 +27,7 @@
#include
#include CORBA_SERVER_HEADER(SMESH_Mesh)
+#include CORBA_SERVER_HEADER(GEOM_Gen)
#include CORBA_SERVER_HEADER(SALOMEDS)
#include
@@ -162,6 +163,9 @@ namespace SMESH
TPythonDump&
operator<<(const SMESH::string_array& theArg);
+ TPythonDump&
+ operator<<(const SMESH::nodes_array& theArg);
+
TPythonDump&
operator<<(SMESH::SMESH_Hypothesis_ptr theArg);
@@ -216,6 +220,9 @@ namespace SMESH
TPythonDump&
operator<<(const SMESH::ListOfGroups * theList);
+ TPythonDump&
+ operator<<(const GEOM::ListOfGO& theList);
+
TPythonDump&
operator<<(const SMESH::ListOfIDSources& theList);
diff --git a/src/SMESH_SWIG/StdMeshersBuilder.py b/src/SMESH_SWIG/StdMeshersBuilder.py
index e28659b55..4e5b2d217 100644
--- a/src/SMESH_SWIG/StdMeshersBuilder.py
+++ b/src/SMESH_SWIG/StdMeshersBuilder.py
@@ -199,7 +199,8 @@ class StdMeshersBuilder_Segment(Mesh_Algorithm):
hyp.SetDeflection(deflection)
return hyp
- ## Defines "Arithmetic1D" hypothesis to cut an edge in several segments with increasing arithmetic length
+ ## Defines "Arithmetic1D" hypothesis to cut an edge in several segments with a length
+ # that changes in arithmetic progression
# @param start defines the length of the first segment
# @param end defines the length of the last segment
# @param reversedEdges is a list of edges to mesh using reversed orientation.
@@ -226,6 +227,32 @@ class StdMeshersBuilder_Segment(Mesh_Algorithm):
hyp.SetObjectEntry( entry )
return hyp
+ ## Defines "GeometricProgression" hypothesis to cut an edge in several
+ # segments with a length that changes in Geometric progression
+ # @param start defines the length of the first segment
+ # @param ratio defines the common ratio of the geometric progression
+ # @param reversedEdges is a list of edges to mesh using reversed orientation.
+ # A list item can also be a tuple (edge, 1st_vertex_of_edge)
+ # @param UseExisting if ==true - searches for an existing hypothesis created with
+ # the same parameters, else (default) - creates a new one
+ # @return an instance of StdMeshers_Geometric1D hypothesis
+ # @ingroup l3_hypos_1dhyps
+ def GeometricProgression(self, start, ratio, reversedEdges=[], UseExisting=0):
+ reversedEdgeInd = self.ReversedEdgeIndices(reversedEdges)
+ entry = self.MainShapeEntry()
+ from salome.smesh.smeshBuilder import IsEqual
+ compFun = lambda hyp, args: ( IsEqual(hyp.GetLength(1), args[0]) and \
+ IsEqual(hyp.GetLength(0), args[1]) and \
+ hyp.GetReversedEdges() == args[2] and \
+ (not args[2] or hyp.GetObjectEntry() == args[3]))
+ hyp = self.Hypothesis("GeometricProgression", [start, ratio, reversedEdgeInd, entry],
+ UseExisting=UseExisting, CompareMethod=compFun)
+ hyp.SetStartLength( start )
+ hyp.SetCommonRatio( ratio )
+ hyp.SetReversedEdges( reversedEdgeInd )
+ hyp.SetObjectEntry( entry )
+ return hyp
+
## Defines "FixedPoints1D" hypothesis to cut an edge using parameter
# on curve from 0 to 1 (additionally it is neecessary to check
# orientation of edges and create list of reversed edges if it is
@@ -237,7 +264,7 @@ class StdMeshersBuilder_Segment(Mesh_Algorithm):
# A list item can also be a tuple (edge, 1st_vertex_of_edge)
# @param UseExisting if ==true - searches for an existing hypothesis created with
# the same parameters, else (default) - creates a new one
- # @return an instance of StdMeshers_Arithmetic1D hypothesis
+ # @return an instance of StdMeshers_FixedPoints1D hypothesis
# @ingroup l3_hypos_1dhyps
def FixedPoints1D(self, points, nbSegs=[1], reversedEdges=[], UseExisting=0):
if not isinstance(reversedEdges,list): #old version script, before adding reversedEdges
@@ -295,12 +322,23 @@ class StdMeshersBuilder_Segment(Mesh_Algorithm):
hyp.SetDeflection(d)
return hyp
- ## Defines "Propagation" hypothesis that propagates all other hypotheses on all other edges that are at
- # the opposite side in case of quadrangular faces
+ ## Defines "Propagation" hypothesis that propagates 1D hypotheses
+ # from an edge where this hypothesis is assigned to
+ # on all other edges that are at the opposite side in case of quadrangular faces
+ # This hypothesis should be assigned to an edge to propagate a hypothesis from.
# @ingroup l3_hypos_additi
def Propagation(self):
return self.Hypothesis("Propagation", UseExisting=1, CompareMethod=self.CompareEqualHyp)
+ ## Defines "Propagation of Node Distribution" hypothesis that propagates
+ # distribution of nodes from an edge where this hypothesis is assigned to,
+ # to opposite edges of quadrangular faces, so that number of segments on all these
+ # edges will be the same, as well as relations between segment lengths.
+ # @ingroup l3_hypos_additi
+ def PropagationOfDistribution(self):
+ return self.Hypothesis("PropagOfDistribution", UseExisting=1,
+ CompareMethod=self.CompareEqualHyp)
+
## Defines "AutomaticLength" hypothesis
# @param fineness for the fineness [0-1]
# @param UseExisting if ==true - searches for an existing hypothesis created with the
@@ -552,28 +590,56 @@ class StdMeshersBuilder_Quadrangle(Mesh_Algorithm):
# same number of segments, the other pair must have an even difference
# between the numbers of segments on the sides.
# @param triangleVertex: vertex of a trilateral geometrical face, around which triangles
- # will be created while other elements will be quadrangles.
- # Vertex can be either a GEOM_Object or a vertex ID within the
- # shape to mesh
- # @param UseExisting: if ==true - searches for the existing hypothesis created with
- # the same parameters, else (default) - creates a new one
+ # will be created while other elements will be quadrangles.
+ # Vertex can be either a GEOM_Object or a vertex ID within the
+ # shape to mesh
+ # @param enfVertices: list of shapes defining positions where nodes (enforced nodes)
+ # must be created by the mesher. Shapes can be of any type,
+ # vertices of given shapes define positions of enforced nodes.
+ # Only vertices successfully projected to the face are used.
+ # @param enfPoint: list of points giving positions of enforced nodes.
+ # Point can be defined either as SMESH.PointStruct's
+ # ([SMESH.PointStruct(x1,y1,z1), SMESH.PointStruct(x2,y2,z2),...])
+ # or triples of values ([[x1,y1,z1], [x2,y2,z2], ...]).
+ # In the case if the defined QuadrangleParameters() refer to a sole face,
+ # all given points must lie on this face, else the mesher fails.
+ # @param UseExisting: if \c True - searches for the existing hypothesis created with
+ # the same parameters, else (default) - creates a new one
# @ingroup l3_hypos_quad
- def QuadrangleParameters(self, quadType=StdMeshers.QUAD_STANDARD, triangleVertex=0, UseExisting=0):
- import GEOM
+ def QuadrangleParameters(self, quadType=StdMeshers.QUAD_STANDARD, triangleVertex=0,
+ enfVertices=[],enfPoints=[],UseExisting=0):
+ import GEOM, SMESH
vertexID = triangleVertex
if isinstance( triangleVertex, GEOM._objref_GEOM_Object ):
vertexID = self.mesh.geompyD.GetSubShapeID( self.mesh.geom, triangleVertex )
+ if isinstance( enfVertices, int ) and not enfPoints and not UseExisting:
+ # a call of old syntax, before inserting enfVertices and enfPoints before UseExisting
+ UseExisting, enfVertices = enfVertices, []
+ pStructs, xyz = [], []
+ for p in enfPoints:
+ if isinstance( p, SMESH.PointStruct ):
+ xyz.append(( p.x, p.y, p.z ))
+ pStructs.append( p )
+ else:
+ xyz.append(( p[0], p[1], p[2] ))
+ pStructs.append( SMESH.PointStruct( p[0], p[1], p[2] ))
if not self.params:
compFun = lambda hyp,args: \
hyp.GetQuadType() == args[0] and \
- ( hyp.GetTriaVertex()==args[1] or ( hyp.GetTriaVertex()<1 and args[1]<1))
- self.params = self.Hypothesis("QuadrangleParams", [quadType,vertexID],
+ (hyp.GetTriaVertex()==args[1] or ( hyp.GetTriaVertex()<1 and args[1]<1)) and \
+ ((hyp.GetEnforcedNodes()) == (args[2],args[3])) # True w/o enfVertices only
+ entries = [ shape.GetStudyEntry() for shape in enfVertices ]
+ self.params = self.Hypothesis("QuadrangleParams", [quadType,vertexID,entries,xyz],
UseExisting = UseExisting, CompareMethod=compFun)
pass
if self.params.GetQuadType() != quadType:
self.params.SetQuadType(quadType)
if vertexID > 0:
self.params.SetTriaVertex( vertexID )
+ from salome.smesh.smeshBuilder import AssureGeomPublished
+ for v in enfVertices:
+ AssureGeomPublished( self.mesh, v )
+ self.params.SetEnforcedNodes( enfVertices, pStructs )
return self.params
## Defines "QuadrangleParams" hypothesis with a type of quadrangulation that only
@@ -980,7 +1046,8 @@ class StdMeshersBuilder_Prism3D(Mesh_Algorithm):
return hyp
## Defines "Arithmetic1D" hypothesis, specifying the distribution of segments
- # to build between the inner and the outer shells with a length that changes in arithmetic progression
+ # to build between the inner and the outer shells with a length that changes
+ # in arithmetic progression
# @param start the length of the first segment
# @param end the length of the last segment
def Arithmetic1D(self, start, end ):
@@ -992,6 +1059,20 @@ class StdMeshersBuilder_Prism3D(Mesh_Algorithm):
hyp.SetLength(end , 0)
return hyp
+ ## Defines "GeometricProgression" hypothesis, specifying the distribution of segments
+ # to build between the inner and the outer shells with a length that changes
+ # in Geometric progression
+ # @param start the length of the first segment
+ # @param ratio the common ratio of the geometric progression
+ def GeometricProgression(self, start, ratio ):
+ if self.algoType != "RadialPrism_3D":
+ print "Prism_3D algorith doesn't support any hyposesis"
+ return None
+ hyp = self.OwnHypothesis("GeometricProgression", [start, ratio])
+ hyp.SetStartLength( start )
+ hyp.SetCommonRatio( ratio )
+ return hyp
+
## Defines "StartEndLength" hypothesis, specifying distribution of segments
# to build between the inner and the outer shells as geometric length increasing
# @param start for the length of the first segment
@@ -1148,6 +1229,16 @@ class StdMeshersBuilder_RadialQuadrangle1D2D(Mesh_Algorithm):
hyp.SetLength(end , 0)
return hyp
+ ## Defines "GeometricProgression" hypothesis, specifying the distribution of segments
+ # with a length that changes in Geometric progression
+ # @param start the length of the first segment
+ # @param ratio the common ratio of the geometric progression
+ def GeometricProgression(self, start, ratio ):
+ hyp = self.OwnHypothesis("GeometricProgression", [start, ratio])
+ hyp.SetStartLength( start )
+ hyp.SetCommonRatio( ratio )
+ return hyp
+
## Defines "StartEndLength" hypothesis, specifying distribution of segments
# as geometric length increasing
# @param start for the length of the first segment
diff --git a/src/SMESH_SWIG/smeshBuilder.py b/src/SMESH_SWIG/smeshBuilder.py
index 5e68dc230..a5aae93d2 100644
--- a/src/SMESH_SWIG/smeshBuilder.py
+++ b/src/SMESH_SWIG/smeshBuilder.py
@@ -2418,6 +2418,12 @@ class Mesh:
def GetElemFaceNodes(self,elemId, faceIndex):
return self.mesh.GetElemFaceNodes(elemId, faceIndex)
+ ## Returns three components of normal of given mesh face
+ # (or an empty array in KO case)
+ # @ingroup l1_meshinfo
+ def GetFaceNormal(self, faceId):
+ return self.mesh.GetFaceNormal(faceId)
+
## Returns an element based on all given nodes.
# @ingroup l1_meshinfo
def FindElementByNodes(self,nodes):
@@ -3181,7 +3187,8 @@ class Mesh:
# Note that nodes built on edges and boundary nodes are always fixed.
# @param MaxNbOfIterations the maximum number of iterations
# @param MaxAspectRatio varies in range [1.0, inf]
- # @param Method is Laplacian(LAPLACIAN_SMOOTH) or Centroidal(CENTROIDAL_SMOOTH)
+ # @param Method is either Laplacian (SMESH.SMESH_MeshEditor.LAPLACIAN_SMOOTH)
+ # or Centroidal (SMESH.SMESH_MeshEditor.CENTROIDAL_SMOOTH)
# @return TRUE in case of success, FALSE otherwise.
# @ingroup l2_modif_smooth
def Smooth(self, IDsOfElements, IDsOfFixedNodes,
@@ -3199,7 +3206,8 @@ class Mesh:
# Note that nodes built on edges and boundary nodes are always fixed.
# @param MaxNbOfIterations the maximum number of iterations
# @param MaxAspectRatio varies in range [1.0, inf]
- # @param Method is Laplacian(LAPLACIAN_SMOOTH) or Centroidal(CENTROIDAL_SMOOTH)
+ # @param Method is either Laplacian (SMESH.SMESH_MeshEditor.LAPLACIAN_SMOOTH)
+ # or Centroidal (SMESH.SMESH_MeshEditor.CENTROIDAL_SMOOTH)
# @return TRUE in case of success, FALSE otherwise.
# @ingroup l2_modif_smooth
def SmoothObject(self, theObject, IDsOfFixedNodes,
@@ -3215,7 +3223,8 @@ class Mesh:
# Note that nodes built on edges and boundary nodes are always fixed.
# @param MaxNbOfIterations the maximum number of iterations
# @param MaxAspectRatio varies in range [1.0, inf]
- # @param Method is Laplacian(LAPLACIAN_SMOOTH) or Centroidal(CENTROIDAL_SMOOTH)
+ # @param Method is either Laplacian (SMESH.SMESH_MeshEditor.LAPLACIAN_SMOOTH)
+ # or Centroidal (SMESH.SMESH_MeshEditor.CENTROIDAL_SMOOTH)
# @return TRUE in case of success, FALSE otherwise.
# @ingroup l2_modif_smooth
def SmoothParametric(self, IDsOfElements, IDsOfFixedNodes,
@@ -3233,7 +3242,8 @@ class Mesh:
# Note that nodes built on edges and boundary nodes are always fixed.
# @param MaxNbOfIterations the maximum number of iterations
# @param MaxAspectRatio varies in range [1.0, inf]
- # @param Method Laplacian(LAPLACIAN_SMOOTH) or Centroidal(CENTROIDAL_SMOOTH)
+ # @param Method is either Laplacian (SMESH.SMESH_MeshEditor.LAPLACIAN_SMOOTH)
+ # or Centroidal (SMESH.SMESH_MeshEditor.CENTROIDAL_SMOOTH)
# @return TRUE in case of success, FALSE otherwise.
# @ingroup l2_modif_smooth
def SmoothParametricObject(self, theObject, IDsOfFixedNodes,
diff --git a/src/SMESH_SWIG/smesh_algorithm.py b/src/SMESH_SWIG/smesh_algorithm.py
index a81f825a6..0d018d52e 100644
--- a/src/SMESH_SWIG/smesh_algorithm.py
+++ b/src/SMESH_SWIG/smesh_algorithm.py
@@ -267,21 +267,26 @@ class Mesh_Algorithm:
# @param thickness total thickness of layers of prisms
# @param numberOfLayers number of layers of prisms
# @param stretchFactor factor (>1.0) of growth of layer thickness towards inside of mesh
- # @param ignoreFaces list of geometrical faces (or their ids) not to generate layers on
+ # @param faces list of geometrical faces (or their ids).
+ # Viscous layers are either generated on these faces or not, depending on
+ # the value of \a isFacesToIgnore parameter.
+ # @param isFacesToIgnore if \c True, the Viscous layers are not generated on the
+ # faces specified by the previous parameter (\a faces).
# @ingroup l3_hypos_additi
- def ViscousLayers(self, thickness, numberOfLayers, stretchFactor, ignoreFaces=[]):
+ def ViscousLayers(self, thickness, numberOfLayers, stretchFactor,
+ faces=[], isFacesToIgnore=True ):
if not isinstance(self.algo, SMESH._objref_SMESH_3D_Algo):
raise TypeError, "ViscousLayers are supported by 3D algorithms only"
if not "ViscousLayers" in self.GetCompatibleHypothesis():
raise TypeError, "ViscousLayers are not supported by %s"%self.algo.GetName()
- if ignoreFaces and isinstance( ignoreFaces[0], geomBuilder.GEOM._objref_GEOM_Object ):
- ignoreFaces = [ self.mesh.geompyD.GetSubShapeID(self.mesh.geom, f) for f in ignoreFaces ]
+ if faces and isinstance( faces[0], geomBuilder.GEOM._objref_GEOM_Object ):
+ faces = [ self.mesh.geompyD.GetSubShapeID(self.mesh.geom, f) for f in faces ]
hyp = self.Hypothesis("ViscousLayers",
- [thickness, numberOfLayers, stretchFactor, ignoreFaces])
+ [thickness, numberOfLayers, stretchFactor, faces])
hyp.SetTotalThickness(thickness)
hyp.SetNumberLayers(numberOfLayers)
hyp.SetStretchFactor(stretchFactor)
- hyp.SetIgnoreFaces(ignoreFaces)
+ hyp.SetFaces(faces, isFacesToIgnore)
return hyp
## Defines "ViscousLayers2D" hypothesis to give parameters of layers of quadrilateral
@@ -290,9 +295,9 @@ class Mesh_Algorithm:
# @param thickness total thickness of layers of quadrilaterals
# @param numberOfLayers number of layers
# @param stretchFactor factor (>1.0) of growth of layer thickness towards inside of mesh
- # @param edges list of geometrical edge (or their ids).
+ # @param edges list of geometrical edges (or their ids).
# Viscous layers are either generated on these edges or not, depending on
- # the values of \a isEdgesToIgnore parameter.
+ # the value of \a isEdgesToIgnore parameter.
# @param isEdgesToIgnore if \c True, the Viscous layers are not generated on the
# edges specified by the previous parameter (\a edges).
# @ingroup l3_hypos_additi
@@ -313,7 +318,7 @@ class Mesh_Algorithm:
hyp.SetEdges(edges, isEdgesToIgnore)
return hyp
- ## Transform a list of ether edges or tuples (edge, 1st_vertex_of_edge)
+ ## Transform a list of either edges or tuples (edge, 1st_vertex_of_edge)
# into a list acceptable to SetReversedEdges() of some 1D hypotheses
# @ingroup l3_hypos_1dhyps
def ReversedEdgeIndices(self, reverseList):
diff --git a/src/StdMeshers/CMakeLists.txt b/src/StdMeshers/CMakeLists.txt
index de84b5026..2dde1b291 100644
--- a/src/StdMeshers/CMakeLists.txt
+++ b/src/StdMeshers/CMakeLists.txt
@@ -75,8 +75,10 @@ ENDIF(SALOME_SMESH_ENABLE_MEFISTO)
# header files / no moc processing
SET(StdMeshers_HEADERS
StdMeshers_LocalLength.hxx
+ StdMeshers_Reversible1D.hxx
StdMeshers_StartEndLength.hxx
StdMeshers_Arithmetic1D.hxx
+ StdMeshers_Geometric1D.hxx
StdMeshers_FixedPoints1D.hxx
StdMeshers_NumberOfSegments.hxx
StdMeshers_Deflection1D.hxx
@@ -136,8 +138,10 @@ ENDIF(SALOME_SMESH_ENABLE_MEFISTO)
# sources / static
SET(StdMeshers_SOURCES
StdMeshers_LocalLength.cxx
+ StdMeshers_Reversible1D.cxx
StdMeshers_StartEndLength.cxx
StdMeshers_Arithmetic1D.cxx
+ StdMeshers_Geometric1D.cxx
StdMeshers_FixedPoints1D.cxx
StdMeshers_NumberOfSegments.cxx
StdMeshers_Deflection1D.cxx
diff --git a/src/StdMeshers/StdMeshers_CartesianParameters3D.cxx b/src/StdMeshers/StdMeshers_CartesianParameters3D.cxx
index fa4aa909f..369d4e424 100644
--- a/src/StdMeshers/StdMeshers_CartesianParameters3D.cxx
+++ b/src/StdMeshers/StdMeshers_CartesianParameters3D.cxx
@@ -32,11 +32,12 @@
#include "utilities.h"
-#include
-#include
-
#include
+#include
+#include
+#include
+
using namespace std;
//=======================================================================
@@ -48,10 +49,23 @@ StdMeshers_CartesianParameters3D::StdMeshers_CartesianParameters3D(int h
int studyId,
SMESH_Gen * gen)
: SMESH_Hypothesis(hypId, studyId, gen),
- _sizeThreshold( 4.0 ) // default according to the customer specification
+ _sizeThreshold( 4.0 ), // default according to the customer specification
+ _toAddEdges( false )
{
_name = "CartesianParameters3D"; // used by "Cartesian_3D"
_param_algo_dim = 3; // 3D
+
+ _axisDirs[0] = 1.;
+ _axisDirs[1] = 0.;
+ _axisDirs[2] = 0.;
+
+ _axisDirs[3] = 0.;
+ _axisDirs[4] = 1.;
+ _axisDirs[5] = 0.;
+
+ _axisDirs[6] = 0.;
+ _axisDirs[7] = 0.;
+ _axisDirs[8] = 1.;
}
@@ -308,6 +322,44 @@ void StdMeshers_CartesianParameters3D::GetCoordinates(std::vector& xNode
zNodes = _coords[2];
}
+//=======================================================================
+//function : SetAxisDirs
+//purpose : Sets directions of axes
+//=======================================================================
+
+void StdMeshers_CartesianParameters3D::SetAxisDirs(const double* the9DirComps)
+ throw ( SALOME_Exception )
+{
+ gp_Vec x( the9DirComps[0],
+ the9DirComps[1],
+ the9DirComps[2] );
+ gp_Vec y( the9DirComps[3],
+ the9DirComps[4],
+ the9DirComps[5] );
+ gp_Vec z( the9DirComps[6],
+ the9DirComps[7],
+ the9DirComps[8] );
+ if ( x.Magnitude() < RealSmall() ||
+ y.Magnitude() < RealSmall() ||
+ z.Magnitude() < RealSmall() )
+ throw SALOME_Exception("Zero magnitude of axis direction");
+
+ if ( x.IsParallel( y, M_PI / 180. ) ||
+ x.IsParallel( z, M_PI / 180. ) ||
+ y.IsParallel( z, M_PI / 180. ))
+ throw SALOME_Exception("Parallel axis directions");
+
+ bool isChanged = false;
+ for ( int i = 0; i < 9; ++i )
+ {
+ if ( Abs( _axisDirs[i] - the9DirComps[i] ) > 1e-7 )
+ isChanged = true;
+ _axisDirs[i] = the9DirComps[i];
+ }
+ if ( isChanged )
+ NotifySubMeshesHypothesisModification();
+}
+
//=======================================================================
//function : GetGrid
//purpose : Return coordinates of node positions along the three axes
@@ -332,6 +384,33 @@ double StdMeshers_CartesianParameters3D::GetSizeThreshold() const
return _sizeThreshold;
}
+//=======================================================================
+//function : SetToAddEdges
+//purpose : Enables implementation of geometrical edges into the mesh. If this feature
+// is disabled, sharp edges of the shape are lost ("smoothed") in the mesh if
+// they don't coincide with the grid lines
+//=======================================================================
+
+void StdMeshers_CartesianParameters3D::SetToAddEdges(bool toAdd)
+{
+ if ( _toAddEdges != toAdd )
+ {
+ _toAddEdges = toAdd;
+ NotifySubMeshesHypothesisModification();
+ }
+}
+
+//=======================================================================
+//function : GetToAddEdges
+//purpose : Returns true if implementation of geometrical edges into the
+// mesh is enabled
+//=======================================================================
+
+bool StdMeshers_CartesianParameters3D::GetToAddEdges() const
+{
+ return _toAddEdges;
+}
+
//=======================================================================
//function : IsDefined
//purpose : Return true if parameters are well defined
@@ -369,6 +448,7 @@ std::ostream & StdMeshers_CartesianParameters3D::SaveTo(std::ostream & save)
for ( size_t j = 0; j < _spaceFunctions[i].size(); ++j )
save << _spaceFunctions[i][j] << " ";
}
+ save << _toAddEdges << " ";
return save;
}
@@ -382,7 +462,7 @@ std::istream & StdMeshers_CartesianParameters3D::LoadFrom(std::istream & load)
{
bool ok;
- ok = (load >> _sizeThreshold );
+ ok = ( load >> _sizeThreshold );
for ( int ax = 0; ax < 3; ++ax )
{
if (ok)
@@ -419,6 +499,9 @@ std::istream & StdMeshers_CartesianParameters3D::LoadFrom(std::istream & load)
}
}
}
+
+ load >> _toAddEdges;
+
return load;
}
diff --git a/src/StdMeshers/StdMeshers_CartesianParameters3D.hxx b/src/StdMeshers/StdMeshers_CartesianParameters3D.hxx
index adb22f00c..98970956b 100644
--- a/src/StdMeshers/StdMeshers_CartesianParameters3D.hxx
+++ b/src/StdMeshers/StdMeshers_CartesianParameters3D.hxx
@@ -100,6 +100,10 @@ public:
std::vector& yNodes,
std::vector& zNodes,
const Bnd_Box& bndBox) const throw ( SALOME_Exception );
+
+ void SetAxisDirs(const double* the9DirComps) throw ( SALOME_Exception );
+ const double* GetAxisDirs() const { return _axisDirs; }
+
/*!
* Set size threshold. A polyhedral cell got by cutting an initial
* hexahedron by geometry boundary is considered small and is removed if
@@ -111,6 +115,14 @@ public:
*/
double GetSizeThreshold() const;
+ /*!
+ * \brief Enables implementation of geometrical edges into the mesh. If this feature
+ * is disabled, sharp edges of the shape are lost ("smoothed") in the mesh if
+ * they don't coincide with the grid lines
+ */
+ void SetToAddEdges(bool toAdd);
+ bool GetToAddEdges() const;
+
/*!
* \brief Return true if parameters are well defined
*/
@@ -138,7 +150,10 @@ public:
std::vector _spaceFunctions[3];
std::vector _internalPoints[3];
+ double _axisDirs[9];
+
double _sizeThreshold;
+ bool _toAddEdges;
};
#endif
diff --git a/src/StdMeshers/StdMeshers_Cartesian_3D.cxx b/src/StdMeshers/StdMeshers_Cartesian_3D.cxx
index 83447b16a..36b2e2d48 100644
--- a/src/StdMeshers/StdMeshers_Cartesian_3D.cxx
+++ b/src/StdMeshers/StdMeshers_Cartesian_3D.cxx
@@ -33,10 +33,11 @@
#include "SMESH_subMeshEventListener.hxx"
#include "StdMeshers_CartesianParameters3D.hxx"
-#include "utilities.h"
-#include "Utils_ExceptHandlers.hxx"
+#include
+#include
#include
+#include
#include
#include
#include
@@ -44,6 +45,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -63,7 +65,6 @@
#include
#include
#include
-#include
#include
#include
#include
@@ -76,7 +77,7 @@
#include
#include
-//#undef WITH_TBB
+#undef WITH_TBB
#ifdef WITH_TBB
#include
//#include
@@ -150,6 +151,8 @@ bool StdMeshers_Cartesian_3D::CheckHypothesis (SMESH_Mesh& aMesh,
namespace
{
+ typedef int TGeomID;
+
//=============================================================================
// Definitions of internal utils
// --------------------------------------------------------------------------
@@ -160,18 +163,41 @@ namespace
Trans_APEX
};
// --------------------------------------------------------------------------
+ /*!
+ * \brief Common data of any intersection between a Grid and a shape
+ */
+ struct B_IntersectPoint
+ {
+ mutable const SMDS_MeshNode* _node;
+ mutable vector< TGeomID > _faceIDs;
+
+ B_IntersectPoint(): _node(NULL) {}
+ void Add( const vector< TGeomID >& fIDs, const SMDS_MeshNode* n=0 ) const;
+ bool HasCommonFace( const B_IntersectPoint * other ) const;
+ bool IsOnFace( int faceID ) const;
+ virtual ~B_IntersectPoint() {}
+ };
+ // --------------------------------------------------------------------------
/*!
* \brief Data of intersection between a GridLine and a TopoDS_Face
*/
- struct IntersectionPoint
+ struct F_IntersectPoint : public B_IntersectPoint
{
- double _paramOnLine;
- mutable Transition _transition;
- mutable const SMDS_MeshNode* _node;
- mutable size_t _indexOnLine;
+ double _paramOnLine;
+ mutable Transition _transition;
+ mutable size_t _indexOnLine;
- IntersectionPoint(): _node(0) {}
- bool operator< ( const IntersectionPoint& o ) const { return _paramOnLine < o._paramOnLine; }
+ bool operator< ( const F_IntersectPoint& o ) const { return _paramOnLine < o._paramOnLine; }
+ };
+ // --------------------------------------------------------------------------
+ /*!
+ * \brief Data of intersection between GridPlanes and a TopoDS_EDGE
+ */
+ struct E_IntersectPoint : public B_IntersectPoint
+ {
+ gp_Pnt _point;
+ double _uvw[3];
+ TGeomID _shapeID;
};
// --------------------------------------------------------------------------
/*!
@@ -181,10 +207,23 @@ namespace
{
gp_Lin _line;
double _length; // line length
- multiset< IntersectionPoint > _intPoints;
+ multiset< F_IntersectPoint > _intPoints;
void RemoveExcessIntPoints( const double tol );
- bool GetIsOutBefore( multiset< IntersectionPoint >::iterator ip, bool prevIsOut );
+ bool GetIsOutBefore( multiset< F_IntersectPoint >::iterator ip, bool prevIsOut );
+ };
+ // --------------------------------------------------------------------------
+ /*!
+ * \brief Planes of the grid used to find intersections of an EDGE with a hexahedron
+ */
+ struct GridPlanes
+ {
+ double _factor;
+ gp_XYZ _uNorm, _vNorm, _zNorm;
+ vector< gp_XYZ > _origins; // origin points of all planes in one direction
+ vector< double > _zProjs; // projections of origins to _zNorm
+
+ gp_XY GetUV( const gp_Pnt& p, const gp_Pnt& origin );
};
// --------------------------------------------------------------------------
/*!
@@ -234,11 +273,15 @@ namespace
struct Grid
{
vector< double > _coords[3]; // coordinates of grid nodes
+ gp_XYZ _axes [3]; // axis directions
vector< GridLine > _lines [3]; // in 3 directions
double _tol, _minCellSize;
- vector< const SMDS_MeshNode* > _nodes; // mesh nodes at grid nodes
- vector< bool > _isBndNode; // is mesh node at intersection with geometry
+ vector< const SMDS_MeshNode* > _nodes; // mesh nodes at grid nodes
+ vector< const F_IntersectPoint* > _gridIntP; // grid node intersection with geometry
+
+ list< E_IntersectPoint > _edgeIntP; // intersections with EDGEs
+ TopTools_IndexedMapOfShape _shapes;
size_t CellIndex( size_t i, size_t j, size_t k ) const
{
@@ -257,6 +300,7 @@ namespace
void SetCoordinates(const vector& xCoords,
const vector& yCoords,
const vector& zCoords,
+ const double* axesDirs,
const TopoDS_Shape& shape );
void ComputeNodes(SMESH_MesherHelper& helper);
};
@@ -302,10 +346,11 @@ namespace
struct FaceGridIntersector
{
TopoDS_Face _face;
+ TGeomID _faceID;
Grid* _grid;
Bnd_Box _bndBox;
__IntCurvesFace_Intersector* _surfaceInt;
- vector< std::pair< GridLine*, IntersectionPoint > > _intersections;
+ vector< std::pair< GridLine*, F_IntersectPoint > > _intersections;
FaceGridIntersector(): _grid(0), _surfaceInt(0) {}
void Intersect();
@@ -314,7 +359,12 @@ namespace
void StoreIntersections()
{
for ( size_t i = 0; i < _intersections.size(); ++i )
- _intersections[i].first->_intPoints.insert( _intersections[i].second );
+ {
+ multiset< F_IntersectPoint >::iterator ip =
+ _intersections[i].first->_intPoints.insert( _intersections[i].second );
+ ip->_faceIDs.reserve( 1 );
+ ip->_faceIDs.push_back( _faceID );
+ }
}
const Bnd_Box& GetFaceBndBox()
{
@@ -352,7 +402,7 @@ namespace
gp_Torus _torus;
__IntCurvesFace_Intersector* _surfaceInt;
- vector< IntersectionPoint > _intPoints;
+ vector< F_IntersectPoint > _intPoints;
void IntersectWithPlane (const GridLine& gridLine);
void IntersectWithCylinder(const GridLine& gridLine);
@@ -381,20 +431,54 @@ namespace
struct _Face;
struct _Link;
// --------------------------------------------------------------------------------
- struct _Node //!< node either at a hexahedron corner or at GridLine intersection
+ struct _Node //!< node either at a hexahedron corner or at intersection
{
- const SMDS_MeshNode* _node; // mesh node at hexahedron corner
- const IntersectionPoint* _intPoint;
+ const SMDS_MeshNode* _node; // mesh node at hexahedron corner
+ const B_IntersectPoint* _intPoint;
- _Node(const SMDS_MeshNode* n=0, const IntersectionPoint* ip=0):_node(n), _intPoint(ip) {}
- const SMDS_MeshNode* Node() const { return _intPoint ? _intPoint->_node : _node; }
- //bool IsCorner() const { return _node; }
+ _Node(const SMDS_MeshNode* n=0, const B_IntersectPoint* ip=0):_node(n), _intPoint(ip) {}
+ const SMDS_MeshNode* Node() const
+ { return ( _intPoint && _intPoint->_node ) ? _intPoint->_node : _node; }
+ const F_IntersectPoint* FaceIntPnt() const
+ { return static_cast< const F_IntersectPoint* >( _intPoint ); }
+ const E_IntersectPoint* EdgeIntPnt() const
+ { return static_cast< const E_IntersectPoint* >( _intPoint ); }
+ void Add( const E_IntersectPoint* ip )
+ {
+ if ( !_intPoint ) {
+ _intPoint = ip;
+ }
+ else if ( !_intPoint->_node ) {
+ ip->Add( _intPoint->_faceIDs );
+ _intPoint = ip;
+ }
+ else {
+ _intPoint->Add( ip->_faceIDs );
+ }
+ }
+ bool IsLinked( const B_IntersectPoint* other ) const
+ {
+ return _intPoint && _intPoint->HasCommonFace( other );
+ }
+ bool IsOnFace( int faceID ) const // returns true if faceID is found
+ {
+ return _intPoint ? _intPoint->IsOnFace( faceID ) : false;
+ }
+ gp_Pnt Point() const
+ {
+ if ( const SMDS_MeshNode* n = Node() )
+ return SMESH_TNodeXYZ( n );
+ if ( const E_IntersectPoint* eip =
+ dynamic_cast< const E_IntersectPoint* >( _intPoint ))
+ return eip->_point;
+ return gp_Pnt( 1e100, 0, 0 );
+ }
};
// --------------------------------------------------------------------------------
struct _Link // link connecting two _Node's
{
_Node* _nodes[2];
- vector< _Node> _intNodes; // _Node's at GridLine intersections
+ vector< _Node > _intNodes; // _Node's at GridLine intersections
vector< _Link > _splits;
vector< _Face*> _faces;
};
@@ -412,21 +496,38 @@ namespace
}
_Node* FirstNode() const { return _link->_nodes[ _reverse ]; }
_Node* LastNode() const { return _link->_nodes[ !_reverse ]; }
+ operator bool() const { return _link; }
+ vector< TGeomID > GetNotUsedFace(const set& usedIDs ) const // returns a supporting FACEs
+ {
+ vector< TGeomID > faces;
+ const B_IntersectPoint *ip0, *ip1;
+ if (( ip0 = _link->_nodes[0]->_intPoint ) &&
+ ( ip1 = _link->_nodes[1]->_intPoint ))
+ {
+ for ( size_t i = 0; i < ip0->_faceIDs.size(); ++i )
+ if ( ip1->IsOnFace ( ip0->_faceIDs[i] ) &&
+ !usedIDs.count( ip0->_faceIDs[i] ) )
+ faces.push_back( ip0->_faceIDs[i] );
+ }
+ return faces;
+ }
};
// --------------------------------------------------------------------------------
struct _Face
{
- vector< _OrientedLink > _links;
- vector< _Link > _polyLinks; // links added to close a polygonal face
+ vector< _OrientedLink > _links; // links on GridLine's
+ vector< _Link > _polyLinks; // links added to close a polygonal face
+ vector< _Node > _edgeNodes; // nodes at intersection with EDGEs
};
// --------------------------------------------------------------------------------
struct _volumeDef // holder of nodes of a volume mesh element
{
- vector< const SMDS_MeshNode* > _nodes;
- vector< int > _quantities;
+ //vector< const SMDS_MeshNode* > _nodes;
+ vector< _Node* > _nodes;
+ vector< int > _quantities;
typedef boost::shared_ptr<_volumeDef> Ptr;
- void set( const vector< const SMDS_MeshNode* >& nodes,
- const vector< int > quant = vector< int >() )
+ void set( const vector< _Node* >& nodes,
+ const vector< int >& quant = vector< int >() )
{ _nodes = nodes; _quantities = quant; }
// static Ptr New( const vector< const SMDS_MeshNode* >& nodes,
// const vector< int > quant = vector< int >() )
@@ -440,13 +541,19 @@ namespace
// topology of a hexahedron
int _nodeShift[8];
- _Node _hexNodes[8];
- _Link _hexLinks[12];
- _Face _hexQuads[6];
+ _Node _hexNodes [8];
+ _Link _hexLinks [12];
+ _Face _hexQuads [6];
// faces resulted from hexahedron intersection
vector< _Face > _polygons;
+ // intresections with EDGEs
+ vector< const E_IntersectPoint* > _edgeIntPnts;
+
+ // nodes inside the hexahedron (at VERTEXes)
+ vector< _Node > _vertexNodes;
+
// computed volume elements
//vector< _volumeDef::Ptr > _volumeDefs;
_volumeDef _volumeDefs;
@@ -459,7 +566,8 @@ namespace
public:
Hexahedron(const double sizeThreshold, Grid* grid);
- int MakeElements(SMESH_MesherHelper& helper);
+ int MakeElements(SMESH_MesherHelper& helper,
+ const map< TGeomID, vector< TGeomID > >& edge2faceIDsMap);
void ComputeElements();
void Init() { init( _i, _j, _k ); }
@@ -467,6 +575,17 @@ namespace
Hexahedron(const Hexahedron& other );
void init( size_t i, size_t j, size_t k );
void init( size_t i );
+ void addEdges(SMESH_MesherHelper& helper,
+ vector< Hexahedron* >& intersectedHex,
+ const map< TGeomID, vector< TGeomID > >& edge2faceIDsMap);
+ gp_Pnt findIntPoint( double u1, double proj1, double u2, double proj2,
+ double proj, BRepAdaptor_Curve& curve,
+ const gp_XYZ& axis, const gp_XYZ& origin );
+ int getEntity( const E_IntersectPoint* ip, int* facets, int& sub );
+ bool addIntersection( const E_IntersectPoint& ip,
+ vector< Hexahedron* >& hexes,
+ int ijk[], int dIJK[] );
+ bool findChain( _Node* n1, _Node* n2, _Face& quad, vector<_Node*>& chainNodes );
int addElements(SMESH_MesherHelper& helper);
bool isInHole() const;
bool checkPolyhedronSize() const;
@@ -474,8 +593,17 @@ namespace
bool addTetra();
bool addPenta();
bool addPyra ();
+ _Node* FindEqualNode( vector< _Node >& nodes,
+ const E_IntersectPoint* ip,
+ const double tol2 )
+ {
+ for ( size_t i = 0; i < nodes.size(); ++i )
+ if ( nodes[i].Point().SquareDistance( ip->_point ) <= tol2 )
+ return & nodes[i];
+ return 0;
+ }
};
-
+
#ifdef WITH_TBB
// --------------------------------------------------------------------------
/*!
@@ -507,11 +635,34 @@ namespace
_faceVec[i].Intersect();
}
};
-
#endif
+
//=============================================================================
// Implementation of internal utils
//=============================================================================
+ /*!
+ * \brief adjust \a i to have \a val between values[i] and values[i+1]
+ */
+ inline void locateValue( int & i, double val, const vector& values,
+ int& di, double tol )
+ {
+ val += values[0]; // input \a val is measured from 0.
+ if ( i > values.size()-2 )
+ i = values.size()-2;
+ else
+ while ( i+2 < values.size() && val > values[ i+1 ])
+ ++i;
+ while ( i > 0 && val < values[ i ])
+ --i;
+
+ if ( i > 0 && val - values[ i ] < tol )
+ di = -1;
+ else if ( i+2 < values.size() && values[ i+1 ] - val < tol )
+ di = 1;
+ else
+ di = 0;
+ }
+ //=============================================================================
/*
* Remove coincident intersection points
*/
@@ -520,15 +671,16 @@ namespace
if ( _intPoints.size() < 2 ) return;
set< Transition > tranSet;
- multiset< IntersectionPoint >::iterator ip1, ip2 = _intPoints.begin();
+ multiset< F_IntersectPoint >::iterator ip1, ip2 = _intPoints.begin();
while ( ip2 != _intPoints.end() )
{
tranSet.clear();
ip1 = ip2++;
- while ( ip2->_paramOnLine - ip1->_paramOnLine <= tol && ip2 != _intPoints.end())
+ while ( ip2 != _intPoints.end() && ip2->_paramOnLine - ip1->_paramOnLine <= tol )
{
tranSet.insert( ip1->_transition );
tranSet.insert( ip2->_transition );
+ ip2->Add( ip1->_faceIDs );
_intPoints.erase( ip1 );
ip1 = ip2++;
}
@@ -547,7 +699,7 @@ namespace
/*
* Return "is OUT" state for nodes before the given intersection point
*/
- bool GridLine::GetIsOutBefore( multiset< IntersectionPoint >::iterator ip, bool prevIsOut )
+ bool GridLine::GetIsOutBefore( multiset< F_IntersectPoint >::iterator ip, bool prevIsOut )
{
if ( ip->_transition == Trans_IN )
return true;
@@ -558,7 +710,7 @@ namespace
// singularity point (apex of a cone)
if ( _intPoints.size() == 1 || ip == _intPoints.begin() )
return true;
- multiset< IntersectionPoint >::iterator ipBef = ip, ipAft = ++ip;
+ multiset< F_IntersectPoint >::iterator ipBef = ip, ipAft = ++ip;
if ( ipAft == _intPoints.end() )
return false;
--ipBef;
@@ -569,13 +721,65 @@ namespace
return prevIsOut; // _transition == Trans_TANGENT
}
//================================================================================
+ /*
+ * Returns parameters of a point in i-th plane
+ */
+ gp_XY GridPlanes::GetUV( const gp_Pnt& p, const gp_Pnt& origin )
+ {
+ gp_Vec v( origin, p );
+ return gp_XY( v.Dot( _uNorm ) * _factor,
+ v.Dot( _vNorm ) * _factor );
+ }
+ //================================================================================
+ /*
+ * Adds face IDs
+ */
+ void B_IntersectPoint::Add( const vector< TGeomID >& fIDs,
+ const SMDS_MeshNode* n) const
+ {
+ if ( _faceIDs.empty() )
+ _faceIDs = fIDs;
+ else
+ for ( size_t i = 0; i < fIDs.size(); ++i )
+ {
+ vector< TGeomID >::iterator it =
+ std::find( _faceIDs.begin(), _faceIDs.end(), fIDs[i] );
+ if ( it == _faceIDs.end() )
+ _faceIDs.push_back( fIDs[i] );
+ }
+ if ( !_node )
+ _node = n;
+ }
+ //================================================================================
+ /*
+ * Returns \c true if \a other B_IntersectPoint holds the same face ID
+ */
+ bool B_IntersectPoint::HasCommonFace( const B_IntersectPoint * other ) const
+ {
+ if ( other )
+ for ( size_t i = 0; i < other->_faceIDs.size(); ++i )
+ if ( IsOnFace( other->_faceIDs[i] ) )
+ return true;
+ return false;
+ }
+ //================================================================================
+ /*
+ * Returns \c true if \a faceID in in this->_faceIDs
+ */
+ bool B_IntersectPoint::IsOnFace( int faceID ) const // returns true if faceID is found
+ {
+ vector< TGeomID >::const_iterator it =
+ std::find( _faceIDs.begin(), _faceIDs.end(), faceID );
+ return ( it != _faceIDs.end() );
+ }
+ //================================================================================
/*
* Return an iterator on GridLine's in a given direction
*/
LineIndexer Grid::GetLineIndexer(size_t iDir) const
{
const size_t indices[] = { 1,2,0, 0,2,1, 0,1,2 };
- const string s[] = { "X", "Y", "Z" };
+ const string s [] = { "X", "Y", "Z" };
LineIndexer li( _coords[0].size(), _coords[1].size(), _coords[2].size(),
indices[iDir*3], indices[iDir*3+1], indices[iDir*3+2],
s[indices[iDir*3]], s[indices[iDir*3+1]], s[indices[iDir*3+2]]);
@@ -588,11 +792,21 @@ namespace
void Grid::SetCoordinates(const vector& xCoords,
const vector& yCoords,
const vector& zCoords,
+ const double* axesDirs,
const TopoDS_Shape& shape)
{
_coords[0] = xCoords;
_coords[1] = yCoords;
_coords[2] = zCoords;
+ _axes[0].SetCoord( axesDirs[0],
+ axesDirs[1],
+ axesDirs[2]);
+ _axes[1].SetCoord( axesDirs[3],
+ axesDirs[4],
+ axesDirs[5]);
+ _axes[2].SetCoord( axesDirs[6],
+ axesDirs[7],
+ axesDirs[8]);
// compute tolerance
_minCellSize = Precision::Infinite();
@@ -649,7 +863,7 @@ namespace
const size_t nbGridNodes = _coords[0].size() * _coords[1].size() * _coords[2].size();
vector< bool > isNodeOut( nbGridNodes, false );
_nodes.resize( nbGridNodes, 0 );
- _isBndNode.resize( nbGridNodes, false );
+ _gridIntP.resize( nbGridNodes, NULL );
for ( int iDir = 0; iDir < 3; ++iDir ) // loop on 3 line directions
{
@@ -669,8 +883,8 @@ namespace
GridLine& line = _lines[ iDir ][ li.LineIndex() ];
line.RemoveExcessIntPoints( _tol );
- multiset< IntersectionPoint >& intPnts = _lines[ iDir ][ li.LineIndex() ]._intPoints;
- multiset< IntersectionPoint >::iterator ip = intPnts.begin();
+ multiset< F_IntersectPoint >& intPnts = _lines[ iDir ][ li.LineIndex() ]._intPoints;
+ multiset< F_IntersectPoint >::iterator ip = intPnts.begin();
bool isOut = true;
const double* nodeCoord = & coords[0], *coord0 = nodeCoord, *coordEnd = coord0 + coords.size();
@@ -706,14 +920,18 @@ namespace
else
{
int nodeIndex = nIndex0 + nShift * ( nodeCoord-coord0 );
- if ( ! _nodes[ nodeIndex ] )
+ if ( !_nodes[ nodeIndex ] )
{
li.SetIndexOnLine( nodeCoord-coord0 );
double xyz[3] = { _coords[0][ li.I() ], _coords[1][ li.J() ], _coords[2][ li.K() ]};
- _nodes[ nodeIndex ] = helper.AddNode( xyz[0], xyz[1], xyz[2] );
- _isBndNode[ nodeIndex ] = true;
+ _nodes [ nodeIndex ] = helper.AddNode( xyz[0], xyz[1], xyz[2] );
+ _gridIntP[ nodeIndex ] = & * ip;
}
- //ip->_node = _nodes[ nodeIndex ];
+ if ( _gridIntP[ nodeIndex ] )
+ _gridIntP[ nodeIndex ]->Add( ip->_faceIDs );
+ else
+ _gridIntP[ nodeIndex ] = & * ip;
+ // ip->_node = _nodes[ nodeIndex ]; -- to differ from ip on links
ip->_indexOnLine = nodeCoord-coord0;
if ( ++nodeCoord < coordEnd )
nodeParam = *nodeCoord - *coord0;
@@ -744,7 +962,7 @@ namespace
LineIndexer li = GetLineIndexer( iDir );
for ( ; li.More(); ++li )
{
- multiset< IntersectionPoint >& intPnts = _lines[ iDir ][ li.LineIndex() ]._intPoints;
+ multiset< F_IntersectPoint >& intPnts = _lines[ iDir ][ li.LineIndex() ]._intPoints;
if ( intPnts.empty() ) continue;
if ( intPnts.size() == 1 )
{
@@ -944,7 +1162,7 @@ namespace
{
if ( !toClassify || UVIsOnFace() )
{
- IntersectionPoint p;
+ F_IntersectPoint p;
p._paramOnLine = _w;
p._transition = _transition;
_intPoints.push_back( p );
@@ -1291,16 +1509,18 @@ namespace
_origNodeInd = _grid->NodeIndex( i,j,k );
for ( int iN = 0; iN < 8; ++iN )
{
- _hexNodes[iN]._node = _grid->_nodes[ _origNodeInd + _nodeShift[iN] ];
+ _hexNodes[iN]._node = _grid->_nodes [ _origNodeInd + _nodeShift[iN] ];
+ _hexNodes[iN]._intPoint = _grid->_gridIntP[ _origNodeInd + _nodeShift[iN] ];
_nbCornerNodes += bool( _hexNodes[iN]._node );
- _nbBndNodes += _grid->_isBndNode[ _origNodeInd + _nodeShift[iN] ];
+ _nbBndNodes += bool( _hexNodes[iN]._intPoint );
}
_sideLength[0] = _grid->_coords[0][i+1] - _grid->_coords[0][i];
_sideLength[1] = _grid->_coords[1][j+1] - _grid->_coords[1][j];
_sideLength[2] = _grid->_coords[2][k+1] - _grid->_coords[2][k];
- if ( _nbCornerNodes < 8 && _nbIntNodes + _nbCornerNodes > 3)
+ if ( _nbIntNodes + _edgeIntPnts.size() > 0 &&
+ _nbIntNodes + _nbCornerNodes + _edgeIntPnts.size() > 3)
{
_Link split;
// create sub-links (_splits) by splitting links with _intNodes
@@ -1309,21 +1529,120 @@ namespace
_Link& link = _hexLinks[ iLink ];
link._splits.clear();
split._nodes[ 0 ] = link._nodes[0];
- for ( size_t i = 0; i < link._intNodes.size(); ++ i )
+ bool isOut = ( ! link._nodes[0]->Node() );
+ //int iEnd = link._intNodes.size() - bool( link._nodes[1]->_intPoint );
+ for ( size_t i = 0; i < link._intNodes.size(); ++i )
{
- if ( split._nodes[ 0 ]->Node() )
+ if ( link._intNodes[i].Node() )
{
- split._nodes[ 1 ] = &link._intNodes[i];
- link._splits.push_back( split );
+ if ( split._nodes[ 0 ]->Node() && !isOut )
+ {
+ split._nodes[ 1 ] = &link._intNodes[i];
+ link._splits.push_back( split );
+ }
+ split._nodes[ 0 ] = &link._intNodes[i];
+ }
+ switch ( link._intNodes[i].FaceIntPnt()->_transition ) {
+ case Trans_OUT: isOut = true; break;
+ case Trans_IN : isOut = false; break;
+ default:; // isOut remains the same
}
- split._nodes[ 0 ] = &link._intNodes[i];
}
- if ( link._nodes[ 1 ]->Node() && split._nodes[ 0 ]->Node() )
+ if ( link._nodes[ 1 ]->Node() && split._nodes[ 0 ]->Node() && !isOut )
{
split._nodes[ 1 ] = link._nodes[1];
link._splits.push_back( split );
}
}
+
+ // Create _Node's at intersections with EDGEs.
+
+ const double tol2 = _grid->_tol * _grid->_tol;
+ int facets[3], nbFacets, subEntity;
+
+ for ( size_t iP = 0; iP < _edgeIntPnts.size(); ++iP )
+ {
+ nbFacets = getEntity( _edgeIntPnts[iP], facets, subEntity );
+ _Node* equalNode = 0;
+ switch( nbFacets ) {
+ case 1: // in a _Face
+ {
+ _Face& quad = _hexQuads[ facets[0] - SMESH_Block::ID_FirstF ];
+ equalNode = FindEqualNode( quad._edgeNodes, _edgeIntPnts[ iP ], tol2 );
+ if ( equalNode ) {
+ equalNode->Add( _edgeIntPnts[ iP ] );
+ }
+ else {
+ quad._edgeNodes.push_back( _Node( 0, _edgeIntPnts[ iP ]));
+ ++_nbIntNodes;
+ }
+ break;
+ }
+ case 2: // on a _Link
+ {
+ _Link& link = _hexLinks[ subEntity - SMESH_Block::ID_FirstE ];
+ if ( link._splits.size() > 0 )
+ {
+ equalNode = FindEqualNode( link._intNodes, _edgeIntPnts[ iP ], tol2 );
+ if ( equalNode )
+ equalNode->Add( _edgeIntPnts[ iP ] );
+ }
+ else
+ {
+ for ( int iF = 0; iF < 2; ++iF )
+ {
+ _Face& quad = _hexQuads[ facets[iF] - SMESH_Block::ID_FirstF ];
+ equalNode = FindEqualNode( quad._edgeNodes, _edgeIntPnts[ iP ], tol2 );
+ if ( equalNode ) {
+ equalNode->Add( _edgeIntPnts[ iP ] );
+ }
+ else {
+ quad._edgeNodes.push_back( _Node( 0, _edgeIntPnts[ iP ]));
+ ++_nbIntNodes;
+ }
+ }
+ }
+ break;
+ }
+ case 3: // at a corner
+ {
+ _Node& node = _hexNodes[ subEntity - SMESH_Block::ID_FirstV ];
+ if ( node.Node() > 0 )
+ {
+ if ( node._intPoint )
+ node._intPoint->Add( _edgeIntPnts[ iP ]->_faceIDs, _edgeIntPnts[ iP ]->_node );
+ }
+ else
+ {
+ for ( int iF = 0; iF < 3; ++iF )
+ {
+ _Face& quad = _hexQuads[ facets[iF] - SMESH_Block::ID_FirstF ];
+ equalNode = FindEqualNode( quad._edgeNodes, _edgeIntPnts[ iP ], tol2 );
+ if ( equalNode ) {
+ equalNode->Add( _edgeIntPnts[ iP ] );
+ }
+ else {
+ quad._edgeNodes.push_back( _Node( 0, _edgeIntPnts[ iP ]));
+ ++_nbIntNodes;
+ }
+ }
+ }
+ break;
+ }
+ default: // inside a hex
+ {
+ equalNode = FindEqualNode( _vertexNodes, _edgeIntPnts[ iP ], tol2 );
+ if ( equalNode ) {
+ equalNode->Add( _edgeIntPnts[ iP ] );
+ }
+ else {
+ _vertexNodes.push_back( _Node( 0, _edgeIntPnts[iP] ));
+ ++_nbIntNodes;
+ }
+ }
+ } // switch( nbFacets )
+
+ } // loop on _edgeIntPnts
}
}
//================================================================================
@@ -1351,87 +1670,173 @@ namespace
if ( _nbCornerNodes + _nbIntNodes < 4 )
return;
- if ( _nbBndNodes == _nbCornerNodes && isInHole() )
+ if ( _nbBndNodes == _nbCornerNodes && _nbIntNodes == 0 && isInHole() )
return;
_polygons.clear();
-
- vector polyhedraNodes;
- vector quantities;
+ _polygons.reserve( 10 );
// create polygons from quadrangles and get their nodes
- vector<_Node*> nodes;
- nodes.reserve( _nbCornerNodes + _nbIntNodes );
-
_Link polyLink;
- polyLink._faces.reserve( 1 );
+ vector< _OrientedLink > splits;
+ vector<_Node*> chainNodes;
+
+ bool hasEdgeIntersections = !_edgeIntPnts.empty();
for ( int iF = 0; iF < 6; ++iF ) // loop on 6 sides of a hexahedron
{
- const _Face& quad = _hexQuads[ iF ] ;
+ _Face& quad = _hexQuads[ iF ] ;
_polygons.resize( _polygons.size() + 1 );
- _Face& polygon = _polygons.back();
- polygon._links.clear();
- polygon._polyLinks.clear(); polygon._polyLinks.reserve( 10 );
+ _Face* polygon = &_polygons.back();
+ polygon->_polyLinks.reserve( 20 );
- // add splits of a link to a polygon and collect info on nodes
- //int nbIn = 0, nbOut = 0, nbCorners = 0;
- nodes.clear();
+ splits.clear();
for ( int iE = 0; iE < 4; ++iE ) // loop on 4 sides of a quadrangle
+ for ( int iS = 0; iS < quad._links[ iE ].NbResultLinks(); ++iS )
+ splits.push_back( quad._links[ iE ].ResultLink( iS ));
+
+ // add splits of links to a polygon and add _polyLinks to make
+ // polygon's boundary closed
+
+ int nbSplits = splits.size();
+ if ( nbSplits < 2 && quad._edgeNodes.empty() )
+ nbSplits = 0;
+
+ if ( nbSplits == 0 && !quad._edgeNodes.empty() )
{
- int nbSpits = quad._links[ iE ].NbResultLinks();
- for ( int iS = 0; iS < nbSpits; ++iS )
+ // make _vertexNodes from _edgeNodes of an empty quad
+ const double tol2 = _grid->_tol * _grid->_tol;
+ for ( size_t iP = 0; iP < quad._edgeNodes.size(); ++iP )
{
- _OrientedLink split = quad._links[ iE ].ResultLink( iS );
- _Node* n = split.FirstNode();
- if ( !polygon._links.empty() )
+ _Node* equalNode =
+ FindEqualNode( _vertexNodes, quad._edgeNodes[ iP ].EdgeIntPnt(), tol2 );
+ if ( equalNode )
+ equalNode->Add( quad._edgeNodes[ iP ].EdgeIntPnt() );
+ else
+ _vertexNodes.push_back( quad._edgeNodes[ iP ]);
+ }
+ }
+
+ while ( nbSplits > 0 )
+ {
+ size_t iS = 0;
+ while ( !splits[ iS ] )
+ ++iS;
+
+ if ( !polygon->_links.empty() )
+ {
+ _polygons.resize( _polygons.size() + 1 );
+ polygon = &_polygons.back();
+ polygon->_polyLinks.reserve( 20 );
+ }
+ polygon->_links.push_back( splits[ iS ] );
+ splits[ iS++ ]._link = 0;
+ --nbSplits;
+
+ _Node* nFirst = polygon->_links.back().FirstNode();
+ _Node *n1,*n2 = polygon->_links.back().LastNode();
+ for ( ; nFirst != n2 && iS < splits.size(); ++iS )
+ {
+ _OrientedLink& split = splits[ iS ];
+ if ( !split ) continue;
+
+ n1 = split.FirstNode();
+ if ( n1 != n2 )
{
- _Node* nPrev = polygon._links.back().LastNode();
- if ( nPrev != n )
+ // try to connect to intersections with EDGES
+ if ( quad._edgeNodes.size() > 0 &&
+ findChain( n2, n1, quad, chainNodes ))
{
- polyLink._nodes[0] = nPrev;
- polyLink._nodes[1] = n;
- polygon._polyLinks.push_back( polyLink );
- polygon._links.push_back( _OrientedLink( &polygon._polyLinks.back() ));
- nodes.push_back( nPrev );
+ for ( size_t i = 1; i < chainNodes.size(); ++i )
+ {
+ polyLink._nodes[0] = chainNodes[i-1];
+ polyLink._nodes[1] = chainNodes[i];
+ polygon->_polyLinks.push_back( polyLink );
+ polygon->_links.push_back( _OrientedLink( &polygon->_polyLinks.back() ));
+ }
+ }
+ // try to connect to a split ending on the same FACE
+ else
+ {
+ _OrientedLink foundSplit;
+ for ( int i = iS; i < splits.size() && !foundSplit; ++i )
+ if (( foundSplit = splits[ i ]) &&
+ ( n2->IsLinked( foundSplit.FirstNode()->_intPoint )))
+ {
+ polyLink._nodes[0] = n2;
+ polyLink._nodes[1] = foundSplit.FirstNode();
+ polygon->_polyLinks.push_back( polyLink );
+ polygon->_links.push_back( _OrientedLink( &polygon->_polyLinks.back() ));
+ iS = i - 1;
+ }
+ else
+ {
+ foundSplit._link = 0;
+ }
+ if ( foundSplit )
+ {
+ n2 = foundSplit.FirstNode();
+ continue;
+ }
+ else
+ {
+ if ( n2->IsLinked( nFirst->_intPoint ))
+ break;
+ polyLink._nodes[0] = n2;
+ polyLink._nodes[1] = n1;
+ polygon->_polyLinks.push_back( polyLink );
+ polygon->_links.push_back( _OrientedLink( &polygon->_polyLinks.back() ));
+ }
}
}
- polygon._links.push_back( split );
- nodes.push_back( n );
- }
- }
- if ( polygon._links.size() > 1 )
- {
- _Node* n1 = polygon._links.back().LastNode();
- _Node* n2 = polygon._links.front().FirstNode();
- if ( n1 != n2 )
+ polygon->_links.push_back( split );
+ split._link = 0;
+ --nbSplits;
+ n2 = polygon->_links.back().LastNode();
+
+ } // loop on splits
+
+ if ( nFirst != n2 ) // close a polygon
{
- polyLink._nodes[0] = n1;
- polyLink._nodes[1] = n2;
- polygon._polyLinks.push_back( polyLink );
- polygon._links.push_back( _OrientedLink( &polygon._polyLinks.back() ));
- nodes.push_back( n1 );
+ findChain( n2, nFirst, quad, chainNodes );
+ for ( size_t i = 1; i < chainNodes.size(); ++i )
+ {
+ polyLink._nodes[0] = chainNodes[i-1];
+ polyLink._nodes[1] = chainNodes[i];
+ polygon->_polyLinks.push_back( polyLink );
+ polygon->_links.push_back( _OrientedLink( &polygon->_polyLinks.back() ));
+ }
}
- // add polygon to its links
- for ( size_t iL = 0; iL < polygon._links.size(); ++iL )
- polygon._links[ iL ]._link->_faces.push_back( &polygon );
- // store polygon nodes
- quantities.push_back( nodes.size() );
- for ( size_t i = 0; i < nodes.size(); ++i )
- polyhedraNodes.push_back( nodes[i]->Node() );
- }
- else
- {
- _polygons.resize( _polygons.size() - 1 );
- }
- }
+
+ if ( polygon->_links.size() < 3 && nbSplits > 0 )
+ {
+ polygon->_polyLinks.clear();
+ polygon->_links.clear();
+ }
+ } // while ( nbSplits > 0 )
+
+ if ( polygon->_links.size() < 3 )
+ _polygons.pop_back();
+
+ } // loop on 6 sides of a hexahedron
// create polygons closing holes in a polyhedron
+ // add polygons to their links
+ for ( size_t iP = 0; iP < _polygons.size(); ++iP )
+ {
+ _Face& polygon = _polygons[ iP ];
+ for ( size_t iL = 0; iL < polygon._links.size(); ++iL )
+ {
+ polygon._links[ iL ]._link->_faces.reserve( 2 );
+ polygon._links[ iL ]._link->_faces.push_back( &polygon );
+ }
+ }
// find free links
vector< _OrientedLink* > freeLinks;
+ freeLinks.reserve(20);
for ( size_t iP = 0; iP < _polygons.size(); ++iP )
{
_Face& polygon = _polygons[ iP ];
@@ -1439,58 +1844,157 @@ namespace
if ( polygon._links[ iL ]._link->_faces.size() < 2 )
freeLinks.push_back( & polygon._links[ iL ]);
}
- // make closed chains of free links
int nbFreeLinks = freeLinks.size();
if ( 0 < nbFreeLinks && nbFreeLinks < 3 ) return;
+
+ set usedFaceIDs;
+
+ // make closed chains of free links
while ( nbFreeLinks > 0 )
{
- nodes.clear();
_polygons.resize( _polygons.size() + 1 );
_Face& polygon = _polygons.back();
- polygon._links.clear();
+ polygon._polyLinks.reserve( 20 );
+ polygon._links.reserve( 20 );
- // get a remaining link to start from
_OrientedLink* curLink = 0;
- for ( size_t iL = 0; iL < freeLinks.size() && !curLink; ++iL )
- if (( curLink = freeLinks[ iL ] ))
- freeLinks[ iL ] = 0;
- nodes.push_back( curLink->LastNode() );
- polygon._links.push_back( *curLink );
-
- // find all links connected to curLink
- _Node* curNode = 0;
- do
+ _Node* curNode;
+ if ( !hasEdgeIntersections )
{
- curNode = curLink->FirstNode();
- curLink = 0;
+ // get a remaining link to start from
for ( size_t iL = 0; iL < freeLinks.size() && !curLink; ++iL )
- if ( freeLinks[ iL ] && freeLinks[ iL ]->LastNode() == curNode )
- {
- curLink = freeLinks[ iL ];
+ if (( curLink = freeLinks[ iL ] ))
freeLinks[ iL ] = 0;
- nodes.push_back( curNode );
- polygon._links.push_back( *curLink );
+ polygon._links.push_back( *curLink );
+ --nbFreeLinks;
+ do
+ {
+ // find all links connected to curLink
+ curNode = curLink->FirstNode();
+ curLink = 0;
+ for ( size_t iL = 0; iL < freeLinks.size() && !curLink; ++iL )
+ if ( freeLinks[ iL ] && freeLinks[ iL ]->LastNode() == curNode )
+ {
+ curLink = freeLinks[ iL ];
+ freeLinks[ iL ] = 0;
+ polygon._links.push_back( *curLink );
+ --nbFreeLinks;
+ }
+ } while ( curLink );
+ }
+ else // there are intersections with EDGEs
+ {
+ TGeomID curFace;
+ // get a remaining link to start from, one lying on minimal
+ // nb of FACEs
+ {
+ map< vector< TGeomID >, int > facesOfLink;
+ map< vector< TGeomID >, int >::iterator f2l;
+ for ( size_t iL = 0; iL < freeLinks.size(); ++iL )
+ if ( freeLinks[ iL ] )
+ {
+ f2l = facesOfLink.insert
+ ( make_pair( freeLinks[ iL ]->GetNotUsedFace( usedFaceIDs ), iL )).first;
+ if ( f2l->first.size() == 1 )
+ break;
+ }
+ f2l = facesOfLink.begin();
+ if ( f2l->first.empty() )
+ return;
+ curFace = f2l->first[0];
+ curLink = freeLinks[ f2l->second ];
+ freeLinks[ f2l->second ] = 0;
+ }
+ usedFaceIDs.insert( curFace );
+ polygon._links.push_back( *curLink );
+ --nbFreeLinks;
+
+ // find all links bounding a FACE of curLink
+ do
+ {
+ // go forward from curLink
+ curNode = curLink->LastNode();
+ curLink = 0;
+ for ( size_t iL = 0; iL < freeLinks.size() && !curLink; ++iL )
+ if ( freeLinks[ iL ] &&
+ freeLinks[ iL ]->FirstNode() == curNode &&
+ freeLinks[ iL ]->LastNode()->IsOnFace( curFace ))
+ {
+ curLink = freeLinks[ iL ];
+ freeLinks[ iL ] = 0;
+ polygon._links.push_back( *curLink );
+ --nbFreeLinks;
+ }
+ } while ( curLink );
+
+ std::reverse( polygon._links.begin(), polygon._links.end() );
+
+ curLink = & polygon._links.back();
+ do
+ {
+ // go backward from curLink
+ curNode = curLink->FirstNode();
+ curLink = 0;
+ for ( size_t iL = 0; iL < freeLinks.size() && !curLink; ++iL )
+ if ( freeLinks[ iL ] &&
+ freeLinks[ iL ]->LastNode() == curNode &&
+ freeLinks[ iL ]->FirstNode()->IsOnFace( curFace ))
+ {
+ curLink = freeLinks[ iL ];
+ freeLinks[ iL ] = 0;
+ polygon._links.push_back( *curLink );
+ --nbFreeLinks;
+ }
+ } while ( curLink );
+
+ curNode = polygon._links.back().FirstNode();
+
+ if ( polygon._links[0].LastNode() != curNode )
+ {
+ if ( !_vertexNodes.empty() )
+ {
+ // add links with _vertexNodes if not already used
+ for ( size_t iN = 0; iN < _vertexNodes.size(); ++iN )
+ if ( _vertexNodes[ iN ].IsOnFace( curFace ))
+ {
+ bool used = ( curNode == &_vertexNodes[ iN ] );
+ for ( size_t iL = 0; iL < polygon._links.size() && !used; ++iL )
+ used = ( &_vertexNodes[ iN ] == polygon._links[ iL ].LastNode() );
+ if ( !used )
+ {
+ polyLink._nodes[0] = &_vertexNodes[ iN ];
+ polyLink._nodes[1] = curNode;
+ polygon._polyLinks.push_back( polyLink );
+ polygon._links.push_back( _OrientedLink( &polygon._polyLinks.back() ));
+ freeLinks.push_back( &polygon._links.back() );
+ ++nbFreeLinks;
+ curNode = &_vertexNodes[ iN ];
+ }
+ // TODO: to reorder _vertexNodes within polygon, if there are several ones
+ }
}
- } while ( curLink );
+ polyLink._nodes[0] = polygon._links[0].LastNode();
+ polyLink._nodes[1] = curNode;
+ polygon._polyLinks.push_back( polyLink );
+ polygon._links.push_back( _OrientedLink( &polygon._polyLinks.back() ));
+ freeLinks.push_back( &polygon._links.back() );
+ ++nbFreeLinks;
+ }
- nbFreeLinks -= polygon._links.size();
+ } // if there are intersections with EDGEs
- if ( curNode != nodes.front() || polygon._links.size() < 3 )
+ if ( polygon._links.size() < 3 ||
+ polygon._links[0].LastNode() != polygon._links.back().FirstNode() )
return; // closed polygon not found -> invalid polyhedron
- quantities.push_back( nodes.size() );
- for ( size_t i = 0; i < nodes.size(); ++i )
- polyhedraNodes.push_back( nodes[i]->Node() );
-
- // add polygon to its links and reverse links
- for ( size_t i = 0; i < polygon._links.size(); ++i )
+ // add polygon to its links
+ for ( size_t iL = 0; iL < polygon._links.size(); ++iL )
{
- polygon._links[i].Reverse();
- polygon._links[i]._link->_faces.push_back( &polygon );
+ polygon._links[ iL ]._link->_faces.reserve( 2 );
+ polygon._links[ iL ]._link->_faces.push_back( &polygon );
+ polygon._links[ iL ].Reverse();
}
-
- //const size_t firstPoly = _polygons.size();
- }
+ } // while ( nbFreeLinks > 0 )
if ( ! checkPolyhedronSize() )
{
@@ -1505,20 +2009,32 @@ namespace
else if ( nbNodes == 6 && _polygons.size() == 5 ) isClassicElem = addPenta();
else if ( nbNodes == 5 && _polygons.size() == 5 ) isClassicElem = addPyra ();
if ( !isClassicElem )
- _volumeDefs.set( polyhedraNodes, quantities );
+ {
+ _volumeDefs._nodes.clear();
+ _volumeDefs._quantities.clear();
+
+ for ( size_t iF = 0; iF < _polygons.size(); ++iF )
+ {
+ const size_t nbLinks = _polygons[ iF ]._links.size();
+ _volumeDefs._quantities.push_back( nbLinks );
+ for ( size_t iL = 0; iL < nbLinks; ++iL )
+ _volumeDefs._nodes.push_back( _polygons[ iF ]._links[ iL ].FirstNode() );
+ }
+ }
}
//================================================================================
/*!
* \brief Create elements in the mesh
*/
- int Hexahedron::MakeElements(SMESH_MesherHelper& helper)
+ int Hexahedron::MakeElements(SMESH_MesherHelper& helper,
+ const map< TGeomID, vector< TGeomID > >& edge2faceIDsMap)
{
SMESHDS_Mesh* mesh = helper.GetMeshDS();
size_t nbCells[3] = { _grid->_coords[0].size() - 1,
_grid->_coords[1].size() - 1,
_grid->_coords[2].size() - 1 };
- const size_t nbGridCells = nbCells[0] *nbCells [1] * nbCells[2];
+ const size_t nbGridCells = nbCells[0] * nbCells[1] * nbCells[2];
vector< Hexahedron* > intersectedHex( nbGridCells, 0 );
int nbIntHex = 0;
@@ -1535,10 +2051,10 @@ namespace
for ( ; lineInd.More(); ++lineInd )
{
GridLine& line = _grid->_lines[ iDir ][ lineInd.LineIndex() ];
- multiset< IntersectionPoint >::const_iterator ip = line._intPoints.begin();
+ multiset< F_IntersectPoint >::const_iterator ip = line._intPoints.begin();
for ( ; ip != line._intPoints.end(); ++ip )
{
- if ( !ip->_node ) continue;
+ //if ( !ip->_node ) continue;
lineInd.SetIndexOnLine( ip->_indexOnLine );
for ( int iL = 0; iL < 4; ++iL ) // loop on 4 cells sharing a link
{
@@ -1561,12 +2077,15 @@ namespace
}
const int iLink = iL + iDir * 4;
hex->_hexLinks[iLink]._intNodes.push_back( _Node( 0, &(*ip) ));
- hex->_nbIntNodes++;
+ hex->_nbIntNodes += bool( ip->_node );
}
}
}
}
+ // implement geom edges into the mesh
+ addEdges( helper, intersectedHex, edge2faceIDsMap );
+
// add not split hexadrons to the mesh
int nbAdded = 0;
vector intHexInd( nbIntHex );
@@ -1636,6 +2155,366 @@ namespace
return nbAdded;
}
+ //================================================================================
+ /*!
+ * \brief Implements geom edges into the mesh
+ */
+ void Hexahedron::addEdges(SMESH_MesherHelper& helper,
+ vector< Hexahedron* >& hexes,
+ const map< TGeomID, vector< TGeomID > >& edge2faceIDsMap)
+ {
+ if ( edge2faceIDsMap.empty() ) return;
+
+ // Prepare planes for intersecting with EDGEs
+ GridPlanes pln[3];
+ {
+ gp_XYZ origPnt = ( _grid->_coords[0][0] * _grid->_axes[0] +
+ _grid->_coords[1][0] * _grid->_axes[1] +
+ _grid->_coords[2][0] * _grid->_axes[2] );
+ for ( int iDirZ = 0; iDirZ < 3; ++iDirZ ) // iDirZ gives normal direction to planes
+ {
+ GridPlanes& planes = pln[ iDirZ ];
+ int iDirX = ( iDirZ + 1 ) % 3;
+ int iDirY = ( iDirZ + 2 ) % 3;
+ planes._uNorm = ( _grid->_axes[ iDirY ] ^ _grid->_axes[ iDirZ ] ).Normalized();
+ planes._vNorm = ( _grid->_axes[ iDirZ ] ^ _grid->_axes[ iDirX ] ).Normalized();
+ planes._zNorm = ( _grid->_axes[ iDirX ] ^ _grid->_axes[ iDirY ] ).Normalized();
+ double uvDot = planes._uNorm * planes._vNorm;
+ planes._factor = sqrt( 1. - uvDot * uvDot );
+ planes._origins.resize( _grid->_coords[ iDirZ ].size() );
+ planes._zProjs.resize ( _grid->_coords[ iDirZ ].size() );
+ planes._origins[0] = origPnt;
+ planes._zProjs [0] = 0;
+ const double zFactor = _grid->_axes[ iDirZ ] * planes._zNorm;
+ const vector< double > & u = _grid->_coords[ iDirZ ];
+ for ( int i = 1; i < planes._origins.size(); ++i )
+ {
+ planes._origins[i] = origPnt + _grid->_axes[ iDirZ ] * ( u[i] - u[0] );
+ planes._zProjs [i] = zFactor * ( u[i] - u[0] );
+ }
+ }
+ }
+ const double deflection = _grid->_minCellSize / 20.;
+ const double tol = _grid->_tol;
+ // int facets[6] = { SMESH_Block::ID_F0yz, SMESH_Block::ID_F1yz,
+ // SMESH_Block::ID_Fx0z, SMESH_Block::ID_Fx1z,
+ // SMESH_Block::ID_Fxy0, SMESH_Block::ID_Fxy1 };
+ E_IntersectPoint ip;
+ //ip._faceIDs.reserve(2);
+
+ // Intersect EDGEs with the planes
+ map< TGeomID, vector< TGeomID > >::const_iterator e2fIt = edge2faceIDsMap.begin();
+ for ( ; e2fIt != edge2faceIDsMap.end(); ++e2fIt )
+ {
+ const TGeomID edgeID = e2fIt->first;
+ const TopoDS_Edge & E = TopoDS::Edge( _grid->_shapes( edgeID ));
+ BRepAdaptor_Curve curve( E );
+
+ ip._faceIDs = e2fIt->second;
+ ip._shapeID = edgeID;
+
+ // discretize the EGDE
+ GCPnts_UniformDeflection discret( curve, deflection, true );
+ if ( !discret.IsDone() || discret.NbPoints() < 2 )
+ continue;
+
+ // perform intersection
+ for ( int iDirZ = 0; iDirZ < 3; ++iDirZ )
+ {
+ GridPlanes& planes = pln[ iDirZ ];
+ int iDirX = ( iDirZ + 1 ) % 3;
+ int iDirY = ( iDirZ + 2 ) % 3;
+ double xLen = _grid->_coords[ iDirX ].back() - _grid->_coords[ iDirX ][0];
+ double yLen = _grid->_coords[ iDirY ].back() - _grid->_coords[ iDirY ][0];
+ double zFactor = _grid->_axes[ iDirZ ] * planes._zNorm;
+ int dIJK[3], d000[3] = { 0,0,0 };
+
+ // locate the 1st point of a segment within the grid
+ gp_XYZ p1 = discret.Value( 1 ).XYZ();
+ double u1 = discret.Parameter( 1 );
+ double zProj1 = planes._zNorm * ( p1 - planes._origins[0] );
+ gp_Pnt orig = planes._origins[0] + planes._zNorm * zProj1;
+ gp_XY uv = planes.GetUV( p1, orig );
+ int iX1 = int( uv.X() / xLen * ( _grid->_coords[ iDirX ].size() - 1. ));
+ int iY1 = int( uv.Y() / yLen * ( _grid->_coords[ iDirY ].size() - 1. ));
+ int iZ1 = int( zProj1 / planes._zProjs.back() * ( planes._zProjs.size() - 1. ));
+ locateValue( iX1, uv.X(), _grid->_coords[ iDirX ], dIJK[ iDirX ], tol );
+ locateValue( iY1, uv.Y(), _grid->_coords[ iDirY ], dIJK[ iDirY ], tol );
+ locateValue( iZ1, zProj1, planes._zProjs , dIJK[ iDirZ ], tol );
+
+ int ijk[3]; // grid index where a segment intersect a plane
+ ijk[ iDirX ] = iX1;
+ ijk[ iDirY ] = iY1;
+ ijk[ iDirZ ] = iZ1;
+ ip._uvw[ iDirX ] = uv.X() + _grid->_coords[ iDirX ][0];
+ ip._uvw[ iDirY ] = uv.Y() + _grid->_coords[ iDirY ][0];
+ ip._uvw[ iDirZ ] = zProj1 / zFactor + _grid->_coords[ iDirZ ][0];
+
+ // add the 1st vertex point to a hexahedron
+ if ( iDirZ == 0 )
+ {
+ //ip._shapeID = _grid->_shapes.Add( helper.IthVertex( 0, curve.Edge(),/*CumOri=*/false));
+ ip._point = p1;
+ _grid->_edgeIntP.push_back( ip );
+ if ( !addIntersection( _grid->_edgeIntP.back(), hexes, ijk, d000 ))
+ _grid->_edgeIntP.pop_back();
+ }
+ for ( int iP = 2; iP <= discret.NbPoints(); ++iP )
+ {
+ // locate the 2nd point of a segment within the grid
+ gp_XYZ p2 = discret.Value( iP ).XYZ();
+ double u2 = discret.Parameter( iP );
+ double zProj2 = planes._zNorm * ( p2 - planes._origins[0] );
+ int iZ2 = iZ1;
+ locateValue( iZ2, zProj2, planes._zProjs, dIJK[ iDirZ ], tol );
+
+ // treat intersections with planes between 2 end points of a segment
+ int dZ = ( iZ1 <= iZ2 ) ? +1 : -1;
+ int iZ = iZ1 + ( iZ1 < iZ2 );
+ for ( int i = 0, nb = Abs( iZ1 - iZ2 ); i < nb; ++i, iZ += dZ )
+ {
+ ip._point = findIntPoint( u1, zProj1, u2, zProj2,
+ planes._zProjs[ iZ ],
+ curve, planes._zNorm, planes._origins[0] );
+ gp_XY uv = planes.GetUV( ip._point, planes._origins[ iZ ]);
+ locateValue( ijk[ iDirX ], uv.X(), _grid->_coords[ iDirX ], dIJK[ iDirX ], tol );
+ locateValue( ijk[ iDirY ], uv.Y(), _grid->_coords[ iDirY ], dIJK[ iDirY ], tol );
+ ijk[ iDirZ ] = iZ;
+ ip._uvw[ iDirX ] = uv.X() + _grid->_coords[ iDirX ][0];
+ ip._uvw[ iDirY ] = uv.Y() + _grid->_coords[ iDirY ][0];
+ ip._uvw[ iDirZ ] = planes._zProjs[ iZ ] / zFactor + _grid->_coords[ iDirZ ][0];
+
+ // add ip to hex "above" the plane
+ _grid->_edgeIntP.push_back( ip );
+ dIJK[ iDirZ ] = 0;
+ bool added = addIntersection(_grid->_edgeIntP.back(), hexes, ijk, dIJK);
+
+ // add ip to hex "below" the plane
+ ijk[ iDirZ ] = iZ-1;
+ if ( !addIntersection( _grid->_edgeIntP.back(), hexes, ijk, dIJK ) &&
+ !added)
+ _grid->_edgeIntP.pop_back();
+ }
+ iZ1 = iZ2;
+ p1 = p2;
+ u1 = u2;
+ zProj1 = zProj2;
+ }
+ // add the 2nd vertex point to a hexahedron
+ if ( iDirZ == 0 )
+ {
+ orig = planes._origins[0] + planes._zNorm * zProj1;
+ uv = planes.GetUV( p1, orig );
+ locateValue( ijk[ iDirX ], uv.X(), _grid->_coords[ iDirX ], dIJK[ iDirX ], tol );
+ locateValue( ijk[ iDirY ], uv.Y(), _grid->_coords[ iDirY ], dIJK[ iDirY ], tol );
+ ijk[ iDirZ ] = iZ1;
+ ip._uvw[ iDirX ] = uv.X() + _grid->_coords[ iDirX ][0];
+ ip._uvw[ iDirY ] = uv.Y() + _grid->_coords[ iDirY ][0];
+ ip._uvw[ iDirZ ] = zProj1 / zFactor + _grid->_coords[ iDirZ ][0];
+ ip._point = p1;
+ _grid->_edgeIntP.push_back( ip );
+ if ( !addIntersection( _grid->_edgeIntP.back(), hexes, ijk, d000 ))
+ _grid->_edgeIntP.pop_back();
+ }
+ } // loop on 3 grid directions
+ } // loop on EDGEs
+
+ // Create nodes at found intersections
+ // const E_IntersectPoint* eip;
+ // for ( size_t i = 0; i < hexes.size(); ++i )
+ // {
+ // Hexahedron* h = hexes[i];
+ // if ( !h ) continue;
+ // for ( int iF = 0; iF < 6; ++iF )
+ // {
+ // _Face& quad = h->_hexQuads[ iF ];
+ // for ( size_t iP = 0; iP < quad._edgeNodes.size(); ++iP )
+ // if ( !quad._edgeNodes[ iP ]._node )
+ // if (( eip = quad._edgeNodes[ iP ].EdgeIntPnt() ))
+ // quad._edgeNodes[ iP ]._intPoint->_node = helper.AddNode( eip->_point.X(),
+ // eip->_point.Y(),
+ // eip->_point.Z() );
+ // }
+ // for ( size_t iP = 0; iP < hexes[i]->_vertexNodes.size(); ++iP )
+ // if (( eip = h->_vertexNodes[ iP ].EdgeIntPnt() ))
+ // h->_vertexNodes[ iP ]._intPoint->_node = helper.AddNode( eip->_point.X(),
+ // eip->_point.Y(),
+ // eip->_point.Z() );
+ // }
+ }
+
+ //================================================================================
+ /*!
+ * \brief Finds intersection of a curve with a plane
+ * \param [in] u1 - parameter of one curve point
+ * \param [in] proj1 - projection of the curve point to the plane normal
+ * \param [in] u2 - parameter of another curve point
+ * \param [in] proj2 - projection of the other curve point to the plane normal
+ * \param [in] proj - projection of a point where the curve intersects the plane
+ * \param [in] curve - the curve
+ * \param [in] axis - the plane normal
+ * \param [in] origin - the plane origin
+ * \return gp_Pnt - the found intersection point
+ */
+ //================================================================================
+
+ gp_Pnt Hexahedron::findIntPoint( double u1, double proj1,
+ double u2, double proj2,
+ double proj,
+ BRepAdaptor_Curve& curve,
+ const gp_XYZ& axis,
+ const gp_XYZ& origin)
+ {
+ double r = (( proj - proj1 ) / ( proj2 - proj1 ));
+ double u = u1 * ( 1 - r ) + u2 * r;
+ gp_Pnt p = curve.Value( u );
+ double newProj = axis * ( p.XYZ() - origin );
+ if ( Abs( proj - newProj ) > _grid->_tol / 10. )
+ {
+ if ( r > 0.5 )
+ return findIntPoint( u2, proj2, u, newProj, proj, curve, axis, origin );
+ else
+ return findIntPoint( u1, proj2, u, newProj, proj, curve, axis, origin );
+ }
+ return p;
+ }
+
+ //================================================================================
+ /*!
+ * \brief Returns index of a hexahedron sub-entities holding a point
+ * \param [in] ip - intersection point
+ * \param [out] facets - 0-3 facets holding a point
+ * \param [out] sub - index of a vertex or an edge holding a point
+ * \return int - number of facets holding a point
+ */
+ int Hexahedron::getEntity( const E_IntersectPoint* ip, int* facets, int& sub )
+ {
+ enum { X = 1, Y = 2, Z = 4 }; // == 001, 010, 100
+ int nbFacets = 0;
+ int vertex = 0, egdeMask = 0;
+
+ if ( Abs( _grid->_coords[0][ _i ] - ip->_uvw[0] ) < _grid->_tol ) {
+ facets[ nbFacets++ ] = SMESH_Block::ID_F0yz;
+ egdeMask |= X;
+ }
+ else if ( Abs( _grid->_coords[0][ _i+1 ] - ip->_uvw[0] ) < _grid->_tol ) {
+ facets[ nbFacets++ ] = SMESH_Block::ID_F1yz;
+ vertex |= X;
+ egdeMask |= X;
+ }
+ if ( Abs( _grid->_coords[1][ _j ] - ip->_uvw[1] ) < _grid->_tol ) {
+ facets[ nbFacets++ ] = SMESH_Block::ID_Fx0z;
+ egdeMask |= Y;
+ }
+ else if ( Abs( _grid->_coords[1][ _j+1 ] - ip->_uvw[1] ) < _grid->_tol ) {
+ facets[ nbFacets++ ] = SMESH_Block::ID_Fx1z;
+ vertex |= Y;
+ egdeMask |= Y;
+ }
+ if ( Abs( _grid->_coords[2][ _k ] - ip->_uvw[2] ) < _grid->_tol ) {
+ facets[ nbFacets++ ] = SMESH_Block::ID_Fxy0;
+ egdeMask |= Z;
+ }
+ else if ( Abs( _grid->_coords[2][ _k+1 ] - ip->_uvw[2] ) < _grid->_tol ) {
+ facets[ nbFacets++ ] = SMESH_Block::ID_Fxy1;
+ vertex |= Z;
+ egdeMask |= Z;
+ }
+
+ switch ( nbFacets )
+ {
+ case 0: sub = 0; break;
+ case 1: sub = facets[0]; break;
+ case 2: {
+ const int edge [3][8] = {
+ { SMESH_Block::ID_E00z, SMESH_Block::ID_E10z,
+ SMESH_Block::ID_E01z, SMESH_Block::ID_E11z },
+ { SMESH_Block::ID_E0y0, SMESH_Block::ID_E1y0, 0, 0,
+ SMESH_Block::ID_E0y1, SMESH_Block::ID_E1y1 },
+ { SMESH_Block::ID_Ex00, 0, SMESH_Block::ID_Ex10, 0,
+ SMESH_Block::ID_Ex01, 0, SMESH_Block::ID_Ex11 }
+ };
+ switch ( egdeMask ) {
+ case X | Y: sub = edge[ 0 ][ vertex ]; break;
+ case X | Z: sub = edge[ 1 ][ vertex ]; break;
+ default: sub = edge[ 2 ][ vertex ];
+ }
+ break;
+ }
+ //case 3:
+ default:
+ sub = vertex + SMESH_Block::ID_FirstV;
+ }
+
+ return nbFacets;
+ }
+ //================================================================================
+ /*!
+ * \brief Adds intersection with an EDGE
+ */
+ bool Hexahedron::addIntersection( const E_IntersectPoint& ip,
+ vector< Hexahedron* >& hexes,
+ int ijk[], int dIJK[] )
+ {
+ bool added = false;
+
+ size_t hexIndex[4] = {
+ _grid->CellIndex( ijk[0], ijk[1], ijk[2] ),
+ dIJK[0] ? _grid->CellIndex( ijk[0]+dIJK[0], ijk[1], ijk[2] ) : -1,
+ dIJK[1] ? _grid->CellIndex( ijk[0], ijk[1]+dIJK[1], ijk[2] ) : -1,
+ dIJK[2] ? _grid->CellIndex( ijk[0], ijk[1], ijk[2]+dIJK[2] ) : -1
+ };
+ for ( int i = 0; i < 4; ++i )
+ {
+ if ( 0 <= hexIndex[i] && hexIndex[i] < hexes.size() && hexes[ hexIndex[i] ] )
+ {
+ Hexahedron* h = hexes[ hexIndex[i] ];
+ // check if ip is really inside the hex
+#ifdef _DEBUG_
+ if (( _grid->_coords[0][ h->_i ] - _grid->_tol > ip._uvw[0] ) ||
+ ( _grid->_coords[0][ h->_i+1 ] + _grid->_tol < ip._uvw[0] ) ||
+ ( _grid->_coords[1][ h->_j ] - _grid->_tol > ip._uvw[1] ) ||
+ ( _grid->_coords[1][ h->_j+1 ] + _grid->_tol < ip._uvw[1] ) ||
+ ( _grid->_coords[2][ h->_k ] - _grid->_tol > ip._uvw[2] ) ||
+ ( _grid->_coords[2][ h->_k+1 ] + _grid->_tol < ip._uvw[2] ))
+ throw SALOME_Exception("ip outside a hex");
+#endif
+ h->_edgeIntPnts.push_back( & ip );
+ added = true;
+ }
+ }
+ return added;
+ }
+ //================================================================================
+ /*!
+ * \brief Finds nodes at a path from one node to another via intersections with EDGEs
+ */
+ bool Hexahedron::findChain( _Node* n1,
+ _Node* n2,
+ _Face& quad,
+ vector<_Node*>& chn )
+ {
+ chn.clear();
+ chn.push_back( n1 );
+ bool found = false;
+ do
+ {
+ found = false;
+ for ( size_t iP = 0; iP < quad._edgeNodes.size(); ++iP )
+ if (( std::find( ++chn.begin(), chn.end(), & quad._edgeNodes[iP]) == chn.end()) &&
+ chn.back()->IsLinked( quad._edgeNodes[ iP ]._intPoint ))
+ {
+ chn.push_back( & quad._edgeNodes[ iP ]);
+ found = true;
+ break;
+ }
+ } while ( found && chn.back() != n2 );
+
+ if ( chn.back() != n2 )
+ chn.push_back( n2 );
+
+ return chn.size() > 2;
+ }
//================================================================================
/*!
* \brief Adds computed elements to the mesh
@@ -1646,8 +2525,19 @@ namespace
// add elements resulted from hexahedron intersection
//for ( size_t i = 0; i < _volumeDefs.size(); ++i )
{
- vector< const SMDS_MeshNode* >& nodes = _volumeDefs._nodes;
-
+ vector< const SMDS_MeshNode* > nodes( _volumeDefs._nodes.size() );
+ for ( size_t iN = 0; iN < nodes.size(); ++iN )
+ if ( !( nodes[iN] = _volumeDefs._nodes[iN]->Node() ))
+ {
+ if ( const E_IntersectPoint* eip = _volumeDefs._nodes[iN]->EdgeIntPnt() )
+ nodes[iN] = _volumeDefs._nodes[iN]->_intPoint->_node =
+ helper.AddNode( eip->_point.X(),
+ eip->_point.Y(),
+ eip->_point.Z() );
+ else
+ throw SALOME_Exception("Bug: no node at intersection point");
+ }
+
if ( !_volumeDefs._quantities.empty() )
{
helper.AddPolyhedralVolume( nodes, _volumeDefs._quantities );
@@ -1679,8 +2569,11 @@ namespace
*/
bool Hexahedron::isInHole() const
{
+ if ( !_vertexNodes.empty() )
+ return false;
+
const int ijk[3] = { _i, _j, _k };
- IntersectionPoint curIntPnt;
+ F_IntersectPoint curIntPnt;
// consider a cell to be in a hole if all links in any direction
// comes OUT of geometry
@@ -1698,19 +2591,19 @@ namespace
{
const _Link& link = _hexLinks[ iL + 4*iDir ];
// check transition of the first node of a link
- const IntersectionPoint* firstIntPnt = 0;
+ const F_IntersectPoint* firstIntPnt = 0;
if ( link._nodes[0]->Node() ) // 1st node is a hexa corner
{
curIntPnt._paramOnLine = coords[ ijk[ iDir ]] - coords[0];
const GridLine& line = _grid->_lines[ iDir ][ lineIndex[ iL ]];
- multiset< IntersectionPoint >::const_iterator ip =
+ multiset< F_IntersectPoint >::const_iterator ip =
line._intPoints.upper_bound( curIntPnt );
--ip;
firstIntPnt = &(*ip);
}
else if ( !link._intNodes.empty() )
{
- firstIntPnt = link._intNodes[0]._intPoint;
+ firstIntPnt = link._intNodes[0].FaceIntPnt();
}
if ( firstIntPnt )
@@ -1736,10 +2629,10 @@ namespace
{
const _Face& polygon = _polygons[iP];
gp_XYZ area (0,0,0);
- SMESH_TNodeXYZ p1 ( polygon._links[ 0 ].FirstNode()->Node() );
+ gp_XYZ p1 = polygon._links[ 0 ].FirstNode()->Point().XYZ();
for ( size_t iL = 0; iL < polygon._links.size(); ++iL )
{
- SMESH_TNodeXYZ p2 ( polygon._links[ iL ].LastNode()->Node() );
+ gp_XYZ p2 = polygon._links[ iL ].LastNode()->Point().XYZ();
area += p1 ^ p2;
p1 = p2;
}
@@ -1764,12 +2657,12 @@ namespace
_polygons[4]._links.size() != 4 ||
_polygons[5]._links.size() != 4 )
return false;
- const SMDS_MeshNode* nodes[8];
+ _Node* nodes[8];
int nbN = 0;
for ( int iL = 0; iL < 4; ++iL )
{
// a base node
- nodes[iL] = _polygons[0]._links[iL].FirstNode()->Node();
+ nodes[iL] = _polygons[0]._links[iL].FirstNode();
++nbN;
// find a top node above the base node
@@ -1781,13 +2674,13 @@ namespace
if ( quad->_links[i]._link == link )
{
// 1st node of a link opposite to in
- nodes[iL+4] = quad->_links[(i+2)%4].FirstNode()->Node();
+ nodes[iL+4] = quad->_links[(i+2)%4].FirstNode();
++nbN;
break;
}
}
if ( nbN == 8 )
- _volumeDefs.set( vector< const SMDS_MeshNode* >( nodes, nodes+8 ));
+ _volumeDefs.set( vector< _Node* >( nodes, nodes+8 ));
return nbN == 8;
}
@@ -1797,10 +2690,10 @@ namespace
*/
bool Hexahedron::addTetra()
{
- const SMDS_MeshNode* nodes[4];
- nodes[0] = _polygons[0]._links[0].FirstNode()->Node();
- nodes[1] = _polygons[0]._links[1].FirstNode()->Node();
- nodes[2] = _polygons[0]._links[2].FirstNode()->Node();
+ _Node* nodes[4];
+ nodes[0] = _polygons[0]._links[0].FirstNode();
+ nodes[1] = _polygons[0]._links[1].FirstNode();
+ nodes[2] = _polygons[0]._links[2].FirstNode();
_Link* link = _polygons[0]._links[0]._link;
ASSERT( link->_faces.size() > 1 );
@@ -1810,8 +2703,8 @@ namespace
for ( int i = 0; i < 3; ++i )
if ( tria->_links[i]._link == link )
{
- nodes[3] = tria->_links[(i+1)%3].LastNode()->Node();
- _volumeDefs.set( vector< const SMDS_MeshNode* >( nodes, nodes+4 ));
+ nodes[3] = tria->_links[(i+1)%3].LastNode();
+ _volumeDefs.set( vector< _Node* >( nodes, nodes+4 ));
return true;
}
@@ -1831,12 +2724,12 @@ namespace
if ( iTri < 0 ) return false;
// find nodes
- const SMDS_MeshNode* nodes[6];
+ _Node* nodes[6];
int nbN = 0;
for ( int iL = 0; iL < 3; ++iL )
{
// a base node
- nodes[iL] = _polygons[ iTri ]._links[iL].FirstNode()->Node();
+ nodes[iL] = _polygons[ iTri ]._links[iL].FirstNode();
++nbN;
// find a top node above the base node
@@ -1849,13 +2742,13 @@ namespace
if ( quad->_links[i]._link == link )
{
// 1st node of a link opposite to in
- nodes[iL+3] = quad->_links[(i+2)%4].FirstNode()->Node();
+ nodes[iL+3] = quad->_links[(i+2)%4].FirstNode();
++nbN;
break;
}
}
if ( nbN == 6 )
- _volumeDefs.set( vector< const SMDS_MeshNode* >( nodes, nodes+6 ));
+ _volumeDefs.set( vector< _Node* >( nodes, nodes+6 ));
return ( nbN == 6 );
}
@@ -1873,11 +2766,11 @@ namespace
if ( iQuad < 0 ) return false;
// find nodes
- const SMDS_MeshNode* nodes[5];
- nodes[0] = _polygons[iQuad]._links[0].FirstNode()->Node();
- nodes[1] = _polygons[iQuad]._links[1].FirstNode()->Node();
- nodes[2] = _polygons[iQuad]._links[2].FirstNode()->Node();
- nodes[3] = _polygons[iQuad]._links[3].FirstNode()->Node();
+ _Node* nodes[5];
+ nodes[0] = _polygons[iQuad]._links[0].FirstNode();
+ nodes[1] = _polygons[iQuad]._links[1].FirstNode();
+ nodes[2] = _polygons[iQuad]._links[2].FirstNode();
+ nodes[3] = _polygons[iQuad]._links[3].FirstNode();
_Link* link = _polygons[iQuad]._links[0]._link;
ASSERT( link->_faces.size() > 1 );
@@ -1888,8 +2781,8 @@ namespace
for ( int i = 0; i < 3; ++i )
if ( tria->_links[i]._link == link )
{
- nodes[4] = tria->_links[(i+1)%3].LastNode()->Node();
- _volumeDefs.set( vector< const SMDS_MeshNode* >( nodes, nodes+5 ));
+ nodes[4] = tria->_links[(i+1)%3].LastNode();
+ _volumeDefs.set( vector< _Node* >( nodes, nodes+5 ));
return true;
}
@@ -1930,25 +2823,37 @@ bool StdMeshers_Cartesian_3D::Compute(SMESH_Mesh & theMesh,
{
Grid grid;
- TopTools_MapOfShape faceMap;
- for ( TopExp_Explorer fExp( theShape, TopAbs_FACE ); fExp.More(); fExp.Next() )
- if ( !faceMap.Add( fExp.Current() ))
- faceMap.Remove( fExp.Current() ); // remove a face shared by two solids
-
- Bnd_Box shapeBox;
- vector facesItersectors( faceMap.Extent() );
- TopTools_MapIteratorOfMapOfShape faceMppIt( faceMap );
- for ( int i = 0; faceMppIt.More(); faceMppIt.Next(), ++i )
+ vector< TopoDS_Shape > faceVec;
{
- facesItersectors[i]._face = TopoDS::Face( faceMppIt.Key() );
- facesItersectors[i]._grid = &grid;
+ TopTools_MapOfShape faceMap;
+ for ( TopExp_Explorer fExp( theShape, TopAbs_FACE ); fExp.More(); fExp.Next() )
+ if ( faceMap.Add( fExp.Current() )) // skip a face shared by two solids
+ faceVec.push_back( fExp.Current() );
+ }
+ Bnd_Box shapeBox;
+ vector facesItersectors( faceVec.size() );
+ map< TGeomID, vector< TGeomID > > edge2faceIDsMap;
+ TopExp_Explorer eExp;
+ for ( int i = 0; i < faceVec.size(); ++i )
+ {
+ facesItersectors[i]._face = TopoDS::Face ( faceVec[i] );
+ facesItersectors[i]._faceID = grid._shapes.Add( faceVec[i] );
+ facesItersectors[i]._grid = &grid;
shapeBox.Add( facesItersectors[i].GetFaceBndBox() );
+
+ if ( _hyp->GetToAddEdges() )
+ for ( eExp.Init( faceVec[i], TopAbs_EDGE ); eExp.More(); eExp.Next() )
+ {
+ const TopoDS_Edge& edge = TopoDS::Edge( eExp.Current() );
+ if ( !SMESH_Algo::isDegenerated( edge ))
+ edge2faceIDsMap[ grid._shapes.Add( edge )].push_back( facesItersectors[i]._faceID );
+ }
}
vector xCoords, yCoords, zCoords;
_hyp->GetCoordinates( xCoords, yCoords, zCoords, shapeBox );
- grid.SetCoordinates( xCoords, yCoords, zCoords, theShape );
+ grid.SetCoordinates( xCoords, yCoords, zCoords, _hyp->GetAxisDirs(), theShape );
// check if the grid encloses the shape
if ( !_hyp->IsGridBySpacing(0) ||
@@ -2015,12 +2920,12 @@ bool StdMeshers_Cartesian_3D::Compute(SMESH_Mesh & theMesh,
// create volume elements
Hexahedron hex( _hyp->GetSizeThreshold(), &grid );
- int nbAdded = hex.MakeElements( helper );
+ int nbAdded = hex.MakeElements( helper, edge2faceIDsMap );
SMESHDS_Mesh* meshDS = theMesh.GetMeshDS();
if ( nbAdded > 0 )
{
- // make all SOLIDS computed
+ // make all SOLIDs computed
if ( SMESHDS_SubMesh* sm1 = meshDS->MeshElements( solidExp.Current()) )
{
SMDS_ElemIteratorPtr volIt = sm1->GetElements();
@@ -2038,23 +2943,28 @@ bool StdMeshers_Cartesian_3D::Compute(SMESH_Mesh & theMesh,
// remove free nodes
if ( SMESHDS_SubMesh * smDS = meshDS->MeshElements( helper.GetSubShapeID() ))
{
- // intersection nodes
+ TIDSortedNodeSet nodesToRemove;
+ // get intersection nodes
for ( int iDir = 0; iDir < 3; ++iDir )
{
vector< GridLine >& lines = grid._lines[ iDir ];
for ( size_t i = 0; i < lines.size(); ++i )
{
- multiset< IntersectionPoint >::iterator ip = lines[i]._intPoints.begin();
+ multiset< F_IntersectPoint >::iterator ip = lines[i]._intPoints.begin();
for ( ; ip != lines[i]._intPoints.end(); ++ip )
if ( ip->_node && ip->_node->NbInverseElements() == 0 )
- meshDS->RemoveFreeNode( ip->_node, smDS, /*fromGroups=*/false );
+ nodesToRemove.insert( nodesToRemove.end(), ip->_node );
}
}
- // grid nodes
+ // get grid nodes
for ( size_t i = 0; i < grid._nodes.size(); ++i )
- if ( !grid._isBndNode[i] ) // nodes on boundary are already removed
- if ( grid._nodes[i] && grid._nodes[i]->NbInverseElements() == 0 )
- meshDS->RemoveFreeNode( grid._nodes[i], smDS, /*fromGroups=*/false );
+ if ( grid._nodes[i] && grid._nodes[i]->NbInverseElements() == 0 )
+ nodesToRemove.insert( nodesToRemove.end(), grid._nodes[i] );
+
+ // do remove
+ TIDSortedNodeSet::iterator n = nodesToRemove.begin();
+ for ( ; n != nodesToRemove.end(); ++n )
+ meshDS->RemoveFreeNode( *n, smDS, /*fromGroups=*/false );
}
return nbAdded;
diff --git a/src/StdMeshers/StdMeshers_FaceSide.cxx b/src/StdMeshers/StdMeshers_FaceSide.cxx
index 4e5e0478a..5382b7e87 100644
--- a/src/StdMeshers/StdMeshers_FaceSide.cxx
+++ b/src/StdMeshers/StdMeshers_FaceSide.cxx
@@ -251,7 +251,8 @@ StdMeshers_FaceSide::StdMeshers_FaceSide(const StdMeshers_FaceSide* theSide,
*/
//================================================================================
-StdMeshers_FaceSide::StdMeshers_FaceSide(UVPtStructVec& theSideNodes)
+StdMeshers_FaceSide::StdMeshers_FaceSide(UVPtStructVec& theSideNodes,
+ const TopoDS_Face& theFace)
{
myEdge.resize( 1 );
myEdgeID.resize( 1, -1 );
@@ -272,12 +273,42 @@ StdMeshers_FaceSide::StdMeshers_FaceSide(UVPtStructVec& theSideNodes)
if ( !myPoints.empty() )
{
myPoints[0].normParam = 0;
- gp_Pnt pPrev = SMESH_TNodeXYZ( myPoints[0].node );
- for ( size_t i = 1; i < myPoints.size(); ++i )
+ if ( myPoints[0].node &&
+ myPoints.back().node &&
+ myPoints[ myNbPonits/2 ].node )
{
- gp_Pnt p = SMESH_TNodeXYZ( myPoints[i].node );
- myLength += ( myPoints[i].normParam = p.Distance( pPrev ));
- pPrev = p;
+ gp_Pnt pPrev = SMESH_TNodeXYZ( myPoints[0].node );
+ for ( size_t i = 1; i < myPoints.size(); ++i )
+ {
+ gp_Pnt p = SMESH_TNodeXYZ( myPoints[i].node );
+ myLength += p.Distance( pPrev );
+ myPoints[i].normParam = myLength;
+ pPrev = p;
+ }
+ }
+ else if ( !theFace.IsNull() )
+ {
+ TopLoc_Location loc;
+ Handle(Geom_Surface) surf = BRep_Tool::Surface( theFace, loc );
+ gp_Pnt pPrev = surf->Value( myPoints[0].u, myPoints[0].v );
+ for ( size_t i = 1; i < myPoints.size(); ++i )
+ {
+ gp_Pnt p = surf->Value( myPoints[i].u, myPoints[i].v );
+ myLength += p.Distance( pPrev );
+ myPoints[i].normParam = myLength;
+ pPrev = p;
+ }
+ }
+ else
+ {
+ gp_Pnt2d pPrev = myPoints[0].UV();
+ for ( size_t i = 1; i < myPoints.size(); ++i )
+ {
+ gp_Pnt2d p = myPoints[i].UV();
+ myLength += p.Distance( pPrev );
+ myPoints[i].normParam = myLength;
+ pPrev = p;
+ }
}
if ( myLength > std::numeric_limits::min() )
for ( size_t i = 1; i < myPoints.size(); ++i )
@@ -926,6 +957,18 @@ gp_Pnt2d StdMeshers_FaceSide::Value2d(double U) const
return myC2d[ i ]->Value(par);
}
+ else if ( !myPoints.empty() )
+ {
+ int i = U * double( myPoints.size()-1 );
+ while ( i > 0 && myPoints[ i ].normParam > U )
+ --i;
+ while ( i+1 < myPoints.size() && myPoints[ i+1 ].normParam < U )
+ ++i;
+ double r = (( U - myPoints[ i ].normParam ) /
+ ( myPoints[ i+1 ].normParam - myPoints[ i ].normParam ));
+ return ( myPoints[ i ].UV() * ( 1 - r ) +
+ myPoints[ i+1 ].UV() * r );
+ }
return myDefaultPnt2d;
}
diff --git a/src/StdMeshers/StdMeshers_FaceSide.hxx b/src/StdMeshers/StdMeshers_FaceSide.hxx
index 4f714d4bf..c08d75cc3 100644
--- a/src/StdMeshers/StdMeshers_FaceSide.hxx
+++ b/src/StdMeshers/StdMeshers_FaceSide.hxx
@@ -35,6 +35,7 @@
#include
#include
#include
+#include
#include
#include
@@ -47,7 +48,6 @@ class SMESH_Mesh;
class Adaptor2d_Curve2d;
class Adaptor3d_Curve;
class BRepAdaptor_CompCurve;
-class TopoDS_Face;
struct SMESH_ComputeError;
class StdMeshers_FaceSide;
@@ -96,7 +96,43 @@ public:
/*!
* \brief Create a side from an UVPtStructVec
*/
- StdMeshers_FaceSide(UVPtStructVec& theSideNodes);
+ StdMeshers_FaceSide(UVPtStructVec& theSideNodes,
+ const TopoDS_Face& theFace = TopoDS_Face());
+
+ // static "consrtuctors"
+ static StdMeshers_FaceSidePtr New(const TopoDS_Face& Face,
+ const TopoDS_Edge& Edge,
+ SMESH_Mesh* Mesh,
+ const bool IsForward,
+ const bool IgnoreMediumNodes,
+ SMESH_ProxyMesh::Ptr ProxyMesh = SMESH_ProxyMesh::Ptr())
+ { return StdMeshers_FaceSidePtr
+ ( new StdMeshers_FaceSide( Face,Edge,Mesh,IsForward,IgnoreMediumNodes,ProxyMesh ));
+ }
+ static StdMeshers_FaceSidePtr New (const TopoDS_Face& Face,
+ std::list& Edges,
+ SMESH_Mesh* Mesh,
+ const bool IsForward,
+ const bool IgnoreMediumNodes,
+ SMESH_ProxyMesh::Ptr ProxyMesh = SMESH_ProxyMesh::Ptr())
+ { return StdMeshers_FaceSidePtr
+ ( new StdMeshers_FaceSide( Face,Edges,Mesh,IsForward,IgnoreMediumNodes,ProxyMesh ));
+ }
+ static StdMeshers_FaceSidePtr New (const StdMeshers_FaceSide* Side,
+ const SMDS_MeshNode* Node,
+ const gp_Pnt2d* Pnt2d1,
+ const gp_Pnt2d* Pnt2d2=NULL,
+ const Handle(Geom2d_Curve)& C2d=NULL,
+ const double UFirst=0.,
+ const double ULast=1.)
+ { return StdMeshers_FaceSidePtr
+ ( new StdMeshers_FaceSide( Side,Node,Pnt2d1,Pnt2d2,C2d,UFirst,ULast ));
+ }
+ static StdMeshers_FaceSidePtr New (UVPtStructVec& theSideNodes,
+ const TopoDS_Face& theFace = TopoDS_Face())
+ {
+ return StdMeshers_FaceSidePtr( new StdMeshers_FaceSide( theSideNodes, theFace ));
+ }
/*!
* \brief Return wires of a face as StdMeshers_FaceSide's
diff --git a/src/StdMeshers/StdMeshers_Geometric1D.cxx b/src/StdMeshers/StdMeshers_Geometric1D.cxx
new file mode 100644
index 000000000..8d2be979c
--- /dev/null
+++ b/src/StdMeshers/StdMeshers_Geometric1D.cxx
@@ -0,0 +1,204 @@
+// Copyright (C) 2007-2013 CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+// SMESH SMESH : implementaion of SMESH idl descriptions
+// File : StdMeshers_Geometric1D.cxx
+// Module : SMESH
+//
+#include "StdMeshers_Geometric1D.hxx"
+
+#include "SMESH_Mesh.hxx"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+//=============================================================================
+/*!
+ * Constructor
+ */
+//=============================================================================
+
+StdMeshers_Geometric1D::StdMeshers_Geometric1D(int hypId, int studyId, SMESH_Gen * gen)
+ :StdMeshers_Reversible1D(hypId, studyId, gen)
+{
+ _begLength = 1.;
+ _ratio = 1.;
+ _name = "GeometricProgression";
+}
+
+//=============================================================================
+/*!
+ * Sets length of the first segment
+ */
+//=============================================================================
+
+void StdMeshers_Geometric1D::SetStartLength(double length)
+ throw(SALOME_Exception)
+{
+ if ( _begLength != length )
+ {
+ if (length <= 0)
+ throw SALOME_Exception(LOCALIZED("length must be positive"));
+ _begLength = length;
+ NotifySubMeshesHypothesisModification();
+ }
+}
+
+//=============================================================================
+/*!
+ * Sets value of Common Ratio
+ */
+//=============================================================================
+
+void StdMeshers_Geometric1D::SetCommonRatio(double factor)
+ throw(SALOME_Exception)
+{
+ if ( _ratio != factor )
+ {
+ if (factor == 0)
+ throw SALOME_Exception(LOCALIZED("Zero factor is not allowed"));
+ _ratio = factor;
+ NotifySubMeshesHypothesisModification();
+ }
+}
+
+//=============================================================================
+/*!
+ * Returns length of the first segment
+ */
+//=============================================================================
+
+double StdMeshers_Geometric1D::GetStartLength() const
+{
+ return _begLength;
+}
+
+//=============================================================================
+/*!
+ * Returns value of Common Ratio
+ */
+//=============================================================================
+
+double StdMeshers_Geometric1D::GetCommonRatio() const
+{
+ return _ratio;
+}
+
+//=============================================================================
+/*!
+ *
+ */
+//=============================================================================
+
+ostream & StdMeshers_Geometric1D::SaveTo(ostream & save)
+{
+ save << _begLength << " " << _ratio << " ";
+
+ StdMeshers_Reversible1D::SaveTo( save );
+
+ return save;
+}
+
+//=============================================================================
+/*!
+ *
+ */
+//=============================================================================
+
+istream & StdMeshers_Geometric1D::LoadFrom(istream & load)
+{
+ bool isOK = true;
+ isOK = (load >> _begLength);
+ isOK = (load >> _ratio);
+
+ if (isOK)
+ StdMeshers_Reversible1D::LoadFrom( load );
+
+ return load;
+}
+
+//================================================================================
+/*!
+ * \brief Initialize start and end length by the mesh built on the geometry
+ * \param theMesh - the built mesh
+ * \param theShape - the geometry of interest
+ * \retval bool - true if parameter values have been successfully defined
+ */
+//================================================================================
+
+bool StdMeshers_Geometric1D::SetParametersByMesh(const SMESH_Mesh* theMesh,
+ const TopoDS_Shape& theShape)
+{
+ if ( !theMesh || theShape.IsNull() )
+ return false;
+
+ _begLength = _ratio = 0.;
+
+ int nbEdges = 0;
+ TopTools_IndexedMapOfShape edgeMap;
+ TopExp::MapShapes( theShape, TopAbs_EDGE, edgeMap );
+ for ( int i = 1; i <= edgeMap.Extent(); ++i )
+ {
+ const TopoDS_Edge& edge = TopoDS::Edge( edgeMap( i ));
+ BRepAdaptor_Curve C( edge );
+
+ vector< double > params;
+ if ( SMESH_Algo::GetNodeParamOnEdge( theMesh->GetMeshDS(), edge, params ))
+ {
+ nbEdges++;
+ double l1 = GCPnts_AbscissaPoint::Length( C, params[0], params[1] );
+ _begLength += l1;
+ if ( params.size() > 2 && l1 > 1e-100 )
+ _ratio += GCPnts_AbscissaPoint::Length( C, params[1], params[2]) / l1;
+ else
+ _ratio += 1;
+ }
+ }
+ if ( nbEdges ) {
+ _begLength /= nbEdges;
+ _ratio /= nbEdges;
+ }
+ else {
+ _begLength = 1;
+ _ratio = 1;
+ }
+ return nbEdges;
+}
+
+//================================================================================
+/*!
+ * \brief Initialize my parameter values by default parameters.
+ * \retval bool - true if parameter values have been successfully defined
+ */
+//================================================================================
+
+bool StdMeshers_Geometric1D::SetParametersByDefaults(const TDefaults& dflts,
+ const SMESH_Mesh* /*mesh*/)
+{
+ return ( _begLength = dflts._elemLength );
+}
+
diff --git a/src/StdMeshers/StdMeshers_Geometric1D.hxx b/src/StdMeshers/StdMeshers_Geometric1D.hxx
new file mode 100644
index 000000000..436c31748
--- /dev/null
+++ b/src/StdMeshers/StdMeshers_Geometric1D.hxx
@@ -0,0 +1,67 @@
+// Copyright (C) 2007-2013 CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+// SMESH SMESH : implementaion of SMESH idl descriptions
+// File : StdMeshers_Geometric1D.hxx
+// Module : SMESH
+//
+#ifndef _SMESH_Geometric1D_HXX_
+#define _SMESH_Geometric1D_HXX_
+
+#include "SMESH_StdMeshers.hxx"
+
+#include "StdMeshers_Reversible1D.hxx"
+#include "Utils_SALOME_Exception.hxx"
+
+class STDMESHERS_EXPORT StdMeshers_Geometric1D: public StdMeshers_Reversible1D
+{
+public:
+ StdMeshers_Geometric1D(int hypId, int studyId, SMESH_Gen* gen);
+
+ void SetStartLength(double length) throw(SALOME_Exception);
+ void SetCommonRatio(double factor) throw(SALOME_Exception);
+
+ double GetStartLength() const;
+ double GetCommonRatio() const;
+
+ virtual std::ostream & SaveTo(std::ostream & save);
+ virtual std::istream & LoadFrom(std::istream & load);
+
+ /*!
+ * \brief Initialize start and end length by the mesh built on the geometry
+ * \param theMesh - the built mesh
+ * \param theShape - the geometry of interest
+ * \retval bool - true if parameter values have been successfully defined
+ */
+ virtual bool SetParametersByMesh(const SMESH_Mesh* theMesh, const TopoDS_Shape& theShape);
+
+ /*!
+ * \brief Initialize my parameter values by default parameters.
+ * \retval bool - true if parameter values have been successfully defined
+ */
+ virtual bool SetParametersByDefaults(const TDefaults& dflts, const SMESH_Mesh* theMesh=0);
+
+protected:
+ double _begLength, _ratio;
+};
+
+#endif
diff --git a/src/StdMeshers/StdMeshers_Hexa_3D.cxx b/src/StdMeshers/StdMeshers_Hexa_3D.cxx
index 949ba6709..a0d205bd1 100644
--- a/src/StdMeshers/StdMeshers_Hexa_3D.cxx
+++ b/src/StdMeshers/StdMeshers_Hexa_3D.cxx
@@ -222,8 +222,8 @@ namespace
* \brief Finds FaceQuadStruct having a side equal to a given one and rearranges
* the found FaceQuadStruct::side to have the given side at a Q_BOTTOM place
*/
- FaceQuadStructPtr getQuadWithBottom( StdMeshers_FaceSide* side,
- FaceQuadStructPtr quad[ 6 ])
+ FaceQuadStructPtr getQuadWithBottom( StdMeshers_FaceSidePtr side,
+ FaceQuadStructPtr quad[ 6 ])
{
FaceQuadStructPtr foundQuad;
for ( int i = 1; i < 6; ++i )
@@ -231,7 +231,7 @@ namespace
if ( !quad[i] ) continue;
for ( unsigned iS = 0; iS < quad[i]->side.size(); ++iS )
{
- const StdMeshers_FaceSide* side2 = quad[i]->side[iS];
+ const StdMeshers_FaceSidePtr side2 = quad[i]->side[iS];
if (( side->FirstVertex().IsSame( side2->FirstVertex() ) ||
side->FirstVertex().IsSame( side2->LastVertex() ))
&&
@@ -241,7 +241,7 @@ namespace
{
if ( iS != Q_BOTTOM )
{
- vector< StdMeshers_FaceSide*> newSides;
+ vector< FaceQuadStruct::Side > newSides;
for ( unsigned j = iS; j < quad[i]->side.size(); ++j )
newSides.push_back( quad[i]->side[j] );
for ( unsigned j = 0; j < iS; ++j )
@@ -391,7 +391,7 @@ bool StdMeshers_Hexa_3D::Compute(SMESH_Mesh & aMesh,
for ( int i = 0; i < 6; ++i )
{
const TopoDS_Face& F = aCubeSide[i]._quad->face;
- StdMeshers_FaceSide* baseQuadSide = aCubeSide[i]._quad->side[ Q_BOTTOM ];
+ StdMeshers_FaceSidePtr baseQuadSide = aCubeSide[i]._quad->side[ Q_BOTTOM ];
list baseEdges( baseQuadSide->Edges().begin(), baseQuadSide->Edges().end() );
// assure correctness of node positions on baseE:
diff --git a/src/StdMeshers/StdMeshers_Prism_3D.cxx b/src/StdMeshers/StdMeshers_Prism_3D.cxx
index 07e9a166d..33bd5e1dc 100644
--- a/src/StdMeshers/StdMeshers_Prism_3D.cxx
+++ b/src/StdMeshers/StdMeshers_Prism_3D.cxx
@@ -107,7 +107,7 @@ namespace {
algo->myProxyMesh->GetMesh() != helper->GetMesh() )
algo->myProxyMesh.reset( new SMESH_ProxyMesh( *helper->GetMesh() ));
- algo->myQuadStruct.reset();
+ algo->myQuadList.clear();
if ( helper )
algo->_quadraticMesh = helper->GetIsQuadratic();
@@ -166,15 +166,15 @@ namespace {
//================================================================================
bool setBottomEdge( const TopoDS_Edge& botE,
- faceQuadStruct::Ptr& quad,
+ FaceQuadStruct::Ptr& quad,
const TopoDS_Shape& face)
{
- quad->side[ QUAD_TOP_SIDE ]->Reverse();
- quad->side[ QUAD_LEFT_SIDE ]->Reverse();
+ quad->side[ QUAD_TOP_SIDE ].grid->Reverse();
+ quad->side[ QUAD_LEFT_SIDE ].grid->Reverse();
int edgeIndex = 0;
for ( size_t i = 0; i < quad->side.size(); ++i )
{
- StdMeshers_FaceSide* quadSide = quad->side[i];
+ StdMeshers_FaceSidePtr quadSide = quad->side[i];
for ( int iE = 0; iE < quadSide->NbEdges(); ++iE )
if ( botE.IsSame( quadSide->Edge( iE )))
{
@@ -681,7 +681,7 @@ bool StdMeshers_Prism_3D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& theSh
continue; // already computed prism
}
// find a source FACE of the SOLID: it's a FACE sharing a bottom EDGE with wFace
- const TopoDS_Edge& wEdge = (*wQuad)->side[ QUAD_TOP_SIDE ]->Edge(0);
+ const TopoDS_Edge& wEdge = (*wQuad)->side[ QUAD_TOP_SIDE ].grid->Edge(0);
PShapeIteratorPtr faceIt = myHelper->GetAncestors( wEdge, *myHelper->GetMesh(),
TopAbs_FACE);
while ( const TopoDS_Shape* f = faceIt->next() )
@@ -879,7 +879,7 @@ bool StdMeshers_Prism_3D::getWallFaces( Prism_3D::TPrismTopo & thePrism,
int nbKnownFaces;
do {
nbKnownFaces = faceMap.Extent();
- StdMeshers_FaceSide *rightSide, *topSide; // sides of the quad
+ StdMeshers_FaceSidePtr rightSide, topSide; // sides of the quad
for ( size_t i = 0; i < thePrism.myWallQuads.size(); ++i )
{
rightSide = thePrism.myWallQuads[i].back()->side[ QUAD_RIGHT_SIDE ];
@@ -911,8 +911,8 @@ bool StdMeshers_Prism_3D::getWallFaces( Prism_3D::TPrismTopo & thePrism,
{
for ( size_t i = 0; i < thePrism.myWallQuads.size(); ++i )
{
- StdMeshers_FaceSide* topSide = thePrism.myWallQuads[i].back()->side[ QUAD_TOP_SIDE ];
- const TopoDS_Edge & topE = topSide->Edge( 0 );
+ StdMeshers_FaceSidePtr topSide = thePrism.myWallQuads[i].back()->side[ QUAD_TOP_SIDE ];
+ const TopoDS_Edge & topE = topSide->Edge( 0 );
if ( topSide->NbEdges() > 1 )
return toSM( error(COMPERR_BAD_SHAPE, TCom("Side face #") <<
shapeID( thePrism.myWallQuads[i].back()->face )
@@ -958,8 +958,8 @@ bool StdMeshers_Prism_3D::getWallFaces( Prism_3D::TPrismTopo & thePrism,
// Check that the top FACE shares all the top EDGEs
for ( size_t i = 0; i < thePrism.myWallQuads.size(); ++i )
{
- StdMeshers_FaceSide* topSide = thePrism.myWallQuads[i].back()->side[ QUAD_TOP_SIDE ];
- const TopoDS_Edge & topE = topSide->Edge( 0 );
+ StdMeshers_FaceSidePtr topSide = thePrism.myWallQuads[i].back()->side[ QUAD_TOP_SIDE ];
+ const TopoDS_Edge & topE = topSide->Edge( 0 );
if ( !myHelper->IsSubShape( topE, thePrism.myTop ))
return toSM( error( TCom("Wrong source face (#") << shapeID( thePrism.myBottom )));
}
@@ -1205,7 +1205,7 @@ bool StdMeshers_Prism_3D::computeWalls(const Prism_3D::TPrismTopo& thePrism)
int wgt = 0; // "weight"
for ( ; quad != thePrism.myWallQuads[iW].end(); ++quad )
{
- StdMeshers_FaceSide* lftSide = (*quad)->side[ QUAD_LEFT_SIDE ];
+ StdMeshers_FaceSidePtr lftSide = (*quad)->side[ QUAD_LEFT_SIDE ];
for ( int i = 0; i < lftSide->NbEdges(); ++i )
{
++wgt;
@@ -1224,7 +1224,7 @@ bool StdMeshers_Prism_3D::computeWalls(const Prism_3D::TPrismTopo& thePrism)
quad = thePrism.myWallQuads[iW].begin();
for ( ; quad != thePrism.myWallQuads[iW].end(); ++quad )
for ( int i = 0; i < NB_QUAD_SIDES; ++i )
- (*quad)->side[ i ]->SetIgnoreMediumNodes( true );
+ (*quad)->side[ i ].grid->SetIgnoreMediumNodes( true );
}
}
@@ -1237,8 +1237,8 @@ bool StdMeshers_Prism_3D::computeWalls(const Prism_3D::TPrismTopo& thePrism)
Prism_3D::TQuadList::const_iterator quad = quads.begin();
for ( ; quad != quads.end(); ++quad )
{
- StdMeshers_FaceSide* rgtSide = (*quad)->side[ QUAD_RIGHT_SIDE ]; // tgt
- StdMeshers_FaceSide* lftSide = (*quad)->side[ QUAD_LEFT_SIDE ]; // src
+ StdMeshers_FaceSidePtr rgtSide = (*quad)->side[ QUAD_RIGHT_SIDE ]; // tgt
+ StdMeshers_FaceSidePtr lftSide = (*quad)->side[ QUAD_LEFT_SIDE ]; // src
bool swapLeftRight = ( lftSide->NbSegments( /*update=*/true ) == 0 &&
rgtSide->NbSegments( /*update=*/true ) > 0 );
if ( swapLeftRight )
@@ -1373,8 +1373,8 @@ bool StdMeshers_Prism_3D::computeWalls(const Prism_3D::TPrismTopo& thePrism)
// to compute stuctured quad mesh on wall FACEs
// ---------------------------------------------------
{
- const TopoDS_Edge& botE = (*quad)->side[ QUAD_BOTTOM_SIDE ]->Edge(0);
- const TopoDS_Edge& topE = (*quad)->side[ QUAD_TOP_SIDE ]->Edge(0);
+ const TopoDS_Edge& botE = (*quad)->side[ QUAD_BOTTOM_SIDE ].grid->Edge(0);
+ const TopoDS_Edge& topE = (*quad)->side[ QUAD_TOP_SIDE ].grid->Edge(0);
SMESH_subMesh* botSM = mesh->GetSubMesh( botE );
SMESH_subMesh* topSM = mesh->GetSubMesh( topE );
SMESH_subMesh* srcSM = botSM;
@@ -2352,7 +2352,7 @@ bool StdMeshers_PrismAsBlock::Init(SMESH_MesherHelper* helper,
Prism_3D::TQuadList::const_iterator quad = thePrism.myWallQuads[ iE ].begin();
for ( ; quad != thePrism.myWallQuads[ iE ].end(); ++quad )
{
- const TopoDS_Edge& quadBot = (*quad)->side[ QUAD_BOTTOM_SIDE ]->Edge( 0 );
+ const TopoDS_Edge& quadBot = (*quad)->side[ QUAD_BOTTOM_SIDE ].grid->Edge( 0 );
if ( !myHelper->LoadNodeColumns( faceColumns, (*quad)->face, quadBot, meshDS ))
return error(COMPERR_BAD_INPUT_MESH, TCom("Can't find regular quadrangle mesh ")
<< "on a side face #" << MeshDS()->ShapeToIndex( (*quad)->face ));
@@ -2373,7 +2373,7 @@ bool StdMeshers_PrismAsBlock::Init(SMESH_MesherHelper* helper,
Prism_3D::TQuadList::const_iterator quad = thePrism.myWallQuads[ iE ].begin();
for ( ; quad != thePrism.myWallQuads[ iE ].end(); ++quad )
{
- const TopoDS_Edge& quadBot = (*quad)->side[ QUAD_BOTTOM_SIDE ]->Edge( 0 );
+ const TopoDS_Edge& quadBot = (*quad)->side[ QUAD_BOTTOM_SIDE ].grid->Edge( 0 );
if ( !myHelper->LoadNodeColumns( faceColumns, (*quad)->face, quadBot, meshDS ))
return error(COMPERR_BAD_INPUT_MESH, TCom("Can't find regular quadrangle mesh ")
<< "on a side face #" << MeshDS()->ShapeToIndex( (*quad)->face ));
diff --git a/src/StdMeshers/StdMeshers_Projection_2D.cxx b/src/StdMeshers/StdMeshers_Projection_2D.cxx
index 6bb6adc1f..96570ecdd 100644
--- a/src/StdMeshers/StdMeshers_Projection_2D.cxx
+++ b/src/StdMeshers/StdMeshers_Projection_2D.cxx
@@ -1018,9 +1018,9 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape&
map< double, const SMDS_MeshNode* >::iterator u_oldNode, u_newNode, u_newOnSeam, newEnd;
set< const SMDS_MeshNode* > seamNodes;
- // mapper puts on a seam edge nodes from 2 edges
+ // mapper changed, no more "mapper puts on a seam edge nodes from 2 edges"
if ( isSeam && ! getBoundaryNodes ( sm, tgtFace, u2nodesOnSeam, seamNodes ))
- RETURN_BAD_RESULT("getBoundaryNodes() failed");
+ ;//RETURN_BAD_RESULT("getBoundaryNodes() failed");
SMDS_NodeIteratorPtr nIt = smDS->GetNodes();
while ( nIt->more() )
diff --git a/src/StdMeshers/StdMeshers_Propagation.cxx b/src/StdMeshers/StdMeshers_Propagation.cxx
index bfe999db9..15bd1944c 100644
--- a/src/StdMeshers/StdMeshers_Propagation.cxx
+++ b/src/StdMeshers/StdMeshers_Propagation.cxx
@@ -64,7 +64,8 @@ namespace {
/*!
* \brief Return an edge from which hypotheses are propagated from
*/
- static TopoDS_Edge GetSource(SMESH_subMesh * submesh);
+ static TopoDS_Edge GetSource(SMESH_subMesh * submesh,
+ bool& isPropagOfDistribution);
/*!
* \brief Does it's main job
*/
@@ -90,23 +91,28 @@ StdMeshers_Propagation::StdMeshers_Propagation (int hypId, int studyId, SMESH_Ge
_name = GetName();
_param_algo_dim = -1; // 1D auxiliary
}
+StdMeshers_PropagOfDistribution::StdMeshers_PropagOfDistribution (int hypId,
+ int studyId,
+ SMESH_Gen * gen)
+ : StdMeshers_Propagation(hypId, studyId, gen) { _name = GetName(); }
StdMeshers_Propagation::~StdMeshers_Propagation() {}
string StdMeshers_Propagation::GetName () { return "Propagation"; }
+string StdMeshers_PropagOfDistribution::GetName () { return "PropagOfDistribution"; }
ostream & StdMeshers_Propagation::SaveTo (ostream & save) { return save; }
istream & StdMeshers_Propagation::LoadFrom (istream & load) { return load; }
-ostream & operator << (ostream & save, StdMeshers_Propagation & hyp) { return hyp.SaveTo(save); }
-istream & operator >> (istream & load, StdMeshers_Propagation & hyp) { return hyp.LoadFrom(load); }
bool StdMeshers_Propagation::SetParametersByMesh(const SMESH_Mesh*,
const TopoDS_Shape& ) { return false; }
bool StdMeshers_Propagation::SetParametersByDefaults(const TDefaults&,const SMESH_Mesh*) { return false; }
void StdMeshers_Propagation::SetPropagationMgr(SMESH_subMesh* subMesh) { PropagationMgr::Set( subMesh ); }
/*!
- * \brief Return an edge from which hypotheses are propagated from
+ * \brief Return an edge from which hypotheses are propagated
*/
-TopoDS_Edge StdMeshers_Propagation::GetPropagationSource(SMESH_Mesh& theMesh,
- const TopoDS_Shape& theEdge)
+TopoDS_Edge StdMeshers_Propagation::GetPropagationSource(SMESH_Mesh& theMesh,
+ const TopoDS_Shape& theEdge,
+ bool& isPropagOfDistribution)
{
- return PropagationMgr::GetSource(theMesh.GetSubMeshContaining( theEdge ));
+ return PropagationMgr::GetSource( theMesh.GetSubMeshContaining( theEdge ),
+ isPropagOfDistribution);
}
//=============================================================================
@@ -126,11 +132,13 @@ namespace {
struct PropagationMgrData : public EventListenerData
{
bool myForward; //!< true if a curve of edge in chain is codirected with one of source edge
+ bool myIsPropagOfDistribution; //!< type of Propagation hyp
PropagationMgrData( SubMeshState state=WAIT_PROPAG_HYP ): EventListenerData(true) {
- myType = state; myForward = true;
+ myType = state; myForward = true; myIsPropagOfDistribution = false;
}
void Init() {
myType = WAIT_PROPAG_HYP; mySubMeshes.clear(); myForward = true;
+ myIsPropagOfDistribution = false;
}
SubMeshState State() const {
return (SubMeshState) myType;
@@ -217,8 +225,13 @@ namespace {
const SMESH_Hypothesis* getProagationHyp (SMESH_Mesh& theMesh,
const TopoDS_Shape& theEdge)
{
- static SMESH_HypoFilter propagHypFilter
- ( SMESH_HypoFilter::HasName( StdMeshers_Propagation::GetName ()));
+ static SMESH_HypoFilter propagHypFilter;
+ if ( propagHypFilter.IsEmpty() )
+ {
+ propagHypFilter.
+ Init( SMESH_HypoFilter::HasName( StdMeshers_Propagation::GetName ())).
+ Or ( SMESH_HypoFilter::HasName( StdMeshers_PropagOfDistribution::GetName ()));
+ }
return theMesh.GetHypothesis( theEdge, propagHypFilter, true );
}
//================================================================================
@@ -248,6 +261,10 @@ namespace {
PropagationMgrData* chainData = getData( theMainSubMesh );
chainData->SetState( HAS_PROPAG_HYP );
+ if ( const SMESH_Hypothesis * propagHyp = getProagationHyp( *mesh, theMainEdge ))
+ chainData->myIsPropagOfDistribution =
+ ( StdMeshers_PropagOfDistribution::GetName() == propagHyp->GetName() );
+
// Edge submeshes, to which the 1D hypothesis will be propagated from theMainEdge
list & chain = chainData->mySubMeshes;
chain.clear();
@@ -462,17 +479,21 @@ namespace {
{
if ( findData( submesh )) return;
DBGMSG( "PropagationMgr::Set() on " << submesh->GetId() );
- EventListenerData* data = new PropagationMgrData();
+ PropagationMgrData* data = new PropagationMgrData();
submesh->SetEventListener( getListener(), data, submesh );
const SMESH_Hypothesis * propagHyp =
getProagationHyp( *submesh->GetFather(), submesh->GetSubShape() );
if ( propagHyp )
+ {
+ data->myIsPropagOfDistribution =
+ ( StdMeshers_PropagOfDistribution::GetName() == propagHyp->GetName() );
getListener()->ProcessEvent( SMESH_subMesh::ADD_HYP,
SMESH_subMesh::ALGO_EVENT,
submesh,
data,
propagHyp);
+ }
}
//================================================================================
/*!
@@ -480,7 +501,8 @@ namespace {
*/
//================================================================================
- TopoDS_Edge PropagationMgr::GetSource(SMESH_subMesh * submesh)
+ TopoDS_Edge PropagationMgr::GetSource(SMESH_subMesh * submesh,
+ bool& isPropagOfDistribution)
{
if ( PropagationMgrData* data = findData( submesh )) {
if ( data->State() == IN_CHAIN ) {
@@ -489,6 +511,9 @@ namespace {
TopoDS_Shape edge = sm->GetSubShape();
edge = edge.Oriented( data->myForward ? TopAbs_FORWARD : TopAbs_REVERSED );
DBGMSG( " GetSource() = edge " << sm->GetId() << " REV = " << (!data->myForward));
+ isPropagOfDistribution = false;
+ if ( PropagationMgrData* data = findData( sm ))
+ isPropagOfDistribution = data->myIsPropagOfDistribution;
if ( edge.ShapeType() == TopAbs_EDGE )
return TopoDS::Edge( edge );
}
@@ -502,9 +527,9 @@ namespace {
*/
//================================================================================
- void PropagationMgr::ProcessEvent(const int event,
- const int eventType,
- SMESH_subMesh* subMesh,
+ void PropagationMgr::ProcessEvent(const int event,
+ const int eventType,
+ SMESH_subMesh* subMesh,
SMESH_subMeshEventListenerData* listenerData,
const SMESH_Hypothesis* hyp)
{
@@ -516,7 +541,8 @@ namespace {
return;
DBGMSG( "PropagationMgr::ProcessEvent() on " << subMesh->GetId() );
- bool isPropagHyp = ( StdMeshers_Propagation::GetName() == hyp->GetName() );
+ bool isPropagHyp = ( StdMeshers_Propagation::GetName() == hyp->GetName() ||
+ StdMeshers_PropagOfDistribution::GetName() == hyp->GetName() );
PropagationMgrData* data = static_cast( listenerData );
switch ( data->State() ) {
diff --git a/src/StdMeshers/StdMeshers_Propagation.hxx b/src/StdMeshers/StdMeshers_Propagation.hxx
index c5a1616f7..e8a2b6e7a 100644
--- a/src/StdMeshers/StdMeshers_Propagation.hxx
+++ b/src/StdMeshers/StdMeshers_Propagation.hxx
@@ -50,8 +50,6 @@ class STDMESHERS_EXPORT StdMeshers_Propagation:public SMESH_Hypothesis
virtual std::ostream & SaveTo(std::ostream & save);
virtual std::istream & LoadFrom(std::istream & load);
- friend std::ostream & operator <<(std::ostream & save, StdMeshers_Propagation & hyp);
- friend std::istream & operator >>(std::istream & load, StdMeshers_Propagation & hyp);
static std::string GetName ();
@@ -69,7 +67,9 @@ class STDMESHERS_EXPORT StdMeshers_Propagation:public SMESH_Hypothesis
* \param theEdge - edge to which hypotheses are propagated
* \retval TopoDS_Edge - source edge, also passing orientation
*/
- static TopoDS_Edge GetPropagationSource(SMESH_Mesh& theMesh, const TopoDS_Shape& theEdge);
+ static TopoDS_Edge GetPropagationSource(SMESH_Mesh& theMesh,
+ const TopoDS_Shape& theEdge,
+ bool& isPropagOfDistribution );
/*!
* \brief Initialize my parameter values by the mesh built on the geometry
@@ -88,4 +88,19 @@ class STDMESHERS_EXPORT StdMeshers_Propagation:public SMESH_Hypothesis
virtual bool SetParametersByDefaults(const TDefaults& dflts, const SMESH_Mesh* theMesh=0);
};
+
+// =======================================================================
+/*!
+ * \brief Propagation Of Distribution hypothesis
+ */
+// =======================================================================
+
+class STDMESHERS_EXPORT StdMeshers_PropagOfDistribution: public StdMeshers_Propagation
+{
+ public:
+ StdMeshers_PropagOfDistribution(int hypId, int studyId, SMESH_Gen * gen);
+
+ static std::string GetName();
+};
+
#endif
diff --git a/src/StdMeshers/StdMeshers_QuadrangleParams.cxx b/src/StdMeshers/StdMeshers_QuadrangleParams.cxx
index 5369e598c..e8ab5ad6a 100644
--- a/src/StdMeshers/StdMeshers_QuadrangleParams.cxx
+++ b/src/StdMeshers/StdMeshers_QuadrangleParams.cxx
@@ -87,6 +87,43 @@ void StdMeshers_QuadrangleParams::SetQuadType (StdMeshers_QuadType type)
}
}
+//================================================================================
+/*!
+ * \brief Set positions of enforced nodes
+ */
+//================================================================================
+
+void StdMeshers_QuadrangleParams::
+SetEnforcedNodes( const std::vector< TopoDS_Shape >& shapes,
+ const std::vector< gp_Pnt >& points )
+{
+ bool isChanged = ( shapes != _enforcedVertices ||
+ points.size() != _enforcedPoints.size() );
+ for ( size_t i = 0; i < points.size() && !isChanged; ++i )
+ isChanged = ( _enforcedPoints[ i ].SquareDistance( points[i] ) > 1e-100 );
+
+ if ( isChanged )
+ {
+ _enforcedVertices = shapes;
+ _enforcedPoints = points;
+ NotifySubMeshesHypothesisModification();
+ }
+}
+
+//================================================================================
+/*!
+ * \brief Returns positions of enforced nodes
+ */
+//================================================================================
+
+void StdMeshers_QuadrangleParams::
+GetEnforcedNodes( std::vector< TopoDS_Shape >& shapes,
+ std::vector< gp_Pnt >& points ) const
+{
+ shapes = _enforcedVertices;
+ points = _enforcedPoints;
+}
+
//=============================================================================
/*!
*
@@ -98,6 +135,13 @@ ostream & StdMeshers_QuadrangleParams::SaveTo(ostream & save)
save << _triaVertexID << " UNDEFINED " << int(_quadType);
else
save << _triaVertexID << " " << _objEntry << " " << int(_quadType);
+
+ save << " " << _enforcedPoints.size();
+ for ( size_t i = 0; i < _enforcedPoints.size(); ++i )
+ save << " " << _enforcedPoints[i].X()
+ << " " << _enforcedPoints[i].Y()
+ << " " << _enforcedPoints[i].Z();
+
return save;
}
@@ -122,29 +166,25 @@ istream & StdMeshers_QuadrangleParams::LoadFrom(istream & load)
if (isOK)
_quadType = StdMeshers_QuadType(type);
+ // _enforcedVertices are loaded at StdMeshers_I level
+ // because GEOM objects are referred by study entry.
+
+ int nbP = 0;
+ double x,y,z;
+ if ( load >> nbP && nbP > 0 )
+ {
+ _enforcedPoints.reserve( nbP );
+ while ( _enforcedPoints.size() < _enforcedPoints.capacity() )
+ if ( load >> x &&
+ load >> y &&
+ load >> z )
+ _enforcedPoints.push_back( gp_Pnt( x,y,z ));
+ else
+ break;
+ }
return load;
}
-//=============================================================================
-/*!
- *
- */
-//=============================================================================
-ostream & operator <<(ostream & save, StdMeshers_QuadrangleParams & hyp)
-{
- return hyp.SaveTo( save );
-}
-
-//=============================================================================
-/*!
- *
- */
-//=============================================================================
-istream & operator >>(istream & load, StdMeshers_QuadrangleParams & hyp)
-{
- return hyp.LoadFrom( load );
-}
-
//================================================================================
/*!
* \brief Redifined method
diff --git a/src/StdMeshers/StdMeshers_QuadrangleParams.hxx b/src/StdMeshers/StdMeshers_QuadrangleParams.hxx
index 9d8374daa..afc6a8523 100644
--- a/src/StdMeshers/StdMeshers_QuadrangleParams.hxx
+++ b/src/StdMeshers/StdMeshers_QuadrangleParams.hxx
@@ -24,9 +24,12 @@
#define _SMESH_QUADRANGLEPARAMS_HXX_
#include "SMESH_StdMeshers.hxx"
-
#include "SMESH_Hypothesis.hxx"
-#include "Utils_SALOME_Exception.hxx"
+
+#include
+
+#include
+#include
enum StdMeshers_QuadType
{
@@ -38,8 +41,7 @@ enum StdMeshers_QuadType
QUAD_NB_TYPES
};
-class STDMESHERS_EXPORT StdMeshers_QuadrangleParams:
- public SMESH_Hypothesis
+class STDMESHERS_EXPORT StdMeshers_QuadrangleParams: public SMESH_Hypothesis
{
public:
StdMeshers_QuadrangleParams(int hypId, int studyId, SMESH_Gen* gen);
@@ -54,12 +56,13 @@ public:
void SetQuadType (StdMeshers_QuadType type);
StdMeshers_QuadType GetQuadType() const { return _quadType; }
+ void SetEnforcedNodes( const std::vector< TopoDS_Shape >& shapes,
+ const std::vector< gp_Pnt >& points );
+ void GetEnforcedNodes( std::vector< TopoDS_Shape >& shapes,
+ std::vector< gp_Pnt >& points ) const;
+
virtual std::ostream & SaveTo(std::ostream & save);
virtual std::istream & LoadFrom(std::istream & load);
- friend std::ostream& operator << (std::ostream & save,
- StdMeshers_QuadrangleParams & hyp);
- friend std::istream& operator >> (std::istream & load,
- StdMeshers_QuadrangleParams & hyp);
/*!
* \brief Initialize start and end length by the mesh built on the geometry
@@ -78,9 +81,11 @@ public:
const SMESH_Mesh* theMesh=0);
protected:
- int _triaVertexID;
- std::string _objEntry;
- StdMeshers_QuadType _quadType;
+ int _triaVertexID;
+ std::string _objEntry;
+ StdMeshers_QuadType _quadType;
+ std::vector< TopoDS_Shape > _enforcedVertices;
+ std::vector< gp_Pnt > _enforcedPoints;
};
#endif
diff --git a/src/StdMeshers/StdMeshers_Quadrangle_2D.cxx b/src/StdMeshers/StdMeshers_Quadrangle_2D.cxx
index 62fadc505..127598867 100644
--- a/src/StdMeshers/StdMeshers_Quadrangle_2D.cxx
+++ b/src/StdMeshers/StdMeshers_Quadrangle_2D.cxx
@@ -33,13 +33,16 @@
#include "SMESH_Block.hxx"
#include "SMESH_Comment.hxx"
#include "SMESH_Gen.hxx"
+#include "SMESH_HypoFilter.hxx"
#include "SMESH_Mesh.hxx"
+#include "SMESH_MeshAlgos.hxx"
#include "SMESH_MesherHelper.hxx"
#include "SMESH_subMesh.hxx"
#include "StdMeshers_FaceSide.hxx"
#include "StdMeshers_QuadrangleParams.hxx"
#include "StdMeshers_ViscousLayers2D.hxx"
+#include
#include
#include
#include
@@ -85,8 +88,9 @@ StdMeshers_Quadrangle_2D::StdMeshers_Quadrangle_2D (int hypId, int studyId,
myTrianglePreference(false),
myTriaVertexID(-1),
myNeedSmooth(false),
+ myParams( NULL ),
myQuadType(QUAD_STANDARD),
- myHelper( 0 )
+ myHelper( NULL )
{
MESSAGE("StdMeshers_Quadrangle_2D::StdMeshers_Quadrangle_2D");
_name = "Quadrangle_2D";
@@ -119,15 +123,16 @@ bool StdMeshers_Quadrangle_2D::CheckHypothesis
const TopoDS_Shape& aShape,
SMESH_Hypothesis::Hypothesis_Status& aStatus)
{
- myTriaVertexID = -1;
- myQuadType = QUAD_STANDARD;
+ myTriaVertexID = -1;
+ myQuadType = QUAD_STANDARD;
myQuadranglePreference = false;
- myTrianglePreference = false;
- myQuadStruct.reset();
- myHelper = NULL;
+ myTrianglePreference = false;
+ myHelper = (SMESH_MesherHelper*)NULL;
+ myParams = NULL;
+ myQuadList.clear();
bool isOk = true;
- aStatus = SMESH_Hypothesis::HYP_OK;
+ aStatus = SMESH_Hypothesis::HYP_OK;
const list & hyps =
GetUsedHypothesis(aMesh, aShape, false);
@@ -138,11 +143,11 @@ bool StdMeshers_Quadrangle_2D::CheckHypothesis
// First assigned hypothesis (if any) is processed now
if (hyps.size() > 0) {
aHyp = hyps.front();
- if (strcmp("QuadrangleParams", aHyp->GetName()) == 0) {
- const StdMeshers_QuadrangleParams* aHyp1 =
- (const StdMeshers_QuadrangleParams*)aHyp;
- myTriaVertexID = aHyp1->GetTriaVertex();
- myQuadType = aHyp1->GetQuadType();
+ if (strcmp("QuadrangleParams", aHyp->GetName()) == 0)
+ {
+ myParams = (const StdMeshers_QuadrangleParams*)aHyp;
+ myTriaVertexID = myParams->GetTriaVertex();
+ myQuadType = myParams->GetQuadType();
if (myQuadType == QUAD_QUADRANGLE_PREF ||
myQuadType == QUAD_QUADRANGLE_PREF_REVERSED)
myQuadranglePreference = true;
@@ -221,22 +226,25 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh,
FaceQuadStruct::Ptr quad = CheckNbEdges( aMesh, F, /*considerMesh=*/true );
if (!quad)
return false;
- myQuadStruct = quad;
+ myQuadList.clear();
+ myQuadList.push_back( quad );
+
+ if ( !getEnforcedUV() )
+ return false;
updateDegenUV( quad );
+ int n1 = quad->side[0].NbPoints();
+ int n2 = quad->side[1].NbPoints();
+ int n3 = quad->side[2].NbPoints();
+ int n4 = quad->side[3].NbPoints();
+
enum { NOT_COMPUTED = -1, COMPUTE_FAILED = 0, COMPUTE_OK = 1 };
int res = NOT_COMPUTED;
if (myQuadranglePreference)
{
- int n1 = quad->side[0]->NbPoints();
- int n2 = quad->side[1]->NbPoints();
- int n3 = quad->side[2]->NbPoints();
- int n4 = quad->side[3]->NbPoints();
int nfull = n1+n2+n3+n4;
- int ntmp = nfull/2;
- ntmp = ntmp*2;
- if (nfull == ntmp && ((n1 != n3) || (n2 != n4)))
+ if ((nfull % 2) == 0 && ((n1 != n3) || (n2 != n4)))
{
// special path genarating only quandrangle faces
res = computeQuadPref( aMesh, F, quad );
@@ -244,10 +252,6 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh,
}
else if (myQuadType == QUAD_REDUCED)
{
- int n1 = quad->side[0]->NbPoints();
- int n2 = quad->side[1]->NbPoints();
- int n3 = quad->side[2]->NbPoints();
- int n4 = quad->side[3]->NbPoints();
int n13 = n1 - n3;
int n24 = n2 - n4;
int n13tmp = n13/2; n13tmp = n13tmp*2;
@@ -275,7 +279,10 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh,
if ( res == NOT_COMPUTED )
{
- res = computeQuadDominant( aMesh, F, quad );
+ if ( n1 != n3 || n2 != n4 )
+ res = computeTriangles( aMesh, F, quad );
+ else
+ res = computeQuadDominant( aMesh, F );
}
if ( res == COMPUTE_OK && myNeedSmooth )
@@ -284,6 +291,83 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh,
return ( res == COMPUTE_OK );
}
+//================================================================================
+/*!
+ * \brief Compute quadrangles and triangles on the quad
+ */
+//================================================================================
+
+bool StdMeshers_Quadrangle_2D::computeTriangles(SMESH_Mesh& aMesh,
+ const TopoDS_Face& aFace,
+ FaceQuadStruct::Ptr quad)
+{
+ int nb = quad->side[0].grid->NbPoints();
+ int nr = quad->side[1].grid->NbPoints();
+ int nt = quad->side[2].grid->NbPoints();
+ int nl = quad->side[3].grid->NbPoints();
+
+ // rotate the quad to have nbNodeOut sides on TOP [and LEFT]
+ if ( nb > nt )
+ quad->shift( nl > nr ? 3 : 2, true );
+ else if ( nr > nl )
+ quad->shift( 1, true );
+ else if ( nl > nr )
+ quad->shift( nt > nb ? 0 : 3, true );
+
+ if ( !setNormalizedGrid( quad ))
+ return false;
+
+ if ( quad->nbNodeOut( QUAD_BOTTOM_SIDE ))
+ {
+ splitQuad( quad, 0, 1 );
+ }
+ if ( quad->nbNodeOut( QUAD_TOP_SIDE ))
+ {
+ splitQuad( quad, 0, quad->jSize-2 );
+ }
+ FaceQuadStruct::Ptr newQuad = myQuadList.back();
+ if ( quad != newQuad ) // split done
+ {
+ // make quad be a greatest one
+ if ( quad->side[ QUAD_LEFT_SIDE ].NbPoints() == 2 ||
+ quad->side[ QUAD_RIGHT_SIDE ].NbPoints() == 2 )
+ quad = newQuad;
+ if ( !setNormalizedGrid( quad ))
+ return false;
+ }
+
+ if ( quad->nbNodeOut( QUAD_RIGHT_SIDE ))
+ {
+ splitQuad( quad, quad->iSize-2, 0 );
+ }
+ if ( quad->nbNodeOut( QUAD_LEFT_SIDE ))
+ {
+ splitQuad( quad, 1, 0 );
+ }
+
+ return computeQuadDominant( aMesh, aFace );
+}
+
+//================================================================================
+/*!
+ * \brief Compute quadrangles and possibly triangles on all quads of myQuadList
+ */
+//================================================================================
+
+bool StdMeshers_Quadrangle_2D::computeQuadDominant(SMESH_Mesh& aMesh,
+ const TopoDS_Face& aFace)
+{
+ if ( !addEnforcedNodes() )
+ return false;
+
+ std::list< FaceQuadStruct::Ptr >::iterator quad = myQuadList.begin();
+ for ( ; quad != myQuadList.end(); ++quad )
+ if ( !computeQuadDominant( aMesh, aFace, *quad ))
+ return false;
+
+ return true;
+}
+
//================================================================================
/*!
* \brief Compute quadrangles and possibly triangles
@@ -294,37 +378,28 @@ bool StdMeshers_Quadrangle_2D::computeQuadDominant(SMESH_Mesh& aMesh,
const TopoDS_Face& aFace,
FaceQuadStruct::Ptr quad)
{
- // set normalized grid on unit square in parametric domain
+ // --- set normalized grid on unit square in parametric domain
- if (!setNormalizedGrid(aMesh, aFace, quad))
+ if ( !setNormalizedGrid( quad ))
return false;
- // --- compute 3D values on points, store points & quadrangles
+ // --- create nodes on points, and create quadrangles
- int nbdown = quad->side[0]->NbPoints();
- int nbup = quad->side[2]->NbPoints();
-
- int nbright = quad->side[1]->NbPoints();
- int nbleft = quad->side[3]->NbPoints();
-
- int nbhoriz = Min(nbdown, nbup);
- int nbvertic = Min(nbright, nbleft);
+ int nbhoriz = quad->iSize;
+ int nbvertic = quad->jSize;
// internal mesh nodes
SMESHDS_Mesh * meshDS = aMesh.GetMeshDS();
Handle(Geom_Surface) S = BRep_Tool::Surface(aFace);
- int i, j, geomFaceID = meshDS->ShapeToIndex(aFace);
- for (i = 1; i < nbhoriz - 1; i++) {
- for (j = 1; j < nbvertic - 1; j++) {
- int ij = j * nbhoriz + i;
- double u = quad->uv_grid[ij].u;
- double v = quad->uv_grid[ij].v;
- gp_Pnt P = S->Value(u, v);
- SMDS_MeshNode * node = meshDS->AddNode(P.X(), P.Y(), P.Z());
- meshDS->SetNodeOnFace(node, geomFaceID, u, v);
- quad->uv_grid[ij].node = node;
+ int i,j, geomFaceID = meshDS->ShapeToIndex(aFace);
+ for (i = 1; i < nbhoriz - 1; i++)
+ for (j = 1; j < nbvertic - 1; j++)
+ {
+ UVPtStruct& uvPnt = quad->UVPt( i, j );
+ gp_Pnt P = S->Value( uvPnt.u, uvPnt.v );
+ uvPnt.node = meshDS->AddNode(P.X(), P.Y(), P.Z());
+ meshDS->SetNodeOnFace( uvPnt.node, geomFaceID, uvPnt.u, uvPnt.v );
}
- }
// mesh faces
@@ -340,21 +415,20 @@ bool StdMeshers_Quadrangle_2D::computeQuadDominant(SMESH_Mesh& aMesh,
// i
// [0]
- i = 0;
int ilow = 0;
int iup = nbhoriz - 1;
- if (quad->isEdgeOut[3]) { ilow++; } else { if (quad->isEdgeOut[1]) iup--; }
+ if (quad->nbNodeOut(3)) { ilow++; } else { if (quad->nbNodeOut(1)) iup--; }
int jlow = 0;
int jup = nbvertic - 1;
- if (quad->isEdgeOut[0]) { jlow++; } else { if (quad->isEdgeOut[2]) jup--; }
+ if (quad->nbNodeOut(0)) { jlow++; } else { if (quad->nbNodeOut(2)) jup--; }
// regular quadrangles
for (i = ilow; i < iup; i++) {
for (j = jlow; j < jup; j++) {
const SMDS_MeshNode *a, *b, *c, *d;
- a = quad->uv_grid[j * nbhoriz + i ].node;
- b = quad->uv_grid[j * nbhoriz + i + 1].node;
+ a = quad->uv_grid[ j * nbhoriz + i ].node;
+ b = quad->uv_grid[ j * nbhoriz + i + 1].node;
c = quad->uv_grid[(j + 1) * nbhoriz + i + 1].node;
d = quad->uv_grid[(j + 1) * nbhoriz + i ].node;
SMDS_MeshFace* face = myHelper->AddFace(a, b, c, d);
@@ -364,19 +438,25 @@ bool StdMeshers_Quadrangle_2D::computeQuadDominant(SMESH_Mesh& aMesh,
}
}
- const vector& uv_e0 = quad->side[0]->GetUVPtStruct(true,0);
- const vector& uv_e1 = quad->side[1]->GetUVPtStruct(false,1);
- const vector& uv_e2 = quad->side[2]->GetUVPtStruct(true,1);
- const vector& uv_e3 = quad->side[3]->GetUVPtStruct(false,0);
+ // Boundary elements (must always be on an outer boundary of the FACE)
+
+ const vector& uv_e0 = quad->side[0].grid->GetUVPtStruct();
+ const vector& uv_e1 = quad->side[1].grid->GetUVPtStruct();
+ const vector& uv_e2 = quad->side[2].grid->GetUVPtStruct();
+ const vector& uv_e3 = quad->side[3].grid->GetUVPtStruct();
if (uv_e0.empty() || uv_e1.empty() || uv_e2.empty() || uv_e3.empty())
return error(COMPERR_BAD_INPUT_MESH);
double eps = Precision::Confusion();
- // Boundary quadrangles
-
- if (quad->isEdgeOut[0]) {
+ int nbdown = (int) uv_e0.size();
+ int nbup = (int) uv_e2.size();
+ int nbright = (int) uv_e1.size();
+ int nbleft = (int) uv_e3.size();
+
+ if (quad->nbNodeOut(0) && nbvertic == 2)
+ {
// Down edge is out
//
// |___|___|___|___|___|___|
@@ -393,8 +473,12 @@ bool StdMeshers_Quadrangle_2D::computeQuadDominant(SMESH_Mesh& aMesh,
// number of last node of the down edge to be processed
int stop = nbdown - 1;
// if right edge is out, we will stop at a node, previous to the last one
- if (quad->isEdgeOut[1]) stop--;
-
+ //if (quad->nbNodeOut(1)) stop--;
+ if ( quad->nbNodeOut( QUAD_RIGHT_SIDE ))
+ quad->UVPt( nbhoriz-1, 1 ).node = uv_e1[1].node;
+ if ( quad->nbNodeOut( QUAD_LEFT_SIDE ))
+ quad->UVPt( 0, 1 ).node = uv_e3[1].node;
+
// for each node of the down edge find nearest node
// in the first row of the regular grid and link them
for (i = 0; i < stop; i++) {
@@ -449,7 +533,7 @@ bool StdMeshers_Quadrangle_2D::computeQuadDominant(SMESH_Mesh& aMesh,
if (face) meshDS->SetMeshElementOnShape(face, geomFaceID);
}
else {
- splitQuad(meshDS, geomFaceID, a, b, c, d);
+ splitQuadFace(meshDS, geomFaceID, a, b, c, d);
}
// if node d is not at position g - make additional triangles
@@ -468,7 +552,8 @@ bool StdMeshers_Quadrangle_2D::computeQuadDominant(SMESH_Mesh& aMesh,
}
}
} else {
- if (quad->isEdgeOut[2]) {
+ if (quad->nbNodeOut(2) && nbvertic == 2)
+ {
// Up edge is out
//
// <-<-<-<-<-<-<-<-<-<-<-<-< -- direction of processing
@@ -483,9 +568,16 @@ bool StdMeshers_Quadrangle_2D::computeQuadDominant(SMESH_Mesh& aMesh,
int g = nbhoriz - 1; // last processed node in the regular grid
+ ilow = 0;
+ iup = nbhoriz - 1;
+
int stop = 0;
// if left edge is out, we will stop at a second node
- if (quad->isEdgeOut[3]) stop++;
+ //if (quad->nbNodeOut(3)) stop++;
+ if ( quad->nbNodeOut( QUAD_RIGHT_SIDE ))
+ quad->UVPt( nbhoriz-1, 0 ).node = uv_e1[ nbright-2 ].node;
+ if ( quad->nbNodeOut( QUAD_LEFT_SIDE ))
+ quad->UVPt( 0, 0 ).node = uv_e3[ nbleft-2 ].node;
// for each node of the up edge find nearest node
// in the first row of the regular grid and link them
@@ -536,10 +628,10 @@ bool StdMeshers_Quadrangle_2D::computeQuadDominant(SMESH_Mesh& aMesh,
if (face) meshDS->SetMeshElementOnShape(face, geomFaceID);
}
else {
- splitQuad(meshDS, geomFaceID, a, b, c, d);
+ splitQuadFace(meshDS, geomFaceID, a, b, c, d);
}
- if (near + 1 < g) { // if d not is at g - make additional triangles
+ if (near + 1 < g) { // if d is not at g - make additional triangles
for (int k = near + 1; k < g; k++) {
c = quad->uv_grid[nbhoriz*(nbvertic - 2) + k].node;
if (k + 1 > iup)
@@ -557,12 +649,14 @@ bool StdMeshers_Quadrangle_2D::computeQuadDominant(SMESH_Mesh& aMesh,
}
// right or left boundary quadrangles
- if (quad->isEdgeOut[1]) {
-// MESSAGE("right edge is out");
+ if (quad->nbNodeOut( QUAD_RIGHT_SIDE ) && nbhoriz == 2)
+ {
int g = 0; // last processed node in the grid
int stop = nbright - 1;
- if (quad->isEdgeOut[2]) stop--;
- for (i = 0; i < stop; i++) {
+ i = 0;
+ if (quad->side[ QUAD_RIGHT_SIDE ].from != i ) i++;
+ if (quad->side[ QUAD_RIGHT_SIDE ].to != stop ) stop--;
+ for ( ; i < stop; i++) {
const SMDS_MeshNode *a, *b, *c, *d;
a = uv_e1[i].node;
b = uv_e1[i + 1].node;
@@ -609,7 +703,7 @@ bool StdMeshers_Quadrangle_2D::computeQuadDominant(SMESH_Mesh& aMesh,
if (face) meshDS->SetMeshElementOnShape(face, geomFaceID);
}
else {
- splitQuad(meshDS, geomFaceID, a, b, c, d);
+ splitQuadFace(meshDS, geomFaceID, a, b, c, d);
}
if (near - 1 > g) { // if d not is at g - make additional triangles
@@ -627,12 +721,14 @@ bool StdMeshers_Quadrangle_2D::computeQuadDominant(SMESH_Mesh& aMesh,
}
}
} else {
- if (quad->isEdgeOut[3]) {
+ if (quad->nbNodeOut(3) && nbhoriz == 2) {
// MESSAGE("left edge is out");
int g = nbvertic - 1; // last processed node in the grid
int stop = 0;
- if (quad->isEdgeOut[0]) stop++;
- for (i = nbleft - 1; i > stop; i--) {
+ i = nbleft - 1;
+ if (quad->side[3].from != stop ) stop++;
+ if (quad->side[3].to != i ) i--;
+ for (; i > stop; i--) {
const SMDS_MeshNode *a, *b, *c, *d;
a = uv_e3[i].node;
b = uv_e3[i - 1].node;
@@ -678,7 +774,7 @@ bool StdMeshers_Quadrangle_2D::computeQuadDominant(SMESH_Mesh& aMesh,
if (face) meshDS->SetMeshElementOnShape(face, geomFaceID);
}
else {
- splitQuad(meshDS, geomFaceID, a, b, c, d);
+ splitQuadFace(meshDS, geomFaceID, a, b, c, d);
}
if (near + 1 < g) { // if d not is at g - make additional triangles
@@ -828,8 +924,8 @@ FaceQuadStruct::Ptr StdMeshers_Quadrangle_2D::CheckNbEdges(SMESH_Mesh &
const TopoDS_Shape & aShape,
const bool considerMesh)
{
- if ( myQuadStruct && myQuadStruct->face.IsSame( aShape ))
- return myQuadStruct;
+ if ( !myQuadList.empty() && myQuadList.front()->face.IsSame( aShape ))
+ return myQuadList.front();
TopoDS_Face F = TopoDS::Face(aShape);
if ( F.Orientation() >= TopAbs_INTERNAL ) F.Orientation( TopAbs_FORWARD );
@@ -852,7 +948,6 @@ FaceQuadStruct::Ptr StdMeshers_Quadrangle_2D::CheckNbEdges(SMESH_Mesh &
return FaceQuadStruct::Ptr();
}
FaceQuadStruct::Ptr quad( new FaceQuadStruct );
- quad->uv_grid = 0;
quad->side.reserve(nbEdgesInWire.front());
quad->face = F;
@@ -870,17 +965,17 @@ FaceQuadStruct::Ptr StdMeshers_Quadrangle_2D::CheckNbEdges(SMESH_Mesh &
else
sideEdges.push_back( *edgeIt++ );
if ( !sideEdges.empty() )
- quad->side.push_back(new StdMeshers_FaceSide(F, sideEdges, &aMesh, iSide < QUAD_TOP_SIDE,
- ignoreMediumNodes, myProxyMesh));
+ quad->side.push_back( StdMeshers_FaceSide::New(F, sideEdges, &aMesh, iSide < QUAD_TOP_SIDE,
+ ignoreMediumNodes, myProxyMesh));
else
--iSide;
}
- const vector& UVPSleft = quad->side[0]->GetUVPtStruct(true,0);
- /* vector& UVPStop = */quad->side[1]->GetUVPtStruct(false,1);
- /* vector& UVPSright = */quad->side[2]->GetUVPtStruct(true,1);
+ const vector& UVPSleft = quad->side[0].GetUVPtStruct(true,0);
+ /* vector& UVPStop = */quad->side[1].GetUVPtStruct(false,1);
+ /* vector& UVPSright = */quad->side[2].GetUVPtStruct(true,1);
const SMDS_MeshNode* aNode = UVPSleft[0].node;
- gp_Pnt2d aPnt2d(UVPSleft[0].u, UVPSleft[0].v);
- quad->side.push_back(new StdMeshers_FaceSide(quad->side[1], aNode, &aPnt2d));
+ gp_Pnt2d aPnt2d = UVPSleft[0].UV();
+ quad->side.push_back( StdMeshers_FaceSide::New( quad->side[1].grid.get(), aNode, &aPnt2d ));
myNeedSmooth = ( nbDegenEdges > 0 );
return quad;
}
@@ -922,15 +1017,15 @@ FaceQuadStruct::Ptr StdMeshers_Quadrangle_2D::CheckNbEdges(SMESH_Mesh &
}
if ( !sideEdges.empty() )
{
- quad->side.push_back(new StdMeshers_FaceSide(F, sideEdges, &aMesh, iSide < QUAD_TOP_SIDE,
- ignoreMediumNodes, myProxyMesh));
+ quad->side.push_back( StdMeshers_FaceSide::New( F, sideEdges, &aMesh, iSide < QUAD_TOP_SIDE,
+ ignoreMediumNodes, myProxyMesh ));
++iSide;
}
else if ( !SMESH_Algo::isDegenerated( *edgeIt ) && // closed EDGE
myHelper->IthVertex( 0, *edgeIt ).IsSame( myHelper->IthVertex( 1, *edgeIt )))
{
- quad->side.push_back(new StdMeshers_FaceSide(F, *edgeIt++, &aMesh, iSide < QUAD_TOP_SIDE,
- ignoreMediumNodes, myProxyMesh));
+ quad->side.push_back( StdMeshers_FaceSide::New( F, *edgeIt++, &aMesh, iSide < QUAD_TOP_SIDE,
+ ignoreMediumNodes, myProxyMesh));
++iSide;
}
if ( quad->side.size() == 4 )
@@ -1155,36 +1250,12 @@ StdMeshers_Quadrangle_2D::CheckAnd2Dcompute (SMESH_Mesh & aMesh,
if ( quad )
{
// set normalized grid on unit square in parametric domain
- if ( ! setNormalizedGrid( aMesh, TopoDS::Face( aShape ), quad))
+ if ( ! setNormalizedGrid( quad ))
quad.reset();
}
return quad;
}
-//=============================================================================
-/*!
- *
- */
-//=============================================================================
-
-faceQuadStruct::~faceQuadStruct()
-{
- for (size_t i = 0; i < side.size(); i++) {
- if (side[i]) {
- delete side[i];
- for (size_t j = i+1; j < side.size(); j++)
- if ( side[i] == side[j] )
- side[j] = 0;
- }
- }
- side.clear();
-
- if (uv_grid) {
- delete [] uv_grid;
- uv_grid = 0;
- }
-}
-
namespace
{
inline const vector& getUVPtStructIn(FaceQuadStruct::Ptr& quad, int i, int nbSeg)
@@ -1192,9 +1263,9 @@ namespace
bool isXConst = (i == QUAD_BOTTOM_SIDE || i == QUAD_TOP_SIDE);
double constValue = (i == QUAD_BOTTOM_SIDE || i == QUAD_LEFT_SIDE) ? 0 : 1;
return
- quad->isEdgeOut[i] ?
- quad->side[i]->SimulateUVPtStruct(nbSeg,isXConst,constValue) :
- quad->side[i]->GetUVPtStruct(isXConst,constValue);
+ quad->nbNodeOut(i) ?
+ quad->side[i].grid->SimulateUVPtStruct(nbSeg,isXConst,constValue) :
+ quad->side[i].grid->GetUVPtStruct (isXConst,constValue);
}
inline gp_UV calcUV(double x, double y,
const gp_UV& a0,const gp_UV& a1,const gp_UV& a2,const gp_UV& a3,
@@ -1212,10 +1283,11 @@ namespace
*/
//=============================================================================
-bool StdMeshers_Quadrangle_2D::setNormalizedGrid (SMESH_Mesh & aMesh,
- const TopoDS_Face& aFace,
- FaceQuadStruct::Ptr & quad)
+bool StdMeshers_Quadrangle_2D::setNormalizedGrid (FaceQuadStruct::Ptr quad)
{
+ if ( !quad->uv_grid.empty() )
+ return true;
+
// Algorithme décrit dans "Génération automatique de maillages"
// P.L. GEORGE, MASSON, § 6.4.1 p. 84-85
// traitement dans le domaine paramétrique 2d u,v
@@ -1233,81 +1305,133 @@ bool StdMeshers_Quadrangle_2D::setNormalizedGrid (SMESH_Mesh & aMesh,
// =down
//
- int nbhoriz = Min(quad->side[0]->NbPoints(), quad->side[2]->NbPoints());
- int nbvertic = Min(quad->side[1]->NbPoints(), quad->side[3]->NbPoints());
+ int nbhoriz = Min(quad->side[0].NbPoints(), quad->side[2].NbPoints());
+ int nbvertic = Min(quad->side[1].NbPoints(), quad->side[3].NbPoints());
- quad->isEdgeOut[0] = (quad->side[0]->NbPoints() > quad->side[2]->NbPoints());
- quad->isEdgeOut[1] = (quad->side[1]->NbPoints() > quad->side[3]->NbPoints());
- quad->isEdgeOut[2] = (quad->side[2]->NbPoints() > quad->side[0]->NbPoints());
- quad->isEdgeOut[3] = (quad->side[3]->NbPoints() > quad->side[1]->NbPoints());
+ if ( myQuadList.size() == 1 )
+ {
+ // all sub-quads must have NO sides with nbNodeOut > 0
+ quad->nbNodeOut(0) = Max( 0, quad->side[0].grid->NbPoints() - quad->side[2].grid->NbPoints());
+ quad->nbNodeOut(1) = Max( 0, quad->side[1].grid->NbPoints() - quad->side[3].grid->NbPoints());
+ quad->nbNodeOut(2) = Max( 0, quad->side[2].grid->NbPoints() - quad->side[0].grid->NbPoints());
+ quad->nbNodeOut(3) = Max( 0, quad->side[3].grid->NbPoints() - quad->side[1].grid->NbPoints());
+ }
+ int from[4] = {
+ quad->side[0].from,
+ quad->side[1].from,
+ quad->side[2].from,
+ quad->side[3].from
+ };
+ const vector& uv_e0_vec = quad->side[ 0 ].GetUVPtStruct();
+ const vector& uv_e1_vec = quad->side[ 1 ].GetUVPtStruct();
+ const vector& uv_e2_vec = quad->side[ 2 ].GetUVPtStruct();
+ const vector& uv_e3_vec = quad->side[ 3 ].GetUVPtStruct();
- UVPtStruct *uv_grid = quad->uv_grid = new UVPtStruct[nbvertic * nbhoriz];
-
- const vector& uv_e0 = getUVPtStructIn(quad, 0, nbhoriz - 1);
- const vector& uv_e1 = getUVPtStructIn(quad, 1, nbvertic - 1);
- const vector& uv_e2 = getUVPtStructIn(quad, 2, nbhoriz - 1);
- const vector& uv_e3 = getUVPtStructIn(quad, 3, nbvertic - 1);
-
- if (uv_e0.empty() || uv_e1.empty() || uv_e2.empty() || uv_e3.empty())
+ if (uv_e0_vec.empty() || uv_e1_vec.empty() || uv_e2_vec.empty() || uv_e3_vec.empty())
//return error("Can't find nodes on sides");
return error(COMPERR_BAD_INPUT_MESH);
+ UVPtStruct* uv_e0 = (UVPtStruct*) & uv_e0_vec[0] + from[0];
+ UVPtStruct* uv_e1 = (UVPtStruct*) & uv_e1_vec[0] + from[1];
+ UVPtStruct* uv_e2 = (UVPtStruct*) & uv_e2_vec[0] + from[2];
+ UVPtStruct* uv_e3 = (UVPtStruct*) & uv_e3_vec[0] + from[3];
+
+ quad->uv_grid.resize( nbvertic * nbhoriz );
+ quad->iSize = nbhoriz;
+ quad->jSize = nbvertic;
+ UVPtStruct *uv_grid = & quad->uv_grid[0];
+
+ quad->uv_box.Clear();
+
// copy data of face boundary
- {
+
+ { // BOTTOM
const int j = 0;
- for (int i = 0; i < nbhoriz; i++) // down
+ const double x0 = uv_e0[ 0 ].normParam;
+ const double dx = uv_e0[ nbhoriz-1 ].normParam - uv_e0[ 0 ].normParam;
+ for (int i = 0; i < nbhoriz; i++) { // down
+ uv_e0[i].x = ( uv_e0[i].normParam - x0 ) / dx;
+ uv_e0[i].y = 0.;
uv_grid[ j * nbhoriz + i ] = uv_e0[i];
+ quad->uv_box.Add( uv_e0[i].UV() );
+ }
}
- {
+ { // RIGHT
const int i = nbhoriz - 1;
- for (int j = 0; j < nbvertic; j++) // right
+ const double y0 = uv_e1[ 0 ].normParam;
+ const double dy = uv_e1[ nbvertic-1 ].normParam - uv_e1[ 0 ].normParam;
+ int j = 0, nb = nbvertic;
+ if ( quad->UVPt( i, j ).node ) ++j; // avoid copying from a split emulated side
+ for ( ; j < nb; j++) { // right
+ uv_e1[j].x = 1.;
+ uv_e1[j].y = ( uv_e1[j].normParam - y0 ) / dy;
uv_grid[ j * nbhoriz + i ] = uv_e1[j];
+ quad->uv_box.Add( uv_e1[j].UV() );
+ }
}
- {
+ { // TOP
const int j = nbvertic - 1;
- for (int i = 0; i < nbhoriz; i++) // up
+ const double x0 = uv_e2[ 0 ].normParam;
+ const double dx = uv_e2[ nbhoriz-1 ].normParam - uv_e2[ 0 ].normParam;
+ int i = 0, nb = nbhoriz;
+ if ( quad->UVPt( nb-1, j ).node ) --nb; // avoid copying from a split emulated side
+ for (; i < nb; i++) { // up
+ uv_e2[i].x = ( uv_e2[i].normParam - x0 ) / dx;
+ uv_e2[i].y = 1.;
uv_grid[ j * nbhoriz + i ] = uv_e2[i];
+ quad->uv_box.Add( uv_e2[i].UV() );
+ }
}
- {
+ { // LEFT
const int i = 0;
- for (int j = 0; j < nbvertic; j++) // left
+ const double y0 = uv_e3[ 0 ].normParam;
+ const double dy = uv_e3[ nbvertic-1 ].normParam - uv_e3[ 0 ].normParam;
+ int j = 0, nb = nbvertic;
+ if ( quad->UVPt( i, j ).node ) ++j; // avoid copying from a split emulated side
+ if ( quad->UVPt( i, nb-1 ).node ) --nb;
+ for ( ; j < nb; j++) { // left
+ uv_e3[j].x = 0.;
+ uv_e3[j].y = ( uv_e3[j].normParam - y0 ) / dy;
uv_grid[ j * nbhoriz + i ] = uv_e3[j];
+ quad->uv_box.Add( uv_e3[j].UV() );
+ }
}
// normalized 2d parameters on grid
- for (int i = 0; i < nbhoriz; i++) {
- for (int j = 0; j < nbvertic; j++) {
- int ij = j * nbhoriz + i;
- // --- droite i cste : x = x0 + y(x1-x0)
- double x0 = uv_e0[i].normParam; // bas - sud
- double x1 = uv_e2[i].normParam; // haut - nord
- // --- droite j cste : y = y0 + x(y1-y0)
- double y0 = uv_e3[j].normParam; // gauche - ouest
- double y1 = uv_e1[j].normParam; // droite - est
+ for (int i = 1; i < nbhoriz-1; i++)
+ {
+ const double x0 = uv_e0[i].x;
+ const double x1 = uv_e2[i].x;
+ for (int j = 1; j < nbvertic-1; j++)
+ {
+ const double y0 = uv_e3[j].y;
+ const double y1 = uv_e1[j].y;
// --- intersection : x=x0+(y0+x(y1-y0))(x1-x0)
double x = (x0 + y0 * (x1 - x0)) / (1 - (y1 - y0) * (x1 - x0));
double y = y0 + x * (y1 - y0);
+ int ij = j * nbhoriz + i;
uv_grid[ij].x = x;
uv_grid[ij].y = y;
+ uv_grid[ij].node = NULL;
}
}
// projection on 2d domain (u,v)
- gp_UV a0 (uv_e0.front().u, uv_e0.front().v);
- gp_UV a1 (uv_e0.back().u, uv_e0.back().v );
- gp_UV a2 (uv_e2.back().u, uv_e2.back().v );
- gp_UV a3 (uv_e2.front().u, uv_e2.front().v);
+ gp_UV a0 = uv_e0[0 ].UV();
+ gp_UV a1 = uv_e0[nbhoriz-1].UV();
+ gp_UV a2 = uv_e2[nbhoriz-1].UV();
+ gp_UV a3 = uv_e2[0 ].UV();
- for (int i = 0; i < nbhoriz; i++)
+ for (int i = 1; i < nbhoriz-1; i++)
{
- gp_UV p0( uv_e0[i].u, uv_e0[i].v );
- gp_UV p2( uv_e2[i].u, uv_e2[i].v );
- for (int j = 0; j < nbvertic; j++)
+ gp_UV p0 = uv_e0[i].UV();
+ gp_UV p2 = uv_e2[i].UV();
+ for (int j = 1; j < nbvertic-1; j++)
{
- gp_UV p1( uv_e1[j].u, uv_e1[j].v );
- gp_UV p3( uv_e3[j].u, uv_e3[j].v );
+ gp_UV p1 = uv_e1[j].UV();
+ gp_UV p3 = uv_e3[j].UV();
int ij = j * nbhoriz + i;
double x = uv_grid[ij].x;
@@ -1343,7 +1467,7 @@ static void shiftQuad(FaceQuadStruct::Ptr& quad, const int num)
void FaceQuadStruct::shift( size_t nb, bool ori )
{
if ( nb == 0 ) return;
- StdMeshers_FaceSide* sideArr[4] = { side[0], side[1], side[2], side[3] };
+ StdMeshers_FaceSidePtr sideArr[4] = { side[0], side[1], side[2], side[3] };
for (int i = QUAD_BOTTOM_SIDE; i < NB_QUAD_SIDES; ++i) {
int id = (i + nb) % NB_QUAD_SIDES;
bool wasForward = (i < QUAD_TOP_SIDE);
@@ -1367,10 +1491,10 @@ static gp_UV calcUV(double x0, double x1, double y0, double y1,
double x = (x0 + y0 * (x1 - x0)) / (1 - (y1 - y0) * (x1 - x0));
double y = y0 + x * (y1 - y0);
- gp_UV p0 = quad->side[QUAD_BOTTOM_SIDE]->Value2d(x).XY();
- gp_UV p1 = quad->side[QUAD_RIGHT_SIDE ]->Value2d(y).XY();
- gp_UV p2 = quad->side[QUAD_TOP_SIDE ]->Value2d(x).XY();
- gp_UV p3 = quad->side[QUAD_LEFT_SIDE ]->Value2d(y).XY();
+ gp_UV p0 = quad->side[QUAD_BOTTOM_SIDE].grid->Value2d(x).XY();
+ gp_UV p1 = quad->side[QUAD_RIGHT_SIDE ].grid->Value2d(y).XY();
+ gp_UV p2 = quad->side[QUAD_TOP_SIDE ].grid->Value2d(x).XY();
+ gp_UV p3 = quad->side[QUAD_LEFT_SIDE ].grid->Value2d(y).XY();
gp_UV uv = calcUV(x,y, a0,a1,a2,a3, p0,p1,p2,p3);
@@ -1387,10 +1511,10 @@ static gp_UV calcUV2(double x, double y,
const gp_UV& a0, const gp_UV& a1,
const gp_UV& a2, const gp_UV& a3)
{
- gp_UV p0 = quad->side[QUAD_BOTTOM_SIDE]->Value2d(x).XY();
- gp_UV p1 = quad->side[QUAD_RIGHT_SIDE ]->Value2d(y).XY();
- gp_UV p2 = quad->side[QUAD_TOP_SIDE ]->Value2d(x).XY();
- gp_UV p3 = quad->side[QUAD_LEFT_SIDE ]->Value2d(y).XY();
+ gp_UV p0 = quad->side[QUAD_BOTTOM_SIDE].grid->Value2d(x).XY();
+ gp_UV p1 = quad->side[QUAD_RIGHT_SIDE ].grid->Value2d(y).XY();
+ gp_UV p2 = quad->side[QUAD_TOP_SIDE ].grid->Value2d(x).XY();
+ gp_UV p3 = quad->side[QUAD_LEFT_SIDE ].grid->Value2d(y).XY();
gp_UV uv = calcUV(x,y, a0,a1,a2,a3, p0,p1,p2,p3);
@@ -1418,24 +1542,37 @@ bool StdMeshers_Quadrangle_2D::computeQuadPref (SMESH_Mesh & aMesh,
bool WisF = true;
int i,j,geomFaceID = meshDS->ShapeToIndex(aFace);
- int nb = quad->side[0]->NbPoints();
- int nr = quad->side[1]->NbPoints();
- int nt = quad->side[2]->NbPoints();
- int nl = quad->side[3]->NbPoints();
+ int nb = quad->side[0].grid->NbPoints();
+ int nr = quad->side[1].grid->NbPoints();
+ int nt = quad->side[2].grid->NbPoints();
+ int nl = quad->side[3].grid->NbPoints();
int dh = abs(nb-nt);
int dv = abs(nr-nl);
- // rotate sides to be as in the picture below and to have
- // dh >= dv and nt > nb
- if ( dh >= dv )
- shiftQuad( quad, ( nt > nb ) ? 0 : 2 );
+ if ( myForcedPnts.empty() )
+ {
+ // rotate sides to be as in the picture below and to have
+ // dh >= dv and nt > nb
+ if ( dh >= dv )
+ shiftQuad( quad, ( nt > nb ) ? 0 : 2 );
+ else
+ shiftQuad( quad, ( nr > nl ) ? 1 : 3 );
+ }
else
- shiftQuad( quad, ( nr > nl ) ? 1 : 3 );
+ {
+ // rotate the quad to have nt > nb [and nr > nl]
+ if ( nb > nt )
+ quad->shift( nr > nl ? 1 : 2, true );
+ else if ( nr > nl )
+ quad->shift( nb == nt ? 1 : 0, true );
+ else if ( nl > nr )
+ quad->shift( 3, true );
+ }
- nb = quad->side[0]->NbPoints();
- nr = quad->side[1]->NbPoints();
- nt = quad->side[2]->NbPoints();
- nl = quad->side[3]->NbPoints();
+ nb = quad->side[0].grid->NbPoints();
+ nr = quad->side[1].grid->NbPoints();
+ nt = quad->side[2].grid->NbPoints();
+ nl = quad->side[3].grid->NbPoints();
dh = abs(nb-nt);
dv = abs(nr-nl);
int nbh = Max(nb,nt);
@@ -1470,6 +1607,302 @@ bool StdMeshers_Quadrangle_2D::computeQuadPref (SMESH_Mesh & aMesh,
// 0------------0
// 0 bottom 1
+ const vector& uv_eb = quad->side[0].GetUVPtStruct(true,0);
+ const vector& uv_er = quad->side[1].GetUVPtStruct(false,1);
+ const vector& uv_et = quad->side[2].GetUVPtStruct(true,1);
+ const vector& uv_el = quad->side[3].GetUVPtStruct(false,0);
+
+ if (uv_eb.size() != nb || uv_er.size() != nr || uv_et.size() != nt || uv_el.size() != nl)
+ return error(COMPERR_BAD_INPUT_MESH);
+
+ gp_UV a0,a1,a2,a3, p0,p1,p2,p3, uv;
+ double x,y;
+
+ a0 = uv_eb[ 0 ].UV();
+ a1 = uv_er[ 0 ].UV();
+ a2 = uv_er[ nr-1 ].UV();
+ a3 = uv_et[ 0 ].UV();
+
+ if ( !myForcedPnts.empty() )
+ {
+ if ( dv != 0 && dh != 0 )
+ {
+ const int dmin = Min( dv, dh );
+
+ // Make a side separating domains L and Cb
+ StdMeshers_FaceSidePtr sideLCb;
+ UVPtStruct p3dom; // a point where 3 domains meat
+ { // dmin
+ vector pointsLCb( dmin+1 ); // 1--------1
+ pointsLCb[0] = uv_eb[0]; // | | |
+ for ( int i = 1; i <= dmin; ++i ) // | |Ct|
+ { // | L | |
+ x = uv_et[ i ].normParam; // | |__|
+ y = uv_er[ i ].normParam; // | / |
+ p0 = quad->side[0].grid->Value2d( x ).XY(); // | / Cb |dmin
+ p1 = uv_er[ i ].UV(); // |/ |
+ p2 = uv_et[ i ].UV(); // 0--------0
+ p3 = quad->side[3].grid->Value2d( y ).XY();
+ uv = calcUV( x,y, a0,a1,a2,a3, p0,p1,p2,p3 );
+ pointsLCb[ i ].u = uv.X();
+ pointsLCb[ i ].v = uv.Y();
+ }
+ sideLCb = StdMeshers_FaceSide::New( pointsLCb, aFace );
+ p3dom = pointsLCb.back();
+ }
+ // Make a side separating domains L and Ct
+ StdMeshers_FaceSidePtr sideLCt;
+ {
+ vector pointsLCt( nl );
+ pointsLCt[0] = p3dom;
+ pointsLCt.back() = uv_et[ dmin ];
+ x = uv_et[ dmin ].normParam;
+ p0 = quad->side[0].grid->Value2d( x ).XY();
+ p2 = uv_et[ dmin ].UV();
+ for ( int i = 1; i < nl; ++i )
+ {
+ y = uv_er[ i + dmin ].normParam;
+ p1 = uv_er[ i + dmin ].UV();
+ p3 = quad->side[3].grid->Value2d( y ).XY();
+ uv = calcUV( x,y, a0,a1,a2,a3, p0,p1,p2,p3 );
+ pointsLCt[ i ].u = uv.X();
+ pointsLCt[ i ].v = uv.Y();
+ }
+ sideLCt = StdMeshers_FaceSide::New( pointsLCt, aFace );
+ }
+ // Make a side separating domains Cb and Ct
+ StdMeshers_FaceSidePtr sideCbCt;
+ {
+ vector pointsCbCt( nb );
+ pointsCbCt[0] = p3dom;
+ pointsCbCt.back() = uv_er[ dmin ];
+ y = uv_er[ dmin ].normParam;
+ p1 = uv_er[ dmin ].UV();
+ p3 = quad->side[3].grid->Value2d( y ).XY();
+ for ( int i = 1; i < nb-1; ++i )
+ {
+ x = uv_et[ i + dmin ].normParam;
+ p2 = uv_et[ i + dmin ].UV();
+ p0 = quad->side[0].grid->Value2d( x ).XY();
+ uv = calcUV( x,y, a0,a1,a2,a3, p0,p1,p2,p3 );
+ pointsCbCt[ i ].u = uv.X();
+ pointsCbCt[ i ].v = uv.Y();
+ }
+ sideCbCt = StdMeshers_FaceSide::New( pointsCbCt, aFace );
+ }
+ // Make Cb quad
+ FaceQuadStruct* qCb = new FaceQuadStruct( quad->face );
+ myQuadList.push_back( FaceQuadStruct::Ptr( qCb ));
+ qCb->side.resize(4);
+ qCb->side[0] = quad->side[0];
+ qCb->side[1] = quad->side[1];
+ qCb->side[2] = sideCbCt;
+ qCb->side[3] = sideLCb;
+ qCb->side[1].to = dmin+1;
+ // Make L quad
+ FaceQuadStruct* qL = new FaceQuadStruct( quad->face );
+ myQuadList.push_back( FaceQuadStruct::Ptr( qL ));
+ qL->side.resize(4);
+ qL->side[0] = sideLCb;
+ qL->side[1] = sideLCt;
+ qL->side[2] = quad->side[2];
+ qL->side[3] = quad->side[3];
+ qL->side[2].to = dmin+1;
+ // Make Ct from the main quad
+ FaceQuadStruct::Ptr qCt = quad;
+ qCt->side[0] = sideCbCt;
+ qCt->side[3] = sideLCt;
+ qCt->side[1].from = dmin;
+ qCt->side[2].from = dmin;
+ qCt->uv_grid.clear();
+
+ // Connect sides
+ qCb->side[3].AddContact( dmin, & qCb->side[2], 0 );
+ qCb->side[3].AddContact( dmin, & qCt->side[3], 0 );
+ qCt->side[3].AddContact( 0, & qCt->side[0], 0 );
+ qCt->side[0].AddContact( 0, & qL ->side[0], dmin );
+ qL ->side[0].AddContact( dmin, & qL ->side[1], 0 );
+ qL ->side[0].AddContact( dmin, & qCb->side[2], 0 );
+
+ if ( dh == dv )
+ return computeQuadDominant( aMesh, aFace );
+ else
+ return computeQuadPref( aMesh, aFace, qCt );
+
+ } // if ( dv != 0 && dh != 0 )
+
+ // Case dv == 0
+ //
+ // lw nb lw = dh/2
+ // +------------+
+ // | | | |
+ // | | Ct | |
+ // | L | | R |
+ // | |____| |
+ // | / \ |
+ // | / Cb \ |
+ // |/ \|
+ // +------------+
+ const int lw = dh/2; // lateral width
+ const int bfrom = quad->side[0].from;
+ const int rfrom = quad->side[1].from;
+ const int tfrom = quad->side[2].from;
+ const int lfrom = quad->side[3].from;
+
+ const double lL = quad->side[3].Length();
+ const double lLwL = quad->side[2].Length( tfrom, tfrom + lw + 1 );
+ const double yCbL = lLwL / ( lLwL + lL );
+
+ const double lR = quad->side[1].Length();
+ const double lLwR = quad->side[2].Length( nt - lw - 1, nt );
+ const double yCbR = lLwR / ( lLwR + lR );
+
+ // Make sides separating domains Cb and L and R
+ StdMeshers_FaceSidePtr sideLCb, sideRCb;
+ UVPtStruct pTBL, pTBR; // points where 3 domains meat
+ {
+ vector pointsLCb( lw+1 ), pointsRCb( lw+1 );
+ pointsLCb[0] = uv_eb[ 0 + bfrom ];
+ pointsRCb[0] = uv_eb[ nb + bfrom ];
+ for ( int i = 1, i2 = nt-2; i <= lw; ++i, --i2 )
+ {
+ x = quad->side[2].Param( i );
+ y = yCbL * i / lw;
+ p0 = quad->side[0].Value2d( x );
+ p1 = quad->side[1].Value2d( y );
+ p2 = uv_et[ i + tfrom ].UV();
+ p3 = quad->side[3].Value2d( y );
+ uv = calcUV( x,y, a0,a1,a2,a3, p0,p1,p2,p3 );
+ pointsLCb[ i ].u = uv.X();
+ pointsLCb[ i ].v = uv.Y();
+ pointsLCb[ i ].x = x;
+
+ x = quad->side[2].Param( i2 );
+ y = yCbR * i / lw;
+ p0 = quad->side[0].Value2d( x );
+ p2 = uv_et[ i2 + tfrom ].UV();
+ uv = calcUV( x,y, a0,a1,a2,a3, p0,p1,p2,p3 );
+ pointsRCb[ i ].u = uv.X();
+ pointsRCb[ i ].v = uv.Y();
+ pointsRCb[ i ].x = x;
+ }
+ sideLCb = StdMeshers_FaceSide::New( pointsLCb, aFace );
+ sideRCb = StdMeshers_FaceSide::New( pointsRCb, aFace );
+ pTBL = pointsLCb.back();
+ pTBR = pointsRCb.back();
+ }
+ // Make sides separating domains Ct and L and R
+ StdMeshers_FaceSidePtr sideLCt, sideRCt;
+ {
+ vector pointsLCt( nl ), pointsRCt( nl );
+ pointsLCt[0] = pTBL;
+ pointsLCt.back() = uv_et[ lw + tfrom ];
+ pointsRCt[0] = pTBR;
+ pointsRCt.back() = uv_et[ lw + nb - 1 + tfrom ];
+ x = pTBL.x;
+ p0 = quad->side[0].Value2d( x );
+ p2 = uv_et[ lw + tfrom ].UV();
+ int iR = lw + nb - 1;
+ double xR = pTBR.x;
+ gp_UV p0R = quad->side[0].Value2d( xR );
+ gp_UV p2R = uv_et[ iR + tfrom ].UV();
+ for ( int i = 1; i < nl; ++i )
+ {
+ y = yCbL + ( 1. - yCbL ) * i / nl;
+ p1 = quad->side[1].Value2d( y );
+ p3 = quad->side[3].Value2d( y );
+ uv = calcUV( x,y, a0,a1,a2,a3, p0,p1,p2,p3 );
+ pointsLCt[ i ].u = uv.X();
+ pointsLCt[ i ].v = uv.Y();
+
+ y = yCbR + ( 1. - yCbR ) * i / nl;
+ p1 = quad->side[1].Value2d( y );
+ p3 = quad->side[3].Value2d( y );
+ uv = calcUV( xR,y, a0,a1,a2,a3, p0,p1,p2,p3 );
+ pointsRCt[ i ].u = uv.X();
+ pointsRCt[ i ].v = uv.Y();
+ }
+ sideLCt = StdMeshers_FaceSide::New( pointsLCt, aFace );
+ sideRCt = StdMeshers_FaceSide::New( pointsRCt, aFace );
+ }
+ // Make a side separating domains Cb and Ct
+ StdMeshers_FaceSidePtr sideCbCt;
+ {
+ vector pointsCbCt( nb );
+ pointsCbCt[0] = pTBL;
+ pointsCbCt.back() = pTBR;
+ p1 = quad->side[1].Value2d( yCbR );
+ p3 = quad->side[3].Value2d( yCbL );
+ for ( int i = 1; i < nb-1; ++i )
+ {
+ x = quad->side[2].Param( i + lw );
+ y = yCbL + ( yCbR - yCbL ) * i / nb;
+ p2 = uv_et[ i + lw + tfrom ].UV();
+ p0 = quad->side[0].Value2d( x );
+ uv = calcUV( x,y, a0,a1,a2,a3, p0,p1,p2,p3 );
+ pointsCbCt[ i ].u = uv.X();
+ pointsCbCt[ i ].v = uv.Y();
+ }
+ sideCbCt = StdMeshers_FaceSide::New( pointsCbCt, aFace );
+ }
+ // Make Cb quad
+ FaceQuadStruct* qCb = new FaceQuadStruct( quad->face );
+ myQuadList.push_back( FaceQuadStruct::Ptr( qCb ));
+ qCb->side.resize(4);
+ qCb->side[0] = quad->side[0];
+ qCb->side[1] = sideRCb;
+ qCb->side[2] = sideCbCt;
+ qCb->side[3] = sideLCb;
+ // Make L quad
+ FaceQuadStruct* qL = new FaceQuadStruct( quad->face );
+ myQuadList.push_back( FaceQuadStruct::Ptr( qL ));
+ qL->side.resize(4);
+ qL->side[0] = sideLCb;
+ qL->side[1] = sideLCt;
+ qL->side[2] = quad->side[2];
+ qL->side[3] = quad->side[3];
+ qL->side[2].to = lw+1;
+ // Make R quad
+ FaceQuadStruct* qR = new FaceQuadStruct( quad->face );
+ myQuadList.push_back( FaceQuadStruct::Ptr( qR ));
+ qR->side.resize(4);
+ qR->side[0] = sideRCb;
+ qR->side[0].from = lw;
+ qR->side[0].to = -1;
+ qR->side[1] = quad->side[1];
+ qR->side[2] = quad->side[2];
+ qR->side[2].from = nb + lw + tfrom;
+ qR->side[3] = sideRCt;
+ // Make Ct from the main quad
+ FaceQuadStruct::Ptr qCt = quad;
+ qCt->side[0] = sideCbCt;
+ qCt->side[1] = sideRCt;
+ qCt->side[2].from = lw + tfrom;
+ qCt->side[2].to = nt - lw + tfrom;
+ qCt->side[3] = sideLCt;
+ qCt->uv_grid.clear();
+
+ // Connect sides
+ qCb->side[3].AddContact( lw, & qCb->side[2], 0 );
+ qCb->side[3].AddContact( lw, & qCt->side[3], 0 );
+ qCt->side[3].AddContact( 0, & qCt->side[0], 0 );
+ qCt->side[0].AddContact( 0, & qL ->side[0], lw );
+ qL ->side[0].AddContact( lw, & qL ->side[1], 0 );
+ qL ->side[0].AddContact( lw, & qCb->side[2], 0 );
+ //
+ qCb->side[1].AddContact( lw, & qCb->side[2], lw );
+ qCb->side[1].AddContact( lw, & qCt->side[1], 0 );
+ qCt->side[0].AddContact( lw, & qCt->side[1], 0 );
+ qCt->side[0].AddContact( lw, & qR ->side[0], lw );
+ qR ->side[3].AddContact( lw, & qR ->side[0], lw );
+ qR ->side[3].AddContact( lw, & qCb->side[2], lw );
+
+ if ( dh == dv )
+ return computeQuadDominant( aMesh, aFace );
+
+
+ }
+
if ( dh > dv ) {
addv = (dh-dv)/2;
nbv = nbv + addv;
@@ -1479,19 +1912,6 @@ bool StdMeshers_Quadrangle_2D::computeQuadPref (SMESH_Mesh & aMesh,
nbh = nbh + addh;
}
- const vector& uv_eb = quad->side[0]->GetUVPtStruct(true,0);
- const vector& uv_er = quad->side[1]->GetUVPtStruct(false,1);
- const vector& uv_et = quad->side[2]->GetUVPtStruct(true,1);
- const vector& uv_el = quad->side[3]->GetUVPtStruct(false,0);
-
- if (uv_eb.size() != nb || uv_er.size() != nr || uv_et.size() != nt || uv_el.size() != nl)
- return error(COMPERR_BAD_INPUT_MESH);
-
- if ( !OldVersion )
- {
- // dh/2, Min(nb,nt), dh - dh/2, dv
- }
-
// arrays for normalized params
TColStd_SequenceOfReal npb, npr, npt, npl;
for (i=0; i0) {
// add top nodes
- for (i=1; i<=dl; i++)
+ for (i=1; i<=dl; i++)
NodesL.SetValue(i+1,nl,uv_et[i].node);
// create and add needed nodes
TColgp_SequenceOfXY UVtmp;
@@ -1580,13 +1995,13 @@ bool StdMeshers_Quadrangle_2D::computeQuadPref (SMESH_Mesh & aMesh,
if (WisF) {
SMDS_MeshFace* F =
myHelper->AddFace(NodesL.Value(i,j), NodesL.Value(i+1,j),
- NodesL.Value(i+1,j+1), NodesL.Value(i,j+1));
+ NodesL.Value(i+1,j+1), NodesL.Value(i,j+1));
if (F) meshDS->SetMeshElementOnShape(F, geomFaceID);
}
else {
SMDS_MeshFace* F =
myHelper->AddFace(NodesL.Value(i,j), NodesL.Value(i,j+1),
- NodesL.Value(i+1,j+1), NodesL.Value(i+1,j));
+ NodesL.Value(i+1,j+1), NodesL.Value(i+1,j));
if (F) meshDS->SetMeshElementOnShape(F, geomFaceID);
}
}
@@ -1598,15 +2013,15 @@ bool StdMeshers_Quadrangle_2D::computeQuadPref (SMESH_Mesh & aMesh,
UVL.Append(gp_UV (uv_el[i].u, uv_el[i].v));
}
}
-
+
// step2: create faces for right domain
StdMeshers_Array2OfNode NodesR(1,dr+1,1,nr);
// add right nodes
- for (j=1; j<=nr; j++)
+ for (j=1; j<=nr; j++)
NodesR.SetValue(1,j,uv_er[nr-j].node);
if (dr>0) {
// add top nodes
- for (i=1; i<=dr; i++)
+ for (i=1; i<=dr; i++)
NodesR.SetValue(i+1,1,uv_et[nt-1-i].node);
// create and add needed nodes
TColgp_SequenceOfXY UVtmp;
@@ -1643,13 +2058,13 @@ bool StdMeshers_Quadrangle_2D::computeQuadPref (SMESH_Mesh & aMesh,
if (WisF) {
SMDS_MeshFace* F =
myHelper->AddFace(NodesR.Value(i,j), NodesR.Value(i+1,j),
- NodesR.Value(i+1,j+1), NodesR.Value(i,j+1));
+ NodesR.Value(i+1,j+1), NodesR.Value(i,j+1));
if (F) meshDS->SetMeshElementOnShape(F, geomFaceID);
}
else {
SMDS_MeshFace* F =
myHelper->AddFace(NodesR.Value(i,j), NodesR.Value(i,j+1),
- NodesR.Value(i+1,j+1), NodesR.Value(i+1,j));
+ NodesR.Value(i+1,j+1), NodesR.Value(i+1,j));
if (F) meshDS->SetMeshElementOnShape(F, geomFaceID);
}
}
@@ -1661,7 +2076,7 @@ bool StdMeshers_Quadrangle_2D::computeQuadPref (SMESH_Mesh & aMesh,
UVR.Append(gp_UV(uv_er[i].u, uv_er[i].v));
}
}
-
+
// step3: create faces for central domain
StdMeshers_Array2OfNode NodesC(1,nb,1,nbv);
// add first line using NodesL
@@ -1675,12 +2090,12 @@ bool StdMeshers_Quadrangle_2D::computeQuadPref (SMESH_Mesh & aMesh,
for (i=1; iAddFace(NodesC.Value(i,j), NodesC.Value(i+1,j),
- NodesC.Value(i+1,j+1), NodesC.Value(i,j+1));
+ NodesC.Value(i+1,j+1), NodesC.Value(i,j+1));
if (F) meshDS->SetMeshElementOnShape(F, geomFaceID);
}
else {
SMDS_MeshFace* F =
myHelper->AddFace(NodesC.Value(i,j), NodesC.Value(i,j+1),
- NodesC.Value(i+1,j+1), NodesC.Value(i+1,j));
+ NodesC.Value(i+1,j+1), NodesC.Value(i+1,j));
if (F) meshDS->SetMeshElementOnShape(F, geomFaceID);
}
}
@@ -1760,13 +2175,13 @@ bool StdMeshers_Quadrangle_2D::computeQuadPref (SMESH_Mesh & aMesh,
if (WisF) {
SMDS_MeshFace* F =
myHelper->AddFace(NodesBRD.Value(i,j), NodesBRD.Value(i+1,j),
- NodesBRD.Value(i+1,j+1), NodesBRD.Value(i,j+1));
+ NodesBRD.Value(i+1,j+1), NodesBRD.Value(i,j+1));
if (F) meshDS->SetMeshElementOnShape(F, geomFaceID);
}
else {
SMDS_MeshFace* F =
myHelper->AddFace(NodesBRD.Value(i,j), NodesBRD.Value(i,j+1),
- NodesBRD.Value(i+1,j+1), NodesBRD.Value(i+1,j));
+ NodesBRD.Value(i+1,j+1), NodesBRD.Value(i+1,j));
if (F) meshDS->SetMeshElementOnShape(F, geomFaceID);
}
}
@@ -1812,7 +2227,7 @@ bool StdMeshers_Quadrangle_2D::computeQuadPref (SMESH_Mesh & aMesh,
double yy1 = y1 + dy1*i;
double dyy = yy1 - yy0;
for (j=1; j<=nb; j++) {
- double x = npt.Value(i+1+drl) +
+ double x = npt.Value(i+1+drl) +
npb.Value(j) * (npt.Value(nt-i) - npt.Value(i+1+drl));
double y = yy0 + dyy*x;
gp_UV UV = calcUV2(x, y, quad, a0, a1, a2, a3);
@@ -1855,7 +2270,7 @@ bool StdMeshers_Quadrangle_2D::computeQuadPref (SMESH_Mesh & aMesh,
double yy1 = y1 + dy1*i;
double dyy = yy1 - yy0;
for (j=1; j<=nb; j++) {
- double x = npt.Value(i+1) +
+ double x = npt.Value(i+1) +
npb.Value(j) * (npt.Value(nt-i-drl) - npt.Value(i+1));
double y = yy0 + dyy*x;
gp_UV UV = calcUV2(x, y, quad, a0, a1, a2, a3);
@@ -1872,13 +2287,13 @@ bool StdMeshers_Quadrangle_2D::computeQuadPref (SMESH_Mesh & aMesh,
if (WisF) {
SMDS_MeshFace* F =
myHelper->AddFace(NodesC.Value(i,j), NodesC.Value(i+1,j),
- NodesC.Value(i+1,j+1), NodesC.Value(i,j+1));
+ NodesC.Value(i+1,j+1), NodesC.Value(i,j+1));
if (F) meshDS->SetMeshElementOnShape(F, geomFaceID);
}
else {
SMDS_MeshFace* F =
myHelper->AddFace(NodesC.Value(i,j), NodesC.Value(i,j+1),
- NodesC.Value(i+1,j+1), NodesC.Value(i+1,j));
+ NodesC.Value(i+1,j+1), NodesC.Value(i+1,j));
if (F) meshDS->SetMeshElementOnShape(F, geomFaceID);
}
}
@@ -1905,13 +2320,13 @@ bool StdMeshers_Quadrangle_2D::computeQuadPref (SMESH_Mesh & aMesh,
if (WisF) {
SMDS_MeshFace* F =
myHelper->AddFace(NodesLast.Value(i,1), NodesLast.Value(i+1,1),
- NodesLast.Value(i+1,2), NodesLast.Value(i,2));
+ NodesLast.Value(i+1,2), NodesLast.Value(i,2));
if (F) meshDS->SetMeshElementOnShape(F, geomFaceID);
}
else {
SMDS_MeshFace* F =
myHelper->AddFace(NodesLast.Value(i,1), NodesLast.Value(i,2),
- NodesLast.Value(i+1,2), NodesLast.Value(i+1,2));
+ NodesLast.Value(i+1,2), NodesLast.Value(i+1,2));
if (F) meshDS->SetMeshElementOnShape(F, geomFaceID);
}
}
@@ -2064,12 +2479,12 @@ bool StdMeshers_Quadrangle_2D::evaluateQuadPref(SMESH_Mesh & aMesh,
*/
//=============================================================================
-void StdMeshers_Quadrangle_2D::splitQuad(SMESHDS_Mesh * theMeshDS,
- int theFaceID,
- const SMDS_MeshNode* theNode1,
- const SMDS_MeshNode* theNode2,
- const SMDS_MeshNode* theNode3,
- const SMDS_MeshNode* theNode4)
+void StdMeshers_Quadrangle_2D::splitQuadFace(SMESHDS_Mesh * theMeshDS,
+ int theFaceID,
+ const SMDS_MeshNode* theNode1,
+ const SMDS_MeshNode* theNode2,
+ const SMDS_MeshNode* theNode3,
+ const SMDS_MeshNode* theNode4)
{
SMDS_MeshFace* face;
if ( SMESH_TNodeXYZ( theNode1 ).SquareDistance( theNode3 ) >
@@ -2100,8 +2515,8 @@ namespace
SMESH_MesherHelper* helper,
Handle(Geom_Surface) S)
{
- const vector& uv_eb = quad->side[QUAD_BOTTOM_SIDE]->GetUVPtStruct();
- const vector& uv_et = quad->side[QUAD_TOP_SIDE ]->GetUVPtStruct();
+ const vector& uv_eb = quad->side[QUAD_BOTTOM_SIDE].GetUVPtStruct();
+ const vector& uv_et = quad->side[QUAD_TOP_SIDE ].GetUVPtStruct();
double rBot = ( uv_eb.size() - 1 ) * uvPt.normParam;
double rTop = ( uv_et.size() - 1 ) * uvPt.normParam;
int iBot = int( rBot );
@@ -2112,9 +2527,9 @@ namespace
gp_UV uv = calcUV(/*x,y=*/x, y,
/*a0,...=*/UVs[UV_A0], UVs[UV_A1], UVs[UV_A2], UVs[UV_A3],
- /*p0=*/quad->side[QUAD_BOTTOM_SIDE]->Value2d( x ).XY(),
+ /*p0=*/quad->side[QUAD_BOTTOM_SIDE].grid->Value2d( x ).XY(),
/*p1=*/UVs[ UV_R ],
- /*p2=*/quad->side[QUAD_TOP_SIDE ]->Value2d( x ).XY(),
+ /*p2=*/quad->side[QUAD_TOP_SIDE ].grid->Value2d( x ).XY(),
/*p3=*/UVs[ UV_L ]);
gp_Pnt P = S->Value( uv.X(), uv.Y() );
uvPt.u = uv.X();
@@ -2280,10 +2695,10 @@ bool StdMeshers_Quadrangle_2D::computeReduced (SMESH_Mesh & aMesh,
Handle(Geom_Surface) S = BRep_Tool::Surface(aFace);
int i,j,geomFaceID = meshDS->ShapeToIndex(aFace);
- int nb = quad->side[0]->NbPoints(); // bottom
- int nr = quad->side[1]->NbPoints(); // right
- int nt = quad->side[2]->NbPoints(); // top
- int nl = quad->side[3]->NbPoints(); // left
+ int nb = quad->side[0].grid->NbPoints(); // bottom
+ int nr = quad->side[1].grid->NbPoints(); // right
+ int nt = quad->side[2].grid->NbPoints(); // top
+ int nl = quad->side[3].grid->NbPoints(); // left
// Simple Reduce 10->8->6->4 (3 steps) Multiple Reduce 10->4 (1 step)
//
@@ -2372,10 +2787,10 @@ bool StdMeshers_Quadrangle_2D::computeReduced (SMESH_Mesh & aMesh,
}
}
- nb = quad->side[0]->NbPoints();
- nr = quad->side[1]->NbPoints();
- nt = quad->side[2]->NbPoints();
- nl = quad->side[3]->NbPoints();
+ nb = quad->side[0].grid->NbPoints();
+ nr = quad->side[1].grid->NbPoints();
+ nt = quad->side[2].grid->NbPoints();
+ nl = quad->side[3].grid->NbPoints();
dh = abs(nb-nt);
dv = abs(nr-nl);
int nbh = Max(nb,nt);
@@ -2392,10 +2807,10 @@ bool StdMeshers_Quadrangle_2D::computeReduced (SMESH_Mesh & aMesh,
nbh = nbh + addh;
}
- const vector& uv_eb = quad->side[0]->GetUVPtStruct(true,0);
- const vector& uv_er = quad->side[1]->GetUVPtStruct(false,1);
- const vector& uv_et = quad->side[2]->GetUVPtStruct(true,1);
- const vector& uv_el = quad->side[3]->GetUVPtStruct(false,0);
+ const vector& uv_eb = quad->side[0].GetUVPtStruct(true,0);
+ const vector& uv_er = quad->side[1].GetUVPtStruct(false,1);
+ const vector& uv_et = quad->side[2].GetUVPtStruct(true,1);
+ const vector& uv_el = quad->side[3].GetUVPtStruct(false,0);
if (uv_eb.size() != nb || uv_er.size() != nr || uv_et.size() != nt || uv_el.size() != nl)
return error(COMPERR_BAD_INPUT_MESH);
@@ -2646,10 +3061,10 @@ bool StdMeshers_Quadrangle_2D::computeReduced (SMESH_Mesh & aMesh,
}
}
- nb = quad->side[0]->NbPoints();
- nr = quad->side[1]->NbPoints();
- nt = quad->side[2]->NbPoints();
- nl = quad->side[3]->NbPoints();
+ nb = quad->side[0].grid->NbPoints();
+ nr = quad->side[1].grid->NbPoints();
+ nt = quad->side[2].grid->NbPoints();
+ nl = quad->side[3].grid->NbPoints();
// number of rows and columns
int nrows = nr - 1; // and also == nl - 1
@@ -2711,10 +3126,10 @@ bool StdMeshers_Quadrangle_2D::computeReduced (SMESH_Mesh & aMesh,
}
}
- const vector& uv_eb = quad->side[0]->GetUVPtStruct(true,0);
- const vector& uv_er = quad->side[1]->GetUVPtStruct(false,1);
- const vector& uv_et = quad->side[2]->GetUVPtStruct(true,1);
- const vector& uv_el = quad->side[3]->GetUVPtStruct(false,0);
+ const vector& uv_eb = quad->side[0].GetUVPtStruct(true,0);
+ const vector& uv_er = quad->side[1].GetUVPtStruct(false,1);
+ const vector& uv_et = quad->side[2].GetUVPtStruct(true,1);
+ const vector& uv_el = quad->side[3].GetUVPtStruct(false,0);
if (uv_eb.size() != nb || uv_er.size() != nr || uv_et.size() != nt || uv_el.size() != nl)
return error(COMPERR_BAD_INPUT_MESH);
@@ -3234,8 +3649,7 @@ void StdMeshers_Quadrangle_2D::updateDegenUV(FaceQuadStruct::Ptr quad)
// --------------------------------------------------------------------------
for ( unsigned i = 0; i < quad->side.size(); ++i )
{
- StdMeshers_FaceSide* side = quad->side[i];
- const vector& uvVec = side->GetUVPtStruct();
+ const vector& uvVec = quad->side[i].GetUVPtStruct();
// find which end of the side is on degenerated shape
int degenInd = -1;
@@ -3251,10 +3665,9 @@ void StdMeshers_Quadrangle_2D::updateDegenUV(FaceQuadStruct::Ptr quad)
if ( i >= QUAD_TOP_SIDE )
isPrev = !isPrev;
int i2 = ( isPrev ? ( i + 3 ) : ( i + 1 )) % 4;
- StdMeshers_FaceSide* side2 = quad->side[ i2 ];
- const vector& uvVec2 = side2->GetUVPtStruct();
+ const vector& uvVec2 = quad->side[ i2 ].GetUVPtStruct();
int degenInd2 = -1;
- if ( uvVec[ degenInd ].node == uvVec2[0].node )
+ if ( uvVec[ degenInd ].node == uvVec2.front().node )
degenInd2 = 0;
else if ( uvVec[ degenInd ].node == uvVec2.back().node )
degenInd2 = uvVec2.size() - 1;
@@ -3274,10 +3687,10 @@ void StdMeshers_Quadrangle_2D::updateDegenUV(FaceQuadStruct::Ptr quad)
// ----------------------------------------------------------------------------
for ( unsigned i = 0; i < quad->side.size(); ++i )
{
- StdMeshers_FaceSide* degSide = quad->side[i];
+ StdMeshers_FaceSidePtr degSide = quad->side[i];
if ( !myHelper->IsDegenShape( degSide->EdgeID(0) ))
continue;
- StdMeshers_FaceSide* oppSide = quad->side[( i+2 ) % quad->side.size() ];
+ StdMeshers_FaceSidePtr oppSide = quad->side[( i+2 ) % quad->side.size() ];
if ( degSide->NbSegments() == oppSide->NbSegments() )
continue;
@@ -3286,11 +3699,10 @@ void StdMeshers_Quadrangle_2D::updateDegenUV(FaceQuadStruct::Ptr quad)
const SMDS_MeshNode* n = uvVecDegOld[0].node;
Handle(Geom2d_Curve) c2d = degSide->Curve2d(0);
double f = degSide->FirstU(0), l = degSide->LastU(0);
- gp_Pnt2d p1( uvVecDegOld.front().u, uvVecDegOld.front().v );
- gp_Pnt2d p2( uvVecDegOld.back().u, uvVecDegOld.back().v );
+ gp_Pnt2d p1 = uvVecDegOld.front().UV();
+ gp_Pnt2d p2 = uvVecDegOld.back().UV();
- delete degSide;
- quad->side[i] = new StdMeshers_FaceSide( oppSide, n, &p1, &p2, c2d, f, l );
+ quad->side[i] = StdMeshers_FaceSide::New( oppSide.get(), n, &p1, &p2, c2d, f, l );
}
}
@@ -3344,11 +3756,11 @@ void StdMeshers_Quadrangle_2D::smooth (FaceQuadStruct::Ptr quad)
// set _uv of smooth nodes on FACE boundary
for ( unsigned i = 0; i < quad->side.size(); ++i )
{
- const vector& uvVec = quad->side[i]->GetUVPtStruct();
+ const vector& uvVec = quad->side[i].GetUVPtStruct();
for ( unsigned j = 0; j < uvVec.size(); ++j )
{
TSmoothNode & sNode = smooNoMap[ uvVec[j].node ];
- sNode._uv.SetCoord( uvVec[j].u, uvVec[j].v );
+ sNode._uv = uvVec[j].UV();
sNode._xyz = SMESH_TNodeXYZ( uvVec[j].node );
}
}
@@ -3704,3 +4116,1004 @@ int StdMeshers_Quadrangle_2D::getCorners(const TopoDS_Face& theFace,
return nbCorners;
}
+
+//================================================================================
+/*!
+ * \brief Constructor of a side of quad
+ */
+//================================================================================
+
+FaceQuadStruct::Side::Side(StdMeshers_FaceSidePtr theGrid)
+ : grid(theGrid), nbNodeOut(0), from(0), to(theGrid ? theGrid->NbPoints() : 0 )
+{
+}
+
+//=============================================================================
+/*!
+ * \brief Constructor of a quad
+ */
+//=============================================================================
+
+FaceQuadStruct::FaceQuadStruct(const TopoDS_Face& F) : face( F )
+{
+ side.reserve(4);
+}
+
+//================================================================================
+/*!
+ * \brief Fills myForcedPnts
+ */
+//================================================================================
+
+bool StdMeshers_Quadrangle_2D::getEnforcedUV()
+{
+ myForcedPnts.clear();
+ if ( !myParams ) return true; // missing hypothesis
+
+ std::vector< TopoDS_Shape > shapes;
+ std::vector< gp_Pnt > points;
+ myParams->GetEnforcedNodes( shapes, points );
+
+ TopTools_IndexedMapOfShape vMap;
+ for ( size_t i = 0; i < shapes.size(); ++i )
+ if ( !shapes[i].IsNull() )
+ TopExp::MapShapes( shapes[i], TopAbs_VERTEX, vMap );
+
+ size_t nbPoints = points.size();
+ for ( int i = 1; i <= vMap.Extent(); ++i )
+ points.push_back( BRep_Tool::Pnt( TopoDS::Vertex( vMap( i ))));
+
+ // find out if all points must be in the FACE, which is so if
+ // myParams is a local hypothesis on the FACE being meshed
+ bool isStrictCheck = false;
+ {
+ SMESH_HypoFilter paramFilter( SMESH_HypoFilter::Is( myParams ));
+ TopoDS_Shape assignedTo;
+ if ( myHelper->GetMesh()->GetHypothesis( myHelper->GetSubShape(),
+ paramFilter,
+ /*ancestors=*/true,
+ &assignedTo ))
+ isStrictCheck = ( assignedTo.IsSame( myHelper->GetSubShape() ));
+ }
+
+ multimap< double, ForcedPoint > sortedFP; // sort points by distance from EDGEs
+
+ Standard_Real u1,u2,v1,v2;
+ const TopoDS_Face& face = TopoDS::Face( myHelper->GetSubShape() );
+ const double tol = BRep_Tool::Tolerance( face );
+ Handle(Geom_Surface) surf = BRep_Tool::Surface( face );
+ surf->Bounds( u1,u2,v1,v2 );
+ GeomAPI_ProjectPointOnSurf project;
+ project.Init(surf, u1,u2, v1,v2, tol );
+
+ for ( size_t iP = 0; iP < points.size(); ++iP )
+ {
+ project.Perform( points[ iP ]);
+ if ( !project.IsDone() )
+ {
+ if ( isStrictCheck && iP < nbPoints )
+ return error
+ (TComm("Projection of an enforced point to the face failed - (")
+ << points[ iP ].X() << ", "<< points[ iP ].Y() << ", "<< points[ iP ].Z() << " )");
+ continue;
+ }
+ if ( project.LowerDistance() > tol*1000 )
+ {
+ if ( isStrictCheck && iP < nbPoints )
+ return error
+ (COMPERR_BAD_PARMETERS, TComm("An enforced point is too far from the face, dist = ")
+ << project.LowerDistance() << " - ("
+ << points[ iP ].X() << ", "<< points[ iP ].Y() << ", "<< points[ iP ].Z() << " )");
+ continue;
+ }
+ Quantity_Parameter u, v;
+ project.LowerDistanceParameters(u, v);
+ gp_Pnt2d uv( u, v );
+ BRepClass_FaceClassifier clsf ( face, uv, tol );
+ switch ( clsf.State() ) {
+ case TopAbs_IN:
+ {
+ double edgeDist = ( Min( Abs( u - u1 ), Abs( u - u2 )) +
+ Min( Abs( v - v1 ), Abs( v - v2 )));
+ ForcedPoint fp;
+ fp.uv = uv.XY();
+ fp.xyz = points[ iP ].XYZ();
+ if ( iP >= nbPoints )
+ fp.vertex = TopoDS::Vertex( vMap( iP - nbPoints + 1 ));
+
+ sortedFP.insert( make_pair( edgeDist, fp ));
+ break;
+ }
+ case TopAbs_OUT:
+ {
+ if ( isStrictCheck && iP < nbPoints )
+ return error
+ (COMPERR_BAD_PARMETERS, TComm("An enforced point is out of the face boundary - ")
+ << points[ iP ].X() << ", "<< points[ iP ].Y() << ", "<< points[ iP ].Z() << " )");
+ break;
+ }
+ case TopAbs_ON:
+ {
+ if ( isStrictCheck && iP < nbPoints )
+ return error
+ (COMPERR_BAD_PARMETERS, TComm("An enforced point is on the face boundary - ")
+ << points[ iP ].X() << ", "<< points[ iP ].Y() << ", "<< points[ iP ].Z() << " )");
+ break;
+ }
+ default:
+ {
+ if ( isStrictCheck && iP < nbPoints )
+ return error
+ (TComm("Classification of an enforced point ralative to the face boundary failed - ")
+ << points[ iP ].X() << ", "<< points[ iP ].Y() << ", "<< points[ iP ].Z() << " )");
+ }
+ }
+ }
+
+ multimap< double, ForcedPoint >::iterator d2uv = sortedFP.begin();
+ for ( ; d2uv != sortedFP.end(); ++d2uv )
+ myForcedPnts.push_back( (*d2uv).second );
+
+ return true;
+}
+
+//================================================================================
+/*!
+ * \brief Splits quads by adding points of enforced nodes and create nodes on
+ * the sides shared by quads
+ */
+//================================================================================
+
+bool StdMeshers_Quadrangle_2D::addEnforcedNodes()
+{
+ // if ( myForcedPnts.empty() )
+ // return true;
+
+ // make a map of quads sharing a side
+ map< StdMeshers_FaceSidePtr, vector< FaceQuadStruct::Ptr > > quadsBySide;
+ list< FaceQuadStruct::Ptr >::iterator quadIt = myQuadList.begin();
+ for ( ; quadIt != myQuadList.end(); ++quadIt )
+ for ( size_t iSide = 0; iSide < (*quadIt)->side.size(); ++iSide )
+ quadsBySide[ (*quadIt)->side[iSide] ].push_back( *quadIt );
+
+ SMESH_Mesh* mesh = myHelper->GetMesh();
+ SMESHDS_Mesh* meshDS = myHelper->GetMeshDS();
+ const TopoDS_Face& face = TopoDS::Face( myHelper->GetSubShape() );
+ Handle(Geom_Surface) surf = BRep_Tool::Surface( face );
+
+ for ( size_t iFP = 0; iFP < myForcedPnts.size(); ++iFP )
+ {
+ bool isNodeEnforced = false;
+
+ // look for a quad enclosing a enforced point
+ for ( quadIt = myQuadList.begin(); quadIt != myQuadList.end(); ++quadIt )
+ {
+ FaceQuadStruct::Ptr quad = *quadIt;
+ int i,j;
+ if ( !setNormalizedGrid( quad ))
+ return false;
+ if ( !quad->findCell( myForcedPnts[ iFP ], i, j ))
+ continue;
+
+ // a grid cell is found, select a node of the cell to move
+ // to the enforced point to and to split the quad at
+ multimap< double, pair< int, int > > ijByDist;
+ for ( int di = 0; di < 2; ++di )
+ for ( int dj = 0; dj < 2; ++dj )
+ {
+ double dist2 = ( myForcedPnts[ iFP ].uv - quad->UVPt( i+di,j+dj ).UV() ).SquareModulus();
+ ijByDist.insert( make_pair( dist2, make_pair( i+di,j+dj )));
+ }
+ // try all nodes starting from the closest one
+ set< FaceQuadStruct::Ptr > changedQuads;
+ multimap< double, pair< int, int > >::iterator d2ij = ijByDist.begin();
+ for ( ; !isNodeEnforced && d2ij != ijByDist.end(); ++d2ij )
+ {
+ i = d2ij->second.first;
+ j = d2ij->second.second;
+
+ // check if a node is at a side
+ int iSide = -1;
+ if ( j == 0 )
+ iSide = QUAD_BOTTOM_SIDE;
+ else if ( j+1 == quad->jSize )
+ iSide = QUAD_TOP_SIDE;
+ else if ( i == 0 )
+ iSide = QUAD_LEFT_SIDE;
+ else if ( i+1 == quad->iSize )
+ iSide = QUAD_RIGHT_SIDE;
+
+ if ( iSide > -1 ) // ----- node is at a side
+ {
+ FaceQuadStruct::Side& side = quad->side[ iSide ];
+ // check if this node can be moved
+ if ( quadsBySide[ side ].size() < 2 )
+ continue; // its a face boundary -> can't move the node
+
+ int quadNodeIndex = ( iSide % 2 ) ? j : i;
+ int sideNodeIndex = side.ToSideIndex( quadNodeIndex );
+ if ( side.IsForced( sideNodeIndex ))
+ {
+ // the node is already moved to another enforced point
+ isNodeEnforced = quad->isEqual( myForcedPnts[ iFP ], i, j );
+ continue;
+ }
+ // make a node of a side forced
+ vector& points = (vector&) side.GetUVPtStruct();
+ points[ sideNodeIndex ].u = myForcedPnts[ iFP ].U();
+ points[ sideNodeIndex ].v = myForcedPnts[ iFP ].V();
+
+ updateSideUV( side, sideNodeIndex, quadsBySide );
+
+ // update adjacent sides
+ set< StdMeshers_FaceSidePtr > updatedSides;
+ updatedSides.insert( side );
+ for ( size_t i = 0; i < side.contacts.size(); ++i )
+ if ( side.contacts[i].point == sideNodeIndex )
+ {
+ const vector< FaceQuadStruct::Ptr >& adjQuads =
+ quadsBySide[ *side.contacts[i].other_side ];
+ if ( adjQuads.size() > 1 &&
+ updatedSides.insert( * side.contacts[i].other_side ).second )
+ {
+ updateSideUV( *side.contacts[i].other_side,
+ side.contacts[i].other_point,
+ quadsBySide );
+ }
+ changedQuads.insert( adjQuads.begin(), adjQuads.end() );
+ }
+ const vector< FaceQuadStruct::Ptr >& adjQuads = quadsBySide[ side ];
+ changedQuads.insert( adjQuads.begin(), adjQuads.end() );
+
+ isNodeEnforced = true;
+ }
+ else // ------------------ node is inside the quad
+ {
+ // make a new side passing through IJ node and split the quad
+ int indForced, iNewSide;
+ if ( quad->iSize < quad->jSize ) // split vertically
+ {
+ quad->updateUV( myForcedPnts[ iFP ].uv, i, j, /*isVert=*/true );
+ indForced = i;
+ iNewSide = splitQuad( quad, i, 0 );
+ }
+ else
+ {
+ quad->updateUV( myForcedPnts[ iFP ].uv, i, j, /*isVert=*/false );
+ indForced = j;
+ iNewSide = splitQuad( quad, 0, j );
+ }
+ FaceQuadStruct::Ptr newQuad = myQuadList.back();
+ FaceQuadStruct::Side& newSide = newQuad->side[ iNewSide ];
+
+ newSide.forced_nodes.insert( indForced );
+ quad->side[( iNewSide+2 ) % 4 ].forced_nodes.insert( indForced );
+
+ quadsBySide[ newSide ].push_back( quad );
+ quadsBySide[ newSide ].push_back( newQuad );
+
+ isNodeEnforced = true;
+
+ } // end of "node is inside the quad"
+
+ } // loop on nodes of the cell
+
+ // remove out-of-date uv grid of changedQuads
+ set< FaceQuadStruct::Ptr >::iterator qIt = changedQuads.begin();
+ for ( ; qIt != changedQuads.end(); ++qIt )
+ (*qIt)->uv_grid.clear();
+
+ } // loop on quads
+
+ if ( !isNodeEnforced )
+ {
+ if ( !myForcedPnts[ iFP ].vertex.IsNull() )
+ return error(TComm("Unable to move any node to vertex #")
+ <GetMeshDS()->ShapeToIndex( myForcedPnts[ iFP ].vertex ));
+ else
+ return error(TComm("Unable to move any node to point ( ")
+ << myForcedPnts[iFP].xyz.X() << ", "
+ << myForcedPnts[iFP].xyz.Y() << ", "
+ << myForcedPnts[iFP].xyz.Z() << " )");
+ }
+
+ } // loop on enforced points
+
+ // Compute nodes on all sides, where not yet present
+
+ for ( quadIt = myQuadList.begin(); quadIt != myQuadList.end(); ++quadIt )
+ {
+ FaceQuadStruct::Ptr quad = *quadIt;
+ for ( int iSide = 0; iSide < 4; ++iSide )
+ {
+ FaceQuadStruct::Side & side = quad->side[ iSide ];
+ if ( side.nbNodeOut > 0 )
+ continue; // emulated side
+ vector< FaceQuadStruct::Ptr >& quadVec = quadsBySide[ side ];
+ if ( quadVec.size() <= 1 )
+ continue; // outer side
+
+ bool missedNodesOnSide = false;
+ const vector& points = side.grid->GetUVPtStruct();
+ for ( size_t iC = 0; iC < side.contacts.size(); ++iC )
+ {
+ const vector& oGrid = side.contacts[iC].other_side->grid->GetUVPtStruct();
+ const UVPtStruct& uvPt = points[ side.contacts[iC].point ];
+ if ( side.contacts[iC].other_point >= oGrid.size() ||
+ side.contacts[iC].point >= points.size() )
+ throw SALOME_Exception( "StdMeshers_Quadrangle_2D::addEnforcedNodes(): wrong contact" );
+ if ( oGrid[ side.contacts[iC].other_point ].node )
+ (( UVPtStruct& ) uvPt).node = oGrid[ side.contacts[iC].other_point ].node;
+ }
+ for ( size_t iP = 0; iP < points.size(); ++iP )
+ if ( !points[ iP ].node )
+ {
+ UVPtStruct& uvPnt = ( UVPtStruct& ) points[ iP ];
+ gp_Pnt P = surf->Value( uvPnt.u, uvPnt.v );
+ uvPnt.node = meshDS->AddNode(P.X(), P.Y(), P.Z());
+ meshDS->SetNodeOnFace( uvPnt.node, myHelper->GetSubShapeID(), uvPnt.u, uvPnt.v );
+ missedNodesOnSide = true;
+ }
+ if ( missedNodesOnSide )
+ {
+ // clear uv_grid where nodes are missing
+ for ( size_t iQ = 0; iQ < quadVec.size(); ++iQ )
+ quadVec[ iQ ]->uv_grid.clear();
+ }
+ }
+ }
+
+ return true;
+}
+
+//================================================================================
+/*!
+ * \brief Splits a quad at I or J. Returns an index of a new side in the new quad
+ */
+//================================================================================
+
+int StdMeshers_Quadrangle_2D::splitQuad(FaceQuadStruct::Ptr quad, int I, int J)
+{
+ FaceQuadStruct* newQuad = new FaceQuadStruct( quad->face );
+ myQuadList.push_back( FaceQuadStruct::Ptr( newQuad ));
+
+ vector points;
+ if ( I > 0 )
+ {
+ points.reserve( quad->jSize );
+ for ( int jP = 0; jP < quad->jSize; ++jP )
+ points.push_back( quad->UVPt( I, jP ));
+
+ newQuad->side.resize( 4 );
+ newQuad->side[ QUAD_BOTTOM_SIDE ] = quad->side[ QUAD_BOTTOM_SIDE ];
+ newQuad->side[ QUAD_RIGHT_SIDE ] = quad->side[ QUAD_RIGHT_SIDE ];
+ newQuad->side[ QUAD_TOP_SIDE ] = quad->side[ QUAD_TOP_SIDE ];
+ newQuad->side[ QUAD_LEFT_SIDE ] = StdMeshers_FaceSide::New( points, quad->face );
+
+ FaceQuadStruct::Side& newSide = newQuad->side[ QUAD_LEFT_SIDE ];
+ FaceQuadStruct::Side& newSide2 = quad->side [ QUAD_RIGHT_SIDE ];
+
+ quad->side[ QUAD_RIGHT_SIDE ] = newSide;
+
+ int iBot = quad->side[ QUAD_BOTTOM_SIDE ].ToSideIndex( I );
+ int iTop = quad->side[ QUAD_TOP_SIDE ].ToSideIndex( I );
+
+ newSide.AddContact ( 0, & quad->side[ QUAD_BOTTOM_SIDE ], iBot );
+ newSide2.AddContact( 0, & quad->side[ QUAD_BOTTOM_SIDE ], iBot );
+ newSide.AddContact ( quad->jSize - 1, & quad->side[ QUAD_TOP_SIDE ], iTop );
+ newSide2.AddContact( quad->jSize - 1, & quad->side[ QUAD_TOP_SIDE ], iTop );
+ // cout << "Contact: L " << &newSide << " "<< newSide.NbPoints()
+ // << " R " << &newSide2 << " "<< newSide2.NbPoints()
+ // << " B " << &quad->side[ QUAD_BOTTOM_SIDE ] << " "<< quad->side[ QUAD_BOTTOM_SIDE].NbPoints()
+ // << " T " << &quad->side[ QUAD_TOP_SIDE ] << " "<< quad->side[ QUAD_TOP_SIDE].NbPoints()<< endl;
+
+ newQuad->side[ QUAD_BOTTOM_SIDE ].from = iBot;
+ newQuad->side[ QUAD_TOP_SIDE ].from = iTop;
+
+ quad->side[ QUAD_BOTTOM_SIDE ].to = iBot + 1;
+ quad->side[ QUAD_TOP_SIDE ].to = iTop + 1;
+ quad->uv_grid.clear();
+
+ return QUAD_LEFT_SIDE;
+ }
+ else if ( J > 0 ) //// split horizontally
+ {
+ points.reserve( quad->iSize );
+ for ( int iP = 0; iP < quad->iSize; ++iP )
+ points.push_back( quad->UVPt( iP, J ));
+
+ newQuad->side.resize( 4 );
+ newQuad->side[ QUAD_BOTTOM_SIDE ] = quad->side[ QUAD_BOTTOM_SIDE ];
+ newQuad->side[ QUAD_RIGHT_SIDE ] = quad->side[ QUAD_RIGHT_SIDE ];
+ newQuad->side[ QUAD_TOP_SIDE ] = StdMeshers_FaceSide::New( points, quad->face );
+ newQuad->side[ QUAD_LEFT_SIDE ] = quad->side[ QUAD_LEFT_SIDE ];
+
+ FaceQuadStruct::Side& newSide = newQuad->side[ QUAD_TOP_SIDE ];
+ FaceQuadStruct::Side& newSide2 = quad->side [ QUAD_BOTTOM_SIDE ];
+
+ quad->side[ QUAD_BOTTOM_SIDE ] = newSide;
+
+ int iLft = quad->side[ QUAD_LEFT_SIDE ].ToSideIndex( J );
+ int iRgt = quad->side[ QUAD_RIGHT_SIDE ].ToSideIndex( J );
+
+ newSide.AddContact ( 0, & quad->side[ QUAD_LEFT_SIDE ], iLft );
+ newSide2.AddContact( 0, & quad->side[ QUAD_LEFT_SIDE ], iLft );
+ newSide.AddContact ( quad->iSize - 1, & quad->side[ QUAD_RIGHT_SIDE ], iRgt );
+ newSide2.AddContact( quad->iSize - 1, & quad->side[ QUAD_RIGHT_SIDE ], iRgt );
+ // cout << "Contact: T " << &newSide << " "<< newSide.NbPoints()
+ // << " B " << &newSide2 << " "<< newSide2.NbPoints()
+ // << " L " << &quad->side[ QUAD_LEFT_SIDE ] << " "<< quad->side[ QUAD_LEFT_SIDE].NbPoints()
+ // << " R " << &quad->side[ QUAD_RIGHT_SIDE ] << " "<< quad->side[ QUAD_RIGHT_SIDE].NbPoints()<< endl;
+
+ newQuad->side[ QUAD_RIGHT_SIDE ].to = iRgt+1;
+ newQuad->side[ QUAD_LEFT_SIDE ].to = iLft+1;
+
+ quad->side[ QUAD_RIGHT_SIDE ].from = iRgt;
+ quad->side[ QUAD_LEFT_SIDE ].from = iLft;
+ quad->uv_grid.clear();
+
+ return QUAD_TOP_SIDE;
+ }
+}
+
+//================================================================================
+/*!
+ * \brief Updates UV of a side after moving its node
+ */
+//================================================================================
+
+void StdMeshers_Quadrangle_2D::updateSideUV( FaceQuadStruct::Side& side,
+ int iForced,
+ const TQuadsBySide& quadsBySide,
+ int * iNext)
+{
+ if ( !iNext )
+ {
+ side.forced_nodes.insert( iForced );
+
+ // update parts of the side before and after iForced
+
+ set::iterator iIt = side.forced_nodes.upper_bound( iForced );
+ int iEnd = Min( side.NbPoints()-1, ( iIt == side.forced_nodes.end() ) ? int(1e7) : *iIt );
+ if ( iForced + 1 < iEnd )
+ updateSideUV( side, iForced, quadsBySide, &iEnd );
+
+ iIt = side.forced_nodes.lower_bound( iForced );
+ int iBeg = Max( 0, ( iIt == side.forced_nodes.begin() ) ? 0 : *--iIt );
+ if ( iForced - 1 > iBeg )
+ updateSideUV( side, iForced, quadsBySide, &iBeg );
+
+ return;
+ }
+
+ const int iFrom = Min ( iForced, *iNext );
+ const int iTo = Max ( iForced, *iNext ) + 1;
+ const int sideSize = iTo - iFrom;
+
+ vector points[4];
+
+ // get from the quads grid points adjacent to the side
+ // to make two sides of another temporary quad
+ vector< FaceQuadStruct::Ptr > quads = quadsBySide.find( side )->second; // copy!
+ for ( int is2nd = 0; is2nd < 2; ++is2nd )
+ {
+ points[ is2nd ].reserve( sideSize );
+ int nbLoops = 0;
+ while ( points[is2nd].size() < sideSize )
+ {
+ int iCur = iFrom + points[is2nd].size() - int( !points[is2nd].empty() );
+
+ // look for a quad adjacent to iCur-th point of the side
+ for ( size_t iQ = 0; iQ < quads.size(); ++iQ )
+ {
+ FaceQuadStruct::Ptr q = quads[ iQ ];
+ if ( !q ) continue;
+ size_t iS;
+ for ( iS = 0; iS < q->side.size(); ++iS )
+ if ( side.grid == q->side[ iS ].grid )
+ break;
+ bool isOut;
+ if ( !q->side[ iS ].IsReversed() )
+ isOut = ( q->side[ iS ].from > iCur || q->side[ iS ].to-1 <= iCur );
+ else
+ isOut = ( q->side[ iS ].to >= iCur || q->side[ iS ].from <= iCur );
+ if ( isOut )
+ continue;
+
+ // found - copy points
+ int i,j,di,dj,nb;
+ if ( iS % 2 ) // right ot left
+ {
+ i = ( iS == QUAD_LEFT_SIDE ) ? 1 : q->iSize-2;
+ j = q->side[ iS ].ToQuadIndex( iCur );
+ di = 0;
+ dj = ( q->side[ iS ].IsReversed() ) ? -1 : +1;
+ nb = ( q->side[ iS ].IsReversed() ) ? j+1 : q->jSize-j;
+ }
+ else // bottom or top
+ {
+ i = q->side[ iS ].ToQuadIndex( iCur );
+ j = ( iS == QUAD_BOTTOM_SIDE ) ? 1 : q->jSize-2;
+ di = ( q->side[ iS ].IsReversed() ) ? -1 : +1;
+ dj = 0;
+ nb = ( q->side[ iS ].IsReversed() ) ? i+1 : q->iSize-i;
+ }
+ if ( !points[is2nd].empty() )
+ {
+ gp_UV lastUV = points[is2nd].back().UV();
+ gp_UV quadUV = q->UVPt( i, j ).UV();
+ if ( ( lastUV - quadUV ).SquareModulus() > 1e-10 )
+ continue; // quad is on the other side of the side
+ i += di; j += dj; --nb;
+ }
+ for ( ; nb > 0 ; --nb )
+ {
+ points[ is2nd ].push_back( q->UVPt( i, j ));
+ if ( points[is2nd].size() >= sideSize )
+ break;
+ i += di; j += dj;
+ }
+ quads[ iQ ].reset(); // not to use this quad anymore
+
+ if ( points[is2nd].size() >= sideSize )
+ break;
+ } // loop on quads
+
+ if ( nbLoops++ > quads.size() )
+ throw SALOME_Exception( "StdMeshers_Quadrangle_2D::updateSideUV() bug: infinite loop" );
+
+ } // while ( points[is2nd].size() < sideSize )
+ } // two loops to fill points[0] and points[1]
+
+ // points for other pair of opposite sides of the temporary quad
+
+ enum { L,R,B,T }; // side index of points[]
+
+ points[B].push_back( points[L].front() );
+ points[B].push_back( side.GetUVPtStruct()[ iFrom ]);
+ points[B].push_back( points[R].front() );
+
+ points[T].push_back( points[L].back() );
+ points[T].push_back( side.GetUVPtStruct()[ iTo-1 ]);
+ points[T].push_back( points[R].back() );
+
+ // make the temporary quad
+ FaceQuadStruct::Ptr tmpQuad( new FaceQuadStruct( TopoDS::Face( myHelper->GetSubShape() )));
+ tmpQuad->side.push_back( StdMeshers_FaceSide::New( points[B] )); // bottom
+ tmpQuad->side.push_back( StdMeshers_FaceSide::New( points[R] )); // right
+ tmpQuad->side.push_back( StdMeshers_FaceSide::New( points[T] ));
+ tmpQuad->side.push_back( StdMeshers_FaceSide::New( points[L] ));
+
+ // compute new UV of the side
+ setNormalizedGrid( tmpQuad );
+ gp_UV uv = tmpQuad->UVPt(1,0).UV();
+ tmpQuad->updateUV( uv, 1,0, /*isVertical=*/true );
+
+ // update UV of the side
+ vector& sidePoints = (vector&) side.GetUVPtStruct();
+ for ( int i = iFrom; i < iTo; ++i )
+ sidePoints[ i ] = tmpQuad->UVPt( 1, i-iFrom );
+}
+
+//================================================================================
+/*!
+ * \brief Finds indices of a grid quad enclosing the given enforced UV
+ */
+//================================================================================
+
+bool FaceQuadStruct::findCell( const gp_XY& UV, int & I, int & J )
+{
+ // setNormalizedGrid() must be called before!
+ if ( uv_box.IsOut( UV ))
+ return false;
+
+ // find an approximate position
+ double x = 0.5, y = 0.5;
+ gp_XY t0 = UVPt( iSize - 1, 0 ).UV();
+ gp_XY t1 = UVPt( 0, jSize - 1 ).UV();
+ gp_XY t2 = UVPt( 0, 0 ).UV();
+ SMESH_MeshAlgos::GetBarycentricCoords( UV, t0, t1, t2, x, y );
+ x = Min( 1., Max( 0., x ));
+ y = Min( 1., Max( 0., y ));
+
+ // precise the position
+ //int i, j;
+ normPa2IJ( x,y, I,J );
+ if ( !isNear( UV, I,J ))
+ {
+ // look for the most close IJ by traversing uv_grid in the middle
+ double dist2, minDist2 = ( UV - UVPt( I,J ).UV() ).SquareModulus();
+ for ( int isU = 0; isU < 2; ++isU )
+ {
+ int ind1 = isU ? 0 : iSize / 2;
+ int ind2 = isU ? jSize / 2 : 0;
+ int di1 = isU ? Max( 2, iSize / 20 ) : 0;
+ int di2 = isU ? 0 : Max( 2, jSize / 20 );
+ int i,nb = isU ? iSize / di1 : jSize / di2;
+ for ( i = 0; i < nb; ++i, ind1 += di1, ind2 += di2 )
+ if (( dist2 = ( UV - UVPt( ind1,ind2 ).UV() ).SquareModulus() ) < minDist2 )
+ {
+ I = ind1;
+ J = ind2;
+ if ( isNear( UV, I,J ))
+ return true;
+ minDist2 = ( UV - UVPt( I,J ).UV() ).SquareModulus();
+ }
+ }
+ if ( !isNear( UV, I,J, Max( iSize, jSize ) /2 ))
+ return false;
+ }
+ return true;
+}
+
+//================================================================================
+/*!
+ * \brief Find indices (i,j) of a point in uv_grid by normalized parameters (x,y)
+ */
+//================================================================================
+
+void FaceQuadStruct::normPa2IJ(double X, double Y, int & I, int & J )
+{
+
+ I = Min( int ( iSize * X ), iSize - 2 );
+ J = Min( int ( jSize * Y ), jSize - 2 );
+
+ int oldI, oldJ;
+ do
+ {
+ oldI = I, oldJ = J;
+ while ( X <= UVPt( I,J ).x && I != 0 )
+ --I;
+ while ( X > UVPt( I+1,J ).x && I+1 < iSize )
+ ++I;
+ while ( Y <= UVPt( I,J ).y && J != 0 )
+ --J;
+ while ( Y > UVPt( I,J+1 ).y && J+1 < jSize )
+ ++J;
+ } while ( oldI != I || oldJ != J );
+}
+
+//================================================================================
+/*!
+ * \brief Looks for UV in quads around a given (I,J) and precise (I,J)
+ */
+//================================================================================
+
+bool FaceQuadStruct::isNear( const gp_XY& UV, int & I, int & J, int nbLoops )
+{
+ if ( I+1 >= iSize ) I = iSize - 2;
+ if ( J+1 >= jSize ) J = jSize - 2;
+
+ double bcI, bcJ;
+ gp_XY uvI, uvJ, uv0, uv1;
+ for ( int iLoop = 0; iLoop < nbLoops; ++iLoop )
+ {
+ int oldI = I, oldJ = J;
+
+ uvI = UVPt( I+1, J ).UV();
+ uvJ = UVPt( I, J+1 ).UV();
+ uv0 = UVPt( I, J ).UV();
+ SMESH_MeshAlgos::GetBarycentricCoords( UV, uvI, uvJ, uv0, bcI, bcJ );
+ if ( bcI >= 0. && bcJ >= 0. && bcI + bcJ <= 1.)
+ return true;
+
+ if ( I > 0 && bcI < 0. ) --I;
+ if ( I+1 < iSize && bcI > 1. ) ++I;
+ if ( J > 0 && bcJ < 0. ) --J;
+ if ( J+1 < jSize && bcJ > 1. ) ++J;
+
+ uv1 = UVPt( I+1,J+1).UV();
+ if ( I != oldI || J != oldJ )
+ {
+ uvI = UVPt( I+1, J ).UV();
+ uvJ = UVPt( I, J+1 ).UV();
+ }
+ SMESH_MeshAlgos::GetBarycentricCoords( UV, uvI, uvJ, uv1, bcI, bcJ );
+ if ( bcI >= 0. && bcJ >= 0. && bcI + bcJ <= 1.)
+ return true;
+
+ if ( I > 0 && bcI > 1. ) --I;
+ if ( I+1 < iSize && bcI < 0. ) ++I;
+ if ( J > 0 && bcJ > 1. ) --J;
+ if ( J+1 < jSize && bcJ < 0. ) ++J;
+
+ if ( I == oldI && J == oldJ )
+ return false;
+
+ if ( iLoop+1 == nbLoops )
+ {
+ uvI = UVPt( I+1, J ).UV();
+ uvJ = UVPt( I, J+1 ).UV();
+ uv0 = UVPt( I, J ).UV();
+ SMESH_MeshAlgos::GetBarycentricCoords( UV, uvI, uvJ, uv0, bcI, bcJ );
+ if ( bcI >= 0. && bcJ >= 0. && bcI + bcJ <= 1.)
+ return true;
+
+ uv1 = UVPt( I+1,J+1).UV();
+ SMESH_MeshAlgos::GetBarycentricCoords( UV, uvI, uvJ, uv1, bcI, bcJ );
+ if ( bcI >= 0. && bcJ >= 0. && bcI + bcJ <= 1.)
+ return true;
+ }
+ }
+ return false;
+}
+
+//================================================================================
+/*!
+ * \brief Checks if a given UV is equal to a given frid point
+ */
+//================================================================================
+
+bool FaceQuadStruct::isEqual( const gp_XY& UV, int I, int J )
+{
+ TopLoc_Location loc;
+ Handle(Geom_Surface) surf = BRep_Tool::Surface( face, loc );
+ gp_Pnt p1 = surf->Value( UV.X(), UV.Y() );
+ gp_Pnt p2 = surf->Value( UVPt( I,J ).u, UVPt( I,J ).v );
+
+ double dist2 = 1e100;
+ for ( int di = -1; di < 2; di += 2 )
+ {
+ int i = I + di;
+ if ( i < 0 || i+1 >= iSize ) continue;
+ for ( int dj = -1; dj < 2; dj += 2 )
+ {
+ int j = J + dj;
+ if ( j < 0 || j+1 >= jSize ) continue;
+
+ dist2 = Min( dist2,
+ p2.SquareDistance( surf->Value( UVPt( i,j ).u, UVPt( i,j ).v )));
+ }
+ }
+ double tol2 = dist2 / 1000.;
+ return p1.SquareDistance( p2 ) < tol2;
+}
+
+//================================================================================
+/*!
+ * \brief Recompute UV of grid points around a moved point in one direction
+ */
+//================================================================================
+
+void FaceQuadStruct::updateUV( const gp_XY& UV, int I, int J, bool isVertical )
+{
+ UVPt( I, J ).u = UV.X();
+ UVPt( I, J ).v = UV.Y();
+
+ if ( isVertical )
+ {
+ // above J
+ if ( J+1 < jSize-1 )
+ {
+ gp_UV a0 = UVPt( 0, J ).UV();
+ gp_UV a1 = UVPt( iSize-1, J ).UV();
+ gp_UV a2 = UVPt( iSize-1, jSize-1 ).UV();
+ gp_UV a3 = UVPt( 0, jSize-1 ).UV();
+
+ gp_UV p0 = UVPt( I, J ).UV();
+ gp_UV p2 = UVPt( I, jSize-1 ).UV();
+ const double y0 = UVPt( I, J ).y, dy = 1. - y0;
+ for (int j = J+1; j < jSize-1; j++)
+ {
+ gp_UV p1 = UVPt( iSize-1, j ).UV();
+ gp_UV p3 = UVPt( 0, j ).UV();
+
+ UVPtStruct& uvPt = UVPt( I, j );
+ gp_UV uv = calcUV( uvPt.x, ( uvPt.y - y0 ) / dy, a0,a1,a2,a3, p0,p1,p2,p3);
+ uvPt.u = uv.X();
+ uvPt.v = uv.Y();
+ }
+ }
+ // under J
+ if ( J-1 > 0 )
+ {
+ gp_UV a0 = UVPt( 0, 0 ).UV();
+ gp_UV a1 = UVPt( iSize-1, 0 ).UV();
+ gp_UV a2 = UVPt( iSize-1, J ).UV();
+ gp_UV a3 = UVPt( 0, J ).UV();
+
+ gp_UV p0 = UVPt( I, 0 ).UV();
+ gp_UV p2 = UVPt( I, J ).UV();
+ const double y0 = 0., dy = UVPt( I, J ).y - y0;
+ for (int j = 1; j < J; j++)
+ {
+ gp_UV p1 = UVPt( iSize-1, j ).UV();
+ gp_UV p3 = UVPt( 0, j ).UV();
+
+ UVPtStruct& uvPt = UVPt( I, j );
+ gp_UV uv = calcUV( uvPt.x, ( uvPt.y - y0 ) / dy, a0,a1,a2,a3, p0,p1,p2,p3);
+ uvPt.u = uv.X();
+ uvPt.v = uv.Y();
+ }
+ }
+ }
+ else // horizontally
+ {
+ // before I
+ if ( I-1 > 0 )
+ {
+ gp_UV a0 = UVPt( 0, 0 ).UV();
+ gp_UV a1 = UVPt( I, 0 ).UV();
+ gp_UV a2 = UVPt( I, jSize-1 ).UV();
+ gp_UV a3 = UVPt( 0, jSize-1 ).UV();
+
+ gp_UV p1 = UVPt( I, J ).UV();
+ gp_UV p3 = UVPt( 0, J ).UV();
+ const double x0 = 0., dx = UVPt( I, J ).x - x0;
+ for (int i = 1; i < I; i++)
+ {
+ gp_UV p0 = UVPt( i, 0 ).UV();
+ gp_UV p2 = UVPt( i, jSize-1 ).UV();
+
+ UVPtStruct& uvPt = UVPt( i, J );
+ gp_UV uv = calcUV(( uvPt.x - x0 ) / dx , uvPt.y, a0,a1,a2,a3, p0,p1,p2,p3);
+ uvPt.u = uv.X();
+ uvPt.v = uv.Y();
+ }
+ }
+ // after I
+ if ( I+1 < iSize-1 )
+ {
+ gp_UV a0 = UVPt( I, 0 ).UV();
+ gp_UV a1 = UVPt( iSize-1, 0 ).UV();
+ gp_UV a2 = UVPt( iSize-1, jSize-1 ).UV();
+ gp_UV a3 = UVPt( I, jSize-1 ).UV();
+
+ gp_UV p1 = UVPt( iSize-1, J ).UV();
+ gp_UV p3 = UVPt( I, J ).UV();
+ const double x0 = UVPt( I, J ).x, dx = 1. - x0;
+ for (int i = I+1; i < iSize-1; i++)
+ {
+ gp_UV p0 = UVPt( i, 0 ).UV();
+ gp_UV p2 = UVPt( i, jSize-1 ).UV();
+
+ UVPtStruct& uvPt = UVPt( i, J );
+ gp_UV uv = calcUV(( uvPt.x - x0 ) / dx , uvPt.y, a0,a1,a2,a3, p0,p1,p2,p3);
+ uvPt.u = uv.X();
+ uvPt.v = uv.Y();
+ }
+ }
+ }
+}
+
+//================================================================================
+/*!
+ * \brief Side copying
+ */
+//================================================================================
+
+FaceQuadStruct::Side& FaceQuadStruct::Side::operator=(const Side& otherSide)
+{
+ grid = otherSide.grid;
+ from = otherSide.from;
+ to = otherSide.to;
+ forced_nodes = otherSide.forced_nodes;
+ contacts = otherSide.contacts;
+ nbNodeOut = otherSide.nbNodeOut;
+
+ for ( size_t iC = 0; iC < contacts.size(); ++iC )
+ {
+ FaceQuadStruct::Side* oSide = contacts[iC].other_side;
+ for ( size_t iOC = 0; iOC < oSide->contacts.size(); ++iOC )
+ if ( oSide->contacts[iOC].other_side == & otherSide )
+ {
+ // cout << "SHIFT old " << &otherSide << " " << otherSide.NbPoints()
+ // << " -> new " << this << " " << this->NbPoints() << endl;
+ oSide->contacts[iOC].other_side = this;
+ }
+ }
+}
+
+//================================================================================
+/*!
+ * \brief Converts node index of a quad to node index of this side
+ */
+//================================================================================
+
+int FaceQuadStruct::Side::ToSideIndex( int quadNodeIndex ) const
+{
+ return ( from > to ) ? ( from - quadNodeIndex ) : ( quadNodeIndex + from );
+}
+
+//================================================================================
+/*!
+ * \brief Converts node index of this side to node index of a quad
+ */
+//================================================================================
+
+int FaceQuadStruct::Side::ToQuadIndex( int sideNodeIndex ) const
+{
+ return ( from > to ) ? ( from - sideNodeIndex ) : ( sideNodeIndex - from );
+}
+
+//================================================================================
+/*!
+ * \brief Checks if a node is enforced
+ * \param [in] nodeIndex - an index of a node in a size
+ * \return bool - \c true if the node is forced
+ */
+//================================================================================
+
+bool FaceQuadStruct::Side::IsForced( int nodeIndex ) const
+{
+ if ( nodeIndex < 0 || nodeIndex >= grid->NbPoints() )
+ throw SALOME_Exception( " FaceQuadStruct::Side::IsForced(): wrong index" );
+
+ if ( forced_nodes.count( nodeIndex ) )
+ return true;
+
+ for ( size_t i = 0; i < this->contacts.size(); ++i )
+ if ( contacts[ i ].point == nodeIndex &&
+ contacts[ i ].other_side->forced_nodes.count( contacts[ i ].other_point ))
+ return true;
+
+ return false;
+}
+
+//================================================================================
+/*!
+ * \brief Sets up a contact between this and another side
+ */
+//================================================================================
+
+void FaceQuadStruct::Side::AddContact( int ip, Side* side, int iop )
+{
+ if ( ip >= GetUVPtStruct().size() ||
+ iop >= side->GetUVPtStruct().size() )
+ throw SALOME_Exception( "FaceQuadStruct::Side::AddContact(): wrong point" );
+ {
+ contacts.resize( contacts.size() + 1 );
+ Contact& c = contacts.back();
+ c.point = ip;
+ c.other_side = side;
+ c.other_point = iop;
+ }
+ {
+ side->contacts.resize( side->contacts.size() + 1 );
+ Contact& c = side->contacts.back();
+ c.point = iop;
+ c.other_side = this;
+ c.other_point = ip;
+ }
+}
+
+//================================================================================
+/*!
+ * \brief Returns a normalized parameter of a point indexed within a quadrangle
+ */
+//================================================================================
+
+double FaceQuadStruct::Side::Param( int i ) const
+{
+ const vector& points = GetUVPtStruct();
+ return (( points[ from + i ].normParam - points[ from ].normParam ) /
+ ( points[ to - 1 ].normParam - points[ from ].normParam ));
+}
+
+//================================================================================
+/*!
+ * \brief Returns UV by a parameter normalized within a quadrangle
+ */
+//================================================================================
+
+gp_XY FaceQuadStruct::Side::Value2d( double x ) const
+{
+ const vector& points = GetUVPtStruct();
+ double u = ( points[ from ].normParam +
+ x * ( points[ to-1 ].normParam - points[ from ].normParam ));
+ return grid->Value2d( u ).XY();
+}
+
+//================================================================================
+/*!
+ * \brief Returns side length
+ */
+//================================================================================
+
+double FaceQuadStruct::Side::Length(int theFrom, int theTo) const
+{
+ const vector& points = GetUVPtStruct();
+ double r = ( points[ Max( to, theTo )-1 ].normParam -
+ points[ Max( from, theFrom ) ].normParam );
+ return r * grid->Length();
+}
diff --git a/src/StdMeshers/StdMeshers_Quadrangle_2D.hxx b/src/StdMeshers/StdMeshers_Quadrangle_2D.hxx
index 54a2a0664..9fe6e120a 100644
--- a/src/StdMeshers/StdMeshers_Quadrangle_2D.hxx
+++ b/src/StdMeshers/StdMeshers_Quadrangle_2D.hxx
@@ -30,31 +30,77 @@
#include "SMESH_Algo.hxx"
#include "SMESH_ProxyMesh.hxx"
#include "SMESH_StdMeshers.hxx"
+#include "StdMeshers_FaceSide.hxx"
#include "StdMeshers_QuadrangleParams.hxx"
#include
+#include
class SMDS_MeshNode;
class SMESH_Mesh;
class SMESH_MesherHelper;
class SMESH_ProxyMesh;
-class StdMeshers_FaceSide;
struct uvPtStruct;
enum TSideID { QUAD_BOTTOM_SIDE=0, QUAD_RIGHT_SIDE, QUAD_TOP_SIDE, QUAD_LEFT_SIDE, NB_QUAD_SIDES };
typedef uvPtStruct UVPtStruct;
-typedef struct faceQuadStruct
+struct FaceQuadStruct
{
- std::vector< StdMeshers_FaceSide*> side;
- bool isEdgeOut[4]; // true, if an EDGE has more nodes, than an opposite one
- UVPtStruct* uv_grid;
- TopoDS_Face face;
- ~faceQuadStruct();
- void shift( size_t nb, bool keepUnitOri );
- typedef boost::shared_ptr Ptr;
-} FaceQuadStruct;
+ struct Side // a side of FaceQuadStruct
+ {
+ struct Contact // contact of two sides
+ {
+ int point; // index of a grid point of this side where two sides meat
+ Side* other_side;
+ int other_point;
+ };
+ StdMeshers_FaceSidePtr grid;
+ int from, to; // indices of grid points used by the quad
+ std::set forced_nodes; // indices of forced grid points
+ std::vector contacts; // contacts with sides of other quads
+ int nbNodeOut; // nb of missing nodes on an opposite shorter side
+
+ Side(StdMeshers_FaceSidePtr theGrid = StdMeshers_FaceSidePtr());
+ Side& operator=(const Side& otherSide);
+ operator StdMeshers_FaceSidePtr() { return grid; }
+ operator const StdMeshers_FaceSidePtr() const { return grid; }
+ void AddContact( int ip, Side* side, int iop );
+ int ToSideIndex( int quadNodeIndex ) const;
+ int ToQuadIndex( int sideNodeIndex ) const;
+ bool IsForced( int nodeIndex ) const;
+ bool IsReversed() const { return nbNodeOut ? false : to < from; }
+ int NbPoints() const { return Abs( to - from ); }
+ double Param( int nodeIndex ) const;
+ double Length( int from=-1, int to=-1) const;
+ gp_XY Value2d( double x ) const;
+ // some sortcuts
+ const vector& GetUVPtStruct(bool isXConst=0, double constValue=0) const
+ { return nbNodeOut ?
+ grid->SimulateUVPtStruct( NbPoints()-nbNodeOut-1, isXConst, constValue ) :
+ grid->GetUVPtStruct( isXConst, constValue );
+ }
+ };
+
+ std::vector< Side > side;
+ std::vector< UVPtStruct> uv_grid;
+ int iSize, jSize;
+ TopoDS_Face face;
+ Bnd_B2d uv_box;
+
+ FaceQuadStruct ( const TopoDS_Face& F = TopoDS_Face() );
+ UVPtStruct& UVPt( int i, int j ) { return uv_grid[ i + j * iSize ]; }
+ void shift ( size_t nb, bool keepUnitOri );
+ int & nbNodeOut( int iSide ) { return side[ iSide ].nbNodeOut; }
+ bool findCell ( const gp_XY& uv, int & i, int & j );
+ bool isNear ( const gp_XY& uv, int & i, int & j, int nbLoops=1 );
+ bool isEqual ( const gp_XY& uv, int i, int j );
+ void normPa2IJ( double x, double y, int & i, int & j );
+ void updateUV ( const gp_XY& uv, int i, int j, bool isVertical );
+
+ typedef boost::shared_ptr Ptr;
+};
class STDMESHERS_EXPORT StdMeshers_Quadrangle_2D: public SMESH_2D_Algo
{
@@ -89,16 +135,17 @@ protected:
std::vector& aNbNodes,
bool& IsQuadratic);
- bool setNormalizedGrid(SMESH_Mesh& aMesh,
- const TopoDS_Face& aFace,
- FaceQuadStruct::Ptr& quad);
+ bool setNormalizedGrid(FaceQuadStruct::Ptr quad);
- void splitQuad(SMESHDS_Mesh *theMeshDS,
- const int theFaceID,
- const SMDS_MeshNode* theNode1,
- const SMDS_MeshNode* theNode2,
- const SMDS_MeshNode* theNode3,
- const SMDS_MeshNode* theNode4);
+ void splitQuadFace(SMESHDS_Mesh * theMeshDS,
+ const int theFaceID,
+ const SMDS_MeshNode* theNode1,
+ const SMDS_MeshNode* theNode2,
+ const SMDS_MeshNode* theNode3,
+ const SMDS_MeshNode* theNode4);
+
+ bool computeQuadDominant(SMESH_Mesh& aMesh,
+ const TopoDS_Face& aFace);
bool computeQuadDominant(SMESH_Mesh& aMesh,
const TopoDS_Face& aFace,
@@ -108,6 +155,10 @@ protected:
const TopoDS_Face& aFace,
FaceQuadStruct::Ptr quad);
+ bool computeTriangles(SMESH_Mesh& aMesh,
+ const TopoDS_Face& aFace,
+ FaceQuadStruct::Ptr quad);
+
bool evaluateQuadPref(SMESH_Mesh& aMesh,
const TopoDS_Shape& aShape,
std::vector& aNbNodes,
@@ -129,20 +180,43 @@ protected:
int & theNbDegenEdges,
const bool considerMesh);
+ bool getEnforcedUV();
+
+ bool addEnforcedNodes();
+
+ int splitQuad(FaceQuadStruct::Ptr quad, int i, int j);
+
+ typedef std::map< StdMeshers_FaceSidePtr, std::vector< FaceQuadStruct::Ptr > > TQuadsBySide;
+ void updateSideUV( FaceQuadStruct::Side& side,
+ int iForced,
+ const TQuadsBySide& quads,
+ int * iNext=NULL);
+
+
+ // Fields
- // true if QuadranglePreference hypothesis is assigned that forces
- // construction of quadrangles if the number of nodes on opposite edges
- // is not the same in the case where the global number of nodes on edges
- // is even
bool myQuadranglePreference;
bool myTrianglePreference;
int myTriaVertexID;
bool myNeedSmooth;
+ const StdMeshers_QuadrangleParams* myParams;
+ StdMeshers_QuadType myQuadType;
- StdMeshers_QuadType myQuadType;
- SMESH_MesherHelper* myHelper; // tool for working with quadratic elements
- SMESH_ProxyMesh::Ptr myProxyMesh;
- FaceQuadStruct::Ptr myQuadStruct;
+ SMESH_MesherHelper* myHelper;
+ SMESH_ProxyMesh::Ptr myProxyMesh;
+ std::list< FaceQuadStruct::Ptr > myQuadList;
+
+ struct ForcedPoint
+ {
+ gp_XY uv;
+ gp_XYZ xyz;
+ TopoDS_Vertex vertex;
+
+ double U() const { return uv.X(); }
+ double V() const { return uv.Y(); }
+ operator const gp_XY& () { return uv; }
+ };
+ std::vector< ForcedPoint > myForcedPnts;
};
#endif
diff --git a/src/StdMeshers/StdMeshers_Regular_1D.cxx b/src/StdMeshers/StdMeshers_Regular_1D.cxx
index 5377a6fa5..3470e50a2 100644
--- a/src/StdMeshers/StdMeshers_Regular_1D.cxx
+++ b/src/StdMeshers/StdMeshers_Regular_1D.cxx
@@ -37,6 +37,7 @@
#include "SMESH_subMeshEventListener.hxx"
#include "StdMeshers_Adaptive1D.hxx"
#include "StdMeshers_Arithmetic1D.hxx"
+#include "StdMeshers_Geometric1D.hxx"
#include "StdMeshers_AutomaticLength.hxx"
#include "StdMeshers_Deflection1D.hxx"
#include "StdMeshers_Distribution.hxx"
@@ -89,12 +90,14 @@ StdMeshers_Regular_1D::StdMeshers_Regular_1D(int hypId, int studyId,
_compatibleHypothesis.push_back("StartEndLength");
_compatibleHypothesis.push_back("Deflection1D");
_compatibleHypothesis.push_back("Arithmetic1D");
+ _compatibleHypothesis.push_back("GeometricProgression");
_compatibleHypothesis.push_back("FixedPoints1D");
_compatibleHypothesis.push_back("AutomaticLength");
_compatibleHypothesis.push_back("Adaptive1D");
-
- _compatibleHypothesis.push_back("QuadraticMesh"); // auxiliary !!!
- _compatibleHypothesis.push_back("Propagation"); // auxiliary !!!
+ // auxiliary:
+ _compatibleHypothesis.push_back("QuadraticMesh");
+ _compatibleHypothesis.push_back("Propagation");
+ _compatibleHypothesis.push_back("PropagOfDistribution");
}
//=============================================================================
@@ -223,6 +226,21 @@ bool StdMeshers_Regular_1D::CheckHypothesis( SMESH_Mesh& aMesh,
aStatus = SMESH_Hypothesis::HYP_OK;
}
+ else if (hypName == "GeometricProgression")
+ {
+ const StdMeshers_Geometric1D * hyp =
+ dynamic_cast (theHyp);
+ ASSERT(hyp);
+ _value[ BEG_LENGTH_IND ] = hyp->GetStartLength();
+ _value[ END_LENGTH_IND ] = hyp->GetCommonRatio();
+ ASSERT( _value[ BEG_LENGTH_IND ] > 0 && _value[ END_LENGTH_IND ] > 0 );
+ _hypType = GEOMETRIC_1D;
+
+ _revEdgesIDs = hyp->GetReversedEdges();
+
+ aStatus = SMESH_Hypothesis::HYP_OK;
+ }
+
else if (hypName == "FixedPoints1D") {
_fpHyp = dynamic_cast (theHyp);
ASSERT(_fpHyp);
@@ -616,6 +634,58 @@ bool StdMeshers_Regular_1D::computeInternalParameters(SMESH_Mesh & theMesh,
double f = theFirstU, l = theLastU;
+ // Propagation Of Distribution
+ //
+ if ( !_mainEdge.IsNull() && _isPropagOfDistribution )
+ {
+ TopoDS_Edge mainEdge = TopoDS::Edge( _mainEdge ); // should not be a reference!
+ _gen->Compute( theMesh, mainEdge, /*aShapeOnly=*/true, /*anUpward=*/true);
+
+ SMESHDS_SubMesh* smDS = theMesh.GetMeshDS()->MeshElements( mainEdge );
+ if ( !smDS )
+ return error("No mesh on the source edge of Propagation Of Distribution");
+ if ( smDS->NbNodes() < 1 )
+ return true; // 1 segment
+
+ vector< double > mainEdgeParams;
+ if ( ! SMESH_Algo::GetNodeParamOnEdge( theMesh.GetMeshDS(), mainEdge, mainEdgeParams ))
+ return error("Bad node parameters on the source edge of Propagation Of Distribution");
+
+ vector< double > segLen( mainEdgeParams.size() - 1 );
+ double totalLen = 0;
+ BRepAdaptor_Curve mainEdgeCurve( mainEdge );
+ for ( size_t i = 1; i < mainEdgeParams.size(); ++i )
+ {
+ segLen[ i-1 ] = GCPnts_AbscissaPoint::Length( mainEdgeCurve,
+ mainEdgeParams[i-1],
+ mainEdgeParams[i]);
+ totalLen += segLen[ i-1 ];
+ }
+ for ( size_t i = 0; i < segLen.size(); ++i )
+ segLen[ i ] *= theLength / totalLen;
+
+ size_t iSeg = theReverse ? segLen.size()-1 : 0;
+ size_t dSeg = theReverse ? -1 : +1;
+ double param = theFirstU;
+ int nbParams = 0;
+ for ( int i = 0, nb = segLen.size()-1; i < nb; ++i, iSeg += dSeg )
+ {
+ GCPnts_AbscissaPoint Discret( theC3d, segLen[ iSeg ], param );
+ if ( !Discret.IsDone() ) break;
+ param = Discret.Parameter();
+ theParams.push_back( param );
+ ++nbParams;
+ }
+ if ( nbParams != segLen.size()-1 )
+ return error( SMESH_Comment("Can't divide into ") << segLen.size() << " segements");
+
+ compensateError( segLen[ theReverse ? segLen.size()-1 : 0 ],
+ segLen[ theReverse ? 0 : segLen.size()-1 ],
+ f, l, theLength, theC3d, theParams, true );
+ return true;
+ }
+
+
switch( _hypType )
{
case LOCAL_LENGTH:
@@ -824,9 +894,54 @@ bool StdMeshers_Regular_1D::computeInternalParameters(SMESH_Mesh & theMesh,
return true;
}
+ case GEOMETRIC_1D: {
+
+ double a1 = _value[ BEG_LENGTH_IND ], an;
+ double q = _value[ END_LENGTH_IND ];
+
+ double U1 = theReverse ? l : f;
+ double Un = theReverse ? f : l;
+ double param = U1;
+ double eltSize = a1;
+ if ( theReverse )
+ eltSize = -eltSize;
+
+ int nbParams = 0;
+ while ( true ) {
+ // computes a point on a curve at the distance
+ // from the point of parameter .
+ GCPnts_AbscissaPoint Discret( theC3d, eltSize, param );
+ if ( !Discret.IsDone() ) break;
+ param = Discret.Parameter();
+ if ( f < param && param < l )
+ theParams.push_back( param );
+ else
+ break;
+ an = eltSize;
+ eltSize *= q;
+ ++nbParams;
+ }
+ if ( nbParams > 1 )
+ {
+ if ( Abs( param - Un ) < 0.2 * Abs( param - theParams.back() ))
+ {
+ compensateError( a1, eltSize, U1, Un, theLength, theC3d, theParams );
+ }
+ else if ( Abs( Un - theParams.back() ) <
+ 0.2 * Abs( theParams.back() - *(--theParams.rbegin())))
+ {
+ theParams.pop_back();
+ compensateError( a1, an, U1, Un, theLength, theC3d, theParams );
+ }
+ }
+ if (theReverse) theParams.reverse(); // NPAL18025
+
+ return true;
+ }
+
case FIXED_POINTS_1D: {
const std::vector& aPnts = _fpHyp->GetPoints();
- const std::vector& nbsegs = _fpHyp->GetNbSegments();
+ const std::vector& nbsegs = _fpHyp->GetNbSegments();
int i = 0;
TColStd_SequenceOfReal Params;
for(; i on this edge;
diff --git a/src/StdMeshers/StdMeshers_Regular_1D.hxx b/src/StdMeshers/StdMeshers_Regular_1D.hxx
index fbb9d0380..1298c80a6 100644
--- a/src/StdMeshers/StdMeshers_Regular_1D.hxx
+++ b/src/StdMeshers/StdMeshers_Regular_1D.hxx
@@ -102,7 +102,7 @@ protected:
StdMeshers_SegmentLengthAroundVertex* getVertexHyp(SMESH_Mesh & theMesh,
const TopoDS_Vertex & theV);
- enum HypothesisType { LOCAL_LENGTH, MAX_LENGTH, NB_SEGMENTS, BEG_END_LENGTH, DEFLECTION, ARITHMETIC_1D, FIXED_POINTS_1D, ADAPTIVE, NONE };
+ enum HypothesisType { LOCAL_LENGTH, MAX_LENGTH, NB_SEGMENTS, BEG_END_LENGTH, DEFLECTION, ARITHMETIC_1D, FIXED_POINTS_1D, ADAPTIVE, GEOMETRIC_1D, NONE };
enum ValueIndex {
SCALE_FACTOR_IND = 0,
@@ -140,6 +140,7 @@ protected:
// a source of propagated hypothesis, is set by CheckHypothesis()
// always called before Compute()
TopoDS_Shape _mainEdge;
+ bool _isPropagOfDistribution;
};
#endif
diff --git a/src/StdMeshers/StdMeshers_Reversible1D.cxx b/src/StdMeshers/StdMeshers_Reversible1D.cxx
new file mode 100644
index 000000000..05d25be98
--- /dev/null
+++ b/src/StdMeshers/StdMeshers_Reversible1D.cxx
@@ -0,0 +1,99 @@
+// Copyright (C) 2007-2013 CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+// SMESH SMESH : implementaion of SMESH idl descriptions
+// File : StdMeshers_Reversible1D.cxx
+// Module : SMESH
+//
+
+#include "StdMeshers_Reversible1D.hxx"
+
+//=============================================================================
+/*!
+ *
+ */
+//=============================================================================
+
+StdMeshers_Reversible1D::StdMeshers_Reversible1D(int hypId, int studyId, SMESH_Gen * gen)
+ :SMESH_Hypothesis(hypId, studyId, gen)
+{
+ _param_algo_dim = 1;
+}
+
+//=============================================================================
+/*!
+ *
+ */
+//=============================================================================
+
+void StdMeshers_Reversible1D::SetReversedEdges( const std::vector& ids )
+{
+ if ( ids != _edgeIDs )
+ {
+ _edgeIDs = ids;
+ NotifySubMeshesHypothesisModification();
+ }
+}
+
+//=============================================================================
+/*!
+ *
+ */
+//=============================================================================
+
+std::ostream & StdMeshers_Reversible1D::SaveTo(std::ostream & save)
+{
+ save << " " << _edgeIDs.size() << " ";
+
+ if ( !_edgeIDs.empty() )
+ {
+ for ( size_t i = 0; i < _edgeIDs.size(); i++)
+ save << " " << _edgeIDs[i];
+ save << " " << _objEntry << " ";
+ }
+
+ return save;
+}
+
+//=============================================================================
+/*!
+ *
+ */
+//=============================================================================
+
+std::istream & StdMeshers_Reversible1D::LoadFrom(std::istream & load)
+{
+ bool isOK;
+ int intVal;
+
+ isOK = (load >> intVal);
+ if (isOK && intVal > 0) {
+ _edgeIDs.reserve( intVal );
+ for (int i = 0; i < _edgeIDs.capacity() && isOK; i++) {
+ isOK = (load >> intVal);
+ if ( isOK ) _edgeIDs.push_back( intVal );
+ }
+ isOK = (load >> _objEntry);
+ }
+
+ return load;
+}
diff --git a/src/StdMeshers/StdMeshers_Reversible1D.hxx b/src/StdMeshers/StdMeshers_Reversible1D.hxx
new file mode 100644
index 000000000..e393e2046
--- /dev/null
+++ b/src/StdMeshers/StdMeshers_Reversible1D.hxx
@@ -0,0 +1,59 @@
+// Copyright (C) 2007-2013 CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+// SMESH SMESH : implementaion of SMESH idl descriptions
+// File : StdMeshers_Reversible1D.hxx
+// Module : SMESH
+//
+#ifndef _SMESH_Reversible1D_HXX_
+#define _SMESH_Reversible1D_HXX_
+
+#include "SMESH_StdMeshers.hxx"
+#include "SMESH_Hypothesis.hxx"
+
+#include
+
+/*!
+ * \brief A base of reversible 1D hypotheses
+ */
+class STDMESHERS_EXPORT StdMeshers_Reversible1D : public SMESH_Hypothesis
+{
+public:
+ StdMeshers_Reversible1D(int hypId, int studyId, SMESH_Gen* gen);
+
+ void SetReversedEdges( const std::vector& ids);
+
+ void SetObjectEntry( const char* entry ) { _objEntry = entry; }
+
+ const char* GetObjectEntry() { return _objEntry.c_str(); }
+
+ const std::vector& GetReversedEdges() const { return _edgeIDs; }
+
+ virtual std::ostream & SaveTo(std::ostream & save);
+ virtual std::istream & LoadFrom(std::istream & load);
+
+protected:
+ std::vector _edgeIDs;
+ std::string _objEntry;
+};
+
+#endif
diff --git a/src/StdMeshers/StdMeshers_UseExisting_1D2D.cxx b/src/StdMeshers/StdMeshers_UseExisting_1D2D.cxx
index ee2eb57f6..53b58035c 100644
--- a/src/StdMeshers/StdMeshers_UseExisting_1D2D.cxx
+++ b/src/StdMeshers/StdMeshers_UseExisting_1D2D.cxx
@@ -25,6 +25,9 @@
//
#include "StdMeshers_UseExisting_1D2D.hxx"
+#include "SMESH_Mesh.hxx"
+#include "SMESH_subMesh.hxx"
+
//=======================================================================
//function : StdMeshers_UseExisting_1D
//purpose :
@@ -56,10 +59,11 @@ bool StdMeshers_UseExisting_1D::CheckHypothesis(SMESH_Mesh& ,
//purpose :
//=======================================================================
-bool StdMeshers_UseExisting_1D::Compute(SMESH_Mesh&, const TopoDS_Shape&)
+bool StdMeshers_UseExisting_1D::Compute(SMESH_Mesh& mesh, const TopoDS_Shape& edge)
{
// This algorithm exists to allow mesh generation by mesh
// edition functions in TUI mode
+ mesh.GetSubMesh( edge )->SetIsAlwaysComputed( true );
return true;
}
@@ -110,10 +114,11 @@ bool StdMeshers_UseExisting_2D::CheckHypothesis(SMESH_Mesh& ,
//purpose :
//=======================================================================
-bool StdMeshers_UseExisting_2D::Compute(SMESH_Mesh&, const TopoDS_Shape&)
+bool StdMeshers_UseExisting_2D::Compute(SMESH_Mesh& mesh, const TopoDS_Shape& face)
{
// This algorithm exists to allow mesh generation by mesh edition
// functions in TUI mode
+ mesh.GetSubMesh( face )->SetIsAlwaysComputed( true );
return true;
}
diff --git a/src/StdMeshers/StdMeshers_ViscousLayers.cxx b/src/StdMeshers/StdMeshers_ViscousLayers.cxx
index e38c311ad..c2a3c954b 100644
--- a/src/StdMeshers/StdMeshers_ViscousLayers.cxx
+++ b/src/StdMeshers/StdMeshers_ViscousLayers.cxx
@@ -35,6 +35,7 @@
#include "SMESH_ControlsDef.hxx"
#include "SMESH_Gen.hxx"
#include "SMESH_Group.hxx"
+#include "SMESH_HypoFilter.hxx"
#include "SMESH_Mesh.hxx"
#include "SMESH_MeshAlgos.hxx"
#include "SMESH_MesherHelper.hxx"
@@ -63,6 +64,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -382,8 +384,10 @@ namespace VISCOUS_3D
{
TopoDS_Shape _solid;
const StdMeshers_ViscousLayers* _hyp;
+ TopoDS_Shape _hypShape;
_MeshOfSolid* _proxyMesh;
set _reversedFaceIds;
+ set _ignoreFaceIds;
double _stepSize, _stepSizeCoeff;
const SMDS_MeshNode* _stepSizeNodes[2];
@@ -393,10 +397,10 @@ namespace VISCOUS_3D
// iteration over the map is 5 time longer than over the vector
vector< _LayerEdge* > _edges;
- // key: an id of shape (EDGE or VERTEX) shared by a FACE with
- // layers and a FACE w/o layers
+ // key: an id of shape (EDGE or VERTEX) shared by a FACE with
+ // layers and a FACE w/o layers
// value: the shape (FACE or EDGE) to shrink mesh on.
- // _LayerEdge's basing on nodes on key shape are inflated along the value shape
+ // _LayerEdge's basing on nodes on key shape are inflated along the value shape
map< TGeomID, TopoDS_Shape > _shrinkShape2Shape;
// FACE's WOL, srink on which is forbiden due to algo on the adjacent SOLID
@@ -414,7 +418,9 @@ namespace VISCOUS_3D
_SolidData(const TopoDS_Shape& s=TopoDS_Shape(),
const StdMeshers_ViscousLayers* h=0,
- _MeshOfSolid* m=0) :_solid(s), _hyp(h), _proxyMesh(m) {}
+ const TopoDS_Shape& hs=TopoDS_Shape(),
+ _MeshOfSolid* m=0)
+ :_solid(s), _hyp(h), _hypShape(hs), _proxyMesh(m) {}
~_SolidData();
Handle(Geom_Curve) CurveForSmooth( const TopoDS_Edge& E,
@@ -517,7 +523,6 @@ namespace VISCOUS_3D
SMESH_ComputeErrorPtr _error;
vector< _SolidData > _sdVec;
- set _ignoreShapeIds;
int _tmpFaceID;
};
//--------------------------------------------------------------------------------
@@ -617,7 +622,7 @@ namespace VISCOUS_3D
//
StdMeshers_ViscousLayers::StdMeshers_ViscousLayers(int hypId, int studyId, SMESH_Gen* gen)
:SMESH_Hypothesis(hypId, studyId, gen),
- _isToIgnoreShapes(18), _nbLayers(1), _thickness(1), _stretchFactor(1)
+ _isToIgnoreShapes(1), _nbLayers(1), _thickness(1), _stretchFactor(1)
{
_name = StdMeshers_ViscousLayers::GetHypType();
_param_algo_dim = -3; // auxiliary hyp used by 3D algos
@@ -686,7 +691,7 @@ std::ostream & StdMeshers_ViscousLayers::SaveTo(std::ostream & save)
<< " " << _thickness
<< " " << _stretchFactor
<< " " << _shapeIds.size();
- for ( unsigned i = 0; i < _shapeIds.size(); ++i )
+ for ( size_t i = 0; i < _shapeIds.size(); ++i )
save << " " << _shapeIds[i];
save << " " << !_isToIgnoreShapes; // negate to keep the behavior in old studies.
return save;
@@ -788,7 +793,7 @@ namespace
// get average dir of edges going fromV
gp_XYZ edgeDir;
//if ( edges.size() > 1 )
- for ( unsigned i = 0; i < edges.size(); ++i )
+ for ( size_t i = 0; i < edges.size(); ++i )
{
edgeDir = getEdgeDir( edges[i], fromV );
double size2 = edgeDir.SquareModulus();
@@ -909,9 +914,9 @@ namespace
py = new ofstream(fname);
*py << "import SMESH" << endl
<< "from salome.smesh import smeshBuilder" << endl
- << "smesh = smeshBuilder.New(salome.myStudy)" << endl
+ << "smesh = smeshBuilder.New(salome.myStudy)" << endl
<< "meshSO = smesh.GetCurrentStudy().FindObjectID('0:1:2:3')" << endl
- << "mesh = smesh.Mesh( meshSO.GetObject() )"<GetGen();
+ SMESH_HypoFilter filter;
for ( int i = 1; i <= allSolids.Extent(); ++i )
{
// find StdMeshers_ViscousLayers hyp assigned to the i-th solid
@@ -1122,10 +1128,14 @@ bool _ViscousBuilder::findSolidsWithLayers()
viscHyp = dynamic_cast( *hyp );
if ( viscHyp )
{
+ TopoDS_Shape hypShape;
+ filter.Init( filter.Is( viscHyp ));
+ _mesh->GetHypothesis( allSolids(i), filter, true, &hypShape );
+
_MeshOfSolid* proxyMesh = _ViscousListener::GetSolidMesh( _mesh,
allSolids(i),
/*toCreate=*/true);
- _sdVec.push_back( _SolidData( allSolids(i), viscHyp, proxyMesh ));
+ _sdVec.push_back( _SolidData( allSolids(i), viscHyp, hypShape, proxyMesh ));
_sdVec.back()._index = getMeshDS()->ShapeToIndex( allSolids(i));
}
}
@@ -1144,44 +1154,69 @@ bool _ViscousBuilder::findSolidsWithLayers()
bool _ViscousBuilder::findFacesWithLayers()
{
- // collect all faces to ignore defined by hyp
- vector ignoreFaces;
- for ( unsigned i = 0; i < _sdVec.size(); ++i )
- {
- vector ids = _sdVec[i]._hyp->GetBndShapes();
- for ( unsigned i = 0; i < ids.size(); ++i )
- {
- const TopoDS_Shape& s = getMeshDS()->IndexToShape( ids[i] );
- if ( !s.IsNull() && s.ShapeType() == TopAbs_FACE )
- {
- _ignoreShapeIds.insert( ids[i] );
- ignoreFaces.push_back( s );
- }
- }
- }
-
- // ignore internal faces
SMESH_MesherHelper helper( *_mesh );
TopExp_Explorer exp;
- for ( unsigned i = 0; i < _sdVec.size(); ++i )
+ TopTools_IndexedMapOfShape solids;
+
+ // collect all faces to ignore defined by hyp
+ for ( size_t i = 0; i < _sdVec.size(); ++i )
{
- exp.Init( _sdVec[i]._solid.Oriented( TopAbs_FORWARD ), TopAbs_FACE );
- for ( ; exp.More(); exp.Next() )
+ solids.Add( _sdVec[i]._solid );
+
+ vector ids = _sdVec[i]._hyp->GetBndShapes();
+ if ( _sdVec[i]._hyp->IsToIgnoreShapes() ) // FACEs to ignore are given
{
- TGeomID faceInd = getMeshDS()->ShapeToIndex( exp.Current() );
- if ( helper.NbAncestors( exp.Current(), *_mesh, TopAbs_SOLID ) > 1 )
- {
- _ignoreShapeIds.insert( faceInd );
- ignoreFaces.push_back( exp.Current() );
- if ( helper.IsReversedSubMesh( TopoDS::Face( exp.Current() )))
+ for ( size_t ii = 0; ii < ids.size(); ++ii )
+ {
+ 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
+ {
+ TopTools_IndexedDataMapOfShapeListOfShape solidsOfFace;
+ if ( _sdVec[i]._hyp->IsToIgnoreShapes() )
+ TopExp::MapShapesAndAncestors( _sdVec[i]._hypShape,
+ TopAbs_FACE, TopAbs_SOLID, solidsOfFace);
+
+ exp.Init( _sdVec[i]._solid.Oriented( TopAbs_FORWARD ), TopAbs_FACE );
+ for ( ; exp.More(); exp.Next() )
+ {
+ const TopoDS_Face& face = TopoDS::Face( exp.Current() );
+ if ( helper.NbAncestors( face, *_mesh, TopAbs_SOLID ) < 2 )
+ continue;
+
+ const TGeomID faceInd = getMeshDS()->ShapeToIndex( face );
+ if ( _sdVec[i]._hyp->IsToIgnoreShapes() )
+ {
+ int nbSolids = solidsOfFace.FindFromKey( face ).Extent();
+ if ( nbSolids > 1 )
+ _sdVec[i]._ignoreFaceIds.insert( faceInd );
+ }
+
+ if ( helper.IsReversedSubMesh( face ))
+ {
_sdVec[i]._reversedFaceIds.insert( faceInd );
+ }
}
}
}
// Find faces to shrink mesh on (solution 2 in issue 0020832);
TopTools_IndexedMapOfShape shapes;
- for ( unsigned i = 0; i < _sdVec.size(); ++i )
+ for ( size_t i = 0; i < _sdVec.size(); ++i )
{
shapes.Clear();
TopExp::MapShapes(_sdVec[i]._solid, TopAbs_EDGE, shapes);
@@ -1201,18 +1236,35 @@ bool _ViscousBuilder::findFacesWithLayers()
// check presence of layers on them
int ignore[2];
for ( int j = 0; j < 2; ++j )
- ignore[j] = _ignoreShapeIds.count ( getMeshDS()->ShapeToIndex( FF[j] ));
- if ( ignore[0] == ignore[1] ) continue; // nothing interesting
+ ignore[j] = _sdVec[i]._ignoreFaceIds.count ( getMeshDS()->ShapeToIndex( FF[j] ));
+ if ( ignore[0] == ignore[1] )
+ continue; // nothing interesting
TopoDS_Shape fWOL = FF[ ignore[0] ? 0 : 1 ];
+ // check presence of layers on fWOL within an adjacent SOLID
+ PShapeIteratorPtr sIt = helper.GetAncestors( fWOL, *_mesh, TopAbs_SOLID );
+ while ( const TopoDS_Shape* solid = sIt->next() )
+ if ( !solid->IsSame( _sdVec[i]._solid ))
+ {
+ int iSolid = solids.FindIndex( *solid );
+ int iFace = getMeshDS()->ShapeToIndex( fWOL );
+ if ( iSolid > 0 && !_sdVec[ iSolid-1 ]._ignoreFaceIds.count( iFace ))
+ {
+ _sdVec[i]._noShrinkFaces.insert( iFace );
+ fWOL.Nullify();
+ }
+ }
// add edge to maps
- TGeomID edgeInd = getMeshDS()->ShapeToIndex( edge );
- _sdVec[i]._shrinkShape2Shape.insert( make_pair( edgeInd, fWOL ));
+ if ( !fWOL.IsNull())
+ {
+ TGeomID edgeInd = getMeshDS()->ShapeToIndex( edge );
+ _sdVec[i]._shrinkShape2Shape.insert( make_pair( edgeInd, fWOL ));
+ }
}
}
// Exclude from _shrinkShape2Shape FACE's that can't be shrinked since
// the algo of the SOLID sharing the FACE does not support it
set< string > notSupportAlgos; notSupportAlgos.insert("Hexa_3D");
- for ( unsigned i = 0; i < _sdVec.size(); ++i )
+ for ( size_t i = 0; i < _sdVec.size(); ++i )
{
TopTools_MapOfShape noShrinkVertices;
map< TGeomID, TopoDS_Shape >::iterator e2f = _sdVec[i]._shrinkShape2Shape.begin();
@@ -1229,7 +1281,7 @@ bool _ViscousBuilder::findFacesWithLayers()
SMESH_Algo* algo = _mesh->GetGen()->GetAlgo( *_mesh, *solid );
if ( !algo || !notSupportAlgos.count( algo->GetName() )) continue;
notShrinkFace = true;
- for ( unsigned j = 0; j < _sdVec.size(); ++j )
+ for ( size_t j = 0; j < _sdVec.size(); ++j )
{
if ( _sdVec[j]._solid.IsSame( *solid ) )
if ( _sdVec[j]._shrinkShape2Shape.count( edgeID ))
@@ -1262,10 +1314,10 @@ bool _ViscousBuilder::findFacesWithLayers()
}
}
}
-
+
// Find the SHAPE along which to inflate _LayerEdge based on VERTEX
- for ( unsigned i = 0; i < _sdVec.size(); ++i )
+ for ( size_t i = 0; i < _sdVec.size(); ++i )
{
shapes.Clear();
TopExp::MapShapes(_sdVec[i]._solid, TopAbs_VERTEX, shapes);
@@ -1279,11 +1331,12 @@ bool _ViscousBuilder::findFacesWithLayers()
while ( fIt->more())
{
const TopoDS_Shape* f = fIt->next();
- const int fID = getMeshDS()->ShapeToIndex( *f );
if ( helper.IsSubShape( *f, _sdVec[i]._solid ) )
{
totalNbFaces++;
- if ( _ignoreShapeIds.count ( fID ) && ! _sdVec[i]._noShrinkFaces.count( fID ))
+ const int fID = getMeshDS()->ShapeToIndex( *f );
+ if ( _sdVec[i]._ignoreFaceIds.count ( fID ) &&
+ !_sdVec[i]._noShrinkFaces.count( fID ))
facesWOL.push_back( *f );
}
}
@@ -1293,42 +1346,42 @@ bool _ViscousBuilder::findFacesWithLayers()
switch ( facesWOL.size() )
{
case 1:
+ {
+ helper.SetSubShape( facesWOL[0] );
+ if ( helper.IsRealSeam( vInd )) // inflate along a seam edge?
{
- helper.SetSubShape( facesWOL[0] );
- if ( helper.IsRealSeam( vInd )) // inflate along a seam edge?
- {
- TopoDS_Shape seamEdge;
- PShapeIteratorPtr eIt = helper.GetAncestors(vertex, *_mesh, TopAbs_EDGE);
- while ( eIt->more() && seamEdge.IsNull() )
- {
- const TopoDS_Shape* e = eIt->next();
- if ( helper.IsRealSeam( *e ) )
- seamEdge = *e;
- }
- if ( !seamEdge.IsNull() )
- {
- _sdVec[i]._shrinkShape2Shape.insert( make_pair( vInd, seamEdge ));
- break;
- }
- }
- _sdVec[i]._shrinkShape2Shape.insert( make_pair( vInd, facesWOL[0] ));
- break;
- }
- case 2:
- {
- // find an edge shared by 2 faces
+ TopoDS_Shape seamEdge;
PShapeIteratorPtr eIt = helper.GetAncestors(vertex, *_mesh, TopAbs_EDGE);
- while ( eIt->more())
+ while ( eIt->more() && seamEdge.IsNull() )
{
const TopoDS_Shape* e = eIt->next();
- if ( helper.IsSubShape( *e, facesWOL[0]) &&
- helper.IsSubShape( *e, facesWOL[1]))
- {
- _sdVec[i]._shrinkShape2Shape.insert( make_pair( vInd, *e )); break;
- }
+ if ( helper.IsRealSeam( *e ) )
+ seamEdge = *e;
+ }
+ if ( !seamEdge.IsNull() )
+ {
+ _sdVec[i]._shrinkShape2Shape.insert( make_pair( vInd, seamEdge ));
+ break;
}
- break;
}
+ _sdVec[i]._shrinkShape2Shape.insert( make_pair( vInd, facesWOL[0] ));
+ break;
+ }
+ case 2:
+ {
+ // find an edge shared by 2 faces
+ PShapeIteratorPtr eIt = helper.GetAncestors(vertex, *_mesh, TopAbs_EDGE);
+ while ( eIt->more())
+ {
+ const TopoDS_Shape* e = eIt->next();
+ if ( helper.IsSubShape( *e, facesWOL[0]) &&
+ helper.IsSubShape( *e, facesWOL[1]))
+ {
+ _sdVec[i]._shrinkShape2Shape.insert( make_pair( vInd, *e )); break;
+ }
+ }
+ break;
+ }
default:
return error("Not yet supported case", _sdVec[i]._index);
}
@@ -1351,10 +1404,10 @@ bool _ViscousBuilder::makeLayer(_SolidData& data)
subIds = data._noShrinkFaces;
TopExp_Explorer exp( data._solid, TopAbs_FACE );
for ( ; exp.More(); exp.Next() )
- if ( ! _ignoreShapeIds.count( getMeshDS()->ShapeToIndex( exp.Current() )))
{
SMESH_subMesh* fSubM = _mesh->GetSubMesh( exp.Current() );
- faceIds.insert( fSubM->GetId() );
+ if ( ! data._ignoreFaceIds.count( getMeshDS()->ShapeToIndex( exp.Current() )))
+ faceIds.insert( fSubM->GetId() );
SMESH_subMeshIteratorPtr subIt =
fSubM->getDependsOnIterator(/*includeSelf=*/true, /*complexShapeFirst=*/false);
while ( subIt->more() )
@@ -1368,7 +1421,7 @@ bool _ViscousBuilder::makeLayer(_SolidData& data)
for (; s2s != data._shrinkShape2Shape.end(); ++s2s )
{
TGeomID shapeInd = s2s->first;
- for ( unsigned i = 0; i < _sdVec.size(); ++i )
+ for ( size_t i = 0; i < _sdVec.size(); ++i )
{
if ( _sdVec[i]._index == data._index ) continue;
map< TGeomID, TopoDS_Shape >::iterator s2s2 = _sdVec[i]._shrinkShape2Shape.find( shapeInd );
@@ -1475,7 +1528,7 @@ bool _ViscousBuilder::makeLayer(_SolidData& data)
// Set target nodes into _Simplex and _2NearEdges
TNode2Edge::iterator n2e;
- for ( unsigned i = 0; i < data._edges.size(); ++i )
+ for ( size_t i = 0; i < data._edges.size(); ++i )
{
if ( data._edges[i]->IsOnEdge())
for ( int j = 0; j < 2; ++j )
@@ -1489,7 +1542,7 @@ bool _ViscousBuilder::makeLayer(_SolidData& data)
data._edges[i]->_2neibors->_edges[j] = n2e->second;
}
else
- for ( unsigned j = 0; j < data._edges[i]->_simplices.size(); ++j )
+ for ( size_t j = 0; j < data._edges[i]->_simplices.size(); ++j )
{
_Simplex& s = data._edges[i]->_simplices[j];
s._nNext = data._n2eMap[ s._nNext ]->_nodes.back();
@@ -1573,7 +1626,7 @@ bool _ViscousBuilder::sortEdges( _SolidData& data,
SMESH_MesherHelper helper( *_mesh );
bool ok = true;
- for ( unsigned iS = 0; iS < edgesByGeom.size(); ++iS )
+ for ( size_t iS = 0; iS < edgesByGeom.size(); ++iS )
{
vector<_LayerEdge*>& eS = edgesByGeom[iS];
if ( eS.empty() ) continue;
@@ -1617,7 +1670,7 @@ bool _ViscousBuilder::sortEdges( _SolidData& data,
if ( eE.empty() ) continue;
if ( eE[0]->_sWOL.IsNull() )
{
- for ( unsigned i = 0; i < eE.size() && !needSmooth; ++i )
+ for ( size_t i = 0; i < eE.size() && !needSmooth; ++i )
needSmooth = ( eE[i]->_cosin > 0.1 );
}
else
@@ -1625,7 +1678,7 @@ bool _ViscousBuilder::sortEdges( _SolidData& data,
const TopoDS_Face& F1 = TopoDS::Face( S );
const TopoDS_Face& F2 = TopoDS::Face( eE[0]->_sWOL );
const TopoDS_Edge& E = TopoDS::Edge( eExp.Current() );
- for ( unsigned i = 0; i < eE.size() && !needSmooth; ++i )
+ for ( size_t i = 0; i < eE.size() && !needSmooth; ++i )
{
gp_Vec dir1 = getFaceDir( F1, E, eE[i]->_nodes[0], helper, ok );
gp_Vec dir2 = getFaceDir( F2, E, eE[i]->_nodes[0], helper, ok );
@@ -1664,7 +1717,7 @@ bool _ViscousBuilder::sortEdges( _SolidData& data,
}
// then the rest _LayerEdge's
- for ( unsigned iS = 0; iS < edgesByGeom.size(); ++iS )
+ for ( size_t iS = 0; iS < edgesByGeom.size(); ++iS )
{
vector<_LayerEdge*>& eVec = edgesByGeom[iS];
data._edges.insert( data._edges.end(), eVec.begin(), eVec.end() );
@@ -1870,9 +1923,9 @@ bool _ViscousBuilder::setEdgeData(_LayerEdge& edge,
if ( posType == SMDS_TOP_FACE )
{
- getSimplices( node, edge._simplices, _ignoreShapeIds, &data );
+ getSimplices( node, edge._simplices, data._ignoreFaceIds, &data );
double avgNormProj = 0, avgLen = 0;
- for ( unsigned i = 0; i < edge._simplices.size(); ++i )
+ for ( size_t i = 0; i < edge._simplices.size(); ++i )
{
gp_XYZ vec = edge._pos.back() - SMESH_TNodeXYZ( edge._simplices[i]._nPrev );
avgNormProj += edge._normal * vec;
@@ -2103,7 +2156,7 @@ void _ViscousBuilder::getSimplices( const SMDS_MeshNode* node,
void _ViscousBuilder::makeGroupOfLE()
{
#ifdef _DEBUG_
- for ( unsigned i = 0 ; i < _sdVec.size(); ++i )
+ for ( size_t i = 0 ; i < _sdVec.size(); ++i )
{
if ( _sdVec[i]._edges.empty() ) continue;
// string name = SMESH_Comment("_LayerEdge's_") << i;
@@ -2113,10 +2166,10 @@ void _ViscousBuilder::makeGroupOfLE()
// SMESHDS_Mesh* mDS = _mesh->GetMeshDS();
dumpFunction( SMESH_Comment("make_LayerEdge_") << i );
- for ( unsigned j = 0 ; j < _sdVec[i]._edges.size(); ++j )
+ for ( size_t j = 0 ; j < _sdVec[i]._edges.size(); ++j )
{
_LayerEdge* le = _sdVec[i]._edges[j];
- for ( unsigned iN = 1; iN < le->_nodes.size(); ++iN )
+ for ( size_t iN = 1; iN < le->_nodes.size(); ++iN )
dumpCmd(SMESH_Comment("mesh.AddEdge([ ") <_nodes[iN-1]->GetID()
<< ", " << le->_nodes[iN]->GetID() <<"])");
//gDS->SMDSGroup().Add( mDS->AddEdge( le->_nodes[iN-1], le->_nodes[iN]));
@@ -2124,7 +2177,7 @@ void _ViscousBuilder::makeGroupOfLE()
dumpFunctionEnd();
dumpFunction( SMESH_Comment("makeNormals") << i );
- for ( unsigned j = 0 ; j < _sdVec[i]._edges.size(); ++j )
+ for ( size_t j = 0 ; j < _sdVec[i]._edges.size(); ++j )
{
_LayerEdge& edge = *_sdVec[i]._edges[j];
SMESH_TNodeXYZ nXYZ( edge._nodes[0] );
@@ -2178,7 +2231,7 @@ bool _ViscousBuilder::inflate(_SolidData& data)
auto_ptr searcher
( SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(),
data._proxyMesh->GetFaces( data._solid )) );
- for ( unsigned i = 0; i < data._edges.size(); ++i )
+ for ( size_t i = 0; i < data._edges.size(); ++i )
{
if ( data._edges[i]->IsOnEdge() ) continue;
data._edges[i]->FindIntersection( *searcher, intersecDist, data._epsilon );
@@ -2213,7 +2266,7 @@ bool _ViscousBuilder::inflate(_SolidData& data)
// Elongate _LayerEdge's
dumpFunction(SMESH_Comment("inflate")<SetNewLength( curThick, helper );
}
@@ -2229,7 +2282,7 @@ bool _ViscousBuilder::inflate(_SolidData& data)
if ( nbSteps > 0 )
{
dumpFunction(SMESH_Comment("invalidate")<InvalidateStep( nbSteps+1 );
}
@@ -2241,7 +2294,7 @@ bool _ViscousBuilder::inflate(_SolidData& data)
// Evaluate achieved thickness
avgThick = 0;
- for ( unsigned i = 0; i < data._edges.size(); ++i )
+ for ( size_t i = 0; i < data._edges.size(); ++i )
avgThick += data._edges[i]->_len;
avgThick /= data._edges.size();
#ifdef __myDEBUG
@@ -2289,7 +2342,7 @@ bool _ViscousBuilder::smoothAndCheck(_SolidData& data,
TopoDS_Face F;
int iBeg, iEnd = 0;
- for ( unsigned iS = 0; iS < data._endEdgeToSmooth.size(); ++iS )
+ for ( size_t iS = 0; iS < data._endEdgeToSmooth.size(); ++iS )
{
iBeg = iEnd;
iEnd = data._endEdgeToSmooth[ iS ];
@@ -2355,7 +2408,7 @@ bool _ViscousBuilder::smoothAndCheck(_SolidData& data,
{
_LayerEdge* edge = data._edges[i];
SMESH_TNodeXYZ tgtXYZ( edge->_nodes.back() );
- for ( unsigned j = 0; j < edge->_simplices.size(); ++j )
+ for ( size_t j = 0; j < edge->_simplices.size(); ++j )
if ( !edge->_simplices[j].IsForward( edge->_nodes[0], &tgtXYZ ))
{
cout << "Bad simplex ( " << edge->_nodes[0]->GetID()<< " "<< tgtXYZ._node->GetID()
@@ -2384,7 +2437,7 @@ bool _ViscousBuilder::smoothAndCheck(_SolidData& data,
const SMDS_MeshElement* closestFace = 0;
int iLE = 0;
#endif
- for ( unsigned i = 0; i < data._edges.size(); ++i )
+ for ( size_t i = 0; i < data._edges.size(); ++i )
{
if ( data._edges[i]->FindIntersection( *searcher, dist, data._epsilon, &intFace ))
return false;
@@ -2695,7 +2748,7 @@ bool _ViscousBuilder::updateNormals( _SolidData& data,
vector< const SMDS_MeshNode*> nodes(4); // of a tmp mesh face
dumpFunction(SMESH_Comment("makeTmpFacesOnEdges")<IsOnEdge() || !edge->_sWOL.IsNull() ) continue;
@@ -2712,7 +2765,7 @@ bool _ViscousBuilder::updateNormals( _SolidData& data,
}
// look for a _LayerEdge containg tgt2
// _LayerEdge* neiborEdge = 0;
-// unsigned di = 0; // check _edges[i+di] and _edges[i-di]
+// size_t di = 0; // check _edges[i+di] and _edges[i-di]
// while ( !neiborEdge && ++di <= data._edges.size() )
// {
// if ( i+di < data._edges.size() && data._edges[i+di]->_nodes.back() == tgt2 )
@@ -2751,7 +2804,7 @@ bool _ViscousBuilder::updateNormals( _SolidData& data,
TLEdge2LEdgeSet edge2CloseEdge;
const double eps = data._epsilon * data._epsilon;
- for ( unsigned i = 0; i < data._edges.size(); ++i )
+ for ( size_t i = 0; i < data._edges.size(); ++i )
{
_LayerEdge* edge = data._edges[i];
if ( !edge->IsOnEdge() || !edge->_sWOL.IsNull() ) continue;
@@ -2922,7 +2975,7 @@ bool _ViscousBuilder::updateNormals( _SolidData& data,
// 2) Check absence of intersections
// TODO?
- for ( unsigned i = 0 ; i < tmpFaces.size(); ++i )
+ for ( size_t i = 0 ; i < tmpFaces.size(); ++i )
delete tmpFaces[i];
return true;
@@ -2948,7 +3001,7 @@ bool _LayerEdge::FindIntersection( SMESH_ElementSearcher& searcher,
bool segmentIntersected = false;
distance = Precision::Infinite();
int iFace = -1; // intersected face
- for ( unsigned j = 0 ; j < suspectFaces.size() && !segmentIntersected; ++j )
+ for ( size_t j = 0 ; j < suspectFaces.size() && !segmentIntersected; ++j )
{
const SMDS_MeshElement* face = suspectFaces[j];
if ( face->GetNodeIndex( _nodes.back() ) >= 0 ||
@@ -3236,7 +3289,7 @@ bool _LayerEdge::Smooth(int& badNb)
// compute new position for the last _pos
gp_XYZ newPos (0,0,0);
- for ( unsigned i = 0; i < _simplices.size(); ++i )
+ for ( size_t i = 0; i < _simplices.size(); ++i )
newPos += SMESH_TNodeXYZ( _simplices[i]._nPrev );
newPos /= _simplices.size();
@@ -3259,11 +3312,11 @@ bool _LayerEdge::Smooth(int& badNb)
// count quality metrics (orientation) of tetras around _tgtNode
int nbOkBefore = 0;
SMESH_TNodeXYZ tgtXYZ( _nodes.back() );
- for ( unsigned i = 0; i < _simplices.size(); ++i )
+ for ( size_t i = 0; i < _simplices.size(); ++i )
nbOkBefore += _simplices[i].IsForward( _nodes[0], &tgtXYZ );
int nbOkAfter = 0;
- for ( unsigned i = 0; i < _simplices.size(); ++i )
+ for ( size_t i = 0; i < _simplices.size(); ++i )
nbOkAfter += _simplices[i].IsForward( _nodes[0], &newPos );
if ( nbOkAfter < nbOkBefore )
@@ -3389,14 +3442,14 @@ bool _ViscousBuilder::refine(_SolidData& data)
gp_XY uv;
bool isOnEdge;
- for ( unsigned i = 0; i < data._edges.size(); ++i )
+ for ( size_t i = 0; i < data._edges.size(); ++i )
{
_LayerEdge& edge = *data._edges[i];
// get accumulated length of segments
vector< double > segLen( edge._pos.size() );
segLen[0] = 0.0;
- for ( unsigned j = 1; j < edge._pos.size(); ++j )
+ for ( size_t j = 1; j < edge._pos.size(); ++j )
segLen[j] = segLen[j-1] + (edge._pos[j-1] - edge._pos[j] ).Modulus();
// allocate memory for new nodes if it is not yet refined
@@ -3444,8 +3497,8 @@ bool _ViscousBuilder::refine(_SolidData& data)
// create intermediate nodes
double hSum = 0, hi = h0/f;
- unsigned iSeg = 1;
- for ( unsigned iStep = 1; iStep < edge._nodes.size(); ++iStep )
+ size_t iSeg = 1;
+ for ( size_t iStep = 1; iStep < edge._nodes.size(); ++iStep )
{
// compute an intermediate position
hi *= f;
@@ -3512,7 +3565,7 @@ bool _ViscousBuilder::refine(_SolidData& data)
if ( !getMeshDS()->IsEmbeddedMode() )
// Log node movement
- for ( unsigned i = 0; i < data._edges.size(); ++i )
+ for ( size_t i = 0; i < data._edges.size(); ++i )
{
_LayerEdge& edge = *data._edges[i];
SMESH_TNodeXYZ p ( edge._nodes.back() );
@@ -3526,7 +3579,7 @@ bool _ViscousBuilder::refine(_SolidData& data)
TopExp_Explorer exp( data._solid, TopAbs_FACE );
for ( ; exp.More(); exp.Next() )
{
- if ( _ignoreShapeIds.count( getMeshDS()->ShapeToIndex( exp.Current() )))
+ if ( data._ignoreFaceIds.count( getMeshDS()->ShapeToIndex( exp.Current() )))
continue;
SMESHDS_SubMesh* fSubM = getMeshDS()->MeshElements( exp.Current() );
SMDS_ElemIteratorPtr fIt = fSubM->GetElements();
@@ -3577,7 +3630,7 @@ bool _ViscousBuilder::shrink()
// make map of (ids of FACEs to shrink mesh on) to (_SolidData containing _LayerEdge's
// inflated along FACE or EDGE)
map< TGeomID, _SolidData* > f2sdMap;
- for ( unsigned i = 0 ; i < _sdVec.size(); ++i )
+ for ( size_t i = 0 ; i < _sdVec.size(); ++i )
{
_SolidData& data = _sdVec[i];
TopTools_MapOfShape FFMap;
@@ -3684,7 +3737,7 @@ bool _ViscousBuilder::shrink()
// Replace source nodes by target nodes in mesh faces to shrink
const SMDS_MeshNode* nodes[20];
- for ( unsigned i = 0; i < lEdges.size(); ++i )
+ for ( size_t i = 0; i < lEdges.size(); ++i )
{
_LayerEdge& edge = *lEdges[i];
const SMDS_MeshNode* srcNode = edge._nodes[0];
@@ -3712,7 +3765,7 @@ bool _ViscousBuilder::shrink()
vector< _SmoothNode > nodesToSmooth( smoothNodes.size() );
{
const bool sortSimplices = isConcaveFace;
- for ( unsigned i = 0; i < smoothNodes.size(); ++i )
+ for ( size_t i = 0; i < smoothNodes.size(); ++i )
{
const SMDS_MeshNode* n = smoothNodes[i];
nodesToSmooth[ i ]._node = n;
@@ -3728,7 +3781,7 @@ bool _ViscousBuilder::shrink()
// Find EDGE's to shrink and set simpices to LayerEdge's
set< _Shrinker1D* > eShri1D;
{
- for ( unsigned i = 0; i < lEdges.size(); ++i )
+ for ( size_t i = 0; i < lEdges.size(); ++i )
{
_LayerEdge* edge = lEdges[i];
if ( edge->_sWOL.ShapeType() == TopAbs_EDGE )
@@ -3801,7 +3854,7 @@ bool _ViscousBuilder::shrink()
int oldBadNb = badNb;
badNb = 0;
moved = false;
- for ( unsigned i = 0; i < nodesToSmooth.size(); ++i )
+ for ( size_t i = 0; i < nodesToSmooth.size(); ++i )
{
moved |= nodesToSmooth[i].Smooth( badNb,surface,helper,refSign,
smoothType, /*set3D=*/isConcaveFace);
@@ -3870,7 +3923,7 @@ bool _ViscousBuilder::shrink()
case 3: smoothType = _SmoothNode::ANGULAR; break;
}
dumpFunction(SMESH_Comment("shrinkFace")<first<<"_st"<<++smooStep); // debug
- for ( unsigned i = 0; i < nodesToSmooth.size(); ++i )
+ for ( size_t i = 0; i < nodesToSmooth.size(); ++i )
{
nodesToSmooth[i].Smooth( badNb,surface,helper,refSign,
smoothType,/*set3D=*/st==1 );
@@ -3883,7 +3936,7 @@ bool _ViscousBuilder::shrink()
if ( !getMeshDS()->IsEmbeddedMode() )
// Log node movement
- for ( unsigned i = 0; i < nodesToSmooth.size(); ++i )
+ for ( size_t i = 0; i < nodesToSmooth.size(); ++i )
{
SMESH_TNodeXYZ p ( nodesToSmooth[i]._node );
getMeshDS()->MoveNode( nodesToSmooth[i]._node, p.X(), p.Y(), p.Z() );
@@ -3937,7 +3990,7 @@ bool _ViscousBuilder::prepareEdgeToShrink( _LayerEdge& edge,
// if ( faceSubMesh->Contains( f ))
// faces.push_back( f );
// }
- // for ( unsigned i = 0; i < faces.size(); ++i )
+ // for ( size_t i = 0; i < faces.size(); ++i )
// {
// const int nbNodes = faces[i]->NbCornerNodes();
// for ( int j = 0; j < nbNodes; ++j )
@@ -4397,11 +4450,11 @@ bool _SmoothNode::Smooth(int& badNb,
// count quality metrics (orientation) of triangles around the node
int nbOkBefore = 0;
gp_XY tgtUV = helper.GetNodeUV( face, _node );
- for ( unsigned i = 0; i < _simplices.size(); ++i )
+ for ( size_t i = 0; i < _simplices.size(); ++i )
nbOkBefore += _simplices[i].IsForward( tgtUV, _node, face, helper, refSign );
int nbOkAfter = 0;
- for ( unsigned i = 0; i < _simplices.size(); ++i )
+ for ( size_t i = 0; i < _simplices.size(); ++i )
nbOkAfter += _simplices[i].IsForward( newPos, _node, face, helper, refSign );
if ( nbOkAfter < nbOkBefore )
@@ -4496,7 +4549,7 @@ gp_XY _SmoothNode::computeAngularPos(vector& uv,
_SolidData::~_SolidData()
{
- for ( unsigned i = 0; i < _edges.size(); ++i )
+ for ( size_t i = 0; i < _edges.size(); ++i )
{
if ( _edges[i] && _edges[i]->_2neibors )
delete _edges[i]->_2neibors;
@@ -4569,7 +4622,7 @@ void _Shrinker1D::AddEdge( const _LayerEdge* e, SMESH_MesherHelper& helper )
{
// remove target node of the _LayerEdge from _nodes
int nbFound = 0;
- for ( unsigned i = 0; i < _nodes.size(); ++i )
+ for ( size_t i = 0; i < _nodes.size(); ++i )
if ( !_nodes[i] || _nodes[i] == tgtNode0 || _nodes[i] == tgtNode1 )
_nodes[i] = 0, nbFound++;
if ( nbFound == _nodes.size() )
@@ -4607,7 +4660,7 @@ void _Shrinker1D::Compute(bool set3D, SMESH_MesherHelper& helper)
l = helper.GetNodeU( E, _edges[1]->_nodes.back(), _nodes.back() );
double totLen = GCPnts_AbscissaPoint::Length( aCurve, f, l );
- for ( unsigned i = 0; i < _nodes.size(); ++i )
+ for ( size_t i = 0; i < _nodes.size(); ++i )
{
if ( !_nodes[i] ) continue;
double len = totLen * _normPar[i];
@@ -4629,7 +4682,7 @@ void _Shrinker1D::Compute(bool set3D, SMESH_MesherHelper& helper)
if ( _edges[1] )
l = helper.GetNodeU( E, _edges[1]->_nodes.back(), _nodes.back() );
- for ( unsigned i = 0; i < _nodes.size(); ++i )
+ for ( size_t i = 0; i < _nodes.size(); ++i )
{
if ( !_nodes[i] ) continue;
double u = f * ( 1-_normPar[i] ) + l * _normPar[i];
@@ -4648,7 +4701,7 @@ void _Shrinker1D::Compute(bool set3D, SMESH_MesherHelper& helper)
void _Shrinker1D::RestoreParams()
{
if ( _done )
- for ( unsigned i = 0; i < _nodes.size(); ++i )
+ for ( size_t i = 0; i < _nodes.size(); ++i )
{
if ( !_nodes[i] ) continue;
SMDS_EdgePosition* pos = static_cast( _nodes[i]->GetPosition() );
@@ -4701,7 +4754,7 @@ bool _ViscousBuilder::addBoundaryElements()
{
SMESH_MesherHelper helper( *_mesh );
- for ( unsigned i = 0; i < _sdVec.size(); ++i )
+ for ( size_t i = 0; i < _sdVec.size(); ++i )
{
_SolidData& data = _sdVec[i];
TopTools_IndexedMapOfShape geomEdges;
@@ -4772,7 +4825,7 @@ bool _ViscousBuilder::addBoundaryElements()
{
const TopoDS_Shape* pF = fIt->next();
if ( helper.IsSubShape( *pF, data._solid) &&
- !_ignoreShapeIds.count( e2f->first ))
+ !data._ignoreFaceIds.count( e2f->first ))
F = *pF;
}
}
@@ -4788,7 +4841,7 @@ bool _ViscousBuilder::addBoundaryElements()
// Make faces
const int dj1 = reverse ? 0 : 1;
const int dj2 = reverse ? 1 : 0;
- for ( unsigned j = 1; j < ledges.size(); ++j )
+ for ( size_t j = 1; j < ledges.size(); ++j )
{
vector< const SMDS_MeshNode*>& nn1 = ledges[j-dj1]->_nodes;
vector< const SMDS_MeshNode*>& nn2 = ledges[j-dj2]->_nodes;
diff --git a/src/StdMeshersGUI/StdMeshersGUI_CartesianParamCreator.cxx b/src/StdMeshersGUI/StdMeshersGUI_CartesianParamCreator.cxx
index 937c79066..c2b58de8d 100644
--- a/src/StdMeshersGUI/StdMeshersGUI_CartesianParamCreator.cxx
+++ b/src/StdMeshersGUI/StdMeshersGUI_CartesianParamCreator.cxx
@@ -42,6 +42,7 @@
#include
#include
#include
+#include
#include