-// Copyright (C) 2007-2013 CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2014 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.
+// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
#include "SMESH_Group.hxx"
#include "SMESH_Mesh.hxx"
#include "SMESH_MesherHelper.hxx"
+#include "SMESH_OctreeNode.hxx"
#include "SMESH_subMesh.hxx"
#include "Utils_SALOME_Exception.hxx"
{
if ( !_sourceHyp ) return false;
- const vector<SMESH_Group*>& srcGroups = _sourceHyp->GetGroups();
+ const vector<SMESH_Group*>& srcGroups = _sourceHyp->GetGroups(/*loaded=*/true);
if ( srcGroups.empty() )
return error("Invalid source groups");
set<int> subShapeIDs;
subShapeIDs.insert( shapeID );
- // get nodes on vertices
- list < SMESH_TNodeXYZ > vertexNodes;
- list < SMESH_TNodeXYZ >::iterator vNIt;
+ // nodes already existing on sub-shapes of the FACE
+ TIDSortedNodeSet existingNodes;
+
+ // get/make nodes on vertices and add them to existingNodes
TopExp_Explorer exp( theShape, TopAbs_VERTEX );
for ( ; exp.More(); exp.Next() )
{
n = SMESH_Algo::VertexNode( v, tgtMesh );
if ( !n ) return false; // very strange
}
- vertexNodes.push_back( SMESH_TNodeXYZ( n ));
+ existingNodes.insert( n );
+ }
+
+ // get EDGESs and their ids and get existing nodes on EDGEs
+ vector< TopoDS_Edge > edges;
+ for ( exp.Init( theShape, TopAbs_EDGE ); exp.More(); exp.Next() )
+ {
+ const TopoDS_Edge & edge = TopoDS::Edge( exp.Current() );
+ if ( !SMESH_Algo::isDegenerated( edge ))
+ if ( subShapeIDs.insert( tgtMesh->ShapeToIndex( edge )).second )
+ {
+ edges.push_back( edge );
+ if ( SMESHDS_SubMesh* eSM = tgtMesh->MeshElements( edge ))
+ {
+ typedef SMDS_StdIterator< const SMDS_MeshNode*, SMDS_NodeIteratorPtr > iterator;
+ existingNodes.insert( iterator( eSM->GetNodes() ), iterator() );
+ }
+ }
}
+ // octree to find existing nodes
+ SMESH_OctreeNode existingNodeOcTr( existingNodes );
+ std::map<double, const SMDS_MeshNode*> dist2foundNodes;
// to count now many times a link between nodes encounters
map<TLink, int> linkCount;
SMDS_MeshElement::iterator node = face->begin_nodes();
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;
+ StdMeshers_Import_1D::TNodeNodeMap::iterator n2nIt =
+ n2n->insert( make_pair( *node, (SMDS_MeshNode*)0 )).first;
if ( n2nIt->second )
{
- if ( !subShapeIDs.count( n2nIt->second->getshapeId() ))
+ if ( !subShapeIDs.count( n2nIt->second->getshapeId() )) // node already on an EDGE
break;
}
else
{
- // find an existing vertex node
- for ( vNIt = vertexNodes.begin(); vNIt != vertexNodes.end(); ++vNIt)
- if ( vNIt->SquareDistance( *node ) < groupTol * groupTol)
- {
- (*n2nIt).second = vNIt->_node;
- vertexNodes.erase( vNIt );
- break;
- }
+ // find a pre-existing node
+ dist2foundNodes.clear();
+ existingNodeOcTr.NodesAround( SMESH_TNodeXYZ( *node ), dist2foundNodes, groupTol );
+ if ( !dist2foundNodes.empty() )
+ (*n2nIt).second = dist2foundNodes.begin()->second;
}
if ( !n2nIt->second )
{
continue; // repeated face in source groups already created
// check future face orientation
+ const int nbCorners = face->NbCornerNodes();
+ const bool isQuad = ( nbCorners != (int) newNodes.size() );
if ( toCheckOri )
{
int iNode = -1;
surface->D1( uv.X(),uv.Y(), p, du,dv );
geomNorm = reverse ? dv^du : du^dv;
}
- while ( geomNorm.SquareMagnitude() < 1e-6 && iNode+1 < face->NbCornerNodes());
+ while ( geomNorm.SquareMagnitude() < 1e-6 && iNode+1 < nbCorners );
- int iNext = helper.WrapIndex( iNode+1, face->NbCornerNodes() );
- int iPrev = helper.WrapIndex( iNode-1, face->NbCornerNodes() );
+ int iNext = helper.WrapIndex( iNode+1, nbCorners );
+ int iPrev = helper.WrapIndex( iNode-1, nbCorners );
SMESH_TNodeXYZ prevNode( newNodes[iPrev] );
SMESH_TNodeXYZ curNode ( newNodes[iNode] );
gp_Vec meshNorm = n1n2 ^ n1n0;
if ( geomNorm * meshNorm < 0 )
- std::reverse( newNodes.begin(), newNodes.end() );
+ SMDS_MeshCell::applyInterlace
+ ( SMDS_MeshCell::reverseSmdsOrder( face->GetEntityType() ), newNodes );
}
// make a new face
- switch ( newNodes.size() )
- {
- case 3:
- newFace = tgtMesh->AddFace( newNodes[0], newNodes[1], newNodes[2] );
- break;
- case 4:
- newFace = tgtMesh->AddFace( newNodes[0], newNodes[1], newNodes[2], newNodes[3] );
- break;
- case 6:
- newFace = tgtMesh->AddFace( newNodes[0], newNodes[1], newNodes[2],
- newNodes[3], newNodes[4], newNodes[5]);
- break;
- case 8:
- newFace = tgtMesh->AddFace( newNodes[0], newNodes[1], newNodes[2], newNodes[3],
- newNodes[4], newNodes[5], newNodes[6], newNodes[7]);
- break;
- default: continue;
- }
+ if ( face->IsPoly() )
+ newFace = tgtMesh->AddPolygonalFace( newNodes );
+ else
+ switch ( newNodes.size() )
+ {
+ case 3:
+ newFace = tgtMesh->AddFace( newNodes[0], newNodes[1], newNodes[2] );
+ break;
+ case 4:
+ newFace = tgtMesh->AddFace( newNodes[0], newNodes[1], newNodes[2], newNodes[3] );
+ break;
+ case 6:
+ newFace = tgtMesh->AddFace( newNodes[0], newNodes[1], newNodes[2],
+ newNodes[3], newNodes[4], newNodes[5]);
+ break;
+ case 8:
+ newFace = tgtMesh->AddFace( newNodes[0], newNodes[1], newNodes[2], newNodes[3],
+ newNodes[4], newNodes[5], newNodes[6], newNodes[7]);
+ break;
+ default: continue;
+ }
tgtMesh->SetMeshElementOnShape( newFace, shapeID );
e2e->insert( make_pair( face, newFace ));
// collect links
- int nbNodes = face->NbCornerNodes();
const SMDS_MeshNode* medium = 0;
- for ( int i = 0; i < nbNodes; ++i )
+ for ( int i = 0; i < nbCorners; ++i )
{
const SMDS_MeshNode* n1 = newNodes[i];
- const SMDS_MeshNode* n2 = newNodes[ (i+1)%nbNodes ];
- if ( newFace->IsQuadratic() )
- medium = newNodes[i+nbNodes];
+ const SMDS_MeshNode* n2 = newNodes[ (i+1)%nbCorners ];
+ if ( isQuad ) // quadratic face
+ medium = newNodes[i+nbCorners];
link2Nb = linkCount.insert( make_pair( TLink( n1, n2, medium ), 0)).first;
++link2Nb->second;
// if ( link2Nb->second == 1 )
// check if the whole geom face is covered by imported faces
// ==========================================================
- vector< TopoDS_Edge > edges;
- for ( exp.Init( theShape, TopAbs_EDGE ); exp.More(); exp.Next() )
- if ( subShapeIDs.insert( tgtMesh->ShapeToIndex( exp.Current() )).second )
- edges.push_back( TopoDS::Edge( exp.Current() ));
-
// use large tolerance for projection of nodes to edges because of
// BLSURF mesher specifics (issue 0020918, Study2.hdf)
const double projTol = minGroupTol;
for ( int is1stN = 0; is1stN < 2 && nodesOnBoundary; ++is1stN )
{
const SMDS_MeshNode* n = is1stN ? link.node1() : link.node2();
- if ( !subShapeIDs.count( n->getshapeId() ))
+ if ( !subShapeIDs.count( n->getshapeId() )) // n is assigned to FACE
{
for ( size_t iE = 0; iE < edges.size(); ++iE )
if ( helper.CheckNodeU( edges[iE], n, u=0, projTol, /*force=*/true ))
// duplicated node on vertex
return error("Source elements overlap one another");
tgtFaceSM->RemoveNode( n, /*isNodeDeleted=*/false );
- tgtMesh->SetNodeOnEdge( (SMDS_MeshNode*)n, edges[iE], u );
+ tgtMesh->SetNodeOnEdge( n, edges[iE], u );
break;
}
nodesOnBoundary = subShapeIDs.count( n->getshapeId());
error("free internal link"); // just for an easier debug
break;
}
- if ( bndShapes.front().ShapeType() == TopAbs_EDGE &&
+ if ( bndShapes.front().ShapeType() == TopAbs_EDGE && // all link nodes are on EDGEs
bndShapes.front() != bndShapes.back() )
// link nodes on different geom edges
return error(COMPERR_BAD_INPUT_MESH, "Source nodes mismatch target vertices");
// find geom edge the link is on
- if ( bndShapes.back().ShapeType() != TopAbs_EDGE )
+ if ( bndShapes.back().ShapeType() != TopAbs_EDGE ) // all link nodes are on VERTEXes
{
// find geom edge by two vertices
TopoDS_Shape geomEdge = helper.GetCommonAncestor( bndShapes.back(),
if ( link._reversed ) std::swap( newNodes[0], newNodes[1] );
if ( link._medium )
{
- newNodes.push_back( link._medium );
- edge = tgtMesh->AddEdge( newNodes[0], newNodes[1], newNodes[2] );
+ edge = tgtMesh->AddEdge( newNodes[0], newNodes[1], link._medium );
TopoDS_Edge geomEdge = TopoDS::Edge(bndShapes.back());
helper.CheckNodeU( geomEdge, link._medium, u, projTol, /*force=*/true );
int sId = editor.FindShape( edge );
nbEdges += subShapeIDs.count( sId );
}
- if ( nbEdges < 2 )
+ if ( nbEdges < 2 && !helper.IsRealSeam( s ))
return false; // weird
if ( nbEdges > 2 )
return error( COMPERR_BAD_INPUT_MESH, "Source elements overlap one another");
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 );
+ // if ( SMESH_Algo::isDegenerated( 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 ")