#include "StdMeshers_Quadrangle_2D.hxx"
-#include "StdMeshers_FaceSide.hxx"
-
-#include "StdMeshers_QuadrangleParams.hxx"
-
+#include "SMDS_EdgePosition.hxx"
+#include "SMDS_FacePosition.hxx"
+#include "SMDS_MeshElement.hxx"
+#include "SMDS_MeshNode.hxx"
+#include "SMESH_Block.hxx"
+#include "SMESH_Comment.hxx"
#include "SMESH_Gen.hxx"
#include "SMESH_Mesh.hxx"
-#include "SMESH_subMesh.hxx"
#include "SMESH_MesherHelper.hxx"
-#include "SMESH_Block.hxx"
-#include "SMESH_Comment.hxx"
-
-#include "SMDS_MeshElement.hxx"
-#include "SMDS_MeshNode.hxx"
-#include "SMDS_EdgePosition.hxx"
-#include "SMDS_FacePosition.hxx"
+#include "SMESH_subMesh.hxx"
+#include "StdMeshers_FaceSide.hxx"
+#include "StdMeshers_QuadrangleParams.hxx"
+#include "StdMeshers_ViscousLayers2D.hxx"
#include <BRep_Tool.hxx>
#include <Geom_Surface.hxx>
StdMeshers_Quadrangle_2D::StdMeshers_Quadrangle_2D (int hypId, int studyId,
SMESH_Gen* gen)
- : SMESH_2D_Algo(hypId, studyId, gen)
+ : SMESH_2D_Algo(hypId, studyId, gen),
+ myHelper( 0 )
{
MESSAGE("StdMeshers_Quadrangle_2D::StdMeshers_Quadrangle_2D");
_name = "Quadrangle_2D";
_compatibleHypothesis.push_back("QuadrangleParams");
_compatibleHypothesis.push_back("QuadranglePreference");
_compatibleHypothesis.push_back("TrianglePreference");
- myHelper = 0;
+ _compatibleHypothesis.push_back("ViscousLayers2D");
}
//=============================================================================
*/
//=============================================================================
-bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh,
- const TopoDS_Shape& aShape)// throw (SALOME_Exception)
+bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh,
+ const TopoDS_Shape& aShape)
{
- // PAL14921. Enable catching std::bad_alloc and Standard_OutOfMemory outside
- //Unexpect aCatchSalomeException);
+ const TopoDS_Face& F = TopoDS::Face(aShape);
+ Handle(Geom_Surface) S = BRep_Tool::Surface(F);
SMESHDS_Mesh * meshDS = aMesh.GetMeshDS();
aMesh.GetSubMesh(aShape);
SMESH_MesherHelper helper (aMesh);
myHelper = &helper;
+ myProxyMesh = StdMeshers_ViscousLayers2D::Compute( aMesh, F );
+ if ( !myProxyMesh )
+ return false;
+
_quadraticMesh = myHelper->IsQuadraticSubMesh(aShape);
myNeedSmooth = false;
int nbhoriz = Min(nbdown, nbup);
int nbvertic = Min(nbright, nbleft);
- const TopoDS_Face& F = TopoDS::Face(aShape);
- Handle(Geom_Surface) S = BRep_Tool::Surface(F);
-
// internal mesh nodes
int i, j, geomFaceID = meshDS->ShapeToIndex(F);
for (i = 1; i < nbhoriz - 1; i++) {
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;
+ d = quad->uv_grid[(j + 1) * nbhoriz + i ].node;
SMDS_MeshFace* face = myHelper->AddFace(a, b, c, d);
if (face) {
meshDS->SetMeshElementOnShape(face, geomFaceID);
}
if (!E1.IsNull() && !E2.IsNull() && !E3.IsNull())
{
- quad->side.push_back(new StdMeshers_FaceSide(F, E1, &aMesh, true, ignoreMediumNodes));
- quad->side.push_back(new StdMeshers_FaceSide(F, E2, &aMesh, true, ignoreMediumNodes));
- quad->side.push_back(new StdMeshers_FaceSide(F, E3, &aMesh, false,ignoreMediumNodes));
+ if ( myProxyMesh->GetProxySubMesh( E1 ) ||
+ myProxyMesh->GetProxySubMesh( E2 ) ||
+ myProxyMesh->GetProxySubMesh( E3 ) )
+
+ quad->side.push_back(new StdMeshers_FaceSide(F, E1, &aMesh, true,
+ ignoreMediumNodes, myProxyMesh));
+ quad->side.push_back(new StdMeshers_FaceSide(F, E2, &aMesh, true,
+ ignoreMediumNodes, myProxyMesh));
+ quad->side.push_back(new StdMeshers_FaceSide(F, E3, &aMesh, false,
+ ignoreMediumNodes, myProxyMesh));
const vector<UVPtStruct>& UVPSleft = quad->side[0]->GetUVPtStruct(true,0);
/* vector<UVPtStruct>& UVPStop = */quad->side[1]->GetUVPtStruct(false,1);
/* vector<UVPtStruct>& UVPSright = */quad->side[2]->GetUVPtStruct(true,1);
else if (nbEdgesInWire.front() == 4) // exactly 4 edges
{
for (; edgeIt != edges.end(); ++edgeIt, nbSides++)
- quad->side.push_back(new StdMeshers_FaceSide(F, *edgeIt, &aMesh,
- nbSides<TOP_SIDE, ignoreMediumNodes));
+ quad->side.push_back(new StdMeshers_FaceSide(F, *edgeIt, &aMesh, nbSides < TOP_SIDE,
+ ignoreMediumNodes, myProxyMesh));
}
else if (nbEdgesInWire.front() > 4) // more than 4 edges - try to unite some
{
if ( sideEdges.size() == 1 && BRep_Tool::Degenerated( sideEdges.front() ))
degenSides.push_back( nbSides );
- quad->side.push_back(new StdMeshers_FaceSide(F, sideEdges, &aMesh,
- nbSides<TOP_SIDE, ignoreMediumNodes));
+ quad->side.push_back(new StdMeshers_FaceSide(F, sideEdges, &aMesh, nbSides < TOP_SIDE,
+ ignoreMediumNodes, myProxyMesh));
++nbSides;
}
if ( !degenSides.empty() && nbSides - degenSides.size() == 4 )
}
}
quad->side.push_back(new StdMeshers_FaceSide(F, sideEdges, &aMesh,
- nbSides<TOP_SIDE, ignoreMediumNodes));
+ nbSides < TOP_SIDE,
+ ignoreMediumNodes, myProxyMesh));
++nbSides;
}
}
if ( myNeedSmooth )
UpdateDegenUV( quad );
- // nodes Id on "in" edges
- if (! quad->isEdgeOut[0]) {
- int j = 0;
- for (int i = 0; i < nbhoriz; i++) { // down
- int ij = j * nbhoriz + i;
- uv_grid[ij].node = uv_e0[i].node;
- }
+ // copy data of face boundary
+ /*if (! quad->isEdgeOut[0])*/ {
+ const int j = 0;
+ for (int i = 0; i < nbhoriz; i++) // down
+ uv_grid[ j * nbhoriz + i ] = uv_e0[i];
}
- if (! quad->isEdgeOut[1]) {
- int i = nbhoriz - 1;
- for (int j = 0; j < nbvertic; j++) { // right
- int ij = j * nbhoriz + i;
- uv_grid[ij].node = uv_e1[j].node;
- }
+ /*if (! quad->isEdgeOut[1])*/ {
+ const int i = nbhoriz - 1;
+ for (int j = 0; j < nbvertic; j++) // right
+ uv_grid[ j * nbhoriz + i ] = uv_e1[j];
}
- if (! quad->isEdgeOut[2]) {
- int j = nbvertic - 1;
- for (int i = 0; i < nbhoriz; i++) { // up
- int ij = j * nbhoriz + i;
- uv_grid[ij].node = uv_e2[i].node;
- }
+ /*if (! quad->isEdgeOut[2])*/ {
+ const int j = nbvertic - 1;
+ for (int i = 0; i < nbhoriz; i++) // up
+ uv_grid[ j * nbhoriz + i ] = uv_e2[i];
}
- if (! quad->isEdgeOut[3]) {
+ /*if (! quad->isEdgeOut[3])*/ {
int i = 0;
- for (int j = 0; j < nbvertic; j++) { // left
- int ij = j * nbhoriz + i;
- uv_grid[ij].node = uv_e3[j].node;
- }
+ for (int j = 0; j < nbvertic; j++) // left
+ uv_grid[ j * nbhoriz + i ] = uv_e3[j];
}
- // normalized 2d values on grid
+ // normalized 2d parameters on grid
for (int i = 0; i < nbhoriz; i++) {
for (int j = 0; j < nbvertic; j++) {
int ij = j * nbhoriz + i;
}
// 4 --- 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.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);
+
+ for (int i = 0; i < nbhoriz; 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 p1( uv_e1[j].u, uv_e1[j].v );
+ gp_UV p3( uv_e3[j].u, uv_e3[j].v );
- for (int i = 0; i < nbhoriz; i++) {
- for (int j = 0; j < nbvertic; j++) {
int ij = j * nbhoriz + i;
double x = uv_grid[ij].x;
double y = uv_grid[ij].y;
- double param_0 = uv_e0[0].normParam + x * (uv_e0.back().normParam - uv_e0[0].normParam); // sud
- double param_2 = uv_e2[0].normParam + x * (uv_e2.back().normParam - uv_e2[0].normParam); // nord
- double param_1 = uv_e1[0].normParam + y * (uv_e1.back().normParam - uv_e1[0].normParam); // est
- double param_3 = uv_e3[0].normParam + y * (uv_e3.back().normParam - uv_e3[0].normParam); // ouest
-
- //MESSAGE("params "<<param_0<<" "<<param_1<<" "<<param_2<<" "<<param_3);
- gp_UV p0 = quad->side[0]->Value2d(param_0).XY();
- gp_UV p1 = quad->side[1]->Value2d(param_1).XY();
- gp_UV p2 = quad->side[2]->Value2d(param_2).XY();
- gp_UV p3 = quad->side[3]->Value2d(param_3).XY();
gp_UV uv = CalcUV(x,y, a0,a1,a2,a3, p0,p1,p2,p3);
static void ShiftQuad(FaceQuadStruct* quad, const int num, bool)
{
- StdMeshers_FaceSide* side[4] = { quad->side[0], quad->side[1], quad->side[2], quad->side[3] };
+ StdMeshers_FaceSide* side[4] = { quad->side[0], quad->side[1],
+ quad->side[2], quad->side[3] };
for (int i = BOTTOM_SIDE; i < NB_SIDES; ++i) {
int id = (i + num) % NB_SIDES;
bool wasForward = (i < TOP_SIDE);
const gp_UV& a0, const gp_UV& a1,
const gp_UV& a2, const gp_UV& a3)
{
- const vector<UVPtStruct>& uv_eb = quad->side[0]->GetUVPtStruct(true,0);
- const vector<UVPtStruct>& uv_er = quad->side[1]->GetUVPtStruct(false,1);
- const vector<UVPtStruct>& uv_et = quad->side[2]->GetUVPtStruct(true,1);
- const vector<UVPtStruct>& uv_el = quad->side[3]->GetUVPtStruct(false,0);
+ // const vector<UVPtStruct>& uv_eb = quad->side[0]->GetUVPtStruct(true,0);
+ // const vector<UVPtStruct>& uv_er = quad->side[1]->GetUVPtStruct(false,1);
+ // const vector<UVPtStruct>& uv_et = quad->side[2]->GetUVPtStruct(true,1);
+ // const vector<UVPtStruct>& uv_el = quad->side[3]->GetUVPtStruct(false,0);
double x = (x0 + y0 * (x1 - x0)) / (1 - (y1 - y0) * (x1 - x0));
double y = y0 + x * (y1 - y0);
- double param_b = uv_eb[0].normParam + x * (uv_eb.back().normParam - uv_eb[0].normParam);
- double param_t = uv_et[0].normParam + x * (uv_et.back().normParam - uv_et[0].normParam);
- double param_r = uv_er[0].normParam + y * (uv_er.back().normParam - uv_er[0].normParam);
- double param_l = uv_el[0].normParam + y * (uv_el.back().normParam - uv_el[0].normParam);
-
- gp_UV p0 = quad->side[BOTTOM_SIDE]->Value2d(param_b).XY();
- gp_UV p1 = quad->side[RIGHT_SIDE ]->Value2d(param_r).XY();
- gp_UV p2 = quad->side[TOP_SIDE ]->Value2d(param_t).XY();
- gp_UV p3 = quad->side[LEFT_SIDE ]->Value2d(param_l).XY();
+ gp_UV p0 = quad->side[BOTTOM_SIDE]->Value2d(x).XY();
+ gp_UV p1 = quad->side[RIGHT_SIDE ]->Value2d(y).XY();
+ gp_UV p2 = quad->side[TOP_SIDE ]->Value2d(x).XY();
+ gp_UV p3 = quad->side[LEFT_SIDE ]->Value2d(y).XY();
gp_UV uv = CalcUV(x,y, a0,a1,a2,a3, p0,p1,p2,p3);
int curr_base_len = nb;
int next_base_len = 0;
- if ( is_tree_42 || is_tree_31 )
+ if ( true )
+ { // ------------------------------------------------------------------
+ // New algorithm implemented by request of IPAL22856
+ // "2D quadrangle mesher of reduced type works wrong"
+ // http://bugtracker.opencascade.com/show_bug.cgi?id=22856
+
+ // the algorithm is following: all reduces are centred in horizontal
+ // direction and are distributed among all rows
+
+ if (ncol_bot > max_tree42) {
+ is_lin_31 = true;
+ }
+ else {
+ if ((ncol_top/3)*3 == ncol_top ) {
+ is_lin_31 = true;
+ }
+ else {
+ is_lin_42 = true;
+ }
+ }
+
+ const int col_top_size = is_lin_42 ? 2 : 1;
+ const int col_base_size = is_lin_42 ? 4 : 3;
+
+ // Compute nb of "columns" (like in "linear" simple reducing) in all rows
+
+ vector<int> nb_col_by_row;
+
+ int delta_all = nb - nt;
+ int delta_one_col = nrows * 2;
+ int nb_col = delta_all / delta_one_col;
+ int remainder = delta_all - nb_col * delta_one_col;
+ if (remainder > 0) {
+ nb_col++;
+ }
+ if ( nb_col * col_top_size >= nt ) // == "tree" reducing situation
+ {
+ // top row is full (all elements reduced), add "columns" one by one
+ // in rows below until all bottom elements are reduced
+ nb_col = ( nt - 1 ) / col_top_size;
+ nb_col_by_row.resize( nrows, nb_col );
+ int nbrows_not_full = nrows - 1;
+ int cur_top_size = nt - 1;
+ remainder = delta_all - nb_col * delta_one_col;
+ while ( remainder > 0 )
+ {
+ delta_one_col = nbrows_not_full * 2;
+ int nb_col_add = remainder / delta_one_col;
+ cur_top_size += 2 * nb_col_by_row[ nbrows_not_full ];
+ int nb_col_free = cur_top_size / col_top_size - nb_col_by_row[ nbrows_not_full-1 ];
+ if ( nb_col_add > nb_col_free )
+ nb_col_add = nb_col_free;
+ for ( int irow = 0; irow < nbrows_not_full; ++irow )
+ nb_col_by_row[ irow ] += nb_col_add;
+ nbrows_not_full --;
+ remainder -= nb_col_add * delta_one_col;
+ }
+ }
+ else // == "linear" reducing situation
+ {
+ nb_col_by_row.resize( nrows, nb_col );
+ if (remainder > 0)
+ for ( int irow = remainder / 2; irow < nrows; ++irow )
+ nb_col_by_row[ irow ]--;
+ }
+
+ // Make elements
+
+ PReduceFunction reduceFunction = & ( is_lin_42 ? reduce42 : reduce31 );
+
+ const int reduce_grp_size = is_lin_42 ? 4 : 3;
+
+ for (i = 1; i < nr; i++) // layer by layer
+ {
+ nb_col = nb_col_by_row[ i-1 ];
+ int nb_next = curr_base_len - nb_col * 2;
+ if (nb_next < nt) nb_next = nt;
+
+ const double y = uv_el[ i ].normParam;
+
+ if ( i + 1 == nr ) // top
+ {
+ next_base = uv_et;
+ }
+ else
+ {
+ next_base.clear();
+ next_base.resize( nb_next, nullUVPtStruct );
+ next_base.front() = uv_el[i];
+ next_base.back() = uv_er[i];
+
+ // compute normalized param u
+ double du = 1. / ( nb_next - 1 );
+ next_base[0].normParam = 0.;
+ for ( j = 1; j < nb_next; ++j )
+ next_base[j].normParam = next_base[j-1].normParam + du;
+ }
+ uv[ UV_L ].SetCoord( next_base.front().u, next_base.front().v );
+ uv[ UV_R ].SetCoord( next_base.back().u, next_base.back().v );
+
+ int free_left = ( curr_base_len - 1 - nb_col * col_base_size ) / 2;
+ int free_middle = curr_base_len - 1 - nb_col * col_base_size - 2 * free_left;
+
+ // not reduced left elements
+ for (j = 0; j < free_left; j++)
+ {
+ // f (i + 1, j + 1)
+ const SMDS_MeshNode*& Nf = next_base[++next_base_len].node;
+ if ( !Nf )
+ Nf = makeNode( next_base[ next_base_len ], y, quad, uv, myHelper, S );
+
+ myHelper->AddFace(curr_base[ j ].node,
+ curr_base[ j+1 ].node,
+ Nf,
+ next_base[ next_base_len-1 ].node);
+ }
+
+ for (int icol = 1; icol <= nb_col; icol++)
+ {
+ // add "H"
+ reduceFunction( curr_base, next_base, j, next_base_len, quad, uv, y, myHelper, S );
+
+ j += reduce_grp_size;
+
+ // elements in the middle of "columns" added for symmetry
+ if ( free_middle > 0 && ( nb_col % 2 == 0 ) && icol == nb_col / 2 )
+ {
+ for (int imiddle = 1; imiddle <= free_middle; imiddle++) {
+ // f (i + 1, j + imiddle)
+ const SMDS_MeshNode*& Nf = next_base[++next_base_len].node;
+ if ( !Nf )
+ Nf = makeNode( next_base[ next_base_len ], y, quad, uv, myHelper, S );
+
+ myHelper->AddFace(curr_base[ j-1+imiddle ].node,
+ curr_base[ j +imiddle ].node,
+ Nf,
+ next_base[ next_base_len-1 ].node);
+ }
+ j += free_middle;
+ }
+ }
+
+ // not reduced right elements
+ for (; j < curr_base_len-1; j++) {
+ // f (i + 1, j + 1)
+ const SMDS_MeshNode*& Nf = next_base[++next_base_len].node;
+ if ( !Nf )
+ Nf = makeNode( next_base[ next_base_len ], y, quad, uv, myHelper, S );
+
+ myHelper->AddFace(curr_base[ j ].node,
+ curr_base[ j+1 ].node,
+ Nf,
+ next_base[ next_base_len-1 ].node);
+ }
+
+ curr_base_len = next_base_len + 1;
+ next_base_len = 0;
+ curr_base.swap( next_base );
+ }
+
+ }
+ else if ( is_tree_42 || is_tree_31 )
{
// "tree" simple reduce "42": 2->4->8->16->32->...
//
} // end "linear" simple reduce
else {
+ return false;
}
} // end Simple Reduce implementation