X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FStdMeshers%2FStdMeshers_Prism_3D.cxx;h=99fdbe90fc90f2844f79c88dd166a62dde373ff6;hb=80fe1ddefc561a7a571ac08807f7d173f45d8080;hp=79fd9f82e0e7d49f4c043ddfe1384632f4390f8f;hpb=e4f3043d7d0128e2c8806d9bcf5e84ede8d40be1;p=modules%2Fsmesh.git
diff --git a/src/StdMeshers/StdMeshers_Prism_3D.cxx b/src/StdMeshers/StdMeshers_Prism_3D.cxx
index 79fd9f82e..99fdbe90f 100644
--- a/src/StdMeshers/StdMeshers_Prism_3D.cxx
+++ b/src/StdMeshers/StdMeshers_Prism_3D.cxx
@@ -65,15 +65,16 @@
using namespace std;
#define RETURN_BAD_RESULT(msg) { MESSAGE(")-: Error: " << msg); return false; }
-#define gpXYZ(n) gp_XYZ(n->X(),n->Y(),n->Z())
-#define SHOWYXZ(msg, xyz) // {\
-// gp_Pnt p (xyz); \
-// cout << msg << " ("<< p.X() << "; " <
NbElements() > 0 ) &&
( !theHelper.IsSameElemGeometry( sm, SMDSGeom_QUADRANGLE ) ))
{
- faceFound;
+ faceFound = true;
break;
}
if ( !faceFound )
@@ -212,6 +213,7 @@ namespace {
quad->side[ QUAD_TOP_SIDE ].grid->Reverse();
quad->side[ QUAD_LEFT_SIDE ].grid->Reverse();
int edgeIndex = 0;
+ bool isComposite = false;
for ( size_t i = 0; i < quad->side.size(); ++i )
{
StdMeshers_FaceSidePtr quadSide = quad->side[i];
@@ -219,7 +221,7 @@ namespace {
if ( botE.IsSame( quadSide->Edge( iE )))
{
if ( quadSide->NbEdges() > 1 )
- return false;
+ isComposite = true; //return false;
edgeIndex = i;
i = quad->side.size(); // to quit from the outer loop
break;
@@ -230,7 +232,7 @@ namespace {
quad->face = TopoDS::Face( face );
- return true;
+ return !isComposite;
}
//================================================================================
@@ -425,10 +427,10 @@ namespace {
*/
//================================================================================
- double normAngle(const TopoDS_Edge & E1, const TopoDS_Edge & E2, const TopoDS_Face & F)
- {
- return SMESH_MesherHelper::GetAngle( E1, E2, F ) / ( 0.5 * M_PI );
- }
+ // double normAngle(const TopoDS_Edge & E1, const TopoDS_Edge & E2, const TopoDS_Face & F)
+ // {
+ // return SMESH_MesherHelper::GetAngle( E1, E2, F ) / ( 0.5 * M_PI );
+ // }
//================================================================================
/*!
@@ -654,6 +656,7 @@ bool StdMeshers_Prism_3D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& theSh
meshedFaces.splice( meshedFaces.begin(), notQuadMeshedFaces );
Prism_3D::TPrismTopo prism;
+ myPropagChains = 0;
if ( nbSolids == 1 )
{
@@ -905,10 +908,17 @@ bool StdMeshers_Prism_3D::getWallFaces( Prism_3D::TPrismTopo & thePrism,
if ( !quadList.back() )
return toSM( error(TCom("Side face #") << shapeID( face )
<< " not meshable with quadrangles"));
- if ( ! setBottomEdge( *edge, quadList.back(), face ))
- return toSM( error(TCom("Composite 'horizontal' edges are not supported")));
- thePrism.myWallQuads.push_back( quadList );
- faceMap.Add( face );
+ bool isCompositeBase = ! setBottomEdge( *edge, quadList.back(), face );
+ if ( isCompositeBase )
+ {
+ // it's OK if all EDGEs of the bottom side belongs to the bottom FACE
+ StdMeshers_FaceSidePtr botSide = quadList.back()->side[ QUAD_BOTTOM_SIDE ];
+ for ( int iE = 0; iE < botSide->NbEdges(); ++iE )
+ if ( !myHelper->IsSubShape( botSide->Edge(iE), thePrism.myBottom ))
+ return toSM( error(TCom("Composite 'horizontal' edges are not supported")));
+ }
+ if ( faceMap.Add( face ))
+ thePrism.myWallQuads.push_back( quadList );
break;
}
}
@@ -1076,7 +1086,7 @@ bool StdMeshers_Prism_3D::compute(const Prism_3D::TPrismTopo& thePrism)
// Projections on the top and bottom faces are taken from nodes existing
// on these faces; find correspondence between bottom and top nodes
myBotToColumnMap.clear();
- if ( !assocOrProjBottom2Top( bottomToTopTrsf ) ) // it also fills myBotToColumnMap
+ if ( !assocOrProjBottom2Top( bottomToTopTrsf, thePrism ) ) // it also fills myBotToColumnMap
return false;
@@ -1254,34 +1264,36 @@ bool StdMeshers_Prism_3D::computeWalls(const Prism_3D::TPrismTopo& thePrism)
TProjction1dAlgo* projector1D = TProjction1dAlgo::instance( this );
StdMeshers_Quadrangle_2D* quadAlgo = TQuadrangleAlgo::instance( this, myHelper );
- SMESH_HypoFilter hyp1dFilter( SMESH_HypoFilter::IsAlgo(),/*not=*/true);
- hyp1dFilter.And( SMESH_HypoFilter::HasDim( 1 ));
- hyp1dFilter.And( SMESH_HypoFilter::IsMoreLocalThan( thePrism.myShape3D, *mesh ));
+ // SMESH_HypoFilter hyp1dFilter( SMESH_HypoFilter::IsAlgo(),/*not=*/true);
+ // hyp1dFilter.And( SMESH_HypoFilter::HasDim( 1 ));
+ // hyp1dFilter.And( SMESH_HypoFilter::IsMoreLocalThan( thePrism.myShape3D, *mesh ));
// Discretize equally 'vertical' EDGEs
// -----------------------------------
// find source FACE sides for projection: either already computed ones or
// the 'most composite' ones
- multimap< int, int > wgt2quad;
- for ( size_t iW = 0; iW != thePrism.myWallQuads.size(); ++iW )
+ const size_t nbWalls = thePrism.myWallQuads.size();
+ vector< int > wgt( nbWalls, 0 ); // "weight" of a wall
+ for ( size_t iW = 0; iW != nbWalls; ++iW )
{
Prism_3D::TQuadList::const_iterator quad = thePrism.myWallQuads[iW].begin();
- int wgt = 0; // "weight"
for ( ; quad != thePrism.myWallQuads[iW].end(); ++quad )
{
StdMeshers_FaceSidePtr lftSide = (*quad)->side[ QUAD_LEFT_SIDE ];
for ( int i = 0; i < lftSide->NbEdges(); ++i )
{
- ++wgt;
+ ++wgt[ iW ];
const TopoDS_Edge& E = lftSide->Edge(i);
if ( mesh->GetSubMesh( E )->IsMeshComputed() )
- wgt += 10;
- else if ( mesh->GetHypothesis( E, hyp1dFilter, true )) // local hypothesis!
- wgt += 100;
+ {
+ wgt[ iW ] += 100;
+ wgt[ myHelper->WrapIndex( iW+1, nbWalls)] += 10;
+ wgt[ myHelper->WrapIndex( iW-1, nbWalls)] += 10;
+ }
+ // else if ( mesh->GetHypothesis( E, hyp1dFilter, true )) // local hypothesis!
+ // wgt += 100;
}
}
- wgt2quad.insert( make_pair( wgt, iW ));
-
// in quadratic mesh, pass ignoreMediumNodes to quad sides
if ( myHelper->GetIsQuadratic() )
{
@@ -1291,6 +1303,9 @@ bool StdMeshers_Prism_3D::computeWalls(const Prism_3D::TPrismTopo& thePrism)
(*quad)->side[ i ].grid->SetIgnoreMediumNodes( true );
}
}
+ multimap< int, int > wgt2quad;
+ for ( size_t iW = 0; iW != nbWalls; ++iW )
+ wgt2quad.insert( make_pair( wgt[ iW ], iW ));
// Project 'vertical' EDGEs, from left to right
multimap< int, int >::reverse_iterator w2q = wgt2quad.rbegin();
@@ -1339,7 +1354,11 @@ bool StdMeshers_Prism_3D::computeWalls(const Prism_3D::TPrismTopo& thePrism)
{
const TopoDS_Edge& tgtE = rgtSide->Edge(i);
SMESH_subMesh* tgtSM = mesh->GetSubMesh( tgtE );
- if (( isTgtEdgeComputed[ i ] = tgtSM->IsMeshComputed() )) {
+ if ( !( isTgtEdgeComputed[ i ] = tgtSM->IsMeshComputed() )) {
+ tgtSM->ComputeSubMeshStateEngine( SMESH_subMesh::COMPUTE );
+ tgtSM->ComputeStateEngine ( SMESH_subMesh::COMPUTE );
+ }
+ if ( tgtSM->IsMeshComputed() ) {
++nbTgtMeshed;
nbTgtSegments += tgtSM->GetSubMeshDS()->NbElements();
}
@@ -1348,16 +1367,33 @@ bool StdMeshers_Prism_3D::computeWalls(const Prism_3D::TPrismTopo& thePrism)
{
if ( nbTgtSegments != nbSrcSegments )
{
- for ( int i = 0; i < lftSide->NbEdges(); ++i )
- addBadInputElements( meshDS->MeshElements( lftSide->Edge( i )));
+ bool badMeshRemoved = false;
+ // remove just computed segments
for ( int i = 0; i < rgtSide->NbEdges(); ++i )
- addBadInputElements( meshDS->MeshElements( rgtSide->Edge( i )));
- return toSM( error( TCom("Different nb of segment on logically vertical edges #")
- << shapeID( lftSide->Edge(0) ) << " and #"
- << shapeID( rgtSide->Edge(0) ) << ": "
- << nbSrcSegments << " != " << nbTgtSegments ));
+ if ( !isTgtEdgeComputed[ i ])
+ {
+ const TopoDS_Edge& tgtE = rgtSide->Edge(i);
+ SMESH_subMesh* tgtSM = mesh->GetSubMesh( tgtE );
+ tgtSM->ComputeStateEngine( SMESH_subMesh::CLEAN );
+ badMeshRemoved = true;
+ nbTgtMeshed--;
+ }
+ if ( !badMeshRemoved )
+ {
+ for ( int i = 0; i < lftSide->NbEdges(); ++i )
+ addBadInputElements( meshDS->MeshElements( lftSide->Edge( i )));
+ for ( int i = 0; i < rgtSide->NbEdges(); ++i )
+ addBadInputElements( meshDS->MeshElements( rgtSide->Edge( i )));
+ return toSM( error( TCom("Different nb of segment on logically vertical edges #")
+ << shapeID( lftSide->Edge(0) ) << " and #"
+ << shapeID( rgtSide->Edge(0) ) << ": "
+ << nbSrcSegments << " != " << nbTgtSegments ));
+ }
+ }
+ else // if ( nbTgtSegments == nbSrcSegments )
+ {
+ continue;
}
- continue;
}
// Compute 'vertical projection'
if ( nbTgtMeshed == 0 )
@@ -1399,13 +1435,22 @@ bool StdMeshers_Prism_3D::computeWalls(const Prism_3D::TPrismTopo& thePrism)
// new nodes are on different EDGEs; put one of them on VERTEX
const int edgeIndex = rgtSide->EdgeIndex( srcNodeStr[ iN-1 ].normParam );
const double vertexParam = rgtSide->LastParameter( edgeIndex );
- const gp_Pnt p = BRep_Tool::Pnt( rgtSide->LastVertex( edgeIndex ));
+ TopoDS_Vertex vertex = rgtSide->LastVertex( edgeIndex );
+ const SMDS_MeshNode* vn = SMESH_Algo::VertexNode( vertex, meshDS );
+ const gp_Pnt p = BRep_Tool::Pnt( vertex );
const int isPrev = ( Abs( srcNodeStr[ iN-1 ].normParam - vertexParam ) <
Abs( srcNodeStr[ iN ].normParam - vertexParam ));
meshDS->UnSetNodeOnShape( newNodes[ iN-isPrev ] );
- meshDS->SetNodeOnVertex ( newNodes[ iN-isPrev ], rgtSide->LastVertex( edgeIndex ));
+ meshDS->SetNodeOnVertex ( newNodes[ iN-isPrev ], vertex );
meshDS->MoveNode ( newNodes[ iN-isPrev ], p.X(), p.Y(), p.Z() );
id2type.first = newNodes[ iN-(1-isPrev) ]->getshapeId();
+ if ( vn )
+ {
+ SMESH_MeshEditor::TListOfListOfNodes lln( 1, list< const SMDS_MeshNode* >() );
+ lln.back().push_back ( vn );
+ lln.back().push_front( newNodes[ iN-isPrev ] ); // to keep
+ SMESH_MeshEditor( mesh ).MergeNodes( lln );
+ }
}
SMDS_MeshElement* newEdge = myHelper->AddEdge( newNodes[ iN-1 ], newNodes[ iN ] );
meshDS->SetMeshElementOnShape( newEdge, id2type.first );
@@ -1442,10 +1487,13 @@ bool StdMeshers_Prism_3D::computeWalls(const Prism_3D::TPrismTopo& thePrism)
Prism_3D::TQuadList::const_iterator quad = thePrism.myWallQuads[iW].begin();
for ( ; quad != thePrism.myWallQuads[iW].end(); ++quad )
{
- // Top EDGEs must be projections from the bottom ones
- // to compute stuctured quad mesh on wall FACEs
- // ---------------------------------------------------
+ const TopoDS_Face& face = (*quad)->face;
+ SMESH_subMesh* fSM = mesh->GetSubMesh( face );
+ if ( ! fSM->IsMeshComputed() )
{
+ // Top EDGEs must be projections from the bottom ones
+ // to compute stuctured quad mesh on wall FACEs
+ // ---------------------------------------------------
const TopoDS_Edge& botE = (*quad)->side[ QUAD_BOTTOM_SIDE ].grid->Edge(0);
const TopoDS_Edge& topE = (*quad)->side[ QUAD_TOP_SIDE ].grid->Edge(0);
SMESH_subMesh* botSM = mesh->GetSubMesh( botE );
@@ -1502,14 +1550,11 @@ bool StdMeshers_Prism_3D::computeWalls(const Prism_3D::TPrismTopo& thePrism)
}
}
tgtSM->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE );
- }
- // Compute quad mesh on wall FACEs
- // -------------------------------
- const TopoDS_Face& face = (*quad)->face;
- SMESH_subMesh* fSM = mesh->GetSubMesh( face );
- if ( ! fSM->IsMeshComputed() )
- {
+
+ // Compute quad mesh on wall FACEs
+ // -------------------------------
+
// make all EDGES meshed
fSM->ComputeSubMeshStateEngine( SMESH_subMesh::COMPUTE );
if ( !fSM->SubMeshesComputed() )
@@ -1545,9 +1590,10 @@ bool StdMeshers_Prism_3D::computeWalls(const Prism_3D::TPrismTopo& thePrism)
TopoDS_Edge StdMeshers_Prism_3D::findPropagationSource( const TopoDS_Edge& E )
{
- for ( size_t i = 0; !myPropagChains[i].IsEmpty(); ++i )
- if ( myPropagChains[i].Contains( E ))
- return TopoDS::Edge( myPropagChains[i].FindKey( 1 ));
+ if ( myPropagChains )
+ for ( size_t i = 0; !myPropagChains[i].IsEmpty(); ++i )
+ if ( myPropagChains[i].Contains( E ))
+ return TopoDS::Edge( myPropagChains[i].FindKey( 1 ));
return TopoDS_Edge();
}
@@ -1801,7 +1847,8 @@ void StdMeshers_Prism_3D::AddPrisms( vector & columns,
*/
//================================================================================
-bool StdMeshers_Prism_3D::assocOrProjBottom2Top( const gp_Trsf & bottomToTopTrsf )
+bool StdMeshers_Prism_3D::assocOrProjBottom2Top( const gp_Trsf & bottomToTopTrsf,
+ const Prism_3D::TPrismTopo& thePrism)
{
SMESH_subMesh * botSM = myBlock.SubMesh( ID_BOT_FACE );
SMESH_subMesh * topSM = myBlock.SubMesh( ID_TOP_FACE );
@@ -1811,14 +1858,14 @@ bool StdMeshers_Prism_3D::assocOrProjBottom2Top( const gp_Trsf & bottomToTopTrsf
if ( !botSMDS || botSMDS->NbElements() == 0 )
{
- _gen->Compute( *myHelper->GetMesh(), botSM->GetSubShape() );
+ _gen->Compute( *myHelper->GetMesh(), botSM->GetSubShape(), /*aShapeOnly=*/true );
botSMDS = botSM->GetSubMeshDS();
if ( !botSMDS || botSMDS->NbElements() == 0 )
return toSM( error(TCom("No elements on face #") << botSM->GetId() ));
}
bool needProject = !topSM->IsMeshComputed();
- if ( !needProject &&
+ if ( !needProject &&
(botSMDS->NbElements() != topSMDS->NbElements() ||
botSMDS->NbNodes() != topSMDS->NbNodes()))
{
@@ -1844,19 +1891,70 @@ bool StdMeshers_Prism_3D::assocOrProjBottom2Top( const gp_Trsf & bottomToTopTrsf
TopoDS_Face topFace = TopoDS::Face( myBlock.Shape( ID_TOP_FACE ));
// associate top and bottom faces
TAssocTool::TShapeShapeMap shape2ShapeMap;
- if ( !TAssocTool::FindSubShapeAssociation( botFace, myBlock.Mesh(),
- topFace, myBlock.Mesh(),
- shape2ShapeMap) )
- return toSM( error(TCom("Topology of faces #") << botSM->GetId()
- <<" and #"<< topSM->GetId() << " seems different" ));
+ const bool sameTopo =
+ TAssocTool::FindSubShapeAssociation( botFace, myBlock.Mesh(),
+ topFace, myBlock.Mesh(),
+ shape2ShapeMap);
+ if ( !sameTopo )
+ for ( size_t iQ = 0; iQ < thePrism.myWallQuads.size(); ++iQ )
+ {
+ const Prism_3D::TQuadList& quadList = thePrism.myWallQuads[iQ];
+ StdMeshers_FaceSidePtr botSide = quadList.front()->side[ QUAD_BOTTOM_SIDE ];
+ StdMeshers_FaceSidePtr topSide = quadList.back ()->side[ QUAD_TOP_SIDE ];
+ if ( botSide->NbEdges() == topSide->NbEdges() )
+ {
+ for ( int iE = 0; iE < botSide->NbEdges(); ++iE )
+ {
+ TAssocTool::InsertAssociation( botSide->Edge( iE ),
+ topSide->Edge( iE ), shape2ShapeMap );
+ TAssocTool::InsertAssociation( myHelper->IthVertex( 0, botSide->Edge( iE )),
+ myHelper->IthVertex( 0, topSide->Edge( iE )),
+ shape2ShapeMap );
+ }
+ }
+ else
+ {
+ TopoDS_Vertex vb, vt;
+ StdMeshers_FaceSidePtr sideB, sideT;
+ vb = myHelper->IthVertex( 0, botSide->Edge( 0 ));
+ vt = myHelper->IthVertex( 0, topSide->Edge( 0 ));
+ sideB = quadList.front()->side[ QUAD_LEFT_SIDE ];
+ sideT = quadList.back ()->side[ QUAD_LEFT_SIDE ];
+ if ( vb.IsSame( sideB->FirstVertex() ) &&
+ vt.IsSame( sideT->LastVertex() ))
+ {
+ TAssocTool::InsertAssociation( botSide->Edge( 0 ),
+ topSide->Edge( 0 ), shape2ShapeMap );
+ TAssocTool::InsertAssociation( vb, vt, shape2ShapeMap );
+ }
+ vb = myHelper->IthVertex( 1, botSide->Edge( botSide->NbEdges()-1 ));
+ vt = myHelper->IthVertex( 1, topSide->Edge( topSide->NbEdges()-1 ));
+ sideB = quadList.front()->side[ QUAD_RIGHT_SIDE ];
+ sideT = quadList.back ()->side[ QUAD_RIGHT_SIDE ];
+ if ( vb.IsSame( sideB->FirstVertex() ) &&
+ vt.IsSame( sideT->LastVertex() ))
+ {
+ TAssocTool::InsertAssociation( botSide->Edge( botSide->NbEdges()-1 ),
+ topSide->Edge( topSide->NbEdges()-1 ),
+ shape2ShapeMap );
+ TAssocTool::InsertAssociation( vb, vt, shape2ShapeMap );
+ }
+ }
+ }
// Find matching nodes of top and bottom faces
TNodeNodeMap n2nMap;
if ( ! TAssocTool::FindMatchingNodesOnFaces( botFace, myBlock.Mesh(),
topFace, myBlock.Mesh(),
shape2ShapeMap, n2nMap ))
- return toSM( error(TCom("Mesh on faces #") << botSM->GetId()
- <<" and #"<< topSM->GetId() << " seems different" ));
+ {
+ if ( sameTopo )
+ return toSM( error(TCom("Mesh on faces #") << botSM->GetId()
+ <<" and #"<< topSM->GetId() << " seems different" ));
+ else
+ return toSM( error(TCom("Topology of faces #") << botSM->GetId()
+ <<" and #"<< topSM->GetId() << " seems different" ));
+ }
// Fill myBotToColumnMap
@@ -2496,6 +2594,29 @@ namespace Prism_3D
myWallQuads.clear();
}
+ //================================================================================
+ /*!
+ * \brief Set upside-down
+ */
+ //================================================================================
+
+ void TPrismTopo::SetUpsideDown()
+ {
+ std::swap( myBottom, myTop );
+ myBottomEdges.clear();
+ std::reverse( myBottomEdges.begin(), myBottomEdges.end() );
+ for ( size_t i = 0; i < myWallQuads.size(); ++i )
+ {
+ myWallQuads[i].reverse();
+ TQuadList::iterator q = myWallQuads[i].begin();
+ for ( ; q != myWallQuads[i].end(); ++q )
+ {
+ (*q)->shift( 2, /*keepUnitOri=*/true );
+ }
+ myBottomEdges.push_back( myWallQuads[i].front()->side[ QUAD_BOTTOM_SIDE ].grid->Edge(0) );
+ }
+ }
+
} // namespace Prism_3D
//================================================================================
@@ -2602,7 +2723,7 @@ bool StdMeshers_Prism_3D::initPrism(Prism_3D::TPrismTopo& thePrism,
SMESH_subMesh * botSM = 0;
SMESH_subMesh * topSM = 0;
- if ( hasNotQuad ) // can chose a bottom FACE
+ if ( hasNotQuad ) // can choose a bottom FACE
{
if ( nbNotQuadMeshed > 0 ) botSM = notQuadElemSubMesh.front();
else botSM = notQuadGeomSubMesh.front();
@@ -2710,6 +2831,12 @@ bool StdMeshers_Prism_3D::initPrism(Prism_3D::TPrismTopo& thePrism,
"Non-quadrilateral faces are not opposite"));
}
+ if ( thePrism.myBottomEdges.size() > thePrism.myWallQuads.size() )
+ {
+ // composite bottom sides => set thePrism upside-down
+ thePrism.SetUpsideDown();
+ }
+
return true;
}
@@ -3634,8 +3761,8 @@ gp_Pnt StdMeshers_PrismAsBlock::TSideFace::Value(const Standard_Real U,
}
if ( !edge.IsNull() )
{
- double u1 = myHelper.GetNodeU( edge, nn[0] );
- double u3 = myHelper.GetNodeU( edge, nn[2] );
+ double u1 = myHelper.GetNodeU( edge, nn[0], nn[2] );
+ double u3 = myHelper.GetNodeU( edge, nn[2], nn[0] );
double u = u1 * ( 1 - hR ) + u3 * hR;
TopLoc_Location loc; double f,l;
Handle(Geom_Curve) curve = BRep_Tool::Curve( edge,loc,f,l );