0020958: EDF 1529 SMESH : If some faces have been meshed with small

quadrangles Netgen 3D creates pyramids with volume zero and fails

* Fix HasIntersection3(): use reasonable tolerances
* Improve performace using SMESH_ElementSearcher
This commit is contained in:
eap 2010-08-19 09:23:39 +00:00
parent 14c9e5320c
commit 1aa25c0e23
2 changed files with 299 additions and 225 deletions

View File

@ -44,9 +44,20 @@ using namespace std;
enum EQuadNature { NOT_QUAD, QUAD, DEGEN_QUAD }; enum EQuadNature { NOT_QUAD, QUAD, DEGEN_QUAD };
// sdt-like iterator used to get coordinates of nodes of mesh element // std-like iterator used to get coordinates of nodes of mesh element
typedef SMDS_StdIterator< SMESH_MeshEditor::TNodeXYZ, SMDS_ElemIteratorPtr > TXyzIterator; typedef SMDS_StdIterator< SMESH_MeshEditor::TNodeXYZ, SMDS_ElemIteratorPtr > TXyzIterator;
//================================================================================
/*!
* \brief Constructor
*/
//================================================================================
StdMeshers_QuadToTriaAdaptor::StdMeshers_QuadToTriaAdaptor():
myElemSearcher(0)
{
}
//================================================================================ //================================================================================
/*! /*!
* \brief Destructor * \brief Destructor
@ -69,6 +80,9 @@ StdMeshers_QuadToTriaAdaptor::~StdMeshers_QuadToTriaAdaptor()
// TF2PyramMap::iterator itp = myPyram2Trias.begin(); // TF2PyramMap::iterator itp = myPyram2Trias.begin();
// for(; itp!=myPyram2Trias.end(); itp++) // for(; itp!=myPyram2Trias.end(); itp++)
// cout << itp->second << endl; // cout << itp->second << endl;
if ( myElemSearcher ) delete myElemSearcher;
myElemSearcher=0;
} }
@ -120,7 +134,7 @@ static bool HasIntersection3(const gp_Pnt& P, const gp_Pnt& PC, gp_Pnt& Pint,
return false; return false;
if( IAICQ.NbPoints() == 1 ) { if( IAICQ.NbPoints() == 1 ) {
gp_Pnt PIn = IAICQ.Point(1); gp_Pnt PIn = IAICQ.Point(1);
double preci = 1.e-6; const double preci = 1.e-10 * P.Distance(PC);
// check if this point is internal for segment [PC,P] // check if this point is internal for segment [PC,P]
bool IsExternal = bool IsExternal =
( (PC.X()-PIn.X())*(P.X()-PIn.X()) > preci ) || ( (PC.X()-PIn.X())*(P.X()-PIn.X()) > preci ) ||
@ -133,32 +147,34 @@ static bool HasIntersection3(const gp_Pnt& P, const gp_Pnt& PC, gp_Pnt& Pint,
gp_Vec V1(PIn,P1); gp_Vec V1(PIn,P1);
gp_Vec V2(PIn,P2); gp_Vec V2(PIn,P2);
gp_Vec V3(PIn,P3); gp_Vec V3(PIn,P3);
if( V1.Magnitude()<preci || V2.Magnitude()<preci || if( V1.Magnitude()<preci ||
V2.Magnitude()<preci ||
V3.Magnitude()<preci ) { V3.Magnitude()<preci ) {
Pint = PIn; Pint = PIn;
return true; return true;
} }
const double angularTol = 1e-6;
gp_Vec VC1 = V1.Crossed(V2); gp_Vec VC1 = V1.Crossed(V2);
gp_Vec VC2 = V2.Crossed(V3); gp_Vec VC2 = V2.Crossed(V3);
gp_Vec VC3 = V3.Crossed(V1); gp_Vec VC3 = V3.Crossed(V1);
if(VC1.Magnitude()<preci) { if(VC1.Magnitude()<gp::Resolution()) {
if(VC2.IsOpposite(VC3,preci)) { if(VC2.IsOpposite(VC3,angularTol)) {
return false; return false;
} }
} }
else if(VC2.Magnitude()<preci) { else if(VC2.Magnitude()<gp::Resolution()) {
if(VC1.IsOpposite(VC3,preci)) { if(VC1.IsOpposite(VC3,angularTol)) {
return false; return false;
} }
} }
else if(VC3.Magnitude()<preci) { else if(VC3.Magnitude()<gp::Resolution()) {
if(VC1.IsOpposite(VC2,preci)) { if(VC1.IsOpposite(VC2,angularTol)) {
return false; return false;
} }
} }
else { else {
if( VC1.IsOpposite(VC2,preci) || VC1.IsOpposite(VC3,preci) || if( VC1.IsOpposite(VC2,angularTol) || VC1.IsOpposite(VC3,angularTol) ||
VC2.IsOpposite(VC3,preci) ) { VC2.IsOpposite(VC3,angularTol) ) {
return false; return false;
} }
} }
@ -204,41 +220,55 @@ static bool HasIntersection(const gp_Pnt& P, const gp_Pnt& PC, gp_Pnt& Pint,
return false; return false;
} }
//================================================================================
/*!
* \brief Checks if a line segment (P,PC) intersects any mesh face.
* \param P - first segment end
* \param PC - second segment end (it is a gravity center of quadrangle)
* \param Pint - (out) intersection point
* \param aMesh - mesh
* \param aShape - shape to check faces on
* \param NotCheckedFace - not used
* \retval bool - true if there is an intersection
*/
//================================================================================
//======================================================================= bool StdMeshers_QuadToTriaAdaptor::CheckIntersection (const gp_Pnt& P,
//function : CheckIntersection const gp_Pnt& PC,
//purpose : Auxilare for Compute() gp_Pnt& Pint,
// NotCheckedFace - for optimization SMESH_Mesh& aMesh,
//=======================================================================
bool StdMeshers_QuadToTriaAdaptor::CheckIntersection
(const gp_Pnt& P, const gp_Pnt& PC,
gp_Pnt& Pint, SMESH_Mesh& aMesh,
const TopoDS_Shape& aShape, const TopoDS_Shape& aShape,
const TopoDS_Shape& NotCheckedFace) const TopoDS_Shape& NotCheckedFace)
{ {
SMESHDS_Mesh * meshDS = aMesh.GetMeshDS(); if ( !myElemSearcher )
myElemSearcher = SMESH_MeshEditor(&aMesh).GetElementSearcher();
SMESH_ElementSearcher* searcher = const_cast<SMESH_ElementSearcher*>(myElemSearcher);
//SMESHDS_Mesh * meshDS = aMesh.GetMeshDS();
//cout<<" CheckIntersection: meshDS->NbFaces() = "<<meshDS->NbFaces()<<endl; //cout<<" CheckIntersection: meshDS->NbFaces() = "<<meshDS->NbFaces()<<endl;
bool res = false; bool res = false;
double dist = RealLast(); double dist = RealLast(); // find intersection closest to the segment
gp_Pnt Pres; gp_Pnt Pres;
for (TopExp_Explorer exp(aShape,TopAbs_FACE);exp.More();exp.Next()) {
const TopoDS_Shape& aShapeFace = exp.Current(); gp_Ax1 line( P, gp_Vec(P,PC));
if(aShapeFace==NotCheckedFace) vector< const SMDS_MeshElement* > suspectElems;
continue; searcher->GetElementsNearLine( line, SMDSAbs_Face, suspectElems);
const SMESHDS_SubMesh * aSubMeshDSFace = meshDS->MeshElements(aShapeFace);
if ( aSubMeshDSFace ) { // for (TopExp_Explorer exp(aShape,TopAbs_FACE);exp.More();exp.Next()) {
SMDS_ElemIteratorPtr iteratorElem = aSubMeshDSFace->GetElements(); // const TopoDS_Shape& aShapeFace = exp.Current();
while ( iteratorElem->more() ) { // loop on elements on a face // if(aShapeFace==NotCheckedFace)
const SMDS_MeshElement* face = iteratorElem->next(); // continue;
// const SMESHDS_SubMesh * aSubMeshDSFace = meshDS->MeshElements(aShapeFace);
// if ( aSubMeshDSFace ) {
// SMDS_ElemIteratorPtr iteratorElem = aSubMeshDSFace->GetElements();
// while ( iteratorElem->more() ) { // loop on elements on a face
// const SMDS_MeshElement* face = iteratorElem->next();
for ( int i = 0; i < suspectElems.size(); ++i )
{
const SMDS_MeshElement* face = suspectElems[i];
Handle(TColgp_HSequenceOfPnt) aContour = new TColgp_HSequenceOfPnt; Handle(TColgp_HSequenceOfPnt) aContour = new TColgp_HSequenceOfPnt;
SMDS_ElemIteratorPtr nodeIt = face->nodesIterator(); for ( int i = 0; i < face->NbCornerNodes(); ++i )
int nbN = face->NbNodes(); aContour->Append( SMESH_MeshEditor::TNodeXYZ( face->GetNode(i) ));
if( face->IsQuadratic() )
nbN /= 2;
for ( int i = 0; i < nbN; ++i ) {
const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
aContour->Append(gp_Pnt(node->X(), node->Y(), node->Z()));
}
if( HasIntersection(P, PC, Pres, aContour) ) { if( HasIntersection(P, PC, Pres, aContour) ) {
res = true; res = true;
double tmp = PC.Distance(Pres); double tmp = PC.Distance(Pres);
@ -248,8 +278,6 @@ bool StdMeshers_QuadToTriaAdaptor::CheckIntersection
} }
} }
} }
}
}
return res; return res;
} }
@ -410,14 +438,19 @@ bool StdMeshers_QuadToTriaAdaptor::Compute(SMESH_Mesh& aMesh, const TopoDS_Shape
helper.IsQuadraticSubMesh(aShape); helper.IsQuadraticSubMesh(aShape);
helper.SetElementsOnShape( true ); helper.SetElementsOnShape( true );
for (TopExp_Explorer exp(aShape,TopAbs_FACE);exp.More();exp.Next()) {
for (TopExp_Explorer exp(aShape,TopAbs_FACE);exp.More();exp.Next())
{
const TopoDS_Shape& aShapeFace = exp.Current(); const TopoDS_Shape& aShapeFace = exp.Current();
const SMESHDS_SubMesh * aSubMeshDSFace = meshDS->MeshElements( aShapeFace ); const SMESHDS_SubMesh * aSubMeshDSFace = meshDS->MeshElements( aShapeFace );
if ( aSubMeshDSFace ) { if ( aSubMeshDSFace )
{
bool isRev = SMESH_Algo::IsReversedSubMesh( TopoDS::Face(aShapeFace), meshDS ); bool isRev = SMESH_Algo::IsReversedSubMesh( TopoDS::Face(aShapeFace), meshDS );
SMDS_ElemIteratorPtr iteratorElem = aSubMeshDSFace->GetElements(); SMDS_ElemIteratorPtr iteratorElem = aSubMeshDSFace->GetElements();
while ( iteratorElem->more() ) { // loop on elements on a face while ( iteratorElem->more() ) // loop on elements on a geometrical face
{
const SMDS_MeshElement* face = iteratorElem->next(); const SMDS_MeshElement* face = iteratorElem->next();
//cout<<endl<<"================= face->GetID() = "<<face->GetID()<<endl; //cout<<endl<<"================= face->GetID() = "<<face->GetID()<<endl;
// preparation step using face info // preparation step using face info
@ -430,7 +463,8 @@ bool StdMeshers_QuadToTriaAdaptor::Compute(SMESH_Mesh& aMesh, const TopoDS_Shape
if(stat==0) if(stat==0)
continue; continue;
if(stat==2) { if(stat==2)
{
// degenerate face // degenerate face
// add triangles to result map // add triangles to result map
SMDS_FaceOfNodes* NewFace; SMDS_FaceOfNodes* NewFace;
@ -478,7 +512,7 @@ bool StdMeshers_QuadToTriaAdaptor::Compute(SMESH_Mesh& aMesh, const TopoDS_Shape
else { else {
gp_Vec VB(PC,PCbest); gp_Vec VB(PC,PCbest);
gp_Pnt PCbestTmp = PC.XYZ() + VB.XYZ() * 3.0; gp_Pnt PCbestTmp = PC.XYZ() + VB.XYZ() * 3.0;
bool check = CheckIntersection(PCbestTmp, PC, Pint, aMesh, aShape, aShapeFace); check = CheckIntersection(PCbestTmp, PC, Pint, aMesh, aShape, aShapeFace);
if(check) { if(check) {
double dist = PC.Distance(Pint)/3.; double dist = PC.Distance(Pint)/3.;
if(dist<height) { if(dist<height) {
@ -496,11 +530,12 @@ bool StdMeshers_QuadToTriaAdaptor::Compute(SMESH_Mesh& aMesh, const TopoDS_Shape
for(i=0; i<4; i++) for(i=0; i<4; i++)
triaList.push_back( new SMDS_FaceOfNodes( NewNode, FNodes[i], FNodes[i+1] )); triaList.push_back( new SMDS_FaceOfNodes( NewNode, FNodes[i], FNodes[i+1] ));
// create pyramid // create a pyramid
if ( isRev ) swap( FNodes[1], FNodes[3]); if ( isRev ) swap( FNodes[1], FNodes[3]);
SMDS_MeshVolume* aPyram = SMDS_MeshVolume* aPyram =
helper.AddVolume( FNodes[0], FNodes[1], FNodes[2], FNodes[3], NewNode ); helper.AddVolume( FNodes[0], FNodes[1], FNodes[2], FNodes[3], NewNode );
myPyram2Trias.insert(make_pair(aPyram, & triaList)); myPyram2Trias.insert(make_pair(aPyram, & triaList));
} // end loop on elements on a face submesh } // end loop on elements on a face submesh
} }
} // end for(TopExp_Explorer exp(aShape,TopAbs_FACE);exp.More();exp.Next()) { } // end for(TopExp_Explorer exp(aShape,TopAbs_FACE);exp.More();exp.Next()) {
@ -508,11 +543,11 @@ bool StdMeshers_QuadToTriaAdaptor::Compute(SMESH_Mesh& aMesh, const TopoDS_Shape
return Compute2ndPart(aMesh); return Compute2ndPart(aMesh);
} }
//================================================================================
//======================================================================= /*!
//function : Compute * \brief Computes pyramids in mesh with no shape
//purpose : */
//======================================================================= //================================================================================
bool StdMeshers_QuadToTriaAdaptor::Compute(SMESH_Mesh& aMesh) bool StdMeshers_QuadToTriaAdaptor::Compute(SMESH_Mesh& aMesh)
{ {
@ -522,16 +557,16 @@ bool StdMeshers_QuadToTriaAdaptor::Compute(SMESH_Mesh& aMesh)
helper.IsQuadraticSubMesh(aMesh.GetShapeToMesh()); helper.IsQuadraticSubMesh(aMesh.GetShapeToMesh());
helper.SetElementsOnShape( true ); helper.SetElementsOnShape( true );
if ( !myElemSearcher )
myElemSearcher = SMESH_MeshEditor(&aMesh).GetElementSearcher();
SMESH_ElementSearcher* searcher = const_cast<SMESH_ElementSearcher*>(myElemSearcher);
SMESHDS_Mesh * meshDS = aMesh.GetMeshDS(); SMESHDS_Mesh * meshDS = aMesh.GetMeshDS();
SMDS_FaceIteratorPtr fIt = meshDS->facesIterator(); SMDS_FaceIteratorPtr fIt = meshDS->facesIterator(/*idInceasingOrder=*/true);
TIDSortedElemSet sortedFaces; // 0020279: control the "random" use when using mesh algorithms while( fIt->more())
while( fIt->more()) sortedFaces.insert( fIt->next() );
TIDSortedElemSet::iterator itFace = sortedFaces.begin(), fEnd = sortedFaces.end();
for ( ; itFace != fEnd; ++itFace )
{ {
const SMDS_MeshElement* face = *itFace; const SMDS_MeshElement* face = fIt->next();
if ( !face ) continue; if ( !face ) continue;
//cout<<endl<<"================= face->GetID() = "<<face->GetID()<<endl; //cout<<endl<<"================= face->GetID() = "<<face->GetID()<<endl;
// retrieve needed information about a face // retrieve needed information about a face
@ -566,8 +601,13 @@ bool StdMeshers_QuadToTriaAdaptor::Compute(SMESH_Mesh& aMesh)
double dist1 = RealLast(); double dist1 = RealLast();
double dist2 = RealLast(); double dist2 = RealLast();
gp_Pnt Pres1,Pres2; gp_Pnt Pres1,Pres2;
for (TIDSortedElemSet::iterator itF = sortedFaces.begin(); itF != fEnd; ++itF ) {
const SMDS_MeshElement* F = *itF; gp_Ax1 line( PC, VNorm );
vector< const SMDS_MeshElement* > suspectElems;
searcher->GetElementsNearLine( line, SMDSAbs_Face, suspectElems);
for ( int iF = 0; iF < suspectElems.size(); ++iF ) {
const SMDS_MeshElement* F = suspectElems[iF];
if(F==face) continue; if(F==face) continue;
Handle(TColgp_HSequenceOfPnt) aContour = new TColgp_HSequenceOfPnt; Handle(TColgp_HSequenceOfPnt) aContour = new TColgp_HSequenceOfPnt;
for ( int i = 0; i < 4; ++i ) for ( int i = 0; i < 4; ++i )
@ -646,9 +686,14 @@ bool StdMeshers_QuadToTriaAdaptor::Compute(SMESH_Mesh& aMesh)
bool intersected[2] = { false, false }; bool intersected[2] = { false, false };
double dist [2] = { RealLast(), RealLast() }; double dist [2] = { RealLast(), RealLast() };
gp_Pnt intPnt[2]; gp_Pnt intPnt[2];
for (TIDSortedElemSet::iterator itF = sortedFaces.begin(); itF != fEnd; ++itF )
gp_Ax1 line( PC, tmpDir );
vector< const SMDS_MeshElement* > suspectElems;
searcher->GetElementsNearLine( line, SMDSAbs_Face, suspectElems);
for ( int iF = 0; iF < suspectElems.size(); ++iF )
{ {
const SMDS_MeshElement* F = *itF; const SMDS_MeshElement* F = suspectElems[iF];
if(F==face) continue; if(F==face) continue;
Handle(TColgp_HSequenceOfPnt) aContour = new TColgp_HSequenceOfPnt; Handle(TColgp_HSequenceOfPnt) aContour = new TColgp_HSequenceOfPnt;
int nbN = F->NbNodes() / ( F->IsQuadratic() ? 2 : 1 ); int nbN = F->NbNodes() / ( F->IsQuadratic() ? 2 : 1 );
@ -703,13 +748,15 @@ bool StdMeshers_QuadToTriaAdaptor::Compute(SMESH_Mesh& aMesh)
return Compute2ndPart(aMesh); return Compute2ndPart(aMesh);
} }
//======================================================================= //================================================================================
//function : Compute2ndPart /*!
//purpose : Update created pyramids and faces to avoid their intersection * \brief Update created pyramids and faces to avoid their intersection
//======================================================================= */
//================================================================================
bool StdMeshers_QuadToTriaAdaptor::Compute2ndPart(SMESH_Mesh& aMesh) bool StdMeshers_QuadToTriaAdaptor::Compute2ndPart(SMESH_Mesh& aMesh)
{ {
cout << "Compute2ndPart(), nb pyramids = " << myPyram2Trias.size() << endl;
SMESHDS_Mesh * meshDS = aMesh.GetMeshDS(); SMESHDS_Mesh * meshDS = aMesh.GetMeshDS();
// check intersections between created pyramids // check intersections between created pyramids
@ -723,6 +770,10 @@ bool StdMeshers_QuadToTriaAdaptor::Compute2ndPart(SMESH_Mesh& aMesh)
typedef map< const SMDS_MeshElement*, list< TPyram2Trias::iterator > > TPyram2Merged; typedef map< const SMDS_MeshElement*, list< TPyram2Trias::iterator > > TPyram2Merged;
TPyram2Merged MergesInfo; TPyram2Merged MergesInfo;
if ( !myElemSearcher )
myElemSearcher = SMESH_MeshEditor(&aMesh).GetElementSearcher();
SMESH_ElementSearcher* searcher = const_cast<SMESH_ElementSearcher*>(myElemSearcher);
// iterate on all pyramids // iterate on all pyramids
TPyram2Trias::iterator itPi = myPyram2Trias.begin(), itPEnd = myPyram2Trias.end(); TPyram2Trias::iterator itPi = myPyram2Trias.begin(), itPEnd = myPyram2Trias.end();
for ( ; itPi != itPEnd; ++itPi ) for ( ; itPi != itPEnd; ++itPi )
@ -734,32 +785,43 @@ bool StdMeshers_QuadToTriaAdaptor::Compute2ndPart(SMESH_Mesh& aMesh)
vector<gp_Pnt> PsI( xyzIt, TXyzIterator() ); vector<gp_Pnt> PsI( xyzIt, TXyzIterator() );
// compare PrmI with all the rest pyramids // compare PrmI with all the rest pyramids
bool NeedMove = false; bool NeedMove = false;
TPyram2Trias::iterator itPj = itPi;
for ( ++itPj; itPj != itPEnd; ++itPj ) bool hasInt = false;
for(k=0; k<4 && !hasInt; k++) // loop on 4 base nodes of PrmI
{ {
const SMDS_MeshElement* PrmJ = itPj->first; gp_Vec Vtmp(PsI[k],PsI[4]);
TPyram2Merged::iterator pMergesJ = MergesInfo.find( PrmJ ); gp_Pnt Pshift = PsI[k].XYZ() + Vtmp.XYZ() * 0.01; // base node moved a bit to apex
gp_Ax1 line( PsI[k], Vtmp );
vector< const SMDS_MeshElement* > suspectPyrams;
searcher->GetElementsNearLine( line, SMDSAbs_Volume, suspectPyrams);
for ( int j = 0; j < suspectPyrams.size(); ++j )
{
const SMDS_MeshElement* PrmJ = suspectPyrams[j];
if ( PrmJ == PrmI || PrmJ->NbCornerNodes() != 5 ) continue;
TPyram2Trias::iterator itPj = myPyram2Trias.find( PrmJ );
if ( itPj == myPyram2Trias.end() ) continue; // pyramid from other SOLID
// check if two pyramids already merged // check if two pyramids already merged
TPyram2Merged::iterator pMergesJ = MergesInfo.find( PrmJ );
if ( pMergesJ != MergesInfo.end() && if ( pMergesJ != MergesInfo.end() &&
find(pMergesJ->second.begin(),pMergesJ->second.end(), itPi )!=pMergesJ->second.end()) find(pMergesJ->second.begin(),pMergesJ->second.end(), itPi )!=pMergesJ->second.end())
continue; // already merged continue;
xyzIt = TXyzIterator( PrmJ->nodesIterator() ); xyzIt = TXyzIterator( PrmJ->nodesIterator() );
vector<gp_Pnt> PsJ( xyzIt, TXyzIterator() ); vector<gp_Pnt> PsJ( xyzIt, TXyzIterator() );
bool hasInt = false;
gp_Pnt Pint; gp_Pnt Pint;
for(k=0; k<4 && !hasInt; k++) {
gp_Vec Vtmp(PsI[k],PsI[4]);
gp_Pnt Pshift = PsI[k].XYZ() + Vtmp.XYZ() * 0.01;
hasInt = hasInt =
( HasIntersection3( Pshift, PsI[4], Pint, PsJ[0], PsJ[1], PsJ[4]) || ( HasIntersection3( Pshift, PsI[4], Pint, PsJ[0], PsJ[1], PsJ[4]) ||
HasIntersection3( Pshift, PsI[4], Pint, PsJ[1], PsJ[2], PsJ[4]) || HasIntersection3( Pshift, PsI[4], Pint, PsJ[1], PsJ[2], PsJ[4]) ||
HasIntersection3( Pshift, PsI[4], Pint, PsJ[2], PsJ[3], PsJ[4]) || HasIntersection3( Pshift, PsI[4], Pint, PsJ[2], PsJ[3], PsJ[4]) ||
HasIntersection3( Pshift, PsI[4], Pint, PsJ[3], PsJ[0], PsJ[4]) ); HasIntersection3( Pshift, PsI[4], Pint, PsJ[3], PsJ[0], PsJ[4]) );
}
for(k=0; k<4 && !hasInt; k++) { for(k=0; k<4 && !hasInt; k++) {
gp_Vec Vtmp(PsJ[k],PsJ[4]); gp_Vec Vtmp(PsJ[k],PsJ[4]);
gp_Pnt Pshift = PsJ[k].XYZ() + Vtmp.XYZ() * 0.01; gp_Pnt Pshift = PsJ[k].XYZ() + Vtmp.XYZ() * 0.01;
@ -769,18 +831,18 @@ bool StdMeshers_QuadToTriaAdaptor::Compute2ndPart(SMESH_Mesh& aMesh)
HasIntersection3( Pshift, PsJ[4], Pint, PsI[2], PsI[3], PsI[4]) || HasIntersection3( Pshift, PsJ[4], Pint, PsI[2], PsI[3], PsI[4]) ||
HasIntersection3( Pshift, PsJ[4], Pint, PsI[3], PsI[0], PsI[4]) ); HasIntersection3( Pshift, PsJ[4], Pint, PsI[3], PsI[0], PsI[4]) );
} }
if(hasInt) { if ( hasInt ) {
// count common nodes of base faces of two pyramids // count common nodes of base faces of two pyramids
int nbc = 0; int nbc = 0;
for(k=0; k<4; k++) for(k=0; k<4; k++)
nbc += int ( PrmI->GetNodeIndex( PrmJ->GetNode(k) ) >= 0 ); nbc += int ( PrmI->GetNodeIndex( PrmJ->GetNode(k) ) >= 0 );
//cout<<" nbc = "<<nbc<<endl;
if ( nbc == 4 ) if ( nbc == 4 )
continue; // pyrams have a common base face continue; // pyrams have a common base face
if(nbc>0) if(nbc>0)
{ {
cout << "Merge pyram " << PrmI->GetID() <<" to " << PrmJ->GetID() << endl;
// Merge the two pyramids and others already merged with them // Merge the two pyramids and others already merged with them
// initialize merge info of pyramids // initialize merge info of pyramids
@ -915,13 +977,14 @@ bool StdMeshers_QuadToTriaAdaptor::Compute2ndPart(SMESH_Mesh& aMesh)
NeedMove = true; NeedMove = true;
} }
} // end if(hasInt) } // end if(hasInt)
} } // loop on suspectPyrams
} // loop on 4 base nodes of PrmI
if( NeedMove && !meshDS->IsEmbeddedMode() ) if( NeedMove && !meshDS->IsEmbeddedMode() )
{ {
const SMDS_MeshNode* apex = PrmI->GetNode( 4 ); const SMDS_MeshNode* apex = PrmI->GetNode( 4 );
meshDS->MoveNode( apex, apex->X(), apex->Y(), apex->Z() ); meshDS->MoveNode( apex, apex->X(), apex->Y(), apex->Z() );
} }
} } // loop on all pyramids
// rebind triangles of pyramids sharing the same base quadrangle to the first // rebind triangles of pyramids sharing the same base quadrangle to the first
// entrance of the base quadrangle // entrance of the base quadrangle
@ -935,6 +998,10 @@ bool StdMeshers_QuadToTriaAdaptor::Compute2ndPart(SMESH_Mesh& aMesh)
myPyram2Trias.clear(); // no more needed myPyram2Trias.clear(); // no more needed
myDegNodes.clear(); myDegNodes.clear();
delete myElemSearcher;
myElemSearcher=0;
cout << "END Compute2ndPart()" << endl;
return true; return true;
} }

View File

@ -28,6 +28,7 @@
#include "SMDS_FaceOfNodes.hxx" #include "SMDS_FaceOfNodes.hxx"
class SMESH_Mesh; class SMESH_Mesh;
class SMESH_ElementSearcher;
class SMDS_MeshElement; class SMDS_MeshElement;
class SMDS_MeshNode; class SMDS_MeshNode;
class Handle(TColgp_HArray1OfPnt); class Handle(TColgp_HArray1OfPnt);
@ -41,9 +42,13 @@ class gp_Vec;
#include <list> #include <list>
#include <vector> #include <vector>
/*!
* \brief "Transforms" quadrilateral faces into triangular ones by creation of pyramids
*/
class STDMESHERS_EXPORT StdMeshers_QuadToTriaAdaptor class STDMESHERS_EXPORT StdMeshers_QuadToTriaAdaptor
{ {
public: public:
StdMeshers_QuadToTriaAdaptor();
~StdMeshers_QuadToTriaAdaptor(); ~StdMeshers_QuadToTriaAdaptor();
@ -71,6 +76,7 @@ protected:
bool Compute2ndPart(SMESH_Mesh& aMesh); bool Compute2ndPart(SMESH_Mesh& aMesh);
typedef std::list<const SMDS_FaceOfNodes* > TTriaList; typedef std::list<const SMDS_FaceOfNodes* > TTriaList;
typedef std::multimap<const SMDS_MeshElement*, TTriaList > TQuad2Trias; typedef std::multimap<const SMDS_MeshElement*, TTriaList > TQuad2Trias;
typedef std::map<const SMDS_MeshElement*, TTriaList *, TIDCompare> TPyram2Trias; typedef std::map<const SMDS_MeshElement*, TTriaList *, TIDCompare> TPyram2Trias;
@ -80,6 +86,7 @@ protected:
std::list< const SMDS_MeshNode* > myDegNodes; std::list< const SMDS_MeshNode* > myDegNodes;
const SMESH_ElementSearcher* myElemSearcher;
}; };
#endif #endif