Salome HOME
e359fb8b51abac88039df54143f2ae11ef9a8dc3
[modules/smesh.git] / src / SMESHGUI / SMESHGUI_SelectionProxy.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 #include "SMESHGUI_SelectionProxy.h"
24
25 #include "SMDS_Mesh.hxx"
26 #include "SMDS_VolumeTool.hxx"
27 #include "SMESHGUI.h"
28 #include "SMESHGUI_Utils.h"
29 #include "SMESHGUI_VTKUtils.h"
30 #include "SMESH_Actor.h"
31 #include "SMESH_ControlsDef.hxx"
32
33 #include <SALOMEconfig.h>
34 #include CORBA_SERVER_HEADER(SMESH_Filter)
35 #include CORBA_SERVER_HEADER(SMESH_Group)
36
37 #include <SALOMEDSClient_Study.hxx>
38 #include <SUIT_ResourceMgr.h>
39
40 ////////////////////////////////////////////////////////////////////////////////
41 /// \class SMESH::SelectionProxy
42 /// \brief Provide operations over the selected object.
43 ///
44 /// The selection proxy class is aimed to use in dialogs to access mesh object
45 /// data either from actor or directly from CORBA reference, depending on what
46 /// of them is accessible.
47 /// This is useful in situations when some information is needed, but an actor
48 /// was not created yet.
49 /// 
50 /// Selection proxy can be constructed in two ways:
51 /// - From interactive object: this performs full proxy initialization including
52 ///   pick-up of an actor from the current viewer if it exists.
53 /// - From mesh source object (CORBA reference); for performance reasons in this
54 ///   case full initialization is not immediately done and performed only when
55 ///   needed.
56 ////////////////////////////////////////////////////////////////////////////////
57
58 /*!
59   \brief Default constructor. Creates null proxy.
60 */
61 SMESH::SelectionProxy::SelectionProxy(): myActor(0), myDirty(false)
62 {
63 }
64
65 /*!
66   \brief Constructor.
67   \param io Interactive object.
68 */
69 SMESH::SelectionProxy::SelectionProxy( const Handle(SALOME_InteractiveObject)& io ): myActor(0), myDirty(true)
70 {
71   myObject = SMESH::IObjectToInterface<SMESH::SMESH_IDSource>( io );
72   init();
73 }
74
75 /*!
76   \brief Constructor.
77   \param object Mesh source.
78 */
79 SMESH::SelectionProxy::SelectionProxy( SMESH::SMESH_IDSource_ptr object ): myActor(0), myDirty(true)
80 {
81   if ( !CORBA::is_nil( object ) )
82     myObject = SMESH::SMESH_IDSource::_duplicate( object );
83 }
84
85 /*!
86   \brief Copy constructor.
87   \param other Proxy being copied.
88 */
89 SMESH::SelectionProxy::SelectionProxy( const SelectionProxy& other )
90 {
91   myIO = other.myIO;
92   myObject = other.myObject;
93   myActor = other.myActor;
94   myDirty = other.myDirty;
95 }
96
97 /*!
98   \brief Perform internal initialization.
99   \internal
100 */
101 void SMESH::SelectionProxy::init()
102 {
103   if ( myIO.IsNull() )
104     myIO = new SALOME_InteractiveObject(); // create dummy IO to avoid crashes when accesing it
105
106   if ( !CORBA::is_nil( myObject ) )
107   {
108     if ( !myIO->hasEntry() )
109     {
110       _PTR(SObject) sobj = SMESH::ObjectToSObject( myObject.in() );
111       if ( sobj )
112         myIO = new SALOME_InteractiveObject( sobj->GetID().c_str(), "SMESH", sobj->GetName().c_str() );
113     }
114     if ( !myActor && myIO->hasEntry() )
115       myActor = SMESH::FindActorByEntry( myIO->getEntry() );
116   }
117   myDirty = false;
118 }
119
120 /*!
121   \brief Assignment operator.
122   \param other Proxy being copied.
123 */
124 SMESH::SelectionProxy& SMESH::SelectionProxy::operator= ( const SMESH::SelectionProxy& other )
125 {
126   myIO = other.myIO;
127   myObject = other.myObject;
128   myActor = other.myActor;
129   myDirty = other.myDirty;
130   return *this;
131 }
132
133 /*!
134   \brief Equality comparison operator.
135   \param other Proxy to compare with.
136   \return \c true if two proxies are equal; \c false otherwise.
137 */
138 bool SMESH::SelectionProxy::operator== ( const SMESH::SelectionProxy& other )
139 {
140   return !CORBA::is_nil( myObject ) && !CORBA::is_nil( other.myObject ) && 
141     myObject->_is_equivalent( other.myObject );
142 }
143
144 /*!
145   \brief Re-initialize proxy.
146 */
147 void SMESH::SelectionProxy::refresh()
148 {
149   init();
150 }
151
152 /*!
153   \brief Check if proxy is null.
154   \return \c true if proxy is null; \c false otherwise.
155 */
156 bool SMESH::SelectionProxy::isNull() const
157 {
158   return CORBA::is_nil( myObject );
159 }
160
161 /*!
162   \brief Boolean conversion operator.
163   \return \c true if proxy is not null; \c false otherwise.
164 */
165 SMESH::SelectionProxy::operator bool() const
166 {
167   return !isNull();
168 }
169
170 /*!
171   \brief Get interactive object.
172   \return Interactive object referenced by proxy.
173 */
174 const Handle(SALOME_InteractiveObject)& SMESH::SelectionProxy::io() const
175 {
176   if ( myDirty )
177     const_cast<SMESH::SelectionProxy*>(this)->init();
178   return myIO;
179 }
180
181 /*!
182   \brief Get mesh object.
183   \return Mesh object (mesh, sub-mesh, group, etc.) referenced by proxy.
184 */
185 SMESH::SMESH_IDSource_ptr SMESH::SelectionProxy::object() const
186 {
187   return SMESH::SMESH_IDSource::_duplicate( myObject );
188 }
189
190 /*!
191   \brief Get actor.
192   \return Actor referenced by proxy.
193 */
194 SMESH_Actor* SMESH::SelectionProxy::actor() const
195 {
196   if ( myDirty )
197     const_cast<SMESH::SelectionProxy*>(this)->init();
198   return myActor;
199 }
200
201 /*!
202   \brief Get object's validity.
203
204   Mesh object is valid if it is not null and information stored in it is valid.
205
206   \return \c true if object is valid; \c false otherwise.
207 */
208 bool SMESH::SelectionProxy::isValid() const
209 {
210   return !isNull() && myObject->IsMeshInfoCorrect();
211 }
212
213 /*!
214   \brief Load mesh object from study file.
215 */
216 void SMESH::SelectionProxy::load()
217 {
218   if ( !isNull() )
219   {
220     SMESH::SMESH_Mesh_var mesh = myObject->GetMesh();
221     if ( !CORBA::is_nil( mesh ) )
222       mesh->Load();
223   }
224 }
225
226 /*!
227   \brief Get name.
228   \return Mesh object's name.
229 */
230 QString SMESH::SelectionProxy::name() const
231 {
232   QString value;
233   if ( !isNull() )
234     value = io()->getName();
235   return value;
236 }
237
238 /*!
239   \brief Get type.
240   \return Mesh object's type.
241 */
242 SMESH::SelectionProxy::Type SMESH::SelectionProxy::type() const
243 {
244   Type value = Unknown;
245   if ( !isNull() )
246   {
247     SMESH::SMESH_Mesh_var mesh = SMESH::SMESH_Mesh::_narrow( myObject );
248     SMESH::SMESH_subMesh_var submesh = SMESH::SMESH_subMesh::_narrow( myObject );
249     SMESH::SMESH_GroupBase_var group = SMESH::SMESH_GroupBase::_narrow( myObject );
250     SMESH::SMESH_Group_var sGroup = SMESH::SMESH_Group::_narrow( myObject );
251     SMESH::SMESH_GroupOnGeom_var gGroup = SMESH::SMESH_GroupOnGeom::_narrow( myObject );
252     SMESH::SMESH_GroupOnFilter_var fGroup = SMESH::SMESH_GroupOnFilter::_narrow( myObject );
253     
254     if ( !CORBA::is_nil( mesh ) )
255       value = Mesh;
256     else if ( !CORBA::is_nil( submesh ) )
257       value = Submesh;
258     else if ( !CORBA::is_nil( sGroup ) )
259       value = GroupStd;
260     else if ( !CORBA::is_nil( gGroup ) )
261       value = GroupGeom;
262     else if ( !CORBA::is_nil( fGroup ) )
263       value = GroupFilter;
264     else if ( !CORBA::is_nil( group ) )
265       value = Group;
266   }
267   return value;
268 }
269
270 /*!
271   \brief Get mesh information.
272   \return Statistics on stored mesh object.
273 */
274 SMESH::MeshInfo SMESH::SelectionProxy::meshInfo() const
275 {
276   SMESH::MeshInfo info;
277   if ( !isNull() )
278   {
279     SMESH::long_array_var data = myObject->GetMeshInfo();
280     for ( uint type = SMESH::Entity_Node; type < SMESH::Entity_Last; type++ )
281     {
282       if ( type < data->length() )
283         info.addInfo( type, data[ type ] );
284     }
285   }
286   return info;
287 }
288
289 /*!
290   \brief Get parent mesh.
291   \return Proxy object that stores parent mesh object.
292   \note For proxy that stores a mesh, returns its copy.
293 */
294 SMESH::SelectionProxy SMESH::SelectionProxy::mesh() const
295 {
296   SMESH::SelectionProxy parent;
297   if ( !isNull() )
298     parent = SMESH::SelectionProxy( (SMESH::SMESH_Mesh_var) myObject->GetMesh() ); // cast to var to avoid leaks
299   return parent;
300 }
301
302 /*!
303   \brief Check if parent mesh has shape to mesh.
304   \return \c true if Parent mesh is built on a shape; \c false otherwise.
305   \note For group or submesh, this method checks that parent mesh has a shape.
306 */
307 bool SMESH::SelectionProxy::hasShapeToMesh() const
308 {
309   bool result = false;
310   if ( !isNull() )
311   {
312     SMESH::SMESH_Mesh_var mesh = myObject->GetMesh();
313     if ( !CORBA::is_nil( mesh ) )
314       result = mesh->HasShapeToMesh();
315   }
316   return result;
317 }
318
319 /*!
320   \brief Get referenced GEOM object.
321   \return GEOM object referenced by selection proxy.
322
323   The result contains valid pointer only if proxy refers to mesh, sub-mesh
324   or group created on a geometry.
325 */
326 GEOM::GEOM_Object_ptr SMESH::SelectionProxy::shape() const
327 {
328   GEOM::GEOM_Object_var shape;
329   if ( !isNull() )
330   {
331     SMESH::SMESH_Mesh_var mesh = SMESH::SMESH_Mesh::_narrow( myObject );
332     SMESH::SMESH_subMesh_var submesh = SMESH::SMESH_subMesh::_narrow( myObject );
333     SMESH::SMESH_GroupOnGeom_var group = SMESH::SMESH_GroupOnGeom::_narrow( myObject );
334     if ( !CORBA::is_nil( mesh ) )
335       shape = mesh->GetShapeToMesh();
336     else if ( !CORBA::is_nil( submesh ) )
337       shape = submesh->GetSubShape();
338     else if ( !CORBA::is_nil( group ) )
339       shape = group->GetShape();
340   }
341   return shape._retn();
342 }
343
344 /*!
345   \brief Get name of referenced GEOM object.
346   \return Name of GEOM object referenced by selection proxy.
347
348   The result contains non-empty name only if proxy refers to mesh, sub-mesh
349   or group created on a geometry, and if that geometry has valid name.
350 */
351 QString SMESH::SelectionProxy::shapeName() const
352 {
353   QString name;
354   if ( !isNull() )
355   {
356     GEOM::GEOM_Object_var gobj = shape();
357     _PTR(SObject) sobj = SMESH::ObjectToSObject( gobj );
358     if ( sobj )
359       name = QString::fromStdString( sobj->GetName() );
360   }
361   return name;
362 }
363
364 /*!
365   \brief Get type of referenced GEOM object.
366   \return Type of GEOM object referenced by selection proxy.
367
368   The result contains valid type only if proxy refers to mesh, sub-mesh
369   or group created on a geometry.
370 */
371 int SMESH::SelectionProxy::shapeType() const
372 {
373   int type = -1;
374   if ( !isNull() )
375   {
376     GEOM::GEOM_Object_var gobj = shape();
377     if ( !CORBA::is_nil( gobj ) )
378       type = gobj->GetShapeType();
379   }
380   return type;
381 }
382
383 /*!
384   \brief Check if mesh has been loaded from study file.
385   \return \c true if mesh was loaded; \c false otherwise.
386 */
387 bool SMESH::SelectionProxy::isMeshLoaded() const
388 {
389   bool result = true; // set default to true to avoid side effects
390   if ( !isNull() )
391   {
392     SMESH::SMESH_Mesh_var mesh = myObject->GetMesh();
393     if ( !CORBA::is_nil( mesh ) )
394       result = mesh->IsLoaded();
395   }
396   return result;
397 }
398
399 /*!
400   \brief Check if node with given ID is present in the mesh.
401   \param id Mesh node ID.
402   \return \c true if mesh contains node; \c false otherwise.
403 */
404 bool SMESH::SelectionProxy::hasNode( int id )
405 {
406   bool result = false;
407   if ( !isNull() )
408   {
409     if ( actor() )
410     {
411       const SMDS_MeshNode* node = actor()->GetObject()->GetMesh()->FindNode( id );
412       result = node != 0;
413     }
414     else
415     {
416       SMESH::SMESH_Mesh_var mesh = myObject->GetMesh();
417       if ( !CORBA::is_nil( mesh ) )
418       {
419         SMESH::double_array_var coords = mesh->GetNodeXYZ( id );
420         result = coords->length() >= 3;
421       }
422     }
423   }
424   return result; 
425 }
426
427 /*!
428   \brief Get node coordinates.
429   \param id Mesh node ID.
430   \param xyz Returned node coordinates.
431   \return \c true if result is valid; \c false otherwise.
432 */
433 bool SMESH::SelectionProxy::nodeCoordinates( int id, SMESH::XYZ& xyz )
434 {
435   bool result = false;
436   xyz = SMESH::XYZ();
437   
438   if ( !isNull() )
439   {
440     if ( actor() )
441     {
442       const SMDS_MeshNode* node = actor()->GetObject()->GetMesh()->FindNode( id );
443       if ( node )
444       {
445         xyz = SMESH::XYZ( node->X(), node->Y(), node->Z() );
446         result = true;
447       }
448     }
449     else
450     {
451       SMESH::SMESH_Mesh_var mesh = myObject->GetMesh();
452       if ( !CORBA::is_nil( mesh ) )
453       {
454         SMESH::double_array_var coords = mesh->GetNodeXYZ( id );
455         if ( coords->length() >= 3 )
456         {
457           xyz = SMESH::XYZ( coords[0], coords[1], coords[2] );
458           result = true;
459         }
460       }
461     }
462   }
463   return result;
464 }
465
466 /*!
467   \brief Get node connectivity.
468   \param id Mesh node ID.
469   \param connectivity Returned node connectivity.
470   \return \c true if result is valid; \c false otherwise.
471 */
472 bool SMESH::SelectionProxy::nodeConnectivity( int id, SMESH::Connectivity& connectivity )
473 {
474   bool result = false;
475   connectivity.clear();
476   if ( !isNull() )
477   {
478     if ( actor() )
479     {
480       const SMDS_MeshNode* node = actor()->GetObject()->GetMesh()->FindNode( id );
481       if ( node )
482       {
483         SMDS_ElemIteratorPtr it = node->GetInverseElementIterator();
484         while ( it && it->more() )
485         {
486           const SMDS_MeshElement* ne = it->next();
487           connectivity[ ne->GetType() ] << ne->GetID();
488         }
489         result = true;
490       }
491     }
492     else
493     {
494       SMESH::SMESH_Mesh_var mesh = myObject->GetMesh();
495       if ( !CORBA::is_nil( mesh ) )
496       {
497         SMESH::long_array_var elements = mesh->GetNodeInverseElements( id, SMESH::ALL );
498         for ( int i = 0, n = elements->length(); i < n; i++ )
499         {
500           SMESH::ElementType type = mesh->GetElementType( elements[i], true );
501           connectivity[ type ] << elements[i];
502         }
503         result = true;
504       }
505     }
506   }
507   return result;
508 }
509
510 /*!
511   \brief Get node position on a shape.
512   \param id Mesh node ID.
513   \param position Returned node position.
514   \return \c true if result is valid; \c false otherwise.
515 */
516 bool SMESH::SelectionProxy::nodePosition( int id, Position& position )
517 {
518   bool result = false;
519   position = Position();
520   if ( !isNull() )
521   {
522     SMESH::SMESH_Mesh_var mesh = myObject->GetMesh();
523     if ( !CORBA::is_nil( mesh ) )
524     {
525       SMESH::NodePosition_var pos = mesh->GetNodePosition( id );
526       position.setShapeId( pos->shapeID );
527       if ( pos->shapeID > 0 )
528       {
529         position.setShapeType( pos->shapeType );
530         if ( pos->shapeType == GEOM::EDGE && pos->params.length() > 0 )
531         {
532           position.setU( pos->params[0] );
533         }
534         if ( pos->shapeType == GEOM::FACE && pos->params.length() > 1 )
535         {
536           position.setU( pos->params[0] );
537           position.setV( pos->params[1] );
538         }
539         result = true;
540       }
541     }
542   }
543   return result;
544 }
545
546 /*!
547   \brief Get groups given node belongs to.
548   \param id Mesh node ID.
549   \return List of groups containing given node.
550 */
551 QList<SMESH::SelectionProxy> SMESH::SelectionProxy::nodeGroups( int id ) const
552 {
553   QList<SMESH::SelectionProxy> result;
554   if ( !isNull() )
555   {
556     SMESH::SMESH_Mesh_var mesh = myObject->GetMesh();
557     if ( !CORBA::is_nil( mesh ) )
558     {
559       SMESH::ListOfGroups_var groups = mesh->GetGroups();
560       for ( uint i = 0 ; i < groups->length(); i++ )
561       {
562         if ( groups[i]->GetType() == SMESH::NODE && groups[i]->Contains( id ) )
563         {
564           result << SMESH::SelectionProxy( groups[i].in() );
565         }
566       }
567     }
568   }
569   return result;
570 }
571
572 /*!
573   \brief Check if element with given ID is present in the mesh.
574   \param id Mesh element ID.
575   \return \c true if mesh contains element; \c false otherwise.
576 */
577 bool SMESH::SelectionProxy::hasElement( int id )
578 {
579   bool result = false;
580   if ( !isNull() )
581   {
582     if ( actor() )
583     {
584       const SMDS_MeshElement* element = actor()->GetObject()->GetMesh()->FindElement( id );
585       result = element != 0;
586     }
587     else
588     {
589       SMESH::SMESH_Mesh_var mesh = myObject->GetMesh();
590       if ( !CORBA::is_nil( mesh ) )
591       {
592         SMESH::long_array_var nodes = mesh->GetElemNodes( id );
593         result = nodes->length() > 0;
594       }
595     }
596   }
597   return result; 
598 }
599
600 /*!
601   \brief Get type of given mesh element.
602   \param id Mesh element ID.
603   \return Element type.
604 */
605 SMESH::ElementType SMESH::SelectionProxy::elementType( int id ) const
606 {
607   SMESH::ElementType value = SMESH::ALL;
608   if ( !isNull() )
609   {
610     if ( actor() )
611     {
612       const SMDS_MeshElement* element = actor()->GetObject()->GetMesh()->FindElement( id );
613       if ( element )
614       {
615         value = (SMESH::ElementType)element->GetType();
616       }
617     }
618     else
619     {
620       SMESH::SMESH_Mesh_var mesh = myObject->GetMesh();
621       if ( !CORBA::is_nil( mesh ) )
622       {
623         value = mesh->GetElementType( id, true );
624       }
625     }
626   }
627   return value;
628 }
629
630 /*!
631   \brief Get entity type of given mesh element.
632   \param id Mesh element ID.
633   \return Entity type.
634 */
635 int SMESH::SelectionProxy::elementEntityType( int id ) const
636 {
637   SMESH::EntityType value = SMESH::Entity_Last;
638   if ( !isNull() )
639   {
640     if ( actor() )
641     {
642       const SMDS_MeshElement* element = actor()->GetObject()->GetMesh()->FindElement( id );
643       if ( element )
644       {
645         value = (SMESH::EntityType)element->GetEntityType();
646       }
647     }
648     else
649     {
650       SMESH::SMESH_Mesh_var mesh = myObject->GetMesh();
651       if ( !CORBA::is_nil( mesh ) )
652       {
653         value = mesh->GetElementGeomType( id );
654       }
655     }
656   }
657   return value;
658 }
659
660 /*!
661   \brief Get element connectivity.
662   \param id Mesh element ID.
663   \param connectivity Return element connectivity.
664   \return \c true if result is valid; \c false otherwise.
665 */
666 bool SMESH::SelectionProxy::elementConnectivity( int id, Connectivity& connectivity )
667 {
668   bool result = false;
669   connectivity.clear();
670   if ( !isNull() )
671   {
672     QSet<int> nodes; // order of nodes is important
673     if ( actor() )
674     {
675       const SMDS_MeshElement* element = actor()->GetObject()->GetMesh()->FindElement( id );
676       if ( element )
677         if ( SMDS_NodeIteratorPtr it = element->nodeIterator())
678         {
679           while ( it->more() )
680           {
681             int n = it->next()->GetID();
682             if ( !nodes.contains( n ))
683             {
684               connectivity[ SMDSAbs_Node ] << n;
685               nodes << n;
686             }
687           }
688           result = true;
689         }
690     }
691     else
692     {
693       SMESH::SMESH_Mesh_var mesh = myObject->GetMesh();
694       if ( !CORBA::is_nil( mesh ) )
695       {
696         SMESH::long_array_var nn = mesh->GetElemNodes( id );
697         for ( int i = 0, nb = nn->length(); i < nb; i++ )
698         {
699           if ( !nodes.contains( nn[i] ))
700           {
701             connectivity[ SMDSAbs_Node ] << nn[i];
702             nodes << nn[i];
703           }
704         }
705         result = true;
706       }
707     }
708   }
709   return result;
710 }
711
712 /*!
713   \brief Get volume element connectivity.
714   \param id Mesh element ID.
715   \param connectivity Return nodal connectivity of each facet numbered from 1
716   \param nbNodes Return number of unique nodes.
717   \return \c true if result is valid; \c false otherwise.
718 */
719 bool SMESH::SelectionProxy::perFaceConnectivity( int id, Connectivity& connectivity, int& nbNodes )
720 {
721   bool result = false;
722   connectivity.clear();
723   nbNodes = 0;
724   if ( !isNull() )
725   {
726     QSet<int> nodeSet;
727     if ( actor() )
728     {
729       const SMDS_MeshElement* element = actor()->GetObject()->GetMesh()->FindElement( id );
730       SMDS_VolumeTool volTool;
731       if ( volTool.Set( element ))
732       {
733         for ( int iF = 0; iF < volTool.NbFaces(); ++iF )
734         {
735           const SMDS_MeshNode** nn = volTool.GetFaceNodes( iF );
736           int nbN = volTool.NbFaceNodes( iF );
737           for ( int iN = 0; iN < nbN; ++iN )
738           {
739             connectivity[ iF+1 ] << ( nn[ iN ]->GetID() );
740             nodeSet << ( nn[ iN ]->GetID() );
741           }
742         }
743         result = true;
744       }
745     }
746     else
747     {
748       SMESH::SMESH_Mesh_var mesh = myObject->GetMesh();
749       if ( !CORBA::is_nil( mesh ) )
750       {
751         CORBA::Long nbFaces = mesh->ElemNbFaces( id );
752         for ( CORBA::Long iF = 0; iF < nbFaces; ++iF )
753         {
754           SMESH::long_array_var nodes = mesh->GetElemFaceNodes( id, iF );
755           for ( CORBA::ULong iN = 0; iN < nodes->length(); ++iN )
756           {
757             connectivity[ iF ] << nodes[iN];
758             nodeSet << nodes[iN];
759           }
760         }
761         result = ( nbFaces > 0 );
762       }
763     }
764     nbNodes = nodeSet.size();
765   }
766   return result;
767 }
768
769 /*!
770   \brief Get element position on a shape.
771   \param id Mesh element ID.
772   \param position Returned element position.
773   \return \c true if result is valid; \c false otherwise.
774 */
775 bool SMESH::SelectionProxy::elementPosition( int id, Position& position )
776 {
777   bool result = false;
778   position = Position();
779   if ( !isNull() )
780   {
781     SMESH::SMESH_Mesh_var mesh = myObject->GetMesh();
782     if ( !CORBA::is_nil( mesh ) )
783     {
784       SMESH::ElementPosition_var pos = mesh->GetElementPosition( id );
785       position.setShapeId( pos->shapeID );
786       if ( pos->shapeID > 0 )
787       {
788         position.setShapeType( pos->shapeType );
789         result = true;
790       }
791     }
792   }
793   return result;
794 }
795
796 /*!
797   \brief Get gravity center of given element.
798   \param id Mesh element ID.
799   \param xyz Returned gravity center.
800   \return \c true if result is valid; \c false otherwise.
801 */
802 bool SMESH::SelectionProxy::elementGravityCenter( int id, SMESH::XYZ& xyz )
803 {
804   bool result = false;
805   xyz = SMESH::XYZ();
806   if ( !isNull() )
807   {
808     if ( actor() )
809     {
810       const SMDS_MeshElement* element = actor()->GetObject()->GetMesh()->FindElement( id );
811       if ( element )
812       {
813         SMDS_ElemIteratorPtr it = element->nodesIterator();
814         while ( it->more() )
815         {
816           const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*>( it->next() );
817           xyz.add( node->X(), node->Y(), node->Z() );
818         }
819         xyz.divide( element->NbNodes() );
820         result = true;
821       }
822     }
823     else
824     {
825       SMESH::SMESH_Mesh_var mesh = myObject->GetMesh();
826       if ( !CORBA::is_nil( mesh ) )
827       {
828         SMESH::long_array_var nodes = mesh->GetElemNodes( id );
829         for ( int i = 0, n = nodes->length(); i < n; i++ )
830         {
831           SMESH::double_array_var coords = mesh->GetNodeXYZ( nodes[i]  );
832           if ( coords->length() >= 3 )
833           {
834             xyz.add( coords[0], coords[1], coords[2] );
835           }
836         }
837         xyz.divide( nodes->length() );
838         result = true;
839       }
840     }
841   }
842   return result;
843 }
844
845 /*!
846   \brief Get normal vector to given element (face).
847   \param id Mesh element ID.
848   \param xyz Returned normal vector.
849   \return \c true if result is valid; \c false otherwise.
850 */
851 bool SMESH::SelectionProxy::elementNormal( int id, SMESH::XYZ& xyz )
852 {
853   bool result = false;
854   xyz = SMESH::XYZ();
855   if ( !isNull() )
856   {
857     if ( actor() )
858     {
859       const SMDS_MeshElement* element = actor()->GetObject()->GetMesh()->FindElement( id );
860       if ( element && element->GetType() == SMDSAbs_Face )
861       {
862         xyz = SMESH::getNormale( SMDS_Mesh::DownCast<SMDS_MeshFace>( element ) );
863         result = true;
864       }
865     }
866     else
867     {
868       SMESH::SMESH_Mesh_var mesh = myObject->GetMesh();
869       if ( !CORBA::is_nil( mesh ) )
870       {
871         SMESH::double_array_var normal = mesh->GetFaceNormal( id, true );
872         if ( normal->length() >= 3 )
873         {
874           xyz = SMESH::XYZ( normal[0], normal[1], normal[2] );
875           result = true;
876         }
877       }
878     }
879   }
880   return result;
881 }
882
883 /*!
884   \brief Get quality control's value for given element.
885   \param id Mesh element ID.
886   \param control Quality control type.
887   \param precision Precision for control's value.
888   \param value Returned quality control's value.
889   \return \c true if result is valid; \c false otherwise.
890 */
891 bool SMESH::SelectionProxy::elementControl( int id, int control, double precision, double& value ) const
892 {
893   bool result = false;
894   value = 0.;
895   if ( !isNull() )
896   {
897     if ( actor() )
898     {
899       SMESH::Controls::NumericalFunctorPtr functor;
900       switch ( control )
901       {
902       case SMESH::FT_AspectRatio:
903         functor.reset( new SMESH::Controls::AspectRatio() );
904         break;
905       case SMESH::FT_AspectRatio3D:
906         functor.reset( new SMESH::Controls::AspectRatio3D() );
907         break;
908       case SMESH::FT_Warping:
909         functor.reset( new SMESH::Controls::Warping() );
910         break;
911       case SMESH::FT_MinimumAngle:
912         functor.reset( new SMESH::Controls::MinimumAngle() );
913         break;
914       case SMESH::FT_Taper:
915         functor.reset( new SMESH::Controls::Taper() );
916         break;
917       case SMESH::FT_Skew:
918         functor.reset( new SMESH::Controls::Skew() );
919         break;
920       case SMESH::FT_Area:
921         functor.reset(  new SMESH::Controls::Area() );
922         break;
923       case SMESH::FT_Volume3D:
924         functor.reset(  new SMESH::Controls::Volume() );
925         break;
926       case SMESH::FT_MaxElementLength2D:
927         functor.reset( new SMESH::Controls::MaxElementLength2D() );
928         break;
929       case SMESH::FT_MaxElementLength3D:
930         functor.reset(  new SMESH::Controls::MaxElementLength3D() );
931         break;
932       case SMESH::FT_Length:
933         functor.reset( new SMESH::Controls::Length() );
934         break;
935       case SMESH::FT_Length2D:
936         functor.reset( new SMESH::Controls::Length2D() );
937         break;
938       case SMESH::FT_Length3D:
939         functor.reset( new SMESH::Controls::Length3D() );
940         break;
941       case SMESH::FT_BallDiameter:
942         functor.reset( new SMESH::Controls::BallDiameter() );
943         break;
944       default:
945         break;
946       } 
947       const SMDS_MeshElement* element = actor()->GetObject()->GetMesh()->FindElement( id );
948       if ( element && functor && element->GetType() == functor->GetType() )
949       {
950         functor->SetMesh( actor()->GetObject()->GetMesh() );
951         if ( functor->IsApplicable( element ))
952         {
953           functor->SetPrecision( precision );
954           value = functor->GetValue( id );
955           result = true;
956         }
957       }
958     }
959     else
960     {
961       SMESH::SMESH_Gen_var smeshGen = SMESHGUI::GetSMESHGen();
962       if ( smeshGen->_is_nil() )
963         return false;
964       SMESH::FilterManager_var manager = smeshGen->CreateFilterManager();
965       if ( manager->_is_nil() )
966         return false;
967       SMESH::NumericalFunctor_var functor;
968       switch ( control )
969       {
970       case SMESH::FT_AspectRatio:
971         functor = manager->CreateAspectRatio();
972         break;
973       case SMESH::FT_AspectRatio3D:
974         functor = manager->CreateAspectRatio3D();
975         break;
976       case SMESH::FT_Warping:
977         functor = manager->CreateWarping();
978         break;
979       case SMESH::FT_MinimumAngle:
980         functor = manager->CreateMinimumAngle();
981         break;
982       case SMESH::FT_Taper:
983         functor = manager->CreateTaper();
984         break;
985       case SMESH::FT_Skew:
986         functor = manager->CreateSkew();
987         break;
988       case SMESH::FT_Area:
989         functor = manager->CreateArea();
990         break;
991       case SMESH::FT_Volume3D:
992         functor = manager->CreateVolume3D();
993         break;
994       case SMESH::FT_MaxElementLength2D:
995         functor = manager->CreateMaxElementLength2D();
996         break;
997       case SMESH::FT_MaxElementLength3D:
998         functor = manager->CreateMaxElementLength3D();
999         break;
1000       case SMESH::FT_Length:
1001         functor = manager->CreateLength();
1002         break;
1003       case SMESH::FT_Length2D:
1004         functor = manager->CreateLength2D();
1005         break;
1006       case SMESH::FT_Length3D:
1007         functor = manager->CreateLength3D();
1008         break;
1009       case SMESH::FT_BallDiameter:
1010         functor = manager->CreateBallDiameter();
1011         break;
1012       default:
1013         break;
1014       }
1015       SMESH::SMESH_Mesh_var mesh = myObject->GetMesh();
1016       if ( !functor->_is_nil() && !mesh->_is_nil() )
1017       {
1018         functor->SetMesh( mesh );
1019         if ( functor->IsApplicable( id ))
1020         {
1021           functor->SetPrecision( precision );
1022           value = functor->GetValue( id );
1023           result = true;
1024         }
1025       }
1026       manager->UnRegister();
1027     }
1028   }
1029   return result;
1030 }
1031
1032 /*!
1033   \brief Get groups given element belongs to.
1034   \param id Mesh element ID.
1035   \return List of groups containing element.
1036 */
1037 QList<SMESH::SelectionProxy> SMESH::SelectionProxy::elementGroups( int id ) const
1038 {
1039   QList<SMESH::SelectionProxy> result;
1040   if ( !isNull() )
1041   {
1042     SMESH::SMESH_Mesh_var mesh = myObject->GetMesh();
1043     if ( !CORBA::is_nil( mesh ) )
1044     {
1045       SMESH::ListOfGroups_var groups = mesh->GetGroups();
1046       for ( uint i = 0 ; i < groups->length(); i++ )
1047       {
1048         if ( groups[i]->GetType() != SMESH::NODE && groups[i]->Contains( id ) )
1049         {
1050           result << SMESH::SelectionProxy( groups[i].in() );
1051         }
1052       }
1053     }
1054   }
1055   return result;
1056 }
1057
1058 /*!
1059   \brief Get MED file information.
1060   \return MED file information.
1061
1062   The result contains valid data only if proxy refers to mesh object
1063   which has been imported from the MED file.
1064 */
1065 SMESH::MedInfo SMESH::SelectionProxy::medFileInfo() const
1066 {
1067   SMESH::MedInfo info;
1068   if ( !isNull() )
1069   {
1070     SMESH::SMESH_Mesh_var mesh = SMESH::SMESH_Mesh::_narrow( myObject );
1071     if ( !CORBA::is_nil( mesh ) )
1072     {
1073       SMESH::MedFileInfo_var inf = mesh->GetMEDFileInfo();
1074       info.setFileName( inf->fileName.in() );
1075       info.setSize( inf->fileSize );
1076       info.setVersion( inf->major, inf->minor, inf->release );
1077     }
1078   }
1079   return info;
1080 }
1081
1082 /*!
1083   \brief Get child sub-meshes.
1084   \return List of sub-meshes for mesh object; empty list for other types.
1085 */
1086 QList<SMESH::SelectionProxy> SMESH::SelectionProxy::submeshes() const
1087 {
1088   QList<SMESH::SelectionProxy> lst;
1089   if ( !isNull() )
1090   {
1091     SMESH::SMESH_Mesh_var mesh = SMESH::SMESH_Mesh::_narrow( myObject );
1092     if ( !CORBA::is_nil( mesh ) )
1093     {
1094       SMESH::submesh_array_var array = mesh->GetSubMeshes();
1095       for ( uint i = 0 ; i < array->length(); i++ )
1096         lst << SMESH::SelectionProxy( array[i].in() );
1097     }
1098   }
1099   return lst;
1100 }
1101
1102 /*!
1103   \brief Get child groups.
1104   \return List of groups for mesh object; empty list for other types.
1105 */
1106 QList<SMESH::SelectionProxy> SMESH::SelectionProxy::groups() const
1107 {
1108   QList<SMESH::SelectionProxy> lst;
1109   if ( !isNull() )
1110   {
1111     SMESH::SMESH_Mesh_var mesh = SMESH::SMESH_Mesh::_narrow( myObject );
1112     if ( !CORBA::is_nil( mesh ) )
1113     {
1114       SMESH::ListOfGroups_var array = mesh->GetGroups();
1115       for ( uint i = 0 ; i < array->length(); i++ )
1116         lst << SMESH::SelectionProxy( array[i].in() );
1117     }
1118   }
1119   return lst;
1120 }
1121
1122 /*!
1123   \brief Get element type (for group). For other mesh objects result is undefined.
1124   \return Group's element type.
1125 */
1126 SMESH::ElementType SMESH::SelectionProxy::groupElementType() const
1127 {
1128   SMESH::ElementType value = SMESH::ALL;
1129   if ( !isNull() )
1130   {
1131     SMESH::SMESH_GroupBase_var group = SMESH::SMESH_GroupBase::_narrow( myObject );
1132     if ( !CORBA::is_nil( group ) )
1133       value = group->GetType();
1134   }
1135   return value;
1136 }
1137
1138 /*!
1139   \brief Get color (for group). For other mesh objects result is undefined.
1140   \return Group's color.
1141 */
1142 QColor SMESH::SelectionProxy::color() const
1143 {
1144   QColor result;
1145   if ( !isNull() )
1146   {
1147     SMESH::SMESH_GroupBase_var group = SMESH::SMESH_GroupBase::_narrow( myObject );
1148     if ( !CORBA::is_nil( group ) )
1149     {
1150       SALOMEDS::Color c = group->GetColor();
1151       result = QColor::fromRgbF( c.R, c.G, c.B );
1152     }
1153   }
1154   return result;
1155 }
1156
1157 /*!
1158   \brief Get size (for group). For other mesh objects result is undefined.
1159   \param autoCompute Compute size if it is unavailable. Defaults to \c false.
1160   \return Group's size.
1161 */
1162 int SMESH::SelectionProxy::size( bool autoCompute ) const
1163 {
1164   // note: size is not computed for group on filter for performance reasons, see IPAL52831
1165   int result = -1;
1166   if ( !isNull() )
1167   {
1168     SMESH::SMESH_GroupBase_var group = SMESH::SMESH_GroupBase::_narrow( myObject );
1169     if ( !CORBA::is_nil( group ) )
1170     {
1171       if ( type() == GroupFilter )
1172         // for group on filter we check if value is already computed and cached
1173         autoCompute |= group->IsNodeInfoAvailable();
1174       else
1175         // for other groups we force autoCompute to true
1176         autoCompute = true;
1177       if ( autoCompute )
1178         result = group->Size();
1179     }
1180   }
1181   return result;
1182 }
1183
1184 /*!
1185   \brief Get number of underlying nodes (for group of elements). For other
1186   mesh objects result is undefined.
1187   \param autoCompute Compute size if it is unavailable. Defaults to \c false.
1188   \return Number of nodes contained in group.
1189 */
1190 int SMESH::SelectionProxy::nbNodes( bool autoCompute ) const
1191 {
1192   // note: nb of nodes is not computed automatically for performance reasons
1193   int result = -1;
1194   if ( !isNull() )
1195   {
1196     SMESH::SMESH_GroupBase_var group = SMESH::SMESH_GroupBase::_narrow( myObject );
1197     if ( !CORBA::is_nil( group ) && ( autoCompute || isMeshLoaded() ) )
1198     {
1199       int groupSize = size( autoCompute );
1200       if ( groupSize >= 0 )
1201       {
1202         int limit = SMESHGUI::resourceMgr()->integerValue( "SMESH", "info_groups_nodes_limit", 100000 );
1203         if ( group->IsNodeInfoAvailable() || limit <= 0 || groupSize <= limit )
1204           result = group->GetNumberOfNodes();
1205       }
1206     }
1207   }
1208   return result;
1209 }
1210
1211 /*!
1212   \brief Get list of nodes / elements IDs for the mesh group.
1213   \return List of IDs for group object; empty list for other types.
1214 */
1215 QSet<uint> SMESH::SelectionProxy::ids() const
1216 {
1217   QSet<uint> result;
1218   if ( !isNull() )
1219   {
1220     SMESH::SMESH_GroupBase_var group = SMESH::SMESH_GroupBase::_narrow( myObject );
1221     if ( !CORBA::is_nil( group ) )
1222     {
1223       SMESH::long_array_var seq = group->GetListOfID();
1224       for ( int i = 0, n = seq->length(); i < n; i++ )
1225         result << (uint)seq[i];
1226     }
1227   }
1228   return result;
1229 }
1230
1231 ////////////////////////////////////////////////////////////////////////////////
1232 /// \class SMESH::MeshInfo
1233 /// \brief Store statistics on mesh object.
1234 ////////////////////////////////////////////////////////////////////////////////
1235
1236 /*!
1237   \brief Constructor.
1238 */
1239 SMESH::MeshInfo::MeshInfo()
1240 {
1241 }
1242
1243 /*!
1244   \brief Add information on given entity type.
1245   \param type Entity type.
1246   \param value Number of entities.
1247 */
1248 void SMESH::MeshInfo::addInfo( int type, long value )
1249 {
1250   myInfo[type] = value;
1251 }
1252
1253 /*!
1254   \brief Get number of entities of given type.
1255   \param type Entity type.
1256   \return Number of entities.
1257 */
1258 uint SMESH::MeshInfo::info( int type ) const
1259 {
1260   return myInfo.value( type, 0U );
1261 }
1262
1263 /*!
1264   \brief Access operator.
1265   \param type Entity type.
1266   \return Number of entities.
1267 */
1268 uint SMESH::MeshInfo::operator[] ( int type )
1269 {
1270   return (uint)info( type );
1271 }
1272
1273 /*!
1274   \brief Get total number of entities for types in given range.
1275   \param fromType Lower entity type.
1276   \param toType Upper entity type.
1277   \return Number of entities.
1278 */
1279 uint SMESH::MeshInfo::count( int fromType, int toType ) const
1280 {
1281   uint value = 0;
1282   for ( int type = fromType; type <= toType; type++ )
1283     value += info( type );
1284   return value;
1285 }
1286
1287 ////////////////////////////////////////////////////////////////////////////////
1288 /// \class SMESH::MedInfo
1289 /// \brief Provide operations over the selected object
1290 ////////////////////////////////////////////////////////////////////////////////
1291
1292 /*!
1293   \brief Constructor.
1294 */
1295 SMESH::MedInfo::MedInfo()
1296 {
1297 }
1298
1299 /*!
1300   \brief Get validity status.
1301
1302   MED file information is valid if at least stored file name is not null.
1303
1304   \return \c true if MED file info is valid; \c false otherwise.
1305 */
1306 bool SMESH::MedInfo::isValid() const
1307 {
1308   return !myFileName.isEmpty();
1309 }
1310
1311 /*!
1312   \brief Get file name for mesh imported from MED file.
1313   \return MED file name.
1314 */
1315 QString SMESH::MedInfo::fileName() const
1316 {
1317   return myFileName;
1318 }
1319
1320 /*!
1321   \brief Set file name for mesh imported from MED file.
1322   \param fileName MED file name.
1323 */
1324 void SMESH::MedInfo::setFileName( const QString& fileName )
1325 {
1326   myFileName = fileName;
1327 }
1328
1329 /*!
1330   \brief Get file size for mesh imported from MED file.
1331   \return MED file size.
1332 */
1333 uint SMESH::MedInfo::size() const
1334 {
1335   return mySize;
1336 }
1337
1338 /*!
1339   \brief Set file size for mesh imported from MED file.
1340   \param size MED file size.
1341 */
1342 void SMESH::MedInfo::setSize( uint size )
1343 {
1344   mySize = size;
1345 }
1346
1347 /*!
1348   \brief Get version of format for mesh imported from MED file.
1349   \return MED file format version.
1350 */
1351 QString SMESH::MedInfo::version() const
1352 {
1353   QString v = QString( "%1" ).arg( myMajor );
1354   if ( myMinor > 0 || myRelease > 0 ) v += QString( ".%1" ).arg( myMinor );
1355   else if ( myMajor > 0 ) v += ".0";
1356   if ( myRelease > 0 ) v += QString( ".%1" ).arg( myRelease );
1357   return v;
1358 }
1359
1360 /*!
1361   \brief Set version of format for mesh imported from MED file.
1362   \param major Major version number.
1363   \param minor Minor version number.
1364   \param release Release version number.
1365 */
1366 void SMESH::MedInfo::setVersion( uint major, uint minor, uint release )
1367 {
1368   myMajor = major;
1369   myMinor = minor;
1370   myRelease = release;
1371 }
1372
1373 ////////////////////////////////////////////////////////////////////////////////
1374 /// \class SMESH::Position
1375 /// \brief Describes position of mesh node or element on a reference shape.
1376 ////////////////////////////////////////////////////////////////////////////////
1377
1378 /*!
1379   \brief Contructor. Creates invalid position.
1380 */
1381 SMESH::Position::Position():
1382   myShapeId(-1), myShapeType(-1), myU(0), myV(0), myHasU(false), myHasV(false)
1383 {
1384 }
1385
1386 /*!
1387   \brief Check if position is valid.
1388   \return \c true if position is valid; \c false otherwise.
1389 */
1390 bool SMESH::Position::isValid() const
1391 {
1392   return myShapeId > 0 && myShapeType != -1;
1393 }
1394
1395 /*!
1396   \brief Get reference shape ID.
1397   \return Shape / sub-shape ID.
1398 */
1399 int SMESH::Position::shapeId() const
1400 {
1401   return myShapeId;
1402 }
1403
1404 /*!
1405   \brief Set reference shape ID.
1406   \param id Shape / sub-shape ID.
1407 */
1408 void SMESH::Position::setShapeId( int id )
1409 {
1410   myShapeId = id;
1411 }
1412
1413 /*!
1414   \brief Get reference shape type.
1415   \return Shape type.
1416 */
1417 int SMESH::Position::shapeType() const
1418 {
1419   return myShapeType;
1420 }
1421
1422 /*!
1423   \brief Set reference shape type.
1424   \param type Shape type.
1425 */
1426 void SMESH::Position::setShapeType( int type )
1427 {
1428   myShapeType = type;
1429 }
1430
1431 /*!
1432   \brief Check if there is U position on a shape.
1433   \return \c true if U position is valid; \c false otherwise.
1434 */
1435 bool SMESH::Position::hasU() const
1436 {
1437   return myHasU;
1438 }
1439
1440 /*!
1441   \brief Get U position on a shape.
1442   \return U position.
1443 */
1444 double SMESH::Position::u() const
1445 {
1446   return myU;
1447 }
1448
1449 /*!
1450   \brief Set U position on a shape.
1451   \parm u U position.
1452 */
1453 void SMESH::Position::setU( double u )
1454 {
1455   myU = u;
1456   myHasU = true;
1457 }
1458
1459 /*!
1460   \brief Check if there is V position on a shape.
1461   \return \c true if V position is valid; \c false otherwise.
1462 */
1463 bool SMESH::Position::hasV() const
1464 {
1465   return myHasV;
1466 }
1467
1468 /*!
1469   \brief Get V position on a shape.
1470   \return V position.
1471 */
1472 double SMESH::Position::v() const
1473 {
1474   return myV;
1475 }
1476
1477 /*!
1478   \brief Set V position on a shape.
1479   \parm v V position.
1480 */
1481 void SMESH::Position::setV( double v)
1482 {
1483   myV = v;
1484   myHasV = true;
1485 }
1486
1487 ////////////////////////////////////////////////////////////////////////////////
1488 /// \class SMESH::XYZ
1489 /// \brief Simple structure to manage 3D coordinate.
1490 ////////////////////////////////////////////////////////////////////////////////
1491
1492 /*!
1493   \brief Default constructor.
1494 */
1495 SMESH::XYZ::XYZ()
1496 {
1497   myX = myY = myZ = 0.0;
1498 }
1499
1500 /*!
1501   \brief Base constructor.
1502   \param parameter x X coordinate.
1503   \param parameter y Y coordinate.
1504   \param parameter z Z coordinate.
1505 */
1506 SMESH::XYZ::XYZ( double x, double y, double z )
1507 {
1508   myX = x;
1509   myY = y;
1510   myZ = z;
1511 }
1512
1513 /*!
1514   \brief Construction from geometrical point.
1515   \param parameter p Geometrical point.
1516 */
1517 SMESH::XYZ::XYZ( const gp_XYZ& p )
1518 {
1519   myX = p.X();
1520   myY = p.Y();
1521   myZ = p.Z();
1522 }
1523
1524 /*!
1525   \brief Add a point.
1526   \param parameter x X coordinate.
1527   \param parameter y Y coordinate.
1528   \param parameter z Z coordinate.
1529 */
1530 void SMESH::XYZ::add( double x, double y, double z )
1531 {
1532   myX += x;
1533   myY += y;
1534   myZ += z;
1535 }
1536
1537 /*!
1538   \brief Divide point to given coefficient.
1539   \param parameter a Divider coefficient.
1540 */
1541 void SMESH::XYZ::divide( double a )
1542 {
1543   if ( a != 0.)
1544   {
1545     myX /= a;
1546     myY /= a;
1547     myZ /= a;
1548   }
1549 }
1550
1551 /*!
1552   \brief Get X coordinate.
1553   \return X coordinate.
1554 */
1555 double SMESH::XYZ::x() const
1556 {
1557   return myX;
1558 }
1559
1560 /*!
1561   \brief Get Y coordinate.
1562   \return Y coordinate.
1563 */
1564 double SMESH::XYZ::y() const
1565 {
1566   return myY;
1567 }
1568
1569 /*!
1570   \brief Get Z coordinate.
1571   \return Z coordinate.
1572 */
1573 double SMESH::XYZ::z() const
1574 {
1575   return myZ;
1576 }
1577
1578 /*!
1579   \brief Conversion to geometrical point.
1580   \return Geometrical point.
1581 */
1582 SMESH::XYZ::operator gp_XYZ() const
1583 {
1584   return gp_XYZ( myX, myY, myZ );
1585 }