00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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
00080 }
00081
00082
00083 void SMDS_VtkVolume::initPoly(std::vector<vtkIdType> nodeIds, std::vector<int> nbNodesPerFace, SMDS_Mesh* mesh)
00084 {
00085 SMDS_MeshVolume::init();
00086
00087 SMDS_UnstructuredGrid* grid = mesh->getGrid();
00088 double center[3];
00089 this->gravityCenter(grid, &nodeIds[0], nodeIds.size(), ¢er[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
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
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];
00362 if (i == face_ind - 1)
00363 {
00364 if ((node_ind > 0) && (node_ind <= nodesInFace))
00365 node = mesh->FindNodeVtk(ptIds[id + node_ind]);
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];
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
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
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;
00478 break;
00479 case VTK_QUADRATIC_PYRAMID:
00480 rankFirstMedium = 5;
00481 break;
00482 case VTK_QUADRATIC_WEDGE:
00483 rankFirstMedium = 6;
00484 break;
00485 case VTK_QUADRATIC_HEXAHEDRON:
00486 rankFirstMedium = 8;
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
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
00545 case VTK_POLYHEDRON:
00546 aType = SMDSEntity_Polyhedra;
00547 break;
00548
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
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
00587 u[j] = b[j] - a[j];
00588 v[j] = c[j] - a[j];
00589 w[j] = d[j] - a[j];
00590
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 }