Version: 6.3.1

src/SMDS/SMDS_VtkVolume.cxx

Go to the documentation of this file.
00001 // Copyright (C) 2010-2011  CEA/DEN, EDF R&D, OPEN CASCADE
00002 //
00003 // This library is free software; you can redistribute it and/or
00004 // modify it under the terms of the GNU Lesser General Public
00005 // License as published by the Free Software Foundation; either
00006 // version 2.1 of the License.
00007 //
00008 // This library is distributed in the hope that it will be useful,
00009 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00011 // Lesser General Public License for more details.
00012 //
00013 // You should have received a copy of the GNU Lesser General Public
00014 // License along with this library; if not, write to the Free Software
00015 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00016 //
00017 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
00018 //
00019 
00020 #include "SMDS_VtkVolume.hxx"
00021 #include "SMDS_MeshNode.hxx"
00022 #include "SMDS_Mesh.hxx"
00023 #include "SMDS_VtkCellIterator.hxx"
00024 
00025 #include "utilities.h"
00026 
00027 #include <vector>
00028 
00029 SMDS_VtkVolume::SMDS_VtkVolume()
00030 {
00031 }
00032 
00033 SMDS_VtkVolume::SMDS_VtkVolume(std::vector<vtkIdType> nodeIds, SMDS_Mesh* mesh)
00034 {
00035   init(nodeIds, mesh);
00036 }
00041 void SMDS_VtkVolume::init(std::vector<vtkIdType> nodeIds, SMDS_Mesh* mesh)
00042 {
00043   SMDS_MeshVolume::init();
00044   vtkUnstructuredGrid* grid = mesh->getGrid();
00045   myMeshId = mesh->getMeshId();
00046   vtkIdType aType = VTK_TETRA;
00047   switch (nodeIds.size())
00048   {
00049     case 4:
00050       aType = VTK_TETRA;
00051       break;
00052     case 5:
00053       aType = VTK_PYRAMID;
00054       break;
00055     case 6:
00056       aType = VTK_WEDGE;
00057       break;
00058     case 8:
00059       aType = VTK_HEXAHEDRON;
00060       break;
00061     case 10:
00062       aType = VTK_QUADRATIC_TETRA;
00063       break;
00064     case 13:
00065       aType = VTK_QUADRATIC_PYRAMID;
00066       break;
00067     case 15:
00068       aType = VTK_QUADRATIC_WEDGE;
00069       break;
00070     case 20:
00071       aType = VTK_QUADRATIC_HEXAHEDRON;
00072       break;
00073     default:
00074       aType = VTK_HEXAHEDRON;
00075       break;
00076   }
00077   myVtkID = grid->InsertNextLinkedCell(aType, nodeIds.size(), &nodeIds[0]);
00078   mesh->setMyModified();
00079   //MESSAGE("SMDS_VtkVolume::init myVtkID " << myVtkID);
00080 }
00081 
00082 //#ifdef VTK_HAVE_POLYHEDRON
00083 void SMDS_VtkVolume::initPoly(std::vector<vtkIdType> nodeIds, std::vector<int> nbNodesPerFace, SMDS_Mesh* mesh)
00084 {
00085   SMDS_MeshVolume::init();
00086   //MESSAGE("SMDS_VtkVolume::initPoly");
00087   SMDS_UnstructuredGrid* grid = mesh->getGrid();
00088   double center[3];
00089   this->gravityCenter(grid, &nodeIds[0], nodeIds.size(), &center[0]);
00090   vector<vtkIdType> ptIds;
00091   ptIds.clear();
00092   vtkIdType nbFaces = nbNodesPerFace.size();
00093   int k = 0;
00094   for (int i = 0; i < nbFaces; i++)
00095     {
00096       int nf = nbNodesPerFace[i];
00097       ptIds.push_back(nf);
00098       double a[3];
00099       double b[3];
00100       double c[3];
00101       grid->GetPoints()->GetPoint(nodeIds[k], a);
00102       grid->GetPoints()->GetPoint(nodeIds[k + 1], b);
00103       grid->GetPoints()->GetPoint(nodeIds[k + 2], c);
00104       bool isFaceForward = this->isForward(a, b, c, center);
00105       //MESSAGE("isFaceForward " << i << " " << isFaceForward);
00106       vtkIdType *facePts = &nodeIds[k];
00107       if (isFaceForward)
00108         for (int n = 0; n < nf; n++)
00109           ptIds.push_back(facePts[n]);
00110       else
00111         for (int n = nf - 1; n >= 0; n--)
00112           ptIds.push_back(facePts[n]);
00113       k += nf;
00114     }
00115   myVtkID = grid->InsertNextLinkedCell(VTK_POLYHEDRON, nbFaces, &ptIds[0]);
00116   mesh->setMyModified();
00117 }
00118 //#endif
00119 
00120 bool SMDS_VtkVolume::ChangeNodes(const SMDS_MeshNode* nodes[], const int nbNodes)
00121 {
00122   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
00123   vtkIdType npts = 0;
00124   vtkIdType* pts = 0;
00125   grid->GetCellPoints(myVtkID, npts, pts);
00126   if (nbNodes != npts)
00127     {
00128       MESSAGE("ChangeNodes problem: not the same number of nodes " << npts << " -> " << nbNodes);
00129       return false;
00130     }
00131   for (int i = 0; i < nbNodes; i++)
00132     {
00133       pts[i] = nodes[i]->getVtkId();
00134     }
00135   SMDS_Mesh::_meshList[myMeshId]->setMyModified();
00136   return true;
00137 }
00138 
00143 bool SMDS_VtkVolume::vtkOrder(const SMDS_MeshNode* nodes[], const int nbNodes)
00144 {
00145   if (nbNodes != this->NbNodes())
00146     {
00147       MESSAGE("vtkOrder, wrong number of nodes " << nbNodes << " instead of "<< this->NbNodes());
00148       return false;
00149     }
00150   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
00151   vtkIdType aVtkType = grid->GetCellType(this->myVtkID);
00152   switch (aVtkType)
00153   {
00154     case VTK_TETRA:
00155       this->exchange(nodes, 1, 2);
00156       break;
00157     case VTK_QUADRATIC_TETRA:
00158       this->exchange(nodes, 1, 2);
00159       this->exchange(nodes, 4, 6);
00160       this->exchange(nodes, 8, 9);
00161       break;
00162     case VTK_PYRAMID:
00163       this->exchange(nodes, 1, 3);
00164       break;
00165     case VTK_WEDGE:
00166       break;
00167     case VTK_QUADRATIC_PYRAMID:
00168       this->exchange(nodes, 1, 3);
00169       this->exchange(nodes, 5, 8);
00170       this->exchange(nodes, 6, 7);
00171       this->exchange(nodes, 10, 12);
00172       break;
00173     case VTK_QUADRATIC_WEDGE:
00174       break;
00175     case VTK_HEXAHEDRON:
00176       this->exchange(nodes, 1, 3);
00177       this->exchange(nodes, 5, 7);
00178       break;
00179     case VTK_QUADRATIC_HEXAHEDRON:
00180       this->exchange(nodes, 1, 3);
00181       this->exchange(nodes, 5, 7);
00182       this->exchange(nodes, 8, 11);
00183       this->exchange(nodes, 9, 10);
00184       this->exchange(nodes, 12, 15);
00185       this->exchange(nodes, 13, 14);
00186       this->exchange(nodes, 17, 19);
00187       break;
00188     case VTK_POLYHEDRON:
00189     default:
00190       break;
00191   }
00192   return true;
00193 }
00194 
00195 SMDS_VtkVolume::~SMDS_VtkVolume()
00196 {
00197 }
00198 
00199 void SMDS_VtkVolume::Print(ostream & OS) const
00200 {
00201   OS << "volume <" << GetID() << "> : ";
00202 }
00203 
00204 int SMDS_VtkVolume::NbFaces() const
00205 {
00206   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
00207   vtkIdType aVtkType = grid->GetCellType(this->myVtkID);
00208   int nbFaces = 4;
00209   switch (aVtkType)
00210   {
00211     case VTK_TETRA:
00212     case VTK_QUADRATIC_TETRA:
00213       nbFaces = 4;
00214       break;
00215     case VTK_PYRAMID:
00216     case VTK_WEDGE:
00217     case VTK_QUADRATIC_PYRAMID:
00218     case VTK_QUADRATIC_WEDGE:
00219       nbFaces = 5;
00220       break;
00221     case VTK_HEXAHEDRON:
00222     case VTK_QUADRATIC_HEXAHEDRON:
00223       nbFaces = 6;
00224       break;
00225     case VTK_POLYHEDRON:
00226       {
00227         vtkIdType nFaces = 0;
00228         vtkIdType* ptIds = 0;
00229         grid->GetFaceStream(this->myVtkID, nFaces, ptIds);
00230         nbFaces = nFaces;
00231         break;
00232       }
00233     default:
00234       MESSAGE("invalid volume type")
00235       ;
00236       nbFaces = 0;
00237       break;
00238   }
00239   return nbFaces;
00240 }
00241 
00242 int SMDS_VtkVolume::NbNodes() const
00243 {
00244   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
00245   vtkIdType aVtkType = grid->GetCellType(this->myVtkID);
00246   int nbPoints = 0;
00247   if (aVtkType != VTK_POLYHEDRON)
00248     {
00249       nbPoints = grid->GetCell(myVtkID)->GetNumberOfPoints();
00250     }
00251   else
00252     {
00253       vtkIdType nFaces = 0;
00254       vtkIdType* ptIds = 0;
00255       grid->GetFaceStream(this->myVtkID, nFaces, ptIds);
00256       int id = 0;
00257       for (int i = 0; i < nFaces; i++)
00258         {
00259           int nodesInFace = ptIds[id];
00260           nbPoints += nodesInFace;
00261           id += (nodesInFace + 1);
00262         }
00263     }
00264   return nbPoints;
00265 }
00266 
00267 int SMDS_VtkVolume::NbEdges() const
00268 {
00269   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
00270   vtkIdType aVtkType = grid->GetCellType(this->myVtkID);
00271   int nbEdges = 6;
00272   switch (aVtkType)
00273   {
00274     case VTK_TETRA:
00275     case VTK_QUADRATIC_TETRA:
00276       nbEdges = 6;
00277       break;
00278     case VTK_PYRAMID:
00279     case VTK_QUADRATIC_PYRAMID:
00280       nbEdges = 8;
00281       break;
00282     case VTK_WEDGE:
00283     case VTK_QUADRATIC_WEDGE:
00284       nbEdges = 9;
00285       break;
00286     case VTK_HEXAHEDRON:
00287     case VTK_QUADRATIC_HEXAHEDRON:
00288       nbEdges = 12;
00289       break;
00290     case VTK_POLYHEDRON:
00291       {
00292         vtkIdType nFaces = 0;
00293         vtkIdType* ptIds = 0;
00294         grid->GetFaceStream(this->myVtkID, nFaces, ptIds);
00295         nbEdges = 0;
00296         int id = 0;
00297         for (int i = 0; i < nFaces; i++)
00298           {
00299             int edgesInFace = ptIds[id];
00300             id += (edgesInFace + 1);
00301             nbEdges += edgesInFace;
00302           }
00303         nbEdges = nbEdges / 2;
00304         break;
00305       }
00306     default:
00307       MESSAGE("invalid volume type")
00308       ;
00309       nbEdges = 0;
00310       break;
00311   }
00312   return nbEdges;
00313 }
00314 
00318 int SMDS_VtkVolume::NbFaceNodes(const int face_ind) const
00319 {
00320   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
00321   vtkIdType aVtkType = grid->GetCellType(this->myVtkID);
00322   int nbNodes = 0;
00323   if (aVtkType == VTK_POLYHEDRON)
00324     {
00325       vtkIdType nFaces = 0;
00326       vtkIdType* ptIds = 0;
00327       grid->GetFaceStream(this->myVtkID, nFaces, ptIds);
00328       int id = 0;
00329       for (int i = 0; i < nFaces; i++)
00330         {
00331           int nodesInFace = ptIds[id];
00332           id += (nodesInFace + 1);
00333           if (i == face_ind - 1)
00334             {
00335               nbNodes = nodesInFace;
00336               break;
00337             }
00338         }
00339     }
00340   return nbNodes;
00341 }
00342 
00347 const SMDS_MeshNode* SMDS_VtkVolume::GetFaceNode(const int face_ind, const int node_ind) const
00348 {
00349   SMDS_Mesh *mesh = SMDS_Mesh::_meshList[myMeshId];
00350   vtkUnstructuredGrid* grid = mesh->getGrid();
00351   vtkIdType aVtkType = grid->GetCellType(this->myVtkID);
00352   const SMDS_MeshNode* node = 0;
00353   if (aVtkType == VTK_POLYHEDRON)
00354     {
00355       vtkIdType nFaces = 0;
00356       vtkIdType* ptIds = 0;
00357       grid->GetFaceStream(this->myVtkID, nFaces, ptIds);
00358       int id = 0;
00359       for (int i = 0; i < nFaces; i++)
00360         {
00361           int nodesInFace = ptIds[id]; // nodeIds in ptIds[id+1 .. id+nodesInFace]
00362           if (i == face_ind - 1) // first face is number 1
00363             {
00364               if ((node_ind > 0) && (node_ind <= nodesInFace))
00365                 node = mesh->FindNodeVtk(ptIds[id + node_ind]); // ptIds[id+1] : first node
00366               break;
00367             }
00368           id += (nodesInFace + 1);
00369         }
00370     }
00371   return node;
00372 }
00373 
00377 const std::vector<int> SMDS_VtkVolume::GetQuantities() const
00378 {
00379   vector<int> quantities;
00380   quantities.clear();
00381   SMDS_Mesh *mesh = SMDS_Mesh::_meshList[myMeshId];
00382   vtkUnstructuredGrid* grid = mesh->getGrid();
00383   vtkIdType aVtkType = grid->GetCellType(this->myVtkID);
00384   if (aVtkType == VTK_POLYHEDRON)
00385     {
00386       vtkIdType nFaces = 0;
00387       vtkIdType* ptIds = 0;
00388       grid->GetFaceStream(this->myVtkID, nFaces, ptIds);
00389       int id = 0;
00390       for (int i = 0; i < nFaces; i++)
00391         {
00392           int nodesInFace = ptIds[id]; // nodeIds in ptIds[id+1 .. id+nodesInFace]
00393           quantities.push_back(nodesInFace);
00394           id += (nodesInFace + 1);
00395         }
00396     }
00397   return quantities;
00398 }
00399 
00400 SMDS_ElemIteratorPtr SMDS_VtkVolume::elementsIterator(SMDSAbs_ElementType type) const
00401 {
00402   switch (type)
00403   {
00404     case SMDSAbs_Node:
00405       {
00406         SMDSAbs_EntityType aType = this->GetEntityType();
00407         if (aType == SMDSEntity_Polyhedra)
00408           return SMDS_ElemIteratorPtr(new SMDS_VtkCellIteratorPolyH(SMDS_Mesh::_meshList[myMeshId], myVtkID, aType));
00409         else
00410           return SMDS_ElemIteratorPtr(new SMDS_VtkCellIterator(SMDS_Mesh::_meshList[myMeshId], myVtkID, aType));
00411       }
00412     default:
00413       MESSAGE("ERROR : Iterator not implemented");
00414       return SMDS_ElemIteratorPtr((SMDS_ElemIterator*) NULL);
00415   }
00416 }
00417 
00418 SMDS_ElemIteratorPtr SMDS_VtkVolume::nodesIteratorToUNV() const
00419 {
00420   return SMDS_ElemIteratorPtr(new SMDS_VtkCellIteratorToUNV(SMDS_Mesh::_meshList[myMeshId], myVtkID, GetEntityType()));
00421 }
00422 
00423 SMDS_ElemIteratorPtr SMDS_VtkVolume::interlacedNodesElemIterator() const
00424 {
00425   return SMDS_ElemIteratorPtr(new SMDS_VtkCellIteratorToUNV(SMDS_Mesh::_meshList[myMeshId], myVtkID, GetEntityType()));
00426 }
00427 
00428 SMDSAbs_ElementType SMDS_VtkVolume::GetType() const
00429 {
00430   return SMDSAbs_Volume;
00431 }
00432 
00438 const SMDS_MeshNode* SMDS_VtkVolume::GetNode(const int ind) const
00439 {
00440   // TODO optimize if possible (vtkCellIterator)
00441   return SMDS_MeshElement::GetNode(ind);
00442 }
00443 
00444 bool SMDS_VtkVolume::IsQuadratic() const
00445 {
00446   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
00447   vtkIdType aVtkType = grid->GetCellType(this->myVtkID);
00448   // TODO quadratic polyhedrons ?
00449   switch (aVtkType)
00450   {
00451     case VTK_QUADRATIC_TETRA:
00452     case VTK_QUADRATIC_PYRAMID:
00453     case VTK_QUADRATIC_WEDGE:
00454     case VTK_QUADRATIC_HEXAHEDRON:
00455       return true;
00456       break;
00457     default:
00458       return false;
00459   }
00460 }
00461 
00462 bool SMDS_VtkVolume::IsPoly() const
00463 {
00464   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
00465   vtkIdType aVtkType = grid->GetCellType(this->myVtkID);
00466   return (aVtkType == VTK_POLYHEDRON);
00467 }
00468 
00469 bool SMDS_VtkVolume::IsMediumNode(const SMDS_MeshNode* node) const
00470 {
00471   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
00472   vtkIdType aVtkType = grid->GetCellType(this->myVtkID);
00473   int rankFirstMedium = 0;
00474   switch (aVtkType)
00475   {
00476     case VTK_QUADRATIC_TETRA:
00477       rankFirstMedium = 4; // medium nodes are of rank 4 to 9
00478       break;
00479     case VTK_QUADRATIC_PYRAMID:
00480       rankFirstMedium = 5; // medium nodes are of rank 5 to 12
00481       break;
00482     case VTK_QUADRATIC_WEDGE:
00483       rankFirstMedium = 6; // medium nodes are of rank 6 to 14
00484       break;
00485     case VTK_QUADRATIC_HEXAHEDRON:
00486       rankFirstMedium = 8; // medium nodes are of rank 8 to 19
00487       break;
00488     default:
00489       return false;
00490   }
00491   vtkIdType npts = 0;
00492   vtkIdType* pts = 0;
00493   grid->GetCellPoints(myVtkID, npts, pts);
00494   vtkIdType nodeId = node->getVtkId();
00495   for (int rank = 0; rank < npts; rank++)
00496     {
00497       if (pts[rank] == nodeId)
00498         {
00499           if (rank < rankFirstMedium)
00500             return false;
00501           else
00502             return true;
00503         }
00504     }
00505   //throw SALOME_Exception(LOCALIZED("node does not belong to this element"));
00506   MESSAGE("======================================================");
00507   MESSAGE("= IsMediumNode: node does not belong to this element =");
00508   MESSAGE("======================================================");
00509   return false;
00510 }
00511 
00512 SMDSAbs_EntityType SMDS_VtkVolume::GetEntityType() const
00513 {
00514   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
00515   vtkIdType aVtkType = grid->GetCellType(this->myVtkID);
00516 
00517   SMDSAbs_EntityType aType = SMDSEntity_Tetra;
00518   switch (aVtkType)
00519   {
00520     case VTK_TETRA:
00521       aType = SMDSEntity_Tetra;
00522       break;
00523     case VTK_PYRAMID:
00524       aType = SMDSEntity_Pyramid;
00525       break;
00526     case VTK_WEDGE:
00527       aType = SMDSEntity_Penta;
00528       break;
00529     case VTK_HEXAHEDRON:
00530       aType = SMDSEntity_Hexa;
00531       break;
00532     case VTK_QUADRATIC_TETRA:
00533       aType = SMDSEntity_Quad_Tetra;
00534       break;
00535     case VTK_QUADRATIC_PYRAMID:
00536       aType = SMDSEntity_Quad_Pyramid;
00537       break;
00538     case VTK_QUADRATIC_WEDGE:
00539       aType = SMDSEntity_Quad_Penta;
00540       break;
00541     case VTK_QUADRATIC_HEXAHEDRON:
00542       aType = SMDSEntity_Quad_Hexa;
00543       break;
00544 //#ifdef VTK_HAVE_POLYHEDRON
00545     case VTK_POLYHEDRON:
00546       aType = SMDSEntity_Polyhedra;
00547       break;
00548 //#endif
00549     default:
00550       aType = SMDSEntity_Polyhedra;
00551       break;
00552   }
00553   return aType;
00554 }
00555 
00556 vtkIdType SMDS_VtkVolume::GetVtkType() const
00557 {
00558   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
00559   vtkIdType aType = grid->GetCellType(myVtkID);
00560   return aType;
00561 }
00562 
00563 void SMDS_VtkVolume::gravityCenter(SMDS_UnstructuredGrid* grid, vtkIdType *nodeIds, int nbNodes, double* result)
00564 {
00565   for (int j = 0; j < 3; j++)
00566     result[j] = 0;
00567   if (nbNodes <= 0)
00568     return;
00569   for (int i = 0; i < nbNodes; i++)
00570     {
00571       double *coords = grid->GetPoint(nodeIds[i]);
00572       for (int j = 0; j < 3; j++)
00573         result[j] += coords[j];
00574     }
00575   for (int j = 0; j < 3; j++)
00576     result[j] = result[j] / nbNodes;
00577   //MESSAGE("center " << result[0] << " " << result[1] << " "  << result[2]);
00578   return;
00579 }
00580 
00581 bool SMDS_VtkVolume::isForward(double* a, double* b, double* c, double* d)
00582 {
00583   double u[3], v[3], w[3];
00584   for (int j = 0; j < 3; j++)
00585     {
00586       //MESSAGE("a,b,c,d " << a[j] << " " << b[j] << " " << c[j] << " " << d[j]);
00587       u[j] = b[j] - a[j];
00588       v[j] = c[j] - a[j];
00589       w[j] = d[j] - a[j];
00590       //MESSAGE("u,v,w " << u[j] << " " << v[j] << " " << w[j]);
00591     }
00592   double prodmixte = (u[1]*v[2] - u[2]*v[1]) * w[0]
00593                    + (u[2]*v[0] - u[0]*v[2]) * w[1]
00594                    + (u[0]*v[1] - u[1]*v[0]) * w[2];
00595   return (prodmixte < 0);
00596 }
00597 
00601 int SMDS_VtkVolume::NbUniqueNodes() const
00602 {
00603   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
00604   return grid->GetCell(myVtkID)->GetNumberOfPoints();
00605 }
00606 
00610 SMDS_ElemIteratorPtr SMDS_VtkVolume::uniqueNodesIterator() const
00611 {
00612   MESSAGE("uniqueNodesIterator");
00613   return SMDS_ElemIteratorPtr(new SMDS_VtkCellIterator(SMDS_Mesh::_meshList[myMeshId], myVtkID, GetEntityType()));
00614 }
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