Version: 6.3.1
Public Types | Public Member Functions | Protected Member Functions | Protected Attributes

StdMeshers_QuadToTriaAdaptor Class Reference

"Transforms" quadrilateral faces into triangular ones by creation of pyramids More...

#include <StdMeshers_QuadToTriaAdaptor.hxx>

Inheritance diagram for StdMeshers_QuadToTriaAdaptor:
Inheritance graph
[legend]

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_SubMeshGetSubMesh (const TopoDS_Shape &face) const
 Returns the submesh of a shape; it can be a proxy sub-mesh.
const SubMeshGetProxySubMesh (const TopoDS_Shape &face) const
 Returns the proxy sub-mesh of a shape; it can be NULL.
const SMDS_MeshNodeGetProxyNode (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_MeshGetMesh () const
SMESHDS_MeshGetMeshDS () 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.
SubMeshfindProxySubMesh (int shapeIndex=0) const
 Returns a proxy sub-mesh.
SubMeshgetProxySubMesh (int shapeIndex)
 Returns a proxy sub-mesh; it is created if not yet exists.
SubMeshgetProxySubMesh (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_ElementSearchermyElemSearcher
std::vector< SMDSAbs_EntityType_allowedTypes

Detailed Description

"Transforms" quadrilateral faces into triangular ones by creation of pyramids

Definition at line 51 of file StdMeshers_QuadToTriaAdaptor.hxx.


Member Typedef Documentation

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.


Constructor & Destructor Documentation

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;
}

Member Function Documentation

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.

Parameters:
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
Return values:
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]
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.

Parameters:
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
Return values:
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().

{ _mesh = &mesh; }
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]
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();
  }
}

Field Documentation

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().

Definition at line 90 of file StdMeshers_QuadToTriaAdaptor.hxx.

Referenced by Compute2ndPart().

Copyright © 2007-2011 CEA/DEN, EDF R&D, OPEN CASCADE
Copyright © 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS