IPAL53561: Extrusion 3D algo is not applicable to a prism with a seam on top/bottom

This commit is contained in:
eap 2016-09-07 14:43:02 +03:00
parent 7d8e88b13c
commit ac96f997ef
5 changed files with 116 additions and 65 deletions

View File

@ -21,6 +21,8 @@
# @package StdMeshersBuilder # @package StdMeshersBuilder
# Python API for the standard meshing plug-in module. # Python API for the standard meshing plug-in module.
LIBRARY = "libStdMeshersEngine.so"
from salome.smesh.smesh_algorithm import Mesh_Algorithm from salome.smesh.smesh_algorithm import Mesh_Algorithm
import StdMeshers import StdMeshers
@ -961,10 +963,8 @@ class StdMeshersBuilder_Prism3D(Mesh_Algorithm):
shape = geom shape = geom
if not shape: if not shape:
shape = mesh.geom shape = mesh.geom
from salome.geom import geomBuilder isRadial = mesh.smeshpyD.IsApplicable("RadialPrism_3D", LIBRARY, shape, False )
nbSolids = len( geomBuilder.geom.SubShapeAll( shape, geomBuilder.geomBuilder.ShapeType["SOLID"] )) if not isRadial:
nbShells = len( geomBuilder.geom.SubShapeAll( shape, geomBuilder.geomBuilder.ShapeType["SHELL"] ))
if nbSolids == 0 or nbSolids == nbShells:
self.Create(mesh, geom, "Prism_3D") self.Create(mesh, geom, "Prism_3D")
pass pass
else: else:

View File

