Salome HOME
Update copyrights
[modules/smesh.git] / src / SMDS / SMDS_MeshNode.cxx
1 // Copyright (C) 2007-2019  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 //  SMESH SMDS : implementation of Salome mesh data structure
24 //
25 #ifdef _MSC_VER
26 #pragma warning(disable:4786)
27 #endif
28
29 #include "SMDS_MeshNode.hxx"
30
31 #include "SMDS_ElementFactory.hxx"
32 #include "SMDS_Mesh.hxx"
33 #include "SMDS_SetIterator.hxx"
34 #include "SMDS_SpacePosition.hxx"
35
36 #include <utilities.h>
37 #include <Utils_SALOME_Exception.hxx>
38 #include <cassert>
39
40 #include <boost/make_shared.hpp>
41
42 void SMDS_MeshNode::init(double x, double y, double z)
43 {
44   SMDS_UnstructuredGrid * grid = getGrid();
45   vtkPoints *points = grid->GetPoints();
46   points->InsertPoint( GetVtkID(), x, y, z );
47   if ( grid->HasLinks() )
48     grid->GetLinks()->ResizeForPoint( GetVtkID() );
49 }
50
51 //=======================================================================
52 //function : RemoveInverseElement
53 //purpose  :
54 //=======================================================================
55
56 void SMDS_MeshNode::RemoveInverseElement(const SMDS_MeshElement * elem)
57 {
58   if ( getGrid()->HasLinks() )
59     getGrid()->RemoveReferenceToCell( GetVtkID(), elem->GetVtkID());
60 }
61
62 //=======================================================================
63 //function : Print
64 //purpose  :
65 //=======================================================================
66
67 void SMDS_MeshNode::Print(ostream & OS) const
68 {
69   OS << "Node <" << GetID() << "> : X = " << X() << " Y = "
70      << Y() << " Z = " << Z() << endl;
71 }
72
73 //=======================================================================
74 //function : SetPosition
75 //purpose  :
76 //=======================================================================
77
78 void SMDS_MeshNode::SetPosition(const SMDS_PositionPtr& aPos, int shapeID)
79 {
80   myHolder->SetPosition( this, aPos, shapeID );
81 }
82
83 //=======================================================================
84 //function : GetPosition
85 //purpose  : Return a position of this node on shape
86 //warning  : result is std::unique_ptr !
87 //=======================================================================
88
89 SMDS_PositionPtr SMDS_MeshNode::GetPosition() const
90 {
91   return myHolder->GetPosition( this );
92 }
93
94 //=======================================================================
95 /*!
96  * \brief Iterator on list of elements
97  */
98 //=======================================================================
99
100 namespace
101 {
102   struct InverseIterator: public SMDS_ElemIterator
103   {
104     const SMDS_Mesh*       myMesh;
105     size_t                 myIter;
106     std::vector<vtkIdType> myCellList;
107
108     InverseIterator(const SMDS_Mesh *   mesh = 0,
109                     const vtkIdType*    cells = 0,
110                     const int           ncells = 0,
111                     SMDSAbs_ElementType type = SMDSAbs_All)
112       : myMesh(mesh), myIter(0)
113     {
114       if ( ncells )
115       {
116         myCellList.reserve( ncells );
117         if (type == SMDSAbs_All)
118         {
119           myCellList.assign( cells, cells + ncells );
120         }
121         else
122         {
123           for (int i = 0; i < ncells; i++)
124           {
125             int  vtkId = cells[i];
126             int smdsId = myMesh->FromVtkToSmds( vtkId );
127             const SMDS_MeshElement* elem = myMesh->FindElement( smdsId );
128             if ( elem->GetType() == type )
129             {
130               myCellList.push_back(vtkId);
131             }
132           }
133         }
134       }
135     }
136
137     bool more()
138     {
139       return ( myIter < myCellList.size() );
140     }
141
142     const SMDS_MeshElement* next()
143     {
144       int vtkId  = myCellList[ myIter++ ];
145       int smdsId = myMesh->FromVtkToSmds( vtkId );
146       const SMDS_MeshElement* elem = myMesh->FindElement(smdsId);
147       if (!elem)
148       {
149         MESSAGE("InverseIterator problem Null element");
150         throw SALOME_Exception("InverseIterator problem Null element");
151       }
152       return elem;
153     }
154   };
155
156   //=======================================================================
157   /*!
158    * \brief Iterator on a node
159    */
160   //=======================================================================
161
162   template< class ELEM_ITERATOR >
163   struct Iterator : public ELEM_ITERATOR
164   {
165     typedef typename ELEM_ITERATOR::value_type element_type;
166     const SMDS_MeshNode* myNode;
167
168     Iterator( const SMDS_MeshNode* n ): myNode( n ) {}
169
170     virtual bool more()
171     {
172       return myNode;
173     }
174     virtual element_type next()
175     {
176       element_type res = static_cast<element_type>( myNode );
177       myNode = 0;
178       return res;
179     }
180   };
181 }
182
183 SMDS_ElemIteratorPtr SMDS_MeshNode::GetInverseElementIterator(SMDSAbs_ElementType type) const
184 {
185   if ( GetMesh()->NbElements() > 0 ) // avoid building links
186   {
187     vtkCellLinks::Link& l = getGrid()->GetLinks()->GetLink( GetVtkID() );
188     return boost::make_shared< InverseIterator >( GetMesh(), l.cells, l.ncells, type );
189   }
190   else
191   {
192     return boost::make_shared< InverseIterator >();
193   }
194 }
195
196 SMDS_ElemIteratorPtr SMDS_MeshNode::nodesIterator() const
197 {
198   return boost::make_shared< Iterator< SMDS_ElemIterator > >( this );
199 }
200
201 SMDS_NodeIteratorPtr SMDS_MeshNode::nodeIterator() const
202 {
203   return boost::make_shared< Iterator< SMDS_NodeIterator > >( this );
204 }
205
206 const SMDS_MeshNode* SMDS_MeshNode::GetNode(const int ind) const
207 {
208   return ind == 0 ? this : 0;
209 }
210
211 double* SMDS_MeshNode::getCoord() const
212 {
213   return getGrid()->GetPoint( GetVtkID() );
214 }
215
216 double SMDS_MeshNode::X() const
217 {
218   double *coord = getCoord();
219   return coord[0];
220 }
221
222 double SMDS_MeshNode::Y() const
223 {
224   double *coord = getCoord();
225   return coord[1];
226 }
227
228 double SMDS_MeshNode::Z() const
229 {
230   double *coord = getCoord();
231   return coord[2];
232 }
233
234 //================================================================================
235 /*!
236  * \brief thread safe getting coords
237  */
238 //================================================================================
239
240 void SMDS_MeshNode::GetXYZ(double xyz[3]) const
241 {
242   return getGrid()->GetPoint( GetVtkID(), xyz );
243 }
244
245 //================================================================================
246 void SMDS_MeshNode::setXYZ( double x, double y, double z )
247 {
248   vtkPoints *points = getGrid()->GetPoints();
249   points->InsertPoint( GetVtkID(), x, y, z );
250   //GetMesh()->adjustBoundingBox(x, y, z);
251   GetMesh()->setMyModified();
252 }
253
254 //=======================================================================
255 //function : AddInverseElement
256 //purpose  :
257 //=======================================================================
258 void SMDS_MeshNode::AddInverseElement( const SMDS_MeshElement* elem )
259 {
260   SMDS_UnstructuredGrid* grid = getGrid();
261   if ( grid->HasLinks() )
262   {
263     vtkCellLinks *Links = grid->GetLinks();
264     Links->ResizeCellList( GetVtkID(), 1 );
265     Links->AddCellReference( elem->GetVtkID(), GetVtkID() );
266   }
267 }
268
269 //=======================================================================
270 //function : ClearInverseElements
271 //purpose  :
272 //=======================================================================
273 void SMDS_MeshNode::ClearInverseElements()
274 {
275   getGrid()->ResizeCellList( GetVtkID(), 0);
276 }
277
278 //================================================================================
279 /*!
280  * \brief Count inverse elements of given type
281  */
282 //================================================================================
283
284 int SMDS_MeshNode::NbInverseElements(SMDSAbs_ElementType type) const
285 {
286   int nb = 0;
287   SMDS_Mesh *mesh = GetMesh();
288   if ( mesh->NbElements() > 0 ) // avoid building links
289   {
290     vtkCellLinks::Link& l = mesh->GetGrid()->GetLinks()->GetLink( GetVtkID() );
291
292     if ( type == SMDSAbs_All )
293       return l.ncells;
294
295     for ( int i = 0; i < l.ncells; i++ )
296     {
297       const SMDS_MeshElement* elem = mesh->FindElement( mesh->FromVtkToSmds( l.cells[i] ));
298       nb += ( elem->GetType() == type );
299     }
300   }
301   return nb;
302 }