+
+ //================================================================================
+ /*!
+ * \brief Fills groups on nodes to be merged
+ */
+ //================================================================================
+
+ void getNodeGroupsToMerge( const SMESHDS_SubMesh* smDS,
+ const TopoDS_Shape& shape,
+ SMESH_MeshEditor::TListOfListOfNodes& nodeGroupsToMerge)
+ {
+ SMDS_NodeIteratorPtr nIt = smDS->GetNodes();
+ switch ( shape.ShapeType() )
+ {
+ case TopAbs_VERTEX: {
+ std::list< const SMDS_MeshNode* > nodes;
+ while ( nIt->more() )
+ nodes.push_back( nIt->next() );
+ if ( nodes.size() > 1 )
+ nodeGroupsToMerge.push_back( nodes );
+ break;
+ }
+ case TopAbs_EDGE: {
+ std::multimap< double, const SMDS_MeshNode* > u2node;
+ const SMDS_EdgePosition* ePos;
+ while ( nIt->more() )
+ {
+ const SMDS_MeshNode* n = nIt->next();
+ if (( ePos = dynamic_cast< const SMDS_EdgePosition* >( n->GetPosition() )))
+ u2node.insert( make_pair( ePos->GetUParameter(), n ));
+ }
+ if ( u2node.size() < 2 ) return;
+
+ double tol = (( u2node.rbegin()->first - u2node.begin()->first ) / 20.) / u2node.size();
+ std::multimap< double, const SMDS_MeshNode* >::iterator un2, un1;
+ for ( un2 = u2node.begin(), un1 = un2++; un2 != u2node.end(); un1 = un2++ )
+ {
+ if (( un2->first - un1->first ) <= tol )
+ {
+ std::list< const SMDS_MeshNode* > nodes;
+ nodes.push_back( un1->second );
+ while (( un2->first - un1->first ) <= tol )
+ {
+ nodes.push_back( un2->second );
+ if ( ++un2 == u2node.end()) {
+ --un2;
+ break;
+ }
+ }
+ // make nodes created on the boundary of viscous layer replace nodes created
+ // by BLSURF as their SMDS_Position is more correct
+ nodes.sort( ShapeTypeCompare() );
+ nodeGroupsToMerge.push_back( nodes );
+ }
+ }
+ break;
+ }
+ default: ;
+ }
+ // SMESH_MeshEditor::TListOfListOfNodes::const_iterator nll = nodeGroupsToMerge.begin();
+ // for ( ; nll != nodeGroupsToMerge.end(); ++nll )
+ // {
+ // cout << "Merge ";
+ // const std::list< const SMDS_MeshNode* >& nl = *nll;
+ // std::list< const SMDS_MeshNode* >::const_iterator nIt = nl.begin();
+ // for ( ; nIt != nl.end(); ++nIt )
+ // cout << (*nIt) << " ";
+ // cout << endl;
+ // }
+ // cout << endl;
+ }
+
+ //================================================================================
+ /*!
+ * \brief A temporary mesh used to compute mesh on a proxy FACE
+ */
+ //================================================================================
+
+ struct TmpMesh: public SMESH_Mesh
+ {
+ typedef std::map<const SMDS_MeshNode*, const SMDS_MeshNode*, TIDCompare > TN2NMap;
+ TN2NMap _tmp2origNN;
+ TopoDS_Face _proxyFace;
+
+ TmpMesh()
+ {
+ _myMeshDS = new SMESHDS_Mesh( _id, true );
+ }
+ //--------------------------------------------------------------------------------
+ /*!
+ * \brief Creates a FACE bound by viscous layers and mesh each its EDGE with 1 segment
+ */
+ //--------------------------------------------------------------------------------
+
+ const TopoDS_Face& makeProxyFace( SMESH_ProxyMesh::Ptr& viscousMesh,
+ const TopoDS_Face& origFace)
+ {
+ // get data of nodes on inner boundary of viscous layers
+ SMESH_Mesh* origMesh = viscousMesh->GetMesh();
+ TError err;
+ TSideVector wireVec = StdMeshers_FaceSide::GetFaceWires(origFace, *origMesh,
+ /*skipMediumNodes = */true,
+ err, viscousMesh );
+ if ( err && err->IsKO() )
+ throw *err.get(); // it should be caught at SMESH_subMesh
+
+ // proxy nodes and corresponding tmp VERTEXes
+ std::vector<const SMDS_MeshNode*> origNodes;
+ std::vector<TopoDS_Vertex> tmpVertex;
+
+ // create a proxy FACE
+ TopoDS_Shape origFaceCopy = origFace.EmptyCopied();
+ BRepBuilderAPI_MakeFace newFace( TopoDS::Face( origFaceCopy ));
+ for ( size_t iW = 0; iW != wireVec.size(); ++iW )
+ {
+ StdMeshers_FaceSidePtr& wireData = wireVec[iW];
+ const UVPtStructVec& wirePoints = wireData->GetUVPtStruct();
+ if ( wirePoints.size() < 3 )
+ continue;
+
+ BRepBuilderAPI_MakePolygon wire;
+ for ( size_t iN = 1; iN < wirePoints.size(); ++iN )
+ {
+ wire.Add( SMESH_TNodeXYZ( wirePoints[ iN ].node ));
+ origNodes.push_back( wirePoints[ iN ].node );
+ tmpVertex.push_back( wire.LastVertex() );
+ }
+ tmpVertex[0] = wire.FirstVertex();
+ wire.Close();
+ if ( !wire.IsDone() )
+ throw SALOME_Exception("BLSURFPlugin_BLSURF: BRepBuilderAPI_MakePolygon failed");
+ newFace.Add( wire );
+ }
+ _proxyFace = newFace;
+
+ // set a new shape to mesh
+ TopoDS_Compound auxCompoundToMesh;
+ BRep_Builder shapeBuilder;
+ shapeBuilder.MakeCompound( auxCompoundToMesh );
+ shapeBuilder.Add( auxCompoundToMesh, _proxyFace );
+ shapeBuilder.Add( auxCompoundToMesh, origMesh->GetShapeToMesh() );
+
+ ShapeToMesh( auxCompoundToMesh );
+
+ //TopExp_Explorer fExp( auxCompoundToMesh, TopAbs_FACE );
+ //_proxyFace = TopoDS::Face( fExp.Current() );
+
+
+ // Make input mesh for BLSURF: segments on EDGE's of newFace
+
+ // make nodes and fill in _tmp2origNN
+ //
+ SMESHDS_Mesh* tmpMeshDS = GetMeshDS();
+ for ( size_t i = 0; i < origNodes.size(); ++i )
+ {
+ GetSubMesh( tmpVertex[i] )->ComputeStateEngine( SMESH_subMesh::COMPUTE );
+ if ( const SMDS_MeshNode* tmpN = SMESH_Algo::VertexNode( tmpVertex[i], tmpMeshDS ))
+ _tmp2origNN.insert( _tmp2origNN.end(), make_pair( tmpN, origNodes[i] ));
+ else
+ throw SALOME_Exception("BLSURFPlugin_BLSURF: a proxy vertex not meshed");
+ }
+
+ // make segments
+ TopoDS_Vertex v1, v2;
+ for ( TopExp_Explorer edge( _proxyFace, TopAbs_EDGE ); edge.More(); edge.Next() )
+ {
+ const TopoDS_Edge& E = TopoDS::Edge( edge.Current() );
+ TopExp::Vertices( E, v1, v2 );
+ const SMDS_MeshNode* n1 = SMESH_Algo::VertexNode( v1, tmpMeshDS );
+ const SMDS_MeshNode* n2 = SMESH_Algo::VertexNode( v2, tmpMeshDS );
+
+ if ( SMDS_MeshElement* seg = tmpMeshDS->AddEdge( n1, n2 ))
+ tmpMeshDS->SetMeshElementOnShape( seg, E );
+ }
+
+ return _proxyFace;
+ }
+
+ //--------------------------------------------------------------------------------
+ /*!
+ * \brief Fill in the origMesh with faces computed by BLSURF in this tmp mesh
+ */
+ //--------------------------------------------------------------------------------
+
+ void FillInOrigMesh( SMESH_Mesh& origMesh,
+ const TopoDS_Face& origFace )
+ {
+ SMESH_MesherHelper helper( origMesh );
+ helper.SetSubShape( origFace );
+ helper.SetElementsOnShape( true );
+
+ // iterate over tmp faces and copy them in origMesh
+ const SMDS_MeshNode* nodes[27];
+ const SMDS_MeshNode* nullNode = 0;
+ double xyz[3];
+ SMDS_FaceIteratorPtr fIt = GetMeshDS()->facesIterator(/*idInceasingOrder=*/true);
+ while ( fIt->more() )
+ {
+ const SMDS_MeshElement* f = fIt->next();
+ SMDS_ElemIteratorPtr nIt = f->nodesIterator();
+ int nbN = 0;
+ for ( ; nIt->more(); ++nbN )
+ {
+ const SMDS_MeshNode* n = static_cast<const SMDS_MeshNode*>( nIt->next() );
+ TN2NMap::iterator n2nIt =
+ _tmp2origNN.insert( _tmp2origNN.end(), make_pair( n, nullNode ));
+ if ( !n2nIt->second ) {
+ n->GetXYZ( xyz );
+ gp_XY uv = helper.GetNodeUV( _proxyFace, n );
+ n2nIt->second = helper.AddNode( xyz[0], xyz[1], xyz[2], uv.X(), uv.Y() );
+ }
+ nodes[ nbN ] = n2nIt->second;
+ }
+ switch( nbN ) {
+ case 3: helper.AddFace( nodes[0], nodes[1], nodes[2] ); break;
+ // case 6: helper.AddFace( nodes[0], nodes[1], nodes[2],
+ // nodes[3], nodes[4], nodes[5]); break;
+ case 4: helper.AddFace( nodes[0], nodes[1], nodes[2], nodes[3] ); break;
+ // case 9: helper.AddFace( nodes[0], nodes[1], nodes[2], nodes[3],
+ // nodes[4], nodes[5], nodes[6], nodes[7], nodes[8]); break;
+ // case 8: helper.AddFace( nodes[0], nodes[1], nodes[2], nodes[3],
+ // nodes[4], nodes[5], nodes[6], nodes[7]); break;
+ }
+ }
+ }
+ };
+
+ /*!
+ * \brief A structure holding an error description and a verbisity level
+ */
+ struct message_cb_user_data
+ {
+ std::string * _error;
+ int _verbosity;
+ double * _progress;
+ };
+
+