Salome HOME
a8a9b28ffa9d2e531cec866b0b1b871bb0ff0eb7
[modules/smesh.git] / src / SMDS / SMDS_VtkFace.cxx
1 // Copyright (C) 2010-2016  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 #include "SMDS_VtkFace.hxx"
21 #include "SMDS_MeshNode.hxx"
22 #include "SMDS_Mesh.hxx"
23 #include "SMDS_VtkCellIterator.hxx"
24
25 #include "utilities.h"
26
27 #include <vector>
28
29 using namespace std;
30
31 SMDS_VtkFace::SMDS_VtkFace()
32 {
33 }
34
35 SMDS_VtkFace::SMDS_VtkFace(const std::vector<vtkIdType>& nodeIds, SMDS_Mesh* mesh)
36 {
37   init(nodeIds, mesh);
38 }
39
40 SMDS_VtkFace::~SMDS_VtkFace()
41 {
42 }
43
44 void SMDS_VtkFace::init(const std::vector<vtkIdType>& nodeIds, SMDS_Mesh* mesh)
45 {
46   SMDS_MeshFace::init();
47   vtkUnstructuredGrid* grid = mesh->getGrid();
48   myMeshId = mesh->getMeshId();
49   vtkIdType aType = VTK_TRIANGLE;
50   switch (nodeIds.size())
51   {
52     case 3:
53       aType = VTK_TRIANGLE;
54       break;
55     case 4:
56       aType = VTK_QUAD;
57       break;
58     case 6:
59       aType = VTK_QUADRATIC_TRIANGLE;
60       break;
61     case 8:
62       aType = VTK_QUADRATIC_QUAD;
63       break;
64     case 9:
65       aType = VTK_BIQUADRATIC_QUAD;
66       break;
67     case 7:
68       aType = VTK_BIQUADRATIC_TRIANGLE;
69       break;
70     default:
71       aType = VTK_POLYGON;
72       break;
73   }
74   myVtkID = grid->InsertNextLinkedCell(aType, nodeIds.size(), (vtkIdType*) &nodeIds[0]);
75   mesh->setMyModified();
76   //MESSAGE("SMDS_VtkFace::init myVtkID " << myVtkID);
77 }
78
79 void SMDS_VtkFace::initPoly(const std::vector<vtkIdType>& nodeIds, SMDS_Mesh* mesh)
80 {
81   SMDS_MeshFace::init();
82   vtkUnstructuredGrid* grid = mesh->getGrid();
83   myMeshId = mesh->getMeshId();
84   myVtkID = grid->InsertNextLinkedCell(VTK_POLYGON, nodeIds.size(), (vtkIdType*) &nodeIds[0]);
85   mesh->setMyModified();
86 }
87
88 void SMDS_VtkFace::initQuadPoly(const std::vector<vtkIdType>& nodeIds, SMDS_Mesh* mesh)
89 {
90   SMDS_MeshFace::init();
91   vtkUnstructuredGrid* grid = mesh->getGrid();
92   myMeshId = mesh->getMeshId();
93   myVtkID = grid->InsertNextLinkedCell(VTK_QUADRATIC_POLYGON, nodeIds.size(), (vtkIdType*) &nodeIds[0]);
94   mesh->setMyModified();
95 }
96
97 bool SMDS_VtkFace::ChangeNodes(const SMDS_MeshNode* nodes[], const int nbNodes)
98 {
99   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
100   vtkIdType npts = 0;
101   vtkIdType* pts = 0;
102   grid->GetCellPoints(myVtkID, npts, pts);
103   if (nbNodes != npts)
104     {
105       MESSAGE("ChangeNodes problem: not the same number of nodes " << npts << " -> " << nbNodes);
106       return false;
107     }
108   for (int i = 0; i < nbNodes; i++)
109     {
110       pts[i] = nodes[i]->getVtkId();
111     }
112   SMDS_Mesh::_meshList[myMeshId]->setMyModified();
113   return true;
114 }
115
116 void SMDS_VtkFace::Print(std::ostream & OS) const
117 {
118   OS << "face <" << GetID() << "> : ";
119 }
120
121 int SMDS_VtkFace::NbEdges() const
122 {
123   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
124   vtkIdType aVtkType = grid->GetCellType(this->myVtkID);
125   int nbEdges = 3;
126   switch (aVtkType)
127   {
128   case VTK_TRIANGLE:
129   case VTK_QUADRATIC_TRIANGLE:
130   case VTK_BIQUADRATIC_TRIANGLE:
131     nbEdges = 3;
132     break;
133   case VTK_QUAD:
134   case VTK_QUADRATIC_QUAD:
135   case VTK_BIQUADRATIC_QUAD:
136     nbEdges = 4;
137     break;
138   case VTK_QUADRATIC_POLYGON:
139     nbEdges = NbNodes() / 2;
140     break;
141   case VTK_POLYGON:
142   default:
143     nbEdges = NbNodes();
144     break;
145   }
146   return nbEdges;
147 }
148
149 int SMDS_VtkFace::NbFaces() const
150 {
151   return 1;
152 }
153
154 int SMDS_VtkFace::NbNodes() const
155 {
156   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
157   vtkIdType *pts, npts;
158   grid->GetCellPoints( myVtkID, npts, pts );
159   return npts;
160 }
161
162 /*!
163  * \brief Return node by its index
164  * \param ind - node index
165  * \retval const SMDS_MeshNode* - the node
166  */
167 const SMDS_MeshNode*
168 SMDS_VtkFace::GetNode(const int ind) const
169 {
170   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
171   vtkIdType npts, *pts;
172   grid->GetCellPoints( this->myVtkID, npts, pts );
173   return SMDS_Mesh::_meshList[myMeshId]->FindNodeVtk( pts[ ind ]);
174 }
175
176 /*!
177  * \brief Check if a node belongs to the element
178  * \param node - the node to check
179  * \retval int - node index within the element, -1 if not found
180  */
181 int SMDS_VtkFace::GetNodeIndex( const SMDS_MeshNode* node ) const
182 {
183   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
184   vtkIdType npts, *pts;
185   grid->GetCellPoints( this->myVtkID, npts, pts );
186   for ( vtkIdType i = 0; i < npts; ++i )
187     if ( pts[i] == node->getVtkId() )
188       return i;
189   return -1;
190 }
191
192 bool SMDS_VtkFace::IsQuadratic() const
193 {
194   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
195   vtkIdType aVtkType = grid->GetCellType(this->myVtkID);
196   // TODO quadratic polygons ?
197   switch (aVtkType)
198   {
199     case VTK_QUADRATIC_TRIANGLE:
200     case VTK_QUADRATIC_QUAD:
201     case VTK_QUADRATIC_POLYGON:
202     case VTK_BIQUADRATIC_QUAD:
203     case VTK_BIQUADRATIC_TRIANGLE:
204       return true;
205       break;
206     default:
207       return false;
208   }
209 }
210
211 bool SMDS_VtkFace::IsPoly() const
212 {
213   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
214   vtkIdType aVtkType = grid->GetCellType(this->myVtkID);
215   return ( aVtkType == VTK_POLYGON || aVtkType == VTK_QUADRATIC_POLYGON );
216 }
217
218 bool SMDS_VtkFace::IsMediumNode(const SMDS_MeshNode* node) const
219 {
220   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
221   vtkIdType npts = 0;
222   vtkIdType* pts = 0;
223   grid->GetCellPoints(myVtkID, npts, pts);
224
225   vtkIdType aVtkType = grid->GetCellType(this->myVtkID);
226   int rankFirstMedium = 0;
227   switch (aVtkType)
228   {
229   case VTK_QUADRATIC_TRIANGLE:
230   case VTK_BIQUADRATIC_TRIANGLE:
231     rankFirstMedium = 3; // medium nodes are of rank 3,4,5
232     break;
233   case VTK_QUADRATIC_QUAD:
234   case VTK_BIQUADRATIC_QUAD:
235     rankFirstMedium = 4; // medium nodes are of rank 4,5,6,7
236     break;
237   case VTK_QUADRATIC_POLYGON:
238     rankFirstMedium = npts / 2;
239     break;
240   default:
241     //MESSAGE("wrong element type " << aVtkType);
242     return false;
243   }
244   vtkIdType nodeId = node->getVtkId();
245   for (int rank = 0; rank < npts; rank++)
246   {
247     if (pts[rank] == nodeId)
248     {
249       //MESSAGE("rank " << rank << " is medium node " << (rank < rankFirstMedium));
250       if (rank < rankFirstMedium)
251         return false;
252       else
253         return true;
254     }
255   }
256   //throw SALOME_Exception(LOCALIZED("node does not belong to this element"));
257   MESSAGE("======================================================");
258   MESSAGE("= IsMediumNode: node does not belong to this element =");
259   MESSAGE("======================================================");
260   return false;
261 }
262
263 int SMDS_VtkFace::NbCornerNodes() const
264 {
265   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
266   int       nbPoints = NbNodes();
267   vtkIdType aVtkType = grid->GetCellType(myVtkID);
268   switch ( aVtkType )
269   {
270   case VTK_POLYGON:
271     break;
272   case VTK_QUADRATIC_POLYGON:
273     nbPoints /= 2;
274     break;
275   default:
276     if ( nbPoints > 4 )
277       nbPoints /= 2;
278   }
279   return nbPoints;
280 }
281
282 SMDSAbs_EntityType SMDS_VtkFace::GetEntityType() const
283 {
284   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
285   vtkIdType aVtkType = grid->GetCellType(this->myVtkID);
286   return SMDS_MeshCell::toSmdsType( VTKCellType( aVtkType ));
287 }
288
289 SMDSAbs_GeometryType SMDS_VtkFace::GetGeomType() const
290 {
291   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
292   vtkIdType aVtkType = grid->GetCellType(this->myVtkID);
293   switch ( aVtkType ) {
294   case VTK_TRIANGLE:
295   case VTK_QUADRATIC_TRIANGLE:
296   case VTK_BIQUADRATIC_TRIANGLE: return SMDSGeom_TRIANGLE;
297
298   case VTK_QUAD:
299   case VTK_QUADRATIC_QUAD:
300   case VTK_BIQUADRATIC_QUAD: return SMDSGeom_QUADRANGLE;
301
302   case VTK_POLYGON:
303   case VTK_QUADRATIC_POLYGON: return SMDSGeom_POLYGON;
304   default:;
305   }
306   return SMDSGeom_NONE;
307 }
308
309 vtkIdType SMDS_VtkFace::GetVtkType() const
310 {
311   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
312   vtkIdType aVtkType = grid->GetCellType(this->myVtkID);
313   return aVtkType;
314 }
315
316 SMDS_ElemIteratorPtr SMDS_VtkFace::elementsIterator(SMDSAbs_ElementType type) const
317 {
318   switch (type)
319   {
320     case SMDSAbs_Node:
321       return SMDS_ElemIteratorPtr(new SMDS_VtkCellIterator(SMDS_Mesh::_meshList[myMeshId], myVtkID, GetEntityType()));
322     default:
323       MESSAGE("ERROR : Iterator not implemented")
324       ;
325       return SMDS_ElemIteratorPtr((SMDS_ElemIterator*) NULL);
326   }
327 }
328
329 SMDS_NodeIteratorPtr SMDS_VtkFace::nodesIteratorToUNV() const
330 {
331   return SMDS_NodeIteratorPtr(new SMDS_VtkCellIteratorToUNV(SMDS_Mesh::_meshList[myMeshId], myVtkID, GetEntityType()));
332 }
333
334 SMDS_NodeIteratorPtr SMDS_VtkFace::interlacedNodesIterator() const
335 {
336   return nodesIteratorToUNV();
337 }
338
339 //! change only the first node, used for temporary triangles in quadrangle to triangle adaptor
340 void SMDS_VtkFace::ChangeApex(SMDS_MeshNode* node)
341 {
342   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
343   vtkIdType npts = 0;
344   vtkIdType* pts = 0;
345   grid->GetCellPoints(myVtkID, npts, pts);
346   grid->RemoveReferenceToCell(pts[0], myVtkID);
347   pts[0] = node->getVtkId();
348   node->AddInverseElement(this),
349   SMDS_Mesh::_meshList[myMeshId]->setMyModified();
350 }