From b9a943c613149e1744dbcbf98632b8100ae64588 Mon Sep 17 00:00:00 2001 From: eap Date: Mon, 22 Aug 2011 08:44:59 +0000 Subject: [PATCH] 021346: EDF 1938 SMESH: "Use existing elements" functionality fix the bug that edges on the seam edges are not created --- src/StdMeshers/StdMeshers_Import_1D2D.cxx | 108 ++++++++++++++++++++-- 1 file changed, 98 insertions(+), 10 deletions(-) diff --git a/src/StdMeshers/StdMeshers_Import_1D2D.cxx b/src/StdMeshers/StdMeshers_Import_1D2D.cxx index 7b3aed368..121c258cc 100644 --- a/src/StdMeshers/StdMeshers_Import_1D2D.cxx +++ b/src/StdMeshers/StdMeshers_Import_1D2D.cxx @@ -144,6 +144,12 @@ bool StdMeshers_Import_1D2D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & if ( srcGroups.empty() ) return error("Invalid source groups"); + bool allGroupsEmpty = true; + for ( size_t iG = 0; iG < srcGroups.size() && allGroupsEmpty; ++iG ) + allGroupsEmpty = srcGroups[iG]->GetGroupDS()->IsEmpty(); + if ( allGroupsEmpty ) + return error("No faces in source groups"); + SMESH_MesherHelper helper(theMesh); helper.SetSubShape(theShape); SMESHDS_Mesh* tgtMesh = theMesh.GetMeshDS(); @@ -192,7 +198,7 @@ bool StdMeshers_Import_1D2D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & StdMeshers_Import_1D::TNodeNodeMap* n2n; StdMeshers_Import_1D::TElemElemMap* e2e; vector newNodes; - for ( int iG = 0; iG < srcGroups.size(); ++iG ) + for ( size_t iG = 0; iG < srcGroups.size(); ++iG ) { const SMESHDS_GroupBase* srcGroup = srcGroups[iG]->GetGroupDS(); @@ -212,7 +218,7 @@ bool StdMeshers_Import_1D2D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & newNodes.back() = 0; int nbCreatedNodes = 0; SMDS_MeshElement::iterator node = face->begin_nodes(); - for ( unsigned i = 0; i < newNodes.size(); ++i, ++node ) + for ( size_t i = 0; i < newNodes.size(); ++i, ++node ) { StdMeshers_Import_1D::TNodeNodeMap::iterator n2nIt = n2n->insert( make_pair( *node, (SMDS_MeshNode*)0 )).first; if ( n2nIt->second ) @@ -342,7 +348,8 @@ bool StdMeshers_Import_1D2D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & const double projTol = 1e-3 * sqrt( minLinkLen2 ); bool isFaceMeshed = false; - if ( SMESHDS_SubMesh* tgtSM = tgtMesh->MeshElements( theShape )) + SMESHDS_SubMesh* tgtFaceSM = tgtMesh->MeshElements( theShape ); + if ( tgtFaceSM ) { // the imported mesh is valid if all external links (encountered once) // lie on geom edges @@ -354,7 +361,7 @@ bool StdMeshers_Import_1D2D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & int nbFaces = link2Nb->second; if ( nbFaces == 1 ) { - // check if a not shared link lie on face boundary + // check if a not shared link lies on face boundary bool nodesOnBoundary = true; list< TopoDS_Shape > bndShapes; for ( int is1stN = 0; is1stN < 2 && nodesOnBoundary; ++is1stN ) @@ -362,14 +369,14 @@ bool StdMeshers_Import_1D2D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & const SMDS_MeshNode* n = is1stN ? link.node1() : link.node2(); if ( !subShapeIDs.count( n->getshapeId() )) { - for ( unsigned iE = 0; iE < edges.size(); ++iE ) + for ( size_t iE = 0; iE < edges.size(); ++iE ) if ( helper.CheckNodeU( edges[iE], n, u=0, projTol, /*force=*/true )) { BRep_Tool::Range(edges[iE],f,l); if ( Abs(u-f) < 2 * faceTol || Abs(u-l) < 2 * faceTol ) // duplicated node on vertex return error("Source elements overlap one another"); - tgtSM->RemoveNode( n, /*isNodeDeleted=*/false ); + tgtFaceSM->RemoveNode( n, /*isNodeDeleted=*/false ); tgtMesh->SetNodeOnEdge( (SMDS_MeshNode*)n, edges[iE], u ); break; } @@ -421,7 +428,7 @@ bool StdMeshers_Import_1D2D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & TopoDS_Edge geomEdge = TopoDS::Edge(bndShapes.back()); helper.CheckNodeU( geomEdge, link._medium, u, 10*faceTol, /*force=*/true ); - tgtSM->RemoveNode( link._medium, /*isNodeDeleted=*/false ); + tgtFaceSM->RemoveNode( link._medium, /*isNodeDeleted=*/false ); tgtMesh->SetNodeOnEdge( (SMDS_MeshNode*)link._medium, geomEdge, u ); } else @@ -468,16 +475,97 @@ bool StdMeshers_Import_1D2D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & if ( !isFaceMeshed ) return error( "Source elements don't cover totally the geometrical face" ); + if ( helper.HasSeam() ) + { + // links on seam edges are shared by two faces, so no edges were created on them + // by the previous detection of 2D mesh boundary + for ( size_t iE = 0; iE < edges.size(); ++iE ) + { + if ( !helper.IsRealSeam( edges[iE] )) continue; + const TopoDS_Edge& seamEdge = edges[iE]; + // to find nodes lying on the seamEdge we check nodes of mesh faces sharing a node on one + // of its vertices; after finding another node on seamEdge we continue the same way + // until finding all nodes. + TopoDS_Vertex seamVertex = helper.IthVertex( 0, seamEdge ); + const SMDS_MeshNode* vertNode = SMESH_Algo::VertexNode( seamVertex, tgtMesh ); + set< const SMDS_MeshNode* > checkedNodes; checkedNodes.insert( vertNode ); + set< const SMDS_MeshElement* > checkedFaces; + // as a face can have more than one node on the seamEdge, there is a difficulty in selecting + // one of those nodes to treat next; so we simply find all nodes on the seamEdge and + // then sort them by U on edge + typedef list< pair< double, const SMDS_MeshNode* > > TUNodeList; + TUNodeList nodesOnSeam; + double u = helper.GetNodeU( seamEdge, vertNode ); + nodesOnSeam.push_back( make_pair( u, vertNode )); + TUNodeList::iterator u2nIt = nodesOnSeam.begin(); + for ( ; u2nIt != nodesOnSeam.end(); ++u2nIt ) + { + const SMDS_MeshNode* startNode = (*u2nIt).second; + SMDS_ElemIteratorPtr faceIt = startNode->GetInverseElementIterator( SMDSAbs_Face ); + while ( faceIt->more() ) + { + const SMDS_MeshElement* face = faceIt->next(); + if ( !checkedFaces.insert( face ).second ) continue; + for ( int i = 0, nbNodes = face->NbCornerNodes(); i < nbNodes; ++i ) + { + const SMDS_MeshNode* n = face->GetNode( i ); + if ( n == startNode || !checkedNodes.insert( n ).second ) continue; + if ( helper.CheckNodeU( seamEdge, n, u=0, projTol, /*force=*/true )) + nodesOnSeam.push_back( make_pair( u, n )); + } + } + } + // sort the found nodes by U on the seamEdge; most probably they are in a good order, + // so we can use the hint to spead-up map filling + map< double, const SMDS_MeshNode* > u2nodeMap; + for ( u2nIt = nodesOnSeam.begin(); u2nIt != nodesOnSeam.end(); ++u2nIt ) + u2nodeMap.insert( u2nodeMap.end(), *u2nIt ); + + // create edges + { + SMESH_MesherHelper seamHelper( theMesh ); + seamHelper.SetSubShape( edges[ iE ]); + seamHelper.SetElementsOnShape( true ); + + if ( (*checkedFaces.begin())->IsQuadratic() ) + for ( set< const SMDS_MeshElement* >::iterator fIt = checkedFaces.begin(); + fIt != checkedFaces.end(); ++fIt ) + seamHelper.AddTLinks( static_cast( *fIt )); + + map< double, const SMDS_MeshNode* >::iterator n1, n2, u2nEnd = u2nodeMap.end(); + for ( n2 = u2nodeMap.begin(), n1 = n2++; n2 != u2nEnd; ++n1, ++n2 ) + { + const SMDS_MeshNode* node1 = n1->second; + const SMDS_MeshNode* node2 = n2->second; + seamHelper.AddEdge( node1, node2 ); + if ( node2->getshapeId() == helper.GetSubShapeID() ) + { + tgtFaceSM->RemoveNode( node2, /*isNodeDeleted=*/false ); + tgtMesh->SetNodeOnEdge( const_cast( node2 ), seamEdge, n2->first ); + } + } + } + } // loop on edges to find seam ones + } // if ( helper.HasSeam() ) + // notify sub-meshes of edges on computation - for ( unsigned iE = 0; iE < edges.size(); ++iE ) - theMesh.GetSubMesh( edges[iE] )->ComputeStateEngine(SMESH_subMesh::CHECK_COMPUTE_STATE); + for ( size_t iE = 0; iE < edges.size(); ++iE ) + { + SMESH_subMesh * sm = theMesh.GetSubMesh( edges[iE] ); + if ( BRep_Tool::Degenerated( edges[iE] )) + sm->SetIsAlwaysComputed( true ); + sm->ComputeStateEngine(SMESH_subMesh::CHECK_COMPUTE_STATE); + if ( sm->GetComputeState() != SMESH_subMesh::COMPUTE_OK ) + return error(SMESH_Comment("Failed to create segments on the edge ") + << tgtMesh->ShapeToIndex( edges[iE ])); + } // ============ // Copy meshes // ============ vector srcMeshes = _sourceHyp->GetSourceMeshes(); - for ( unsigned i = 0; i < srcMeshes.size(); ++i ) + for ( size_t i = 0; i < srcMeshes.size(); ++i ) StdMeshers_Import_1D::importMesh( srcMeshes[i], theMesh, _sourceHyp, theShape ); return true; -- 2.30.2