@ -29,7 +29,6 @@ INCLUDE_DIRECTORIES(
${Boost_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS}
${VTK_INCLUDE_DIRS} ${VTK_INCLUDE_DIRS}
${KERNEL_INCLUDE_DIRS} ${KERNEL_INCLUDE_DIRS}
${GUI_INCLUDE_DIRS}
${GEOM_INCLUDE_DIRS} ${GEOM_INCLUDE_DIRS}
${PROJECT_SOURCE_DIR}/src/SMESHUtils ${PROJECT_SOURCE_DIR}/src/SMESHUtils
${PROJECT_SOURCE_DIR}/src/SMESH ${PROJECT_SOURCE_DIR}/src/SMESH

View File

@ -944,11 +944,10 @@ bool StdMeshers_Prism_3D::getWallFaces( Prism_3D::TPrismTopo & thePrism,
std::list< int >::iterator nbE = thePrism.myNbEdgesInWires.begin(); std::list< int >::iterator nbE = thePrism.myNbEdgesInWires.begin();
std::list< int > nbQuadsPerWire; std::list< int > nbQuadsPerWire;
int iE = 0; int iE = 0;
double f,l;
while ( edge != thePrism.myBottomEdges.end() ) while ( edge != thePrism.myBottomEdges.end() )
{ {
++iE; ++iE;
if ( BRep_Tool::Curve( *edge, f,l ).IsNull() ) if ( SMESH_Algo::isDegenerated( *edge ))
{ {
edge = thePrism.myBottomEdges.erase( edge ); edge = thePrism.myBottomEdges.erase( edge );
--iE; --iE;
@ -956,12 +955,14 @@ bool StdMeshers_Prism_3D::getWallFaces( Prism_3D::TPrismTopo & thePrism,
} }
else else
{ {
bool hasWallFace = false;
TopTools_ListIteratorOfListOfShape faceIt( edgeToFaces.FindFromKey( *edge )); TopTools_ListIteratorOfListOfShape faceIt( edgeToFaces.FindFromKey( *edge ));
for ( ; faceIt.More(); faceIt.Next() ) for ( ; faceIt.More(); faceIt.Next() )
{ {
const TopoDS_Face& face = TopoDS::Face( faceIt.Value() ); const TopoDS_Face& face = TopoDS::Face( faceIt.Value() );
if ( !thePrism.myBottom.IsSame( face )) if ( !thePrism.myBottom.IsSame( face ))
{ {
hasWallFace = true;
Prism_3D::TQuadList quadList( 1, quadAlgo->CheckNbEdges( *mesh, face )); Prism_3D::TQuadList quadList( 1, quadAlgo->CheckNbEdges( *mesh, face ));
if ( !quadList.back() ) if ( !quadList.back() )
return toSM( error(TCom("Side face #") << shapeID( face ) return toSM( error(TCom("Side face #") << shapeID( face )
@ -980,7 +981,16 @@ bool StdMeshers_Prism_3D::getWallFaces( Prism_3D::TPrismTopo & thePrism,
break; break;
} }
} }
++edge; if ( hasWallFace )
{
++edge;
}
else // seam edge (IPAL53561)
{
edge = thePrism.myBottomEdges.erase( edge );
--iE;
--(*nbE);
}
} }
if ( iE == *nbE ) if ( iE == *nbE )
{ {
@ -1210,7 +1220,8 @@ bool StdMeshers_Prism_3D::compute(const Prism_3D::TPrismTopo& thePrism)
for ( ; bot_column != myBotToColumnMap.end(); ++bot_column ) for ( ; bot_column != myBotToColumnMap.end(); ++bot_column )
{ {
const Prism_3D::TNode& tBotNode = bot_column->first; // bottom TNode const Prism_3D::TNode& tBotNode = bot_column->first; // bottom TNode
if ( tBotNode.GetPositionType() != SMDS_TOP_FACE ) if ( tBotNode.GetPositionType() != SMDS_TOP_FACE &&
myBlock.HasNodeColumn( tBotNode.myNode ))
continue; // node is not inside the FACE continue; // node is not inside the FACE
// column nodes; middle part of the column are zero pointers // column nodes; middle part of the column are zero pointers
@ -1314,16 +1325,17 @@ bool StdMeshers_Prism_3D::compute(const Prism_3D::TPrismTopo& thePrism)
for ( int i = 0; i < nbNodes; ++i ) for ( int i = 0; i < nbNodes; ++i )
{ {
const SMDS_MeshNode* n = face->GetNode( i ); const SMDS_MeshNode* n = face->GetNode( i );
if ( n->GetPosition()->GetTypeOfPosition() == SMDS_TOP_FACE ) { columns[ i ] = NULL;
if ( n->GetPosition()->GetTypeOfPosition() != SMDS_TOP_FACE )
columns[ i ] = myBlock.GetNodeColumn( n );
if ( !columns[ i ] )
{
TNode2ColumnMap::iterator bot_column = myBotToColumnMap.find( n ); TNode2ColumnMap::iterator bot_column = myBotToColumnMap.find( n );
if ( bot_column == myBotToColumnMap.end() ) if ( bot_column == myBotToColumnMap.end() )
return toSM( error(TCom("No nodes found above node ") << n->GetID() ));
columns[ i ] = & bot_column->second;
}
else {
columns[ i ] = myBlock.GetNodeColumn( n );
if ( !columns[ i ] )
return toSM( error(TCom("No side nodes found above node ") << n->GetID() )); return toSM( error(TCom("No side nodes found above node ") << n->GetID() ));
columns[ i ] = & bot_column->second;
} }
} }
// create prisms // create prisms
@ -2074,7 +2086,8 @@ bool StdMeshers_Prism_3D::assocOrProjBottom2Top( const gp_Trsf & bottomToTopTrsf
{ {
const SMDS_MeshNode* botNode = bN_tN->first; const SMDS_MeshNode* botNode = bN_tN->first;
const SMDS_MeshNode* topNode = bN_tN->second; const SMDS_MeshNode* topNode = bN_tN->second;
if ( botNode->GetPosition()->GetTypeOfPosition() != SMDS_TOP_FACE ) if ( botNode->GetPosition()->GetTypeOfPosition() != SMDS_TOP_FACE &&
myBlock.HasNodeColumn( botNode ))
continue; // wall columns are contained in myBlock continue; // wall columns are contained in myBlock
// create node column // create node column
Prism_3D::TNode bN( botNode ); Prism_3D::TNode bN( botNode );
@ -2523,13 +2536,15 @@ namespace // utils used by StdMeshers_Prism_3D::IsApplicable()
struct EdgeWithNeighbors struct EdgeWithNeighbors
{ {
TopoDS_Edge _edge; TopoDS_Edge _edge;
int _iL, _iR; int _iBase; /* index in a WIRE with non-base EDGEs excluded */
EdgeWithNeighbors(const TopoDS_Edge& E, int iE, int nbE, int shift = 0 ): int _iL, _iR; /* used to connect edges in a base FACE */
_edge( E ), bool _isBase; /* is used in a base FACE */
EdgeWithNeighbors(const TopoDS_Edge& E, int iE, int nbE, int shift, bool isBase ):
_edge( E ), _iBase( iE + shift ),
_iL( SMESH_MesherHelper::WrapIndex( iE-1, nbE ) + shift ), _iL( SMESH_MesherHelper::WrapIndex( iE-1, nbE ) + shift ),
_iR( SMESH_MesherHelper::WrapIndex( iE+1, nbE ) + shift ) _iR( SMESH_MesherHelper::WrapIndex( iE+1, nbE ) + shift ),
_isBase( isBase )
{ {
//_edge.Orientation( TopAbs_FORWARD ); // for operator==() to work
} }
EdgeWithNeighbors() {} EdgeWithNeighbors() {}
bool IsInternal() const { return !_edge.IsNull() && _edge.Orientation() == TopAbs_INTERNAL; } bool IsInternal() const { return !_edge.IsNull() && _edge.Orientation() == TopAbs_INTERNAL; }
@ -2571,13 +2586,29 @@ namespace // utils used by StdMeshers_Prism_3D::IsApplicable()
return false; return false;
} }
}; };
//--------------------------------------------------------------------------------
/*!
* \brief Return another faces sharing an edge
*/
const TopoDS_Face & getAnotherFace( const TopoDS_Face& face,
const TopoDS_Edge& edge,
TopTools_IndexedDataMapOfShapeListOfShape& facesOfEdge)
{
TopTools_ListIteratorOfListOfShape faceIt( facesOfEdge.FindFromKey( edge ));
for ( ; faceIt.More(); faceIt.Next() )
if ( !face.IsSame( faceIt.Value() ))
return TopoDS::Face( faceIt.Value() );
return face;
}
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
/*! /*!
* \brief Return ordered edges of a face * \brief Return ordered edges of a face
*/ */
bool getEdges( const TopoDS_Face& face, bool getEdges( const TopoDS_Face& face,
vector< EdgeWithNeighbors > & edges, vector< EdgeWithNeighbors > & edges,
const bool noHolesAllowed) TopTools_IndexedDataMapOfShapeListOfShape& facesOfEdge,
const bool noHolesAllowed)
{ {
TopoDS_Face f = face; TopoDS_Face f = face;
if ( f.Orientation() != TopAbs_FORWARD && if ( f.Orientation() != TopAbs_FORWARD &&
@ -2589,26 +2620,40 @@ namespace // utils used by StdMeshers_Prism_3D::IsApplicable()
if ( nbW > 1 && noHolesAllowed ) if ( nbW > 1 && noHolesAllowed )
return false; return false;
int iE, nbTot = 0; int iE, nbTot = 0, nbBase, iBase;
list< TopoDS_Edge >::iterator e = ee.begin(); list< TopoDS_Edge >::iterator e = ee.begin();
list< int >::iterator nbE = nbEdgesInWires.begin(); list< int >::iterator nbE = nbEdgesInWires.begin();
for ( ; nbE != nbEdgesInWires.end(); ++nbE ) for ( ; nbE != nbEdgesInWires.end(); ++nbE )
for ( iE = 0; iE < *nbE; ++e, ++iE ) for ( iE = 0; iE < *nbE; ++e, ++iE )
if ( SMESH_Algo::isDegenerated( *e )) if ( SMESH_Algo::isDegenerated( *e )) // degenerated EDGE is never used
{ {
e = --ee.erase( e ); e = --ee.erase( e );
--(*nbE); --(*nbE);
--iE; --iE;
} }
vector<int> isBase;
edges.clear(); edges.clear();
e = ee.begin(); e = ee.begin();
for ( nbE = nbEdgesInWires.begin(); nbE != nbEdgesInWires.end(); ++nbE ) for ( nbE = nbEdgesInWires.begin(); nbE != nbEdgesInWires.end(); ++nbE )
{ {
for ( iE = 0; iE < *nbE; ++e, ++iE ) nbBase = 0;
edges.push_back( EdgeWithNeighbors( *e, iE, *nbE, nbTot )); isBase.resize( *nbE );
nbTot += *nbE; list< TopoDS_Edge >::iterator eIt = e;
for ( iE = 0; iE < *nbE; ++eIt, ++iE )
{
isBase[ iE ] = ( getAnotherFace( face, *eIt, facesOfEdge ) != face );
nbBase += isBase[ iE ];
}
for ( iBase = 0, iE = 0; iE < *nbE; ++e, ++iE )
{
edges.push_back( EdgeWithNeighbors( *e, iBase, nbBase, nbTot, isBase[ iE ] ));
iBase += isBase[ iE ];
}
nbTot += nbBase;
} }
if ( nbTot == 0 )
return false;
// IPAL53099. Set correct neighbors to INTERNAL EDGEs, which can be connected to // IPAL53099. Set correct neighbors to INTERNAL EDGEs, which can be connected to
// EDGEs of the outer WIRE but this fact can't be detected by their order. // EDGEs of the outer WIRE but this fact can't be detected by their order.
@ -2623,6 +2668,9 @@ namespace // utils used by StdMeshers_Prism_3D::IsApplicable()
bool isConnectOk = ( vv[0].IsSame( vv[1] )); bool isConnectOk = ( vv[0].IsSame( vv[1] ));
if ( !isConnectOk ) if ( !isConnectOk )
{ {
edges[ iFirst ]._iL = edges[ iFirst ]._iBase; // connect to self
edges[ iLast ]._iR = edges[ iLast ]._iBase;
// look for an EDGE of the outer WIRE connected to vv // look for an EDGE of the outer WIRE connected to vv
TopoDS_Vertex v0, v1; TopoDS_Vertex v0, v1;
for ( iE = 0; iE < nbEdgesInWires.front(); ++iE ) for ( iE = 0; iE < nbEdgesInWires.front(); ++iE )
@ -2630,9 +2678,9 @@ namespace // utils used by StdMeshers_Prism_3D::IsApplicable()
v0 = SMESH_MesherHelper::IthVertex( 0, edges[ iE ]._edge ); v0 = SMESH_MesherHelper::IthVertex( 0, edges[ iE ]._edge );
v1 = SMESH_MesherHelper::IthVertex( 1, edges[ iE ]._edge ); v1 = SMESH_MesherHelper::IthVertex( 1, edges[ iE ]._edge );
if ( vv[0].IsSame( v0 ) || vv[0].IsSame( v1 )) if ( vv[0].IsSame( v0 ) || vv[0].IsSame( v1 ))
edges[ iFirst ]._iL = iE; edges[ iFirst ]._iL = edges[ iE ]._iBase;
if ( vv[1].IsSame( v0 ) || vv[1].IsSame( v1 )) if ( vv[1].IsSame( v0 ) || vv[1].IsSame( v1 ))
edges[ iLast ]._iR = iE; edges[ iLast ]._iR = edges[ iE ]._iBase;
} }
} }
iFirst += *nbE; iFirst += *nbE;
@ -2640,21 +2688,7 @@ namespace // utils used by StdMeshers_Prism_3D::IsApplicable()
} }
return edges.size(); return edges.size();
} }
//--------------------------------------------------------------------------------
/*!
* \brief Return another faces sharing an edge
*/
const TopoDS_Face & getAnotherFace( const TopoDS_Face& face,
const TopoDS_Edge& edge,
TopTools_IndexedDataMapOfShapeListOfShape& facesOfEdge)
{
TopTools_ListIteratorOfListOfShape faceIt( facesOfEdge.FindFromKey( edge ));
for ( ; faceIt.More(); faceIt.Next() )
if ( !face.IsSame( faceIt.Value() ))
return TopoDS::Face( faceIt.Value() );
return face;
}
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
/*! /*!
* \brief Return number of faces sharing given edges * \brief Return number of faces sharing given edges
@ -2694,10 +2728,10 @@ bool StdMeshers_Prism_3D::IsApplicable(const TopoDS_Shape & shape, bool toCheckA
// check nb shells // check nb shells
TopoDS_Shape shell; TopoDS_Shape shell;
TopExp_Explorer shExp( sExp.Current(), TopAbs_SHELL ); TopExp_Explorer shExp( sExp.Current(), TopAbs_SHELL );
if ( shExp.More() ) { while ( shExp.More() ) {
shell = shExp.Current(); shell = shExp.Current();
shExp.Next(); shExp.Next();
if ( shExp.More() ) if ( shExp.More() && BRep_Tool::IsClosed( shExp.Current() ))
shell.Nullify(); shell.Nullify();
} }
if ( shell.IsNull() ) { if ( shell.IsNull() ) {
@ -2706,7 +2740,7 @@ bool StdMeshers_Prism_3D::IsApplicable(const TopoDS_Shape & shape, bool toCheckA
} }
// get all faces // get all faces
TopTools_IndexedMapOfShape allFaces; TopTools_IndexedMapOfShape allFaces;
TopExp::MapShapes( shell, TopAbs_FACE, allFaces ); TopExp::MapShapes( sExp.Current(), TopAbs_FACE, allFaces );
if ( allFaces.Extent() < 3 ) { if ( allFaces.Extent() < 3 ) {
if ( toCheckAll ) return false; if ( toCheckAll ) return false;
continue; continue;
@ -2723,7 +2757,7 @@ bool StdMeshers_Prism_3D::IsApplicable(const TopoDS_Shape & shape, bool toCheckA
} }
} }
#ifdef _DEBUG_ #ifdef _DEBUG_
TopTools_IndexedMapOfShape allShapes; TopTools_IndexedMapOfShape allShapes; // usage: allShapes.FindIndex( s )
TopExp::MapShapes( shape, allShapes ); TopExp::MapShapes( shape, allShapes );
#endif #endif
@ -2750,23 +2784,32 @@ bool StdMeshers_Prism_3D::IsApplicable(const TopoDS_Shape & shape, bool toCheckA
TEdgeWithNeighborsVec& botEdges = faceEdgesVec[ iF ]; TEdgeWithNeighborsVec& botEdges = faceEdgesVec[ iF ];
if ( botEdges.empty() ) if ( botEdges.empty() )
if ( !getEdges( botF, botEdges, /*noHoles=*/false )) if ( !getEdges( botF, botEdges, facesOfEdge, /*noHoles=*/false ))
break; break;
if ( allFaces.Extent()-1 <= (int) botEdges.size() )
int nbBase = 0;
for ( size_t iS = 0; iS < botEdges.size(); ++iS )
nbBase += botEdges[ iS ]._isBase;
if ( allFaces.Extent()-1 <= nbBase )
continue; // all faces are adjacent to botF - no top FACE continue; // all faces are adjacent to botF - no top FACE
// init data of side FACEs // init data of side FACEs
sides.clear(); sides.clear();
sides.resize( botEdges.size() ); sides.resize( nbBase );
for ( size_t iS = 0; iS < botEdges.size(); ++iS ) size_t iS = 0;
for ( size_t iE = 0; iE < botEdges.size(); ++iE )
{ {
sides[ iS ]._topEdge = botEdges[ iS ]._edge; if ( !botEdges[ iE ]._isBase )
continue;
sides[ iS ]._topEdge = botEdges[ iE ]._edge;
sides[ iS ]._face = botF; sides[ iS ]._face = botF;
sides[ iS ]._leftSide = & sides[ botEdges[ iS ]._iR ]; sides[ iS ]._leftSide = & sides[ botEdges[ iE ]._iR ];
sides[ iS ]._rightSide = & sides[ botEdges[ iS ]._iL ]; sides[ iS ]._rightSide = & sides[ botEdges[ iE ]._iL ];
sides[ iS ]._isInternal = botEdges[ iS ].IsInternal(); sides[ iS ]._isInternal = botEdges[ iE ].IsInternal();
sides[ iS ]._faces = & facesOfSide[ iS ]; sides[ iS ]._faces = & facesOfSide[ iS ];
sides[ iS ]._faces->Clear(); sides[ iS ]._faces->Clear();
++iS;
} }
bool isOK = true; // ok for a current botF bool isOK = true; // ok for a current botF
@ -2861,7 +2904,7 @@ bool StdMeshers_Prism_3D::IsApplicable(const TopoDS_Shape & shape, bool toCheckA
int faceID = allFaces.FindIndex( side._face ); int faceID = allFaces.FindIndex( side._face );
side._edges = & faceEdgesVec[ faceID ]; side._edges = & faceEdgesVec[ faceID ];
if ( side._edges->empty() ) if ( side._edges->empty() )
if ( !getEdges( side._face, * side._edges, /*noHoles=*/true )) if ( !getEdges( side._face, * side._edges, facesOfEdge, /*noHoles=*/true ))
break; break;
const int nbE = side._edges->size(); const int nbE = side._edges->size();
if ( nbE >= 4 ) if ( nbE >= 4 )

View File

@ -185,6 +185,16 @@ class STDMESHERS_EXPORT StdMeshers_PrismAsBlock: public SMESH_Block
return col_frw.first; return col_frw.first;
} }
/*!
* \brief Return pointer to column of nodes
* \param node - bottom node from which the returned column goes up
* \retval const TNodeColumn* - the found column
*/
bool HasNodeColumn(const SMDS_MeshNode* node) const
{
return myShapeIndex2ColumnMap.count( node->getshapeId() );
}
/*! /*!
* \brief Return transformations to get coordinates of nodes of each internal layer * \brief Return transformations to get coordinates of nodes of each internal layer
* by nodes of the bottom. Layer is a set of nodes at a certain step * by nodes of the bottom. Layer is a set of nodes at a certain step

View File

@ -414,9 +414,8 @@ namespace {
const gp_Pnt2d& uv, const gp_Pnt2d& uv,
const double& tol2d ) const double& tol2d )
{ {
TopoDS_Vertex VV[2]; TopoDS_Vertex V = SMESH_MesherHelper::IthVertex( vIndex, edge, /*CumOri=*/true );
TopExp::Vertices( edge, VV[0], VV[1], true); gp_Pnt2d v1UV = BRep_Tool::Parameters( V, face);
gp_Pnt2d v1UV = BRep_Tool::Parameters( VV[vIndex], face);
double dist2d = v1UV.Distance( uv ); double dist2d = v1UV.Distance( uv );
return dist2d < tol2d; return dist2d < tol2d;
} }
@ -1111,8 +1110,8 @@ bool StdMeshers_ProjectionUtils::FindSubShapeAssociation(const TopoDS_Shape& the
for ( ; eIt1 != edges1.end(); ++eIt1, ++eIt2 ) for ( ; eIt1 != edges1.end(); ++eIt1, ++eIt2 )
{ {
InsertAssociation( *eIt1, *eIt2, theMap ); InsertAssociation( *eIt1, *eIt2, theMap );
VV1[0] = TopExp::FirstVertex( *eIt1, true ); VV1[0] = SMESH_MesherHelper::IthVertex( 0, *eIt1, true );
VV2[0] = TopExp::FirstVertex( *eIt2, true ); VV2[0] = SMESH_MesherHelper::IthVertex( 0, *eIt2, true );
InsertAssociation( VV1[0], VV2[0], theMap ); InsertAssociation( VV1[0], VV2[0], theMap );
} }
InsertAssociation( theShape1, theShape2, theMap ); InsertAssociation( theShape1, theShape2, theMap );