+
+ //================================================================================
+ // Clear collected data
+ void reset()
+ {
+ StdMeshers_Quadrangle_2D::myQuadList.clear();
+ StdMeshers_Quadrangle_2D::myHelper = nullptr;
+ StdMeshers_Quadrangle_2D::myProxyMesh.reset();
+ myFace2QuadMap.Clear();
+ }
+
+ //================================================================================
+ /*!
+ * \brief Return FaceQuadStruct if a given FACE can be meshed by StdMeshers_Quadrangle_2D
+ */
+ FaceQuadStruct::Ptr CheckNbEdges(SMESH_Mesh& theMesh,
+ const TopoDS_Shape& theShape )
+ {
+ const TopoDS_Face& face = TopoDS::Face( theShape );
+ if ( myFace2QuadMap.IsBound( face ))
+ return myFace2QuadMap.Find( face );
+
+ FaceQuadStruct::Ptr & resultQuad = * myFace2QuadMap.Bound( face, FaceQuadStruct::Ptr() );
+
+ FaceQuadStruct::Ptr quad =
+ StdMeshers_Quadrangle_2D::CheckNbEdges( theMesh, face, /*considerMesh=*/false, myHelper );
+ if ( quad )
+ {
+ // check if the quadrangle mesh would be valid
+
+ // check existing 1D mesh
+ // int nbSegments[4], i = 0;
+ // for ( FaceQuadStruct::Side & side : quad->side )
+ // nbSegments[ i++ ] = side.grid->NbSegments();
+ // if ( nbSegments[0] > 0 && nbSegments[2] > 0 && nbSegments[0] != nbSegments[2] ||
+ // nbSegments[1] > 0 && nbSegments[3] > 0 && nbSegments[1] != nbSegments[3] )
+ // return resultQuad;
+
+ int nbEdges = 0;
+ for ( FaceQuadStruct::Side & side : quad->side )
+ nbEdges += side.grid->NbEdges();
+ if ( nbEdges == 4 )
+ return resultQuad = quad;
+
+ TmpMesh mesh;
+ mesh.ShapeToMesh( face );
+ SMESHDS_Mesh* meshDS = mesh.GetMeshDS();
+ SMESH_MesherHelper helper( mesh );
+ helper.SetSubShape( face );
+ helper.SetElementsOnShape( true );
+
+ // create nodes on all VERTEX'es
+ for ( TopExp_Explorer vert( face, TopAbs_VERTEX ); vert.More(); vert.Next() )
+ mesh.GetSubMesh( vert.Current() )->ComputeStateEngine( SMESH_subMesh::COMPUTE );
+
+ FaceQuadStruct::Ptr tmpQuad( new FaceQuadStruct() );
+ tmpQuad->side.resize( 4 );
+
+ // divide quad sides into halves at least
+ const SMDS_MeshNode* node;
+ for ( int iDir = 0; iDir < 2; ++iDir )
+ {
+ StdMeshers_FaceSidePtr sides[2] = { quad->side[iDir], quad->side[iDir+2] };
+ std::map< double, const SMDS_MeshNode* > nodes[2];
+ for ( int iS : { 0, 1 } )
+ {
+ node = SMESH_Algo::VertexNode( sides[iS]->FirstVertex(), meshDS );
+ nodes[iS].insert( std::make_pair( 0, node ));
+ double curLen = 0;
+ for ( int iE = 1; iE < sides[iS]->NbEdges(); ++iE )
+ {
+ curLen += sides[iS]->EdgeLength( iE - 1 );
+ double u = curLen / sides[iS]->Length();
+ node = SMESH_Algo::VertexNode( sides[iS]->FirstVertex( iE ), meshDS );
+ nodes[iS ].insert( std::make_pair( u, node ));
+ nodes[1-iS].insert( std::make_pair( u, nullptr ));
+ }
+ nodes[iS].insert( std::make_pair( 0.5, nullptr ));
+ node = SMESH_Algo::VertexNode( sides[iS]->LastVertex(), meshDS );
+ nodes[iS].insert( std::make_pair( 1, node ));
+ }
+
+ for ( int iS : { 0, 1 } )
+ {
+ UVPtStructVec sideNodes;
+ sideNodes.reserve( nodes[ iS ].size() );
+ for ( auto & u_node : nodes[ iS ])
+ {
+ if ( !u_node.second )
+ {
+ gp_Pnt p = sides[iS]->Value3d( u_node.first );
+ u_node.second = meshDS->AddNode( p.X(), p.Y(), p.Z() );
+ TopoDS_Edge edge;
+ double param = sides[iS]->Parameter( u_node.first, edge );
+ meshDS->SetNodeOnEdge( u_node.second, edge, param );
+ }
+ sideNodes.push_back( u_node.second );
+ sideNodes.back().SetUV( helper.GetNodeUV( face, u_node.second ));
+ }
+ tmpQuad->side[ iS ? iDir+2 : iDir ] = StdMeshers_FaceSide::New( sideNodes, face );
+ }
+ }
+ StdMeshers_Quadrangle_2D::myCheckOri = true;
+ StdMeshers_Quadrangle_2D::myQuadList.clear();
+ StdMeshers_Quadrangle_2D::myQuadList.push_back( tmpQuad );
+ StdMeshers_Quadrangle_2D::myHelper = &helper;
+ if ( StdMeshers_Quadrangle_2D::computeQuadDominant( mesh, face, tmpQuad ) &&
+ StdMeshers_Quadrangle_2D::check())
+ {
+ resultQuad = quad;
+ }
+ StdMeshers_Quadrangle_2D::myQuadList.clear();
+ StdMeshers_Quadrangle_2D::myHelper = nullptr;
+ }
+ return resultQuad;
+ }