"Transforms" quadrilateral faces into triangular ones by creation of pyramids More...
#include <StdMeshers_QuadToTriaAdaptor.hxx>

Public Types | |
| typedef boost::shared_ptr < SMESH_ProxyMesh > | Ptr |
| typedef std::map< const SMDS_MeshNode *, const SMDS_MeshNode *, TIDCompare > | TN2NMap |
Public Member Functions | |
| StdMeshers_QuadToTriaAdaptor () | |
| Constructor. | |
| ~StdMeshers_QuadToTriaAdaptor () | |
| Destructor. | |
| bool | Compute (SMESH_Mesh &aMesh, const TopoDS_Shape &aShape, SMESH_ProxyMesh *aProxyMesh=0) |
| bool | Compute (SMESH_Mesh &aMesh) |
| Computes pyramids in mesh with no shape. | |
| const SMESHDS_SubMesh * | GetSubMesh (const TopoDS_Shape &face) const |
| Returns the submesh of a shape; it can be a proxy sub-mesh. | |
| const SubMesh * | GetProxySubMesh (const TopoDS_Shape &face) const |
| Returns the proxy sub-mesh of a shape; it can be NULL. | |
| const SMDS_MeshNode * | GetProxyNode (const SMDS_MeshNode *node) const |
| Returns the proxy node of a node; the input node is returned if no proxy exists. | |
| SMDS_ElemIteratorPtr | GetFaces () const |
| Returns iterator on all faces of the mesh taking into account substitutions To be used in case of mesh without shape. | |
| SMDS_ElemIteratorPtr | GetFaces (const TopoDS_Shape &face) const |
| Returns iterator on all faces on the shape taking into account substitutions. | |
| int | NbFaces () const |
| Return total nb of faces taking into account substitutions. | |
| bool | IsTemporary (const SMDS_MeshElement *elem) const |
| Return true if the element is a temporary one. | |
| const SMESH_Mesh * | GetMesh () const |
| SMESHDS_Mesh * | GetMeshDS () const |
| Returns mesh DS. | |
Protected Member Functions | |
| int | Preparation (const SMDS_MeshElement *face, Handle_TColgp_HArray1OfPnt &PN, Handle_TColgp_HArray1OfVec &VN, std::vector< const SMDS_MeshNode * > &FNodes, gp_Pnt &PC, gp_Vec &VNorm, const SMDS_MeshElement **volumes=0) |
| Prepare data for the given face. | |
| bool | CheckIntersection (const gp_Pnt &P, const gp_Pnt &PC, gp_Pnt &Pint, SMESH_Mesh &aMesh, const TopoDS_Shape &aShape, const SMDS_MeshElement *NotCheckedFace) |
| Checks if a line segment (P,PC) intersects any mesh face. | |
| bool | Compute2ndPart (SMESH_Mesh &aMesh, const std::vector< const SMDS_MeshElement * > &pyramids) |
| Update created pyramids and faces to avoid their intersection. | |
| void | MergePiramids (const SMDS_MeshElement *PrmI, const SMDS_MeshElement *PrmJ, std::set< const SMDS_MeshNode * > &nodesToMove) |
| Merge the two pyramids (i.e. | |
| void | MergeAdjacent (const SMDS_MeshElement *PrmI, std::set< const SMDS_MeshNode * > &nodesToMove) |
| Merges adjacent pyramids. | |
| void | setMesh (const SMESH_Mesh &mesh) |
| int | shapeIndex (const TopoDS_Shape &shape) const |
| Returns index of a shape. | |
| SubMesh * | findProxySubMesh (int shapeIndex=0) const |
| Returns a proxy sub-mesh. | |
| SubMesh * | getProxySubMesh (int shapeIndex) |
| Returns a proxy sub-mesh; it is created if not yet exists. | |
| SubMesh * | getProxySubMesh (const TopoDS_Shape &shape=TopoDS_Shape()) |
| Returns a proxy sub-mesh; it is created if not yet exists. | |
| bool | takeProxySubMesh (const TopoDS_Shape &shape, SMESH_ProxyMesh *proxyMesh) |
| Move proxy sub-mesh from other proxy mesh to this, returns true if sub-mesh found. | |
| void | takeTmpElemsInMesh (SMESH_ProxyMesh *proxyMesh) |
| Move tmp elements residing the _mesh from other proxy mesh to this. | |
| void | removeTmpElement (const SMDS_MeshElement *face) |
| Removes tmp faces from the _mesh. | |
| void | storeTmpElement (const SMDS_MeshElement *face) |
| Stores tmp element residing the _mesh. | |
| void | setNode2Node (const SMDS_MeshNode *srcNode, const SMDS_MeshNode *proxyNode, const SubMesh *subMesh) |
| Set node-node correspondence. | |
Protected Attributes | |
| std::set< const SMDS_MeshElement * > | myRemovedTrias |
| std::list< const SMDS_MeshNode * > | myDegNodes |
| const SMESH_ElementSearcher * | myElemSearcher |
| std::vector< SMDSAbs_EntityType > | _allowedTypes |
"Transforms" quadrilateral faces into triangular ones by creation of pyramids
Definition at line 51 of file StdMeshers_QuadToTriaAdaptor.hxx.
typedef boost::shared_ptr<SMESH_ProxyMesh> SMESH_ProxyMesh.Ptr [inherited] |
Definition at line 49 of file SMESH_ProxyMesh.hxx.
typedef std::map<const SMDS_MeshNode*, const SMDS_MeshNode*, TIDCompare > SMESH_ProxyMesh.TN2NMap [inherited] |
Definition at line 51 of file SMESH_ProxyMesh.hxx.
| StdMeshers_QuadToTriaAdaptor::StdMeshers_QuadToTriaAdaptor | ( | ) |
Constructor.
Definition at line 363 of file StdMeshers_QuadToTriaAdaptor.cxx.
: myElemSearcher(0) { }
| StdMeshers_QuadToTriaAdaptor::~StdMeshers_QuadToTriaAdaptor | ( | ) |
Destructor.
Definition at line 374 of file StdMeshers_QuadToTriaAdaptor.cxx.
References myElemSearcher.
{
// temporary faces are deleted by ~SMESH_ProxyMesh()
if ( myElemSearcher ) delete myElemSearcher;
myElemSearcher=0;
}
| bool StdMeshers_QuadToTriaAdaptor::CheckIntersection | ( | const gp_Pnt & | P, |
| const gp_Pnt & | PC, | ||
| gp_Pnt & | Pint, | ||
| SMESH_Mesh & | aMesh, | ||
| const TopoDS_Shape & | aShape, | ||
| const SMDS_MeshElement * | NotCheckedFace | ||
| ) | [protected] |
Checks if a line segment (P,PC) intersects any mesh face.
| P | - first segment end |
| PC | - second segment end (it is a gravity center of quadrangle) |
| Pint | - (out) intersection point |
| aMesh | - mesh |
| aShape | - shape to check faces on |
| NotCheckedFace | - mesh face not to check |
| bool | - true if there is an intersection |
Definition at line 529 of file StdMeshers_QuadToTriaAdaptor.cxx.
References PAL_MESH_043_3D.face, SMESH_ElementSearcher.GetElementsNearLine(), SMDS_MeshElement.GetNode(), Handle(), HasIntersection(), myElemSearcher, SMDS_MeshElement.NbCornerNodes(), SMESH_AdvancedEditor.res, and SMDSAbs_Face.
Referenced by Compute().
{
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;
bool res = false;
double dist = RealLast(); // find intersection closest to the segment
gp_Pnt Pres;
gp_Ax1 line( P, gp_Vec(P,PC));
vector< const SMDS_MeshElement* > suspectElems;
searcher->GetElementsNearLine( line, SMDSAbs_Face, suspectElems);
for ( int i = 0; i < suspectElems.size(); ++i )
{
const SMDS_MeshElement* face = suspectElems[i];
if ( face == NotCheckedFace ) continue;
Handle(TColgp_HSequenceOfPnt) aContour = new TColgp_HSequenceOfPnt;
for ( int i = 0; i < face->NbCornerNodes(); ++i )
aContour->Append( SMESH_TNodeXYZ( face->GetNode(i) ));
if( HasIntersection(P, PC, Pres, aContour) ) {
res = true;
double tmp = PC.Distance(Pres);
if(tmp<dist) {
Pint = Pres;
dist = tmp;
}
}
}
return res;
}
| bool StdMeshers_QuadToTriaAdaptor::Compute | ( | SMESH_Mesh & | aMesh, |
| const TopoDS_Shape & | aShape, | ||
| SMESH_ProxyMesh * | aProxyMesh = 0 |
||
| ) |
Definition at line 704 of file StdMeshers_QuadToTriaAdaptor.cxx.
References SMESHDS_Mesh.AddFace(), SMESH_MesherHelper.AddNode(), SMESH_MesherHelper.AddVolume(), SMESH_ProxyMesh.SubMesh.ChangeElements(), CheckIntersection(), Compute2ndPart(), DEGEN_QUAD, FindBestPoint(), SMESHDS_SubMesh.GetElements(), SMESH_ProxyMesh.GetFaces(), SMESH_ProxyMesh.getProxySubMesh(), SMESH_ProxyMesh.GetSubMesh(), Handle(), ex21_lamp.height, SMESH_MesherHelper.IsQuadraticSubMesh(), SMESH_Algo.IsReversedSubMesh(), SMESHDS_Mesh.MeshElements(), myElemSearcher, SMESH_MesherHelper.NbAncestors(), NOT_QUAD, Preparation(), QUAD, SMESH_ProxyMesh.removeTmpElement(), SMESH_MesherHelper.SetElementsOnShape(), SMESH_ProxyMesh.setMesh(), SMESH_ProxyMesh.storeTmpElement(), SMESH_ProxyMesh.takeProxySubMesh(), SMESH_ProxyMesh.takeTmpElemsInMesh(), SMESH_fixation.xc, SMESH_test3.yc, and SMESH_fixation.zc.
{
SMESH_ProxyMesh::setMesh( aMesh );
if ( aShape.ShapeType() != TopAbs_SOLID &&
aShape.ShapeType() != TopAbs_SHELL )
return false;
vector<const SMDS_MeshElement*> myPyramids;
SMESHDS_Mesh * meshDS = aMesh.GetMeshDS();
SMESH_MesherHelper helper(aMesh);
helper.IsQuadraticSubMesh(aShape);
helper.SetElementsOnShape( true );
if ( myElemSearcher ) delete myElemSearcher;
if ( aProxyMesh )
myElemSearcher = SMESH_MeshEditor(&aMesh).GetElementSearcher( aProxyMesh->GetFaces(aShape));
else
myElemSearcher = SMESH_MeshEditor(&aMesh).GetElementSearcher();
const SMESHDS_SubMesh * aSubMeshDSFace;
Handle(TColgp_HArray1OfPnt) PN = new TColgp_HArray1OfPnt(1,5);
Handle(TColgp_HArray1OfVec) VN = new TColgp_HArray1OfVec(1,4);
vector<const SMDS_MeshNode*> FNodes(5);
gp_Pnt PC;
gp_Vec VNorm;
for (TopExp_Explorer exp(aShape,TopAbs_FACE);exp.More();exp.Next())
{
const TopoDS_Shape& aShapeFace = exp.Current();
if ( aProxyMesh )
aSubMeshDSFace = aProxyMesh->GetSubMesh( aShapeFace );
else
aSubMeshDSFace = meshDS->MeshElements( aShapeFace );
vector<const SMDS_MeshElement*> trias, quads;
bool hasNewTrias = false;
if ( aSubMeshDSFace )
{
bool isRev = false;
if ( helper.NbAncestors( aShapeFace, aMesh, aShape.ShapeType() ) > 1 )
isRev = SMESH_Algo::IsReversedSubMesh( TopoDS::Face(aShapeFace), meshDS );
SMDS_ElemIteratorPtr iteratorElem = aSubMeshDSFace->GetElements();
while ( iteratorElem->more() ) // loop on elements on a geometrical face
{
const SMDS_MeshElement* face = iteratorElem->next();
// preparation step to get face info
int stat = Preparation(face, PN, VN, FNodes, PC, VNorm);
switch ( stat )
{
case NOT_QUAD:
trias.push_back( face );
break;
case DEGEN_QUAD:
{
// degenerate face
// add triangles to result map
SMDS_MeshFace* NewFace;
if(!isRev)
NewFace = meshDS->AddFace( FNodes[0], FNodes[1], FNodes[2] );
else
NewFace = meshDS->AddFace( FNodes[0], FNodes[2], FNodes[1] );
storeTmpElement( NewFace );
trias.push_back ( NewFace );
quads.push_back( face );
hasNewTrias = true;
break;
}
case QUAD:
{
if(!isRev) VNorm.Reverse();
double xc = 0., yc = 0., zc = 0.;
int i = 1;
for(; i<=4; i++) {
gp_Pnt Pbest;
if(!isRev)
Pbest = FindBestPoint(PN->Value(i), PN->Value(i+1), PC, VN->Value(i).Reversed());
else
Pbest = FindBestPoint(PN->Value(i), PN->Value(i+1), PC, VN->Value(i));
xc += Pbest.X();
yc += Pbest.Y();
zc += Pbest.Z();
}
gp_Pnt PCbest(xc/4., yc/4., zc/4.);
// check PCbest
double height = PCbest.Distance(PC);
if(height<1.e-6) {
// create new PCbest using a bit shift along VNorm
PCbest = PC.XYZ() + VNorm.XYZ() * 0.001;
}
else {
// check possible intersection with other faces
gp_Pnt Pint;
bool check = CheckIntersection(PCbest, PC, Pint, aMesh, aShape, face);
if(check) {
//cout<<"--PC("<<PC.X()<<","<<PC.Y()<<","<<PC.Z()<<")"<<endl;
//cout<<" PCbest("<<PCbest.X()<<","<<PCbest.Y()<<","<<PCbest.Z()<<")"<<endl;
double dist = PC.Distance(Pint)/3.;
gp_Dir aDir(gp_Vec(PC,PCbest));
PCbest = PC.XYZ() + aDir.XYZ() * dist;
}
else {
gp_Vec VB(PC,PCbest);
gp_Pnt PCbestTmp = PC.XYZ() + VB.XYZ() * 3.0;
check = CheckIntersection(PCbestTmp, PC, Pint, aMesh, aShape, face);
if(check) {
double dist = PC.Distance(Pint)/3.;
if(dist<height) {
gp_Dir aDir(gp_Vec(PC,PCbest));
PCbest = PC.XYZ() + aDir.XYZ() * dist;
}
}
}
}
// create node for PCbest
SMDS_MeshNode* NewNode = helper.AddNode( PCbest.X(), PCbest.Y(), PCbest.Z() );
// add triangles to result map
for(i=0; i<4; i++)
{
trias.push_back ( meshDS->AddFace( NewNode, FNodes[i], FNodes[i+1] ));
storeTmpElement( trias.back() );
}
// create a pyramid
if ( isRev ) swap( FNodes[1], FNodes[3]);
SMDS_MeshVolume* aPyram =
helper.AddVolume( FNodes[0], FNodes[1], FNodes[2], FNodes[3], NewNode );
myPyramids.push_back(aPyram);
quads.push_back( face );
hasNewTrias = true;
break;
} // case QUAD:
} // switch ( stat )
} // end loop on elements on a face submesh
bool sourceSubMeshIsProxy = false;
if ( aProxyMesh )
{
// move proxy sub-mesh from other proxy mesh to this
sourceSubMeshIsProxy = takeProxySubMesh( aShapeFace, aProxyMesh );
// move also tmp elements added in mesh
takeTmpElemsInMesh( aProxyMesh );
}
if ( hasNewTrias )
{
SMESH_ProxyMesh::SubMesh* prxSubMesh = getProxySubMesh( aShapeFace );
prxSubMesh->ChangeElements( trias.begin(), trias.end() );
// delete tmp quadrangles removed from aProxyMesh
if ( sourceSubMeshIsProxy )
{
for ( unsigned i = 0; i < quads.size(); ++i )
removeTmpElement( quads[i] );
delete myElemSearcher;
myElemSearcher =
SMESH_MeshEditor(&aMesh).GetElementSearcher( aProxyMesh->GetFaces(aShape));
}
}
}
} // end for(TopExp_Explorer exp(aShape,TopAbs_FACE);exp.More();exp.Next()) {
return Compute2ndPart(aMesh, myPyramids);
}
| bool StdMeshers_QuadToTriaAdaptor::Compute | ( | SMESH_Mesh & | aMesh | ) |
Computes pyramids in mesh with no shape.
Definition at line 887 of file StdMeshers_QuadToTriaAdaptor.cxx.
References SMESH_ProxyMesh._allowedTypes, SMESH_ProxyMesh.SubMesh.AddElement(), SMESHDS_Mesh.AddFace(), SMESH_MesherHelper.AddNode(), SMESH_MesherHelper.AddVolume(), Compute2ndPart(), ex13_hole1partial.d, DEGEN_QUAD, SMDS_Mesh.facesIterator(), FindBestPoint(), SMESH_ElementSearcher.GetElementsNearLine(), SMDS_MeshElement.GetNode(), SMESH_ProxyMesh.getProxySubMesh(), Handle(), HasIntersection(), ex21_lamp.height, SMDS_MeshElement.IsQuadratic(), SMESH_MesherHelper.IsQuadraticSubMesh(), Min(), myElemSearcher, SMDS_MeshElement.NbNodes(), NOT_QUAD, Preparation(), SMESH_MesherHelper.SetElementsOnShape(), SMESH_ProxyMesh.setMesh(), SMDSAbs_Face, SMDSEntity_Quad_Triangle, SMDSEntity_Triangle, SMESH_ProxyMesh.storeTmpElement(), and SMESH_AdvancedEditor.volumes.
{
SMESH_ProxyMesh::setMesh( aMesh );
SMESH_ProxyMesh::_allowedTypes.push_back( SMDSEntity_Triangle );
SMESH_ProxyMesh::_allowedTypes.push_back( SMDSEntity_Quad_Triangle );
if ( aMesh.NbQuadrangles() < 1 )
return false;
vector<const SMDS_MeshElement*> myPyramids;
SMESH_MesherHelper helper(aMesh);
helper.IsQuadraticSubMesh(aMesh.GetShapeToMesh());
helper.SetElementsOnShape( true );
if ( !myElemSearcher )
myElemSearcher = SMESH_MeshEditor(&aMesh).GetElementSearcher();
SMESH_ElementSearcher* searcher = const_cast<SMESH_ElementSearcher*>(myElemSearcher);
SMESHDS_Mesh * meshDS = aMesh.GetMeshDS();
SMESH_ProxyMesh::SubMesh* prxSubMesh = getProxySubMesh();
SMDS_FaceIteratorPtr fIt = meshDS->facesIterator(/*idInceasingOrder=*/true);
while( fIt->more())
{
const SMDS_MeshElement* face = fIt->next();
if ( !face ) continue;
// retrieve needed information about a face
Handle(TColgp_HArray1OfPnt) PN = new TColgp_HArray1OfPnt(1,5);
Handle(TColgp_HArray1OfVec) VN = new TColgp_HArray1OfVec(1,4);
vector<const SMDS_MeshNode*> FNodes(5);
gp_Pnt PC;
gp_Vec VNorm;
const SMDS_MeshElement* volumes[2];
int what = Preparation(face, PN, VN, FNodes, PC, VNorm, volumes);
if ( what == NOT_QUAD )
continue;
if ( volumes[0] && volumes[1] )
continue; // face is shared by two volumes - no space for a pyramid
if ( what == DEGEN_QUAD )
{
// degenerate face
// add a triangle to the proxy mesh
SMDS_MeshFace* NewFace;
// check orientation
double tmp = PN->Value(1).Distance(PN->Value(2)) + PN->Value(2).Distance(PN->Value(3));
// far points in VNorm direction
gp_Pnt Ptmp1 = PC.XYZ() + VNorm.XYZ() * tmp * 1.e6;
gp_Pnt Ptmp2 = PC.XYZ() - VNorm.XYZ() * tmp * 1.e6;
// check intersection for Ptmp1 and Ptmp2
bool IsRev = false;
bool IsOK1 = false;
bool IsOK2 = false;
double dist1 = RealLast();
double dist2 = RealLast();
gp_Pnt Pres1,Pres2;
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;
Handle(TColgp_HSequenceOfPnt) aContour = new TColgp_HSequenceOfPnt;
for ( int i = 0; i < 4; ++i )
aContour->Append( SMESH_TNodeXYZ( F->GetNode(i) ));
gp_Pnt PPP;
if( !volumes[0] && HasIntersection(Ptmp1, PC, PPP, aContour) ) {
IsOK1 = true;
double tmp = PC.Distance(PPP);
if(tmp<dist1) {
Pres1 = PPP;
dist1 = tmp;
}
}
if( !volumes[1] && HasIntersection(Ptmp2, PC, PPP, aContour) ) {
IsOK2 = true;
double tmp = PC.Distance(PPP);
if(tmp<dist2) {
Pres2 = PPP;
dist2 = tmp;
}
}
}
if( IsOK1 && !IsOK2 ) {
// using existed direction
}
else if( !IsOK1 && IsOK2 ) {
// using opposite direction
IsRev = true;
}
else { // IsOK1 && IsOK2
double tmp1 = PC.Distance(Pres1);
double tmp2 = PC.Distance(Pres2);
if(tmp1<tmp2) {
// using existed direction
}
else {
// using opposite direction
IsRev = true;
}
}
if(!IsRev)
NewFace = meshDS->AddFace( FNodes[0], FNodes[1], FNodes[2] );
else
NewFace = meshDS->AddFace( FNodes[0], FNodes[2], FNodes[1] );
storeTmpElement( NewFace );
prxSubMesh->AddElement( NewFace );
continue;
}
// Case of non-degenerated quadrangle
// Find pyramid peak
gp_XYZ PCbest(0., 0., 0.); // pyramid peak
int i = 1;
for(; i<=4; i++) {
gp_Pnt Pbest = FindBestPoint(PN->Value(i), PN->Value(i+1), PC, VN->Value(i));
PCbest += Pbest.XYZ();
}
PCbest /= 4;
double height = PC.Distance(PCbest); // pyramid height to precise
if(height<1.e-6) {
// create new PCbest using a bit shift along VNorm
PCbest = PC.XYZ() + VNorm.XYZ() * 0.001;
height = PC.Distance(PCbest);
}
// Restrict pyramid height by intersection with other faces
gp_Vec tmpDir(PC,PCbest); tmpDir.Normalize();
double tmp = PN->Value(1).Distance(PN->Value(3)) + PN->Value(2).Distance(PN->Value(4));
// far points: in (PC, PCbest) direction and vice-versa
gp_Pnt farPnt[2] = { PC.XYZ() + tmpDir.XYZ() * tmp * 1.e6,
PC.XYZ() - tmpDir.XYZ() * tmp * 1.e6 };
// check intersection for farPnt1 and farPnt2
bool intersected[2] = { false, false };
double dist [2] = { RealLast(), RealLast() };
gp_Pnt intPnt[2];
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 = suspectElems[iF];
if(F==face) continue;
Handle(TColgp_HSequenceOfPnt) aContour = new TColgp_HSequenceOfPnt;
int nbN = F->NbNodes() / ( F->IsQuadratic() ? 2 : 1 );
for ( i = 0; i < nbN; ++i )
aContour->Append( SMESH_TNodeXYZ( F->GetNode(i) ));
gp_Pnt intP;
for ( int isRev = 0; isRev < 2; ++isRev )
{
if( !volumes[isRev] && HasIntersection(farPnt[isRev], PC, intP, aContour) ) {
intersected[isRev] = true;
double d = PC.Distance( intP );
if( d < dist[isRev] )
{
intPnt[isRev] = intP;
dist [isRev] = d;
}
}
}
}
// Create one or two pyramids
for ( int isRev = 0; isRev < 2; ++isRev )
{
if( !intersected[isRev] ) continue;
double pyramidH = Min( height, PC.Distance(intPnt[isRev])/3.);
PCbest = PC.XYZ() + tmpDir.XYZ() * (isRev ? -pyramidH : pyramidH);
// create node for PCbest
SMDS_MeshNode* NewNode = helper.AddNode( PCbest.X(), PCbest.Y(), PCbest.Z() );
// add triangles to result map
for(i=0; i<4; i++) {
SMDS_MeshFace* NewFace;
if(isRev)
NewFace = meshDS->AddFace( NewNode, FNodes[i], FNodes[i+1] );
else
NewFace = meshDS->AddFace( NewNode, FNodes[i+1], FNodes[i] );
storeTmpElement( NewFace );
prxSubMesh->AddElement( NewFace );
}
// create a pyramid
SMDS_MeshVolume* aPyram;
if(isRev)
aPyram = helper.AddVolume( FNodes[0], FNodes[1], FNodes[2], FNodes[3], NewNode );
else
aPyram = helper.AddVolume( FNodes[0], FNodes[3], FNodes[2], FNodes[1], NewNode );
myPyramids.push_back(aPyram);
}
} // end loop on all faces
return Compute2ndPart(aMesh, myPyramids);
}
| bool StdMeshers_QuadToTriaAdaptor::Compute2ndPart | ( | SMESH_Mesh & | aMesh, |
| const std::vector< const SMDS_MeshElement * > & | pyramids | ||
| ) | [protected] |
Update created pyramids and faces to avoid their intersection.
Definition at line 1097 of file StdMeshers_QuadToTriaAdaptor.cxx.
References ex21_lamp.faces, SMESH_ProxyMesh.findProxySubMesh(), SMESH_Algo.GetCommonNodes(), SMESH_ElementSearcher.GetElementsNearLine(), SMDS_MeshNode.GetInverseElementIterator(), SMESH_ProxyMesh.GetMeshDS(), SMDS_MeshElement.GetNode(), SMDS_MeshElement.GetNodeIndex(), SMDS_MeshElement.getshapeId(), HasIntersection3(), SMESHDS_Mesh.IsEmbeddedMode(), SMESHDS_Mesh.MaxShapeIndex(), MergeAdjacent(), MergePiramids(), SMESHDS_Mesh.MoveNode(), myDegNodes, myElemSearcher, myRemovedTrias, SMDS_MeshElement.NbCornerNodes(), SMDS_MeshElement.nodesIterator(), PI, SMDS_MeshNode.setXYZ(), ex21_lamp.size, and SMDSAbs_Volume.
Referenced by Compute().
{
if(myPyramids.empty())
return true;
SMESHDS_Mesh * meshDS = aMesh.GetMeshDS();
int i, j, k, myShapeID = myPyramids[0]->GetNode(4)->getshapeId();
if ( myElemSearcher ) delete myElemSearcher;
myElemSearcher = SMESH_MeshEditor(&aMesh).GetElementSearcher();
SMESH_ElementSearcher* searcher = const_cast<SMESH_ElementSearcher*>(myElemSearcher);
set<const SMDS_MeshNode*> nodesToMove;
// check adjacent pyramids
for ( i = 0; i < myPyramids.size(); ++i )
{
const SMDS_MeshElement* PrmI = myPyramids[i];
MergeAdjacent( PrmI, nodesToMove );
}
// iterate on all pyramids
for ( i = 0; i < myPyramids.size(); ++i )
{
const SMDS_MeshElement* PrmI = myPyramids[i];
// compare PrmI with all the rest pyramids
// collect adjacent pyramids and nodes coordinates of PrmI
set<const SMDS_MeshElement*> checkedPyrams;
vector<gp_Pnt> PsI(5);
for(k=0; k<5; k++) // loop on 4 base nodes of PrmI
{
const SMDS_MeshNode* n = PrmI->GetNode(k);
PsI[k] = SMESH_TNodeXYZ( n );
SMDS_ElemIteratorPtr vIt = n->GetInverseElementIterator( SMDSAbs_Volume );
while ( vIt->more() )
{
const SMDS_MeshElement* PrmJ = vIt->next();
if ( SMESH_Algo::GetCommonNodes( PrmI, PrmJ ).size() > 1 )
checkedPyrams.insert( PrmJ );
}
}
// check intersection with distant pyramids
for(k=0; k<4; k++) // loop on 4 base nodes of PrmI
{
gp_Vec Vtmp(PsI[k],PsI[4]);
gp_Ax1 line( PsI[k], Vtmp );
vector< const SMDS_MeshElement* > suspectPyrams;
searcher->GetElementsNearLine( line, SMDSAbs_Volume, suspectPyrams);
for ( j = 0; j < suspectPyrams.size(); ++j )
{
const SMDS_MeshElement* PrmJ = suspectPyrams[j];
if ( PrmJ == PrmI || PrmJ->NbCornerNodes() != 5 )
continue;
if ( myShapeID != PrmJ->GetNode(4)->getshapeId())
continue; // pyramid from other SOLID
if ( PrmI->GetNode(4) == PrmJ->GetNode(4) )
continue; // pyramids PrmI and PrmJ already merged
if ( !checkedPyrams.insert( PrmJ ).second )
continue; // already checked
TXyzIterator xyzIt( PrmJ->nodesIterator() );
vector<gp_Pnt> PsJ( xyzIt, TXyzIterator() );
gp_Pnt Pint;
bool hasInt=false;
for(k=0; k<4 && !hasInt; k++) {
gp_Vec Vtmp(PsI[k],PsI[4]);
gp_Pnt Pshift = PsI[k].XYZ() + Vtmp.XYZ() * 0.01; // base node moved a bit to apex
hasInt =
( 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[2], PsJ[3], PsJ[4]) ||
HasIntersection3( Pshift, PsI[4], Pint, PsJ[3], PsJ[0], PsJ[4]) );
}
for(k=0; k<4 && !hasInt; k++) {
gp_Vec Vtmp(PsJ[k],PsJ[4]);
gp_Pnt Pshift = PsJ[k].XYZ() + Vtmp.XYZ() * 0.01;
hasInt =
( HasIntersection3( Pshift, PsJ[4], Pint, PsI[0], PsI[1], PsI[4]) ||
HasIntersection3( Pshift, PsJ[4], Pint, PsI[1], PsI[2], PsI[4]) ||
HasIntersection3( Pshift, PsJ[4], Pint, PsI[2], PsI[3], PsI[4]) ||
HasIntersection3( Pshift, PsJ[4], Pint, PsI[3], PsI[0], PsI[4]) );
}
if ( hasInt )
{
// count common nodes of base faces of two pyramids
int nbc = 0;
for (k=0; k<4; k++)
nbc += int ( PrmI->GetNodeIndex( PrmJ->GetNode(k) ) >= 0 );
if ( nbc == 4 )
continue; // pyrams have a common base face
if(nbc>0)
{
// Merge the two pyramids and others already merged with them
MergePiramids( PrmI, PrmJ, nodesToMove );
}
else { // nbc==0
// decrease height of pyramids
gp_XYZ PCi(0,0,0), PCj(0,0,0);
for(k=0; k<4; k++) {
PCi += PsI[k].XYZ();
PCj += PsJ[k].XYZ();
}
PCi /= 4; PCj /= 4;
gp_Vec VN1(PCi,PsI[4]);
gp_Vec VN2(PCj,PsJ[4]);
gp_Vec VI1(PCi,Pint);
gp_Vec VI2(PCj,Pint);
double ang1 = fabs(VN1.Angle(VI1));
double ang2 = fabs(VN2.Angle(VI2));
double coef1 = 0.5 - (( ang1<PI/3 ) ? cos(ang1)*0.25 : 0 );
double coef2 = 0.5 - (( ang2<PI/3 ) ? cos(ang2)*0.25 : 0 ); // cos(ang2) ?
// double coef2 = 0.5;
// if(ang2<PI/3)
// coef2 -= cos(ang1)*0.25;
VN1.Scale(coef1);
VN2.Scale(coef2);
SMDS_MeshNode* aNode1 = const_cast<SMDS_MeshNode*>(PrmI->GetNode(4));
aNode1->setXYZ( PCi.X()+VN1.X(), PCi.Y()+VN1.Y(), PCi.Z()+VN1.Z() );
SMDS_MeshNode* aNode2 = const_cast<SMDS_MeshNode*>(PrmJ->GetNode(4));
aNode2->setXYZ( PCj.X()+VN2.X(), PCj.Y()+VN2.Y(), PCj.Z()+VN2.Z() );
nodesToMove.insert( aNode1 );
nodesToMove.insert( aNode2 );
}
// fix intersections that could appear after apex movement
MergeAdjacent( PrmI, nodesToMove );
MergeAdjacent( PrmJ, nodesToMove );
} // end if(hasInt)
} // loop on suspectPyrams
} // loop on 4 base nodes of PrmI
} // loop on all pyramids
if( !nodesToMove.empty() && !meshDS->IsEmbeddedMode() )
{
set<const SMDS_MeshNode*>::iterator n = nodesToMove.begin();
for ( ; n != nodesToMove.end(); ++n )
meshDS->MoveNode( *n, (*n)->X(), (*n)->Y(), (*n)->Z() );
}
// move medium nodes of merged quadratic pyramids
if ( myPyramids[0]->IsQuadratic() )
UpdateQuadraticPyramids( nodesToMove, GetMeshDS() );
// erase removed triangles from the proxy mesh
if ( !myRemovedTrias.empty() )
{
for ( int i = 0; i <= meshDS->MaxShapeIndex(); ++i )
if ( SMESH_ProxyMesh::SubMesh* sm = findProxySubMesh(i))
{
vector<const SMDS_MeshElement *> faces;
faces.reserve( sm->NbElements() );
SMDS_ElemIteratorPtr fIt = sm->GetElements();
while ( fIt->more() )
{
const SMDS_MeshElement* tria = fIt->next();
set<const SMDS_MeshElement*>::iterator rmTria = myRemovedTrias.find( tria );
if ( rmTria != myRemovedTrias.end() )
myRemovedTrias.erase( rmTria );
else
faces.push_back( tria );
}
sm->ChangeElements( faces.begin(), faces.end() );
}
}
myDegNodes.clear();
delete myElemSearcher;
myElemSearcher=0;
return true;
}
| SMESH_ProxyMesh::SubMesh * SMESH_ProxyMesh::findProxySubMesh | ( | int | shapeIndex = 0 | ) | const [protected, inherited] |
Returns a proxy sub-mesh.
Definition at line 353 of file SMESH_ProxyMesh.cxx.
References SMESH_ProxyMesh._subMeshes.
Referenced by Compute2ndPart(), SMESH_ProxyMesh.GetProxyNode(), and SMESH_ProxyMesh.takeProxySubMesh().
{
return shapeIndex < int(_subMeshes.size()) ? _subMeshes[shapeIndex] : 0;
}
| SMDS_ElemIteratorPtr SMESH_ProxyMesh::GetFaces | ( | ) | const [inherited] |
Returns iterator on all faces of the mesh taking into account substitutions To be used in case of mesh without shape.
Definition at line 249 of file SMESH_ProxyMesh.cxx.
References SMESH_ProxyMesh._allowedTypes, SMESH_ProxyMesh._mesh, SMESH_ProxyMesh._subContainer, SMESH_ProxyMesh._subMeshes, SMESHDS_SubMesh.AddSubMesh(), SMDS_Mesh.elementsIterator(), SMESH_ProxyMesh.GetMeshDS(), SMESH_Mesh.HasShapeToMesh(), SMESH_Mesh.NbFaces(), SMESH_ProxyMesh.NbFaces(), SMESHDS_SubMesh.NbSubMeshes(), SMESHDS_SubMesh.RemoveAllSubmeshes(), and SMDSAbs_Face.
Referenced by Compute(), VISCOUS._ViscousBuilder.inflate(), and VISCOUS._ViscousBuilder.smoothAndCheck().
{
if ( _mesh->HasShapeToMesh() )
return SMDS_ElemIteratorPtr();
_subContainer.RemoveAllSubmeshes();
for ( unsigned i = 0; i < _subMeshes.size(); ++i )
if ( _subMeshes[i] )
_subContainer.AddSubMesh( _subMeshes[i] );
if ( _subContainer.NbSubMeshes() == 0 ) // no elements substituted
return GetMeshDS()->elementsIterator(SMDSAbs_Face);
// if _allowedTypes is empty, only elements from _subMeshes are returned,...
SMDS_ElemIteratorPtr proxyIter = _subContainer.SMESHDS_SubMesh::GetElements();
if ( _allowedTypes.empty() || NbFaces() == _mesh->NbFaces() )
return proxyIter;
// ... else elements filtered using allowedTypes are additionally returned
SMDS_ElemIteratorPtr facesIter = GetMeshDS()->elementsIterator(SMDSAbs_Face);
SMDS_ElemIteratorPtr filterIter( new TFilteringIterator( _allowedTypes, facesIter ));
vector< SMDS_ElemIteratorPtr > iters(2);
iters[0] = proxyIter;
iters[1] = filterIter;
typedef vector< SMDS_ElemIteratorPtr > TElemIterVector;
typedef SMDS_IteratorOnIterators<const SMDS_MeshElement *, TElemIterVector> TItersIter;
return SMDS_ElemIteratorPtr( new TItersIter( iters ));
}
| SMDS_ElemIteratorPtr SMESH_ProxyMesh::GetFaces | ( | const TopoDS_Shape & | face | ) | const [inherited] |
Returns iterator on all faces on the shape taking into account substitutions.
Definition at line 226 of file SMESH_ProxyMesh.cxx.
References SMESH_ProxyMesh._mesh, SMESH_ProxyMesh._subContainer, SMESHDS_SubMesh.AddSubMesh(), SMESH_ProxyMesh.GetSubMesh(), SMESH_Mesh.HasShapeToMesh(), and SMESHDS_SubMesh.RemoveAllSubmeshes().
{
if ( !_mesh->HasShapeToMesh() )
return SMDS_ElemIteratorPtr();
_subContainer.RemoveAllSubmeshes();
TopTools_IndexedMapOfShape FF;
TopExp::MapShapes( shape, TopAbs_FACE, FF );
for ( int i = 1; i <= FF.Extent(); ++i )
if ( const SMESHDS_SubMesh* sm = GetSubMesh( FF(i)))
_subContainer.AddSubMesh( sm );
return _subContainer.SMESHDS_SubMesh::GetElements();
}
| const SMESH_Mesh* SMESH_ProxyMesh.GetMesh | ( | ) | const [inherited] |
Definition at line 116 of file SMESH_ProxyMesh.hxx.
References SMESH_ProxyMesh._mesh.
{ return _mesh; }
| SMESHDS_Mesh * SMESH_ProxyMesh::GetMeshDS | ( | ) | const [inherited] |
Returns mesh DS.
Definition at line 364 of file SMESH_ProxyMesh.cxx.
References SMESH_ProxyMesh._mesh, and SMESH_Mesh.GetMeshDS().
Referenced by Compute2ndPart(), SMESH_ProxyMesh.GetFaces(), SMESH_ProxyMesh.GetProxyNode(), SMESH_ProxyMesh.GetSubMesh(), VISCOUS._ViscousBuilder.MakeN2NMap(), SMESH_ProxyMesh.NbFaces(), SMESH_ProxyMesh.removeTmpElement(), SMESH_ProxyMesh.shapeIndex(), and SMESH_ProxyMesh.~SMESH_ProxyMesh().
{
return (SMESHDS_Mesh*)( _mesh ? _mesh->GetMeshDS() : 0 );
}
| const SMDS_MeshNode * SMESH_ProxyMesh::GetProxyNode | ( | const SMDS_MeshNode * | node | ) | const [inherited] |
Returns the proxy node of a node; the input node is returned if no proxy exists.
Definition at line 161 of file SMESH_ProxyMesh.cxx.
References SMESH_ProxyMesh._mesh, SMESH_ProxyMesh.findProxySubMesh(), SMESH_Mesh.GetAncestors(), SMESH_ProxyMesh.GetMeshDS(), SMDS_MeshNode.GetPosition(), SMDS_MeshElement.getshapeId(), SMESH_MesherHelper.GetSubShapeByNode(), SMDS_Position.GetTypeOfPosition(), ex29_refine.node(), SMESH_fixation.shape, SMESH_ProxyMesh.shapeIndex(), and SMDS_TOP_FACE.
Referenced by SMESH_MesherHelper.LoadNodeColumns().
{
const SMDS_MeshNode* proxy = node;
if ( node->GetPosition()->GetTypeOfPosition() == SMDS_TOP_FACE )
{
if ( const SubMesh* proxySM = findProxySubMesh( node->getshapeId() ))
proxy = proxySM->GetProxyNode( node );
}
else
{
TopoDS_Shape shape = SMESH_MesherHelper::GetSubShapeByNode( node, GetMeshDS());
TopTools_ListIteratorOfListOfShape ancIt;
if ( !shape.IsNull() ) ancIt.Initialize( _mesh->GetAncestors( shape ));
for ( ; ancIt.More() && proxy == node; ancIt.Next() )
if ( const SubMesh* proxySM = findProxySubMesh( shapeIndex(ancIt.Value())))
proxy = proxySM->GetProxyNode( node );
}
return proxy;
}
| const SMESH_ProxyMesh::SubMesh * SMESH_ProxyMesh::GetProxySubMesh | ( | const TopoDS_Shape & | face | ) | const [inherited] |
Returns the proxy sub-mesh of a shape; it can be NULL.
Definition at line 149 of file SMESH_ProxyMesh.cxx.
References SMESH_ProxyMesh._subMeshes, and SMESH_ProxyMesh.shapeIndex().
Referenced by VISCOUS._ViscousBuilder.MakeN2NMap().
{
int i = shapeIndex(shape);
return i < _subMeshes.size() ? _subMeshes[i] : 0;
}
| SMESH_ProxyMesh::SubMesh * SMESH_ProxyMesh::getProxySubMesh | ( | int | shapeIndex | ) | [protected, inherited] |
Returns a proxy sub-mesh; it is created if not yet exists.
Definition at line 327 of file SMESH_ProxyMesh.cxx.
References SMESH_ProxyMesh._subMeshes.
Referenced by Compute(), VISCOUS._MeshOfSolid.getFaceSubM(), and SMESH_ProxyMesh.getProxySubMesh().
{
if ( int(_subMeshes.size()) <= index )
_subMeshes.resize( index+1, 0 );
if ( !_subMeshes[index] )
_subMeshes[index] = new SubMesh( index );
return _subMeshes[index];
}
| SMESH_ProxyMesh::SubMesh * SMESH_ProxyMesh::getProxySubMesh | ( | const TopoDS_Shape & | shape = TopoDS_Shape() | ) | [protected, inherited] |
Returns a proxy sub-mesh; it is created if not yet exists.
Definition at line 342 of file SMESH_ProxyMesh.cxx.
References SMESH_ProxyMesh.getProxySubMesh(), and SMESH_ProxyMesh.shapeIndex().
{
return getProxySubMesh( shapeIndex( shape ));
}
| const SMESHDS_SubMesh * SMESH_ProxyMesh::GetSubMesh | ( | const TopoDS_Shape & | face | ) | const [inherited] |
Returns the submesh of a shape; it can be a proxy sub-mesh.
Definition at line 129 of file SMESH_ProxyMesh.cxx.
References SMESH_ProxyMesh._subMeshes, SMESH_ProxyMesh.GetMeshDS(), SMESHDS_Mesh.MeshElements(), and SMESH_ProxyMesh.shapeIndex().
Referenced by Compute(), SMESH_ProxyMesh.GetFaces(), SMESH_MesherHelper.LoadNodeColumns(), and SMESH_ProxyMesh.NbFaces().
{
const SMESHDS_SubMesh* sm = 0;
int i = shapeIndex(shape);
if ( i < _subMeshes.size() )
sm = _subMeshes[i];
if ( !sm )
sm = GetMeshDS()->MeshElements( i );
return sm;
}
| bool SMESH_ProxyMesh::IsTemporary | ( | const SMDS_MeshElement * | elem | ) | const [inherited] |
Return true if the element is a temporary one.
Definition at line 465 of file SMESH_ProxyMesh.cxx.
References SMESH_ProxyMesh._elemsInMesh, and SMDS_MeshElement.GetID().
Referenced by SMESH_MesherHelper.LoadNodeColumns().
{
return ( elem->GetID() < 1 ) || _elemsInMesh.count( elem );
}
| void StdMeshers_QuadToTriaAdaptor::MergeAdjacent | ( | const SMDS_MeshElement * | PrmI, |
| std::set< const SMDS_MeshNode * > & | nodesToMove | ||
| ) | [protected] |
Merges adjacent pyramids.
Definition at line 326 of file StdMeshers_QuadToTriaAdaptor.cxx.
References SMDS_MeshNode.GetInverseElementIterator(), SMDS_MeshElement.GetNode(), SMDS_MeshElement.NbCornerNodes(), and SMDSAbs_Volume.
Referenced by Compute2ndPart().
{
TIDSortedElemSet adjacentPyrams;
bool mergedPyrams = false;
for(int k=0; k<4; k++) // loop on 4 base nodes of PrmI
{
const SMDS_MeshNode* n = PrmI->GetNode(k);
SMDS_ElemIteratorPtr vIt = n->GetInverseElementIterator( SMDSAbs_Volume );
while ( vIt->more() )
{
const SMDS_MeshElement* PrmJ = vIt->next();
if ( PrmJ->NbCornerNodes() != 5 || !adjacentPyrams.insert( PrmJ ).second )
continue;
if ( PrmI != PrmJ && TooCloseAdjacent( PrmI, PrmJ, GetMesh()->HasShapeToMesh() ))
{
MergePiramids( PrmI, PrmJ, nodesToMove );
mergedPyrams = true;
// container of inverse elements can change
vIt = n->GetInverseElementIterator( SMDSAbs_Volume );
}
}
}
if ( mergedPyrams )
{
TIDSortedElemSet::iterator prm;
for (prm = adjacentPyrams.begin(); prm != adjacentPyrams.end(); ++prm)
MergeAdjacent( *prm, nodesToMove );
}
}
| void StdMeshers_QuadToTriaAdaptor::MergePiramids | ( | const SMDS_MeshElement * | PrmI, |
| const SMDS_MeshElement * | PrmJ, | ||
| std::set< const SMDS_MeshNode * > & | nodesToMove | ||
| ) | [protected] |
Merge the two pyramids (i.e.
fuse their apex) and others already merged with them
Definition at line 259 of file StdMeshers_QuadToTriaAdaptor.cxx.
References SMDS_MeshElement.begin_nodes(), SMDS_MeshElement.end_nodes(), SMDS_MeshNode.GetInverseElementIterator(), SMDS_MeshElement.GetNode(), SMDS_MeshElement.getshapeId(), SMDS_MeshElement.GetType(), SMDS_MeshNode.NbInverseElements(), SMESH_AdvancedEditor.nodes, PYRAM_APEX, SMDS_MeshNode.setXYZ(), SMDSAbs_Face, SMDSAbs_Volume, and TRIA_APEX.
Referenced by Compute2ndPart().
{
const SMDS_MeshNode* Nrem = PrmJ->GetNode(4); // node to remove
//int nbJ = Nrem->NbInverseElements( SMDSAbs_Volume );
SMESH_TNodeXYZ Pj( Nrem );
// an apex node to make common to all merged pyramids
SMDS_MeshNode* CommonNode = const_cast<SMDS_MeshNode*>(PrmI->GetNode(4));
if ( CommonNode == Nrem ) return; // already merged
//int nbI = CommonNode->NbInverseElements( SMDSAbs_Volume );
SMESH_TNodeXYZ Pi( CommonNode );
gp_XYZ Pnew = /*( nbI*Pi + nbJ*Pj ) / (nbI+nbJ);*/ 0.5 * ( Pi + Pj );
CommonNode->setXYZ( Pnew.X(), Pnew.Y(), Pnew.Z() );
nodesToMove.insert( CommonNode );
nodesToMove.erase ( Nrem );
typedef SMDS_StdIterator< const SMDS_MeshElement*, SMDS_ElemIteratorPtr > TStdElemIterator;
TStdElemIterator itEnd;
// find and remove coincided faces of merged pyramids
vector< const SMDS_MeshElement* > inverseElems
// copy inverse elements to avoid iteration on changing container
( TStdElemIterator( CommonNode->GetInverseElementIterator(SMDSAbs_Face)), itEnd);
for ( unsigned i = 0; i < inverseElems.size(); ++i )
{
const SMDS_MeshElement* FI = inverseElems[i];
const SMDS_MeshElement* FJEqual = 0;
SMDS_ElemIteratorPtr triItJ = Nrem->GetInverseElementIterator(SMDSAbs_Face);
while ( !FJEqual && triItJ->more() )
{
const SMDS_MeshElement* FJ = triItJ->next();
if ( EqualTriangles( FJ, FI ))
FJEqual = FJ;
}
if ( FJEqual )
{
removeTmpElement( FI );
removeTmpElement( FJEqual );
myRemovedTrias.insert( FI );
myRemovedTrias.insert( FJEqual );
}
}
// set the common apex node to pyramids and triangles merged with J
inverseElems.assign( TStdElemIterator( Nrem->GetInverseElementIterator()), itEnd );
for ( unsigned i = 0; i < inverseElems.size(); ++i )
{
const SMDS_MeshElement* elem = inverseElems[i];
vector< const SMDS_MeshNode* > nodes( elem->begin_nodes(), elem->end_nodes() );
nodes[ elem->GetType() == SMDSAbs_Volume ? PYRAM_APEX : TRIA_APEX ] = CommonNode;
GetMeshDS()->ChangeElementNodes( elem, &nodes[0], nodes.size());
}
ASSERT( Nrem->NbInverseElements() == 0 );
GetMeshDS()->RemoveFreeNode( Nrem,
GetMeshDS()->MeshElements( Nrem->getshapeId()),
/*fromGroups=*/false);
}
| int SMESH_ProxyMesh::NbFaces | ( | ) | const [inherited] |
Return total nb of faces taking into account substitutions.
Definition at line 285 of file SMESH_ProxyMesh.cxx.
References SMESH_ProxyMesh._allowedTypes, SMESH_ProxyMesh._mesh, SMESH_ProxyMesh._subMeshes, SMESH_ProxyMesh.GetMeshDS(), SMDS_Mesh.GetMeshInfo(), SMESH_Mesh.GetShapeToMesh(), SMESH_ProxyMesh.GetSubMesh(), SMESH_Mesh.HasShapeToMesh(), SMDS_MeshInfo.NbEntities(), SMDS_Mesh.NbFaces(), SMDSEntity_Quad_Quadrangle, and SMDSEntity_Triangle.
Referenced by SMESH_ProxyMesh.GetFaces().
{
int nb = 0;
if ( _mesh->HasShapeToMesh() )
{
TopTools_IndexedMapOfShape FF;
TopExp::MapShapes( _mesh->GetShapeToMesh(), TopAbs_FACE, FF );
for ( int i = 1; i <= FF.Extent(); ++i )
if ( const SMESHDS_SubMesh* sm = GetSubMesh( FF(i)))
nb += sm->NbElements();
}
else
{
if ( _subMeshes.empty() )
return GetMeshDS()->NbFaces();
for ( unsigned i = 0; i < _subMeshes.size(); ++i )
if ( _subMeshes[i] )
nb += _subMeshes[i]->NbElements();
// if _allowedTypes is empty, only elements from _subMeshes are returned,
// else elements filtered using allowedTypes are additionally returned
if ( !_allowedTypes.empty() )
{
for ( int t = SMDSEntity_Triangle; t <= SMDSEntity_Quad_Quadrangle; ++t )
{
bool allowed =
( find( _allowedTypes.begin(), _allowedTypes.end(), t ) != _allowedTypes.end() );
if ( allowed )
nb += GetMeshDS()->GetMeshInfo().NbEntities( SMDSAbs_EntityType( t ));
}
}
}
return nb;
}
| int StdMeshers_QuadToTriaAdaptor::Preparation | ( | const SMDS_MeshElement * | face, |
| Handle_TColgp_HArray1OfPnt & | PN, | ||
| Handle_TColgp_HArray1OfVec & | VN, | ||
| std::vector< const SMDS_MeshNode * > & | FNodes, | ||
| gp_Pnt & | PC, | ||
| gp_Vec & | VNorm, | ||
| const SMDS_MeshElement ** | volumes = 0 |
||
| ) | [protected] |
Prepare data for the given face.
| PN | - coordinates of face nodes |
| VN | - cross products of vectors (PC-PN(i)) ^ (PC-PN(i+1)) |
| FNodes | - face nodes |
| PC | - gravity center of nodes |
| VNorm | - face normal (sum of VN) |
| volumes | - two volumes sharing the given face, the first is in VNorm direction |
| int | - 0 if given face is not quad, 1 if given face is quad, 2 if given face is degenerate quad (two nodes are coincided) |
Definition at line 584 of file StdMeshers_QuadToTriaAdaptor.cxx.
References DEGEN_QUAD, SMDS_MeshElement.GetNode(), SMDS_MeshElement.GetNodeIndex(), myDegNodes, SMDS_MeshElement.NbCornerNodes(), SMDS_MeshElement.NbNodes(), SMDS_MeshElement.nodesIterator(), NOT_QUAD, QUAD, SMDSAbs_Volume, SMESH_demo_hexa2_upd.vol, SMDS_MeshNode.X(), SMDS_MeshNode.Y(), and SMDS_MeshNode.Z().
Referenced by Compute().
{
if( face->NbCornerNodes() != 4 )
{
return NOT_QUAD;
}
int i = 0;
gp_XYZ xyzC(0., 0., 0.);
for ( i = 0; i < 4; ++i )
{
gp_XYZ p = SMESH_TNodeXYZ( FNodes[i] = face->GetNode(i) );
PN->SetValue( i+1, p );
xyzC += p;
}
PC = xyzC/4;
int nbp = 4;
int j = 0;
for(i=1; i<4; i++) {
j = i+1;
for(; j<=4; j++) {
if( PN->Value(i).Distance(PN->Value(j)) < 1.e-6 )
break;
}
if(j<=4) break;
}
//int deg_num = IsDegenarate(PN);
//if(deg_num>0) {
bool hasdeg = false;
if(i<4) {
//cout<<"find degeneration"<<endl;
hasdeg = true;
gp_Pnt Pdeg = PN->Value(i);
list< const SMDS_MeshNode* >::iterator itdg = myDegNodes.begin();
const SMDS_MeshNode* DegNode = 0;
for(; itdg!=myDegNodes.end(); itdg++) {
const SMDS_MeshNode* N = (*itdg);
gp_Pnt Ptmp(N->X(),N->Y(),N->Z());
if(Pdeg.Distance(Ptmp)<1.e-6) {
DegNode = N;
//DegNode = const_cast<SMDS_MeshNode*>(N);
break;
}
}
if(!DegNode) {
DegNode = FNodes[i-1];
myDegNodes.push_back(DegNode);
}
else {
FNodes[i-1] = DegNode;
}
for(i=j; i<4; i++) {
PN->SetValue(i,PN->Value(i+1));
FNodes[i-1] = FNodes[i];
}
nbp = 3;
}
PN->SetValue(nbp+1,PN->Value(1));
FNodes[nbp] = FNodes[0];
// find normal direction
gp_Vec V1(PC,PN->Value(nbp));
gp_Vec V2(PC,PN->Value(1));
VNorm = V1.Crossed(V2);
VN->SetValue(nbp,VNorm);
for(i=1; i<nbp; i++) {
V1 = gp_Vec(PC,PN->Value(i));
V2 = gp_Vec(PC,PN->Value(i+1));
gp_Vec Vtmp = V1.Crossed(V2);
VN->SetValue(i,Vtmp);
VNorm += Vtmp;
}
// find volumes sharing the face
if ( volumes )
{
volumes[0] = volumes[1] = 0;
SMDS_ElemIteratorPtr vIt = FNodes[0]->GetInverseElementIterator( SMDSAbs_Volume );
while ( vIt->more() )
{
const SMDS_MeshElement* vol = vIt->next();
bool volSharesAllNodes = true;
for ( int i = 1; i < face->NbNodes() && volSharesAllNodes; ++i )
volSharesAllNodes = ( vol->GetNodeIndex( FNodes[i] ) >= 0 );
if ( volSharesAllNodes )
volumes[ volumes[0] ? 1 : 0 ] = vol;
// we could additionally check that vol has all FNodes in its one face using SMDS_VolumeTool
}
// define volume position relating to the face normal
if ( volumes[0] )
{
// get volume gc
SMDS_ElemIteratorPtr nodeIt = volumes[0]->nodesIterator();
gp_XYZ volGC(0,0,0);
volGC = accumulate( TXyzIterator(nodeIt), TXyzIterator(), volGC ) / volumes[0]->NbNodes();
if ( VNorm * gp_Vec( PC, volGC ) < 0 )
swap( volumes[0], volumes[1] );
}
}
//cout<<" VNorm("<<VNorm.X()<<","<<VNorm.Y()<<","<<VNorm.Z()<<")"<<endl;
return hasdeg ? DEGEN_QUAD : QUAD;
}
| void SMESH_ProxyMesh::removeTmpElement | ( | const SMDS_MeshElement * | face | ) | [protected, inherited] |
Removes tmp faces from the _mesh.
Definition at line 415 of file SMESH_ProxyMesh.cxx.
References SMESH_ProxyMesh._elemsInMesh, PAL_MESH_043_3D.face, SMDS_MeshElement.GetID(), SMESH_ProxyMesh.GetMeshDS(), and SMESHDS_Mesh.RemoveFreeElement().
Referenced by Compute().
{
if ( face && face->GetID() > 0 )
{
set< const SMDS_MeshElement* >::iterator i = _elemsInMesh.find( face );
if ( i != _elemsInMesh.end() )
{
GetMeshDS()->RemoveFreeElement( face, 0 );
_elemsInMesh.erase( i );
}
}
else
{
delete face;
}
}
| void SMESH_ProxyMesh.setMesh | ( | const SMESH_Mesh & | mesh | ) | [protected, inherited] |
Definition at line 124 of file SMESH_ProxyMesh.hxx.
References SMESH_ProxyMesh._mesh, and PAL_MESH_041_mesh.mesh.
Referenced by VISCOUS._MeshOfSolid._MeshOfSolid(), and Compute().
| void SMESH_ProxyMesh::setNode2Node | ( | const SMDS_MeshNode * | srcNode, |
| const SMDS_MeshNode * | proxyNode, | ||
| const SubMesh * | subMesh | ||
| ) | [protected, inherited] |
Set node-node correspondence.
Reimplemented in VISCOUS._MeshOfSolid.
Definition at line 449 of file SMESH_ProxyMesh.cxx.
References SMESH_ProxyMesh.SubMesh._n2n.
Referenced by VISCOUS._MeshOfSolid.setNode2Node().
{
SubMesh* sm = const_cast<SubMesh*>( subMesh );
if ( !subMesh->_n2n )
sm->_n2n = new TN2NMap;
sm->_n2n->insert( make_pair( srcNode, proxyNode ));
}
| int SMESH_ProxyMesh::shapeIndex | ( | const TopoDS_Shape & | shape | ) | const [protected, inherited] |
Returns index of a shape.
Definition at line 118 of file SMESH_ProxyMesh.cxx.
References SMESH_ProxyMesh._mesh, SMESH_ProxyMesh.GetMeshDS(), SMESH_Mesh.HasShapeToMesh(), and SMESHDS_Mesh.ShapeToIndex().
Referenced by VISCOUS._MeshOfSolid.getFaceSubM(), SMESH_ProxyMesh.GetProxyNode(), SMESH_ProxyMesh.getProxySubMesh(), SMESH_ProxyMesh.GetProxySubMesh(), SMESH_ProxyMesh.GetSubMesh(), and SMESH_ProxyMesh.takeProxySubMesh().
{
return ( shape.IsNull() || !_mesh->HasShapeToMesh() ? 0 : GetMeshDS()->ShapeToIndex(shape));
}
| void SMESH_ProxyMesh::storeTmpElement | ( | const SMDS_MeshElement * | face | ) | [protected, inherited] |
Stores tmp element residing the _mesh.
Definition at line 438 of file SMESH_ProxyMesh.cxx.
References SMESH_ProxyMesh._elemsInMesh.
Referenced by Compute().
{
_elemsInMesh.insert( face );
}
| bool SMESH_ProxyMesh::takeProxySubMesh | ( | const TopoDS_Shape & | shape, |
| SMESH_ProxyMesh * | proxyMesh | ||
| ) | [protected, inherited] |
Move proxy sub-mesh from other proxy mesh to this, returns true if sub-mesh found.
Definition at line 375 of file SMESH_ProxyMesh.cxx.
References SMESH_ProxyMesh._mesh, SMESH_ProxyMesh._subMeshes, SMESH_ProxyMesh.findProxySubMesh(), and SMESH_ProxyMesh.shapeIndex().
Referenced by Compute().
{
if ( proxyMesh && proxyMesh->_mesh == _mesh )
{
int iS = shapeIndex( shape );
if ( SubMesh* sm = proxyMesh->findProxySubMesh( iS ))
{
if ( iS >= int(_subMeshes.size()) )
_subMeshes.resize( iS + 1, 0 );
_subMeshes[iS] = sm;
proxyMesh->_subMeshes[iS] = 0;
return true;
}
}
return false;
}
| void SMESH_ProxyMesh::takeTmpElemsInMesh | ( | SMESH_ProxyMesh * | proxyMesh | ) | [protected, inherited] |
Move tmp elements residing the _mesh from other proxy mesh to this.
Definition at line 399 of file SMESH_ProxyMesh.cxx.
References SMESH_ProxyMesh._elemsInMesh.
Referenced by Compute().
{
if ( proxyMesh )
{
_elemsInMesh.insert( proxyMesh->_elemsInMesh.begin(),
proxyMesh->_elemsInMesh.end());
proxyMesh->_elemsInMesh.clear();
}
}
std::vector< SMDSAbs_EntityType> SMESH_ProxyMesh._allowedTypes [protected, inherited] |
Definition at line 157 of file SMESH_ProxyMesh.hxx.
Referenced by Compute(), SMESH_ProxyMesh.GetFaces(), and SMESH_ProxyMesh.NbFaces().
std::list< const SMDS_MeshNode* > StdMeshers_QuadToTriaAdaptor.myDegNodes [protected] |
Definition at line 92 of file StdMeshers_QuadToTriaAdaptor.hxx.
Referenced by Compute2ndPart(), and Preparation().
const SMESH_ElementSearcher* StdMeshers_QuadToTriaAdaptor.myElemSearcher [protected] |
Definition at line 94 of file StdMeshers_QuadToTriaAdaptor.hxx.
Referenced by CheckIntersection(), Compute(), Compute2ndPart(), and ~StdMeshers_QuadToTriaAdaptor().
std::set<const SMDS_MeshElement*> StdMeshers_QuadToTriaAdaptor.myRemovedTrias [protected] |
Definition at line 90 of file StdMeshers_QuadToTriaAdaptor.hxx.
Referenced by Compute2ndPart().