Salome HOME
Copyright update: 2016
[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 = grid->GetCell(myVtkID)->GetNumberOfPoints() / 2;
140     break;
141   case VTK_POLYGON:
142   default:
143     nbEdges = grid->GetCell(myVtkID)->GetNumberOfPoints();
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   int nbPoints = grid->GetCell(myVtkID)->GetNumberOfPoints();
158   return nbPoints;
159 }
160
161 /*!
162  * \brief Return node by its index
163  * \param ind - node index
164  * \retval const SMDS_MeshNode* - the node
165  */
166 const SMDS_MeshNode*
167 SMDS_VtkFace::GetNode(const int ind) const
168 {
169   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
170   vtkIdType npts, *pts;
171   grid->GetCellPoints( this->myVtkID, npts, pts );
172   return SMDS_Mesh::_meshList[myMeshId]->FindNodeVtk( pts[ ind ]);
173 }
174
175 /*!
176  * \brief Check if a node belongs to the element
177  * \param node - the node to check
178  * \retval int - node index within the element, -1 if not found
179  */
180 int SMDS_VtkFace::GetNodeIndex( const SMDS_MeshNode* node ) const
181 {
182   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
183   vtkIdType npts, *pts;
184   grid->GetCellPoints( this->myVtkID, npts, pts );
185   for ( vtkIdType i = 0; i < npts; ++i )
186     if ( pts[i] == node->getVtkId() )
187       return i;
188   return -1;
189 }
190
191 bool SMDS_VtkFace::IsQuadratic() const
192 {
193   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
194   vtkIdType aVtkType = grid->GetCellType(this->myVtkID);
195   // TODO quadratic polygons ?
196   switch (aVtkType)
197   {
198     case VTK_QUADRATIC_TRIANGLE:
199     case VTK_QUADRATIC_QUAD:
200     case VTK_QUADRATIC_POLYGON:
201     case VTK_BIQUADRATIC_QUAD:
202     case VTK_BIQUADRATIC_TRIANGLE:
203       return true;
204       break;
205     default:
206       return false;
207   }
208 }
209
210 bool SMDS_VtkFace::IsPoly() const
211 {
212   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
213   vtkIdType aVtkType = grid->GetCellType(this->myVtkID);
214   return ( aVtkType == VTK_POLYGON || aVtkType == VTK_QUADRATIC_POLYGON );
215 }
216
217 bool SMDS_VtkFace::IsMediumNode(const SMDS_MeshNode* node) const
218 {
219   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
220   vtkIdType aVtkType = grid->GetCellType(this->myVtkID);
221   int rankFirstMedium = 0;
222   switch (aVtkType)
223   {
224   case VTK_QUADRATIC_TRIANGLE:
225   case VTK_BIQUADRATIC_TRIANGLE:
226     rankFirstMedium = 3; // medium nodes are of rank 3,4,5
227     break;
228   case VTK_QUADRATIC_QUAD:
229   case VTK_BIQUADRATIC_QUAD:
230     rankFirstMedium = 4; // medium nodes are of rank 4,5,6,7
231     break;
232   case VTK_QUADRATIC_POLYGON:
233     rankFirstMedium = grid->GetCell(myVtkID)->GetNumberOfPoints() / 2;
234     break;
235   default:
236     //MESSAGE("wrong element type " << aVtkType);
237     return false;
238   }
239   vtkIdType npts = 0;
240   vtkIdType* pts = 0;
241   grid->GetCellPoints(myVtkID, npts, pts);
242   vtkIdType nodeId = node->getVtkId();
243   for (int rank = 0; rank < npts; rank++)
244   {
245     if (pts[rank] == nodeId)
246     {
247       //MESSAGE("rank " << rank << " is medium node " << (rank < rankFirstMedium));
248       if (rank < rankFirstMedium)
249         return false;
250       else
251         return true;
252     }
253   }
254   //throw SALOME_Exception(LOCALIZED("node does not belong to this element"));
255   MESSAGE("======================================================");
256   MESSAGE("= IsMediumNode: node does not belong to this element =");
257   MESSAGE("======================================================");
258   return false;
259 }
260
261 int SMDS_VtkFace::NbCornerNodes() const
262 {
263   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
264   int       nbPoints = grid->GetCell(myVtkID)->GetNumberOfPoints();
265   vtkIdType aVtkType = grid->GetCellType(myVtkID);
266   switch ( aVtkType )
267   {
268   case VTK_POLYGON:
269     break;
270   case VTK_QUADRATIC_POLYGON:
271     nbPoints /= 2;
272     break;
273   default:
274     if ( nbPoints > 4 )
275       nbPoints /= 2;
276   }
277   return nbPoints;
278 }
279
280 SMDSAbs_EntityType SMDS_VtkFace::GetEntityType() const
281 {
282   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
283   vtkIdType aVtkType = grid->GetCellType(this->myVtkID);
284   return SMDS_MeshCell::toSmdsType( VTKCellType( aVtkType ));
285 }
286
287 SMDSAbs_GeometryType SMDS_VtkFace::GetGeomType() const
288 {
289   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
290   vtkIdType aVtkType = grid->GetCellType(this->myVtkID);
291   switch ( aVtkType ) {
292   case VTK_TRIANGLE:
293   case VTK_QUADRATIC_TRIANGLE:
294   case VTK_BIQUADRATIC_TRIANGLE: return SMDSGeom_TRIANGLE;
295
296   case VTK_QUAD:
297   case VTK_QUADRATIC_QUAD:
298   case VTK_BIQUADRATIC_QUAD: return SMDSGeom_QUADRANGLE;
299
300   case VTK_POLYGON:
301   case VTK_QUADRATIC_POLYGON: return SMDSGeom_POLYGON;
302   default:;
303   }
304   return SMDSGeom_NONE;
305 }
306
307 vtkIdType SMDS_VtkFace::GetVtkType() const
308 {
309   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
310   vtkIdType aVtkType = grid->GetCellType(this->myVtkID);
311   return aVtkType;
312 }
313
314 SMDS_ElemIteratorPtr SMDS_VtkFace::elementsIterator(SMDSAbs_ElementType type) const
315 {
316   switch (type)
317   {
318     case SMDSAbs_Node:
319       return SMDS_ElemIteratorPtr(new SMDS_VtkCellIterator(SMDS_Mesh::_meshList[myMeshId], myVtkID, GetEntityType()));
320     default:
321       MESSAGE("ERROR : Iterator not implemented")
322       ;
323       return SMDS_ElemIteratorPtr((SMDS_ElemIterator*) NULL);
324   }
325 }
326
327 SMDS_NodeIteratorPtr SMDS_VtkFace::nodesIteratorToUNV() const
328 {
329   return SMDS_NodeIteratorPtr(new SMDS_VtkCellIteratorToUNV(SMDS_Mesh::_meshList[myMeshId], myVtkID, GetEntityType()));
330 }
331
332 SMDS_NodeIteratorPtr SMDS_VtkFace::interlacedNodesIterator() const
333 {
334   return nodesIteratorToUNV();
335 }
336
337 //! change only the first node, used for temporary triangles in quadrangle to triangle adaptor
338 void SMDS_VtkFace::ChangeApex(SMDS_MeshNode* node)
339 {
340   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
341   vtkIdType npts = 0;
342   vtkIdType* pts = 0;
343   grid->GetCellPoints(myVtkID, npts, pts);
344   grid->RemoveReferenceToCell(pts[0], myVtkID);
345   pts[0] = node->getVtkId();
346   node->AddInverseElement(this),
347   SMDS_Mesh::_meshList[myMeshId]->setMyModified();
348 }