Salome HOME
bos #32738 [CEA] Scaled Jacobian quality mesh measure for volumetric elements.
[modules/smesh.git] / src / SMESHGUI / SMESHGUI_SelectionProxy.cxx
1 // Copyright (C) 2007-2023  CEA, EDF, 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 accessing 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::smIdType_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::smIdType_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::smIdType_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( SMESH::smIdType id, Connectivity& connectivity )
667 {
668   bool result = false;
669   connectivity.clear();
670   if ( !isNull() )
671   {
672     QSet<SMESH::smIdType> 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             SMESH::smIdType 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::smIdType_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::smIdType_array_var nodes = mesh->GetElemFaceNodes( id, iF );
755           for ( CORBA::ULong iN = 0; iN < nodes->length(); ++iN )
756           {
757             connectivity[ iF+1 ] << 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::smIdType_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       case SMESH::FT_ScaledJacobian:
945         functor.reset( new SMESH::Controls::ScaledJacobian() );
946         break;
947       default:
948         break;
949       } 
950       const SMDS_MeshElement* element = actor()->GetObject()->GetMesh()->FindElement( id );
951       if ( element && functor && element->GetType() == functor->GetType() )
952       {
953         functor->SetMesh( actor()->GetObject()->GetMesh() );
954         if ( functor->IsApplicable( element ))
955         {
956           functor->SetPrecision( precision );
957           value = functor->GetValue( id );
958           result = true;
959         }
960       }
961     }
962     else
963     {
964       SMESH::SMESH_Gen_var smeshGen = SMESHGUI::GetSMESHGen();
965       if ( smeshGen->_is_nil() )
966         return false;
967       SMESH::FilterManager_var manager = smeshGen->CreateFilterManager();
968       if ( manager->_is_nil() )
969         return false;
970       SMESH::NumericalFunctor_var functor;
971       switch ( control )
972       {
973       case SMESH::FT_AspectRatio:
974         functor = manager->CreateAspectRatio();
975         break;
976       case SMESH::FT_AspectRatio3D:
977         functor = manager->CreateAspectRatio3D();
978         break;
979       case SMESH::FT_Warping:
980         functor = manager->CreateWarping();
981         break;
982       case SMESH::FT_MinimumAngle:
983         functor = manager->CreateMinimumAngle();
984         break;
985       case SMESH::FT_Taper:
986         functor = manager->CreateTaper();
987         break;
988       case SMESH::FT_Skew:
989         functor = manager->CreateSkew();
990         break;
991       case SMESH::FT_Area:
992         functor = manager->CreateArea();
993         break;
994       case SMESH::FT_Volume3D:
995         functor = manager->CreateVolume3D();
996         break;
997       case SMESH::FT_MaxElementLength2D:
998         functor = manager->CreateMaxElementLength2D();
999         break;
1000       case SMESH::FT_MaxElementLength3D:
1001         functor = manager->CreateMaxElementLength3D();
1002         break;
1003       case SMESH::FT_Length:
1004         functor = manager->CreateLength();
1005         break;
1006       case SMESH::FT_Length2D:
1007         functor = manager->CreateLength2D();
1008         break;
1009       case SMESH::FT_Length3D:
1010         functor = manager->CreateLength3D();
1011         break;
1012       case SMESH::FT_BallDiameter:
1013         functor = manager->CreateBallDiameter();
1014         break;
1015       case SMESH::FT_ScaledJacobian:
1016         functor = manager->CreateScaledJacobian();
1017         break;
1018       default:
1019         break;
1020       }
1021       SMESH::SMESH_Mesh_var mesh = myObject->GetMesh();
1022       if ( !functor->_is_nil() && !mesh->_is_nil() )
1023       {
1024         functor->SetMesh( mesh );
1025         if ( functor->IsApplicable( id ))
1026         {
1027           functor->SetPrecision( precision );
1028           value = functor->GetValue( id );
1029           result = true;
1030         }
1031       }
1032       manager->UnRegister();
1033     }
1034   }
1035   return result;
1036 }
1037
1038 /*!
1039   \brief Get groups given element belongs to.
1040   \param id Mesh element ID.
1041   \return List of groups containing element.
1042 */
1043 QList<SMESH::SelectionProxy> SMESH::SelectionProxy::elementGroups( int id ) const
1044 {
1045   QList<SMESH::SelectionProxy> result;
1046   if ( !isNull() )
1047   {
1048     SMESH::SMESH_Mesh_var mesh = myObject->GetMesh();
1049     if ( !CORBA::is_nil( mesh ) )
1050     {
1051       SMESH::ListOfGroups_var groups = mesh->GetGroups();
1052       for ( uint i = 0 ; i < groups->length(); i++ )
1053       {
1054         if ( groups[i]->GetType() != SMESH::NODE && groups[i]->Contains( id ) )
1055         {
1056           result << SMESH::SelectionProxy( groups[i].in() );
1057         }
1058       }
1059     }
1060   }
1061   return result;
1062 }
1063
1064 /*!
1065   \brief Get MED file information.
1066   \return MED file information.
1067
1068   The result contains valid data only if proxy refers to mesh object
1069   which has been imported from the MED file.
1070 */
1071 SMESH::MedInfo SMESH::SelectionProxy::medFileInfo() const
1072 {
1073   SMESH::MedInfo info;
1074   if ( !isNull() )
1075   {
1076     SMESH::SMESH_Mesh_var mesh = SMESH::SMESH_Mesh::_narrow( myObject );
1077     if ( !CORBA::is_nil( mesh ) )
1078     {
1079       SMESH::MedFileInfo_var inf = mesh->GetMEDFileInfo();
1080       info.setFileName( inf->fileName.in() );
1081       info.setSize( inf->fileSize );
1082       info.setVersion( inf->major, inf->minor, inf->release );
1083     }
1084   }
1085   return info;
1086 }
1087
1088 /*!
1089   \brief Get child sub-meshes.
1090   \return List of sub-meshes for mesh object; empty list for other types.
1091 */
1092 QList<SMESH::SelectionProxy> SMESH::SelectionProxy::submeshes() const
1093 {
1094   QList<SMESH::SelectionProxy> lst;
1095   if ( !isNull() )
1096   {
1097     SMESH::SMESH_Mesh_var mesh = SMESH::SMESH_Mesh::_narrow( myObject );
1098     if ( !CORBA::is_nil( mesh ) )
1099     {
1100       SMESH::submesh_array_var array = mesh->GetSubMeshes();
1101       for ( uint i = 0 ; i < array->length(); i++ )
1102         lst << SMESH::SelectionProxy( array[i].in() );
1103     }
1104   }
1105   return lst;
1106 }
1107
1108 /*!
1109   \brief Get child groups.
1110   \return List of groups for mesh object; empty list for other types.
1111 */
1112 QList<SMESH::SelectionProxy> SMESH::SelectionProxy::groups() const
1113 {
1114   QList<SMESH::SelectionProxy> lst;
1115   if ( !isNull() )
1116   {
1117     SMESH::SMESH_Mesh_var mesh = SMESH::SMESH_Mesh::_narrow( myObject );
1118     if ( !CORBA::is_nil( mesh ) )
1119     {
1120       SMESH::ListOfGroups_var array = mesh->GetGroups();
1121       for ( uint i = 0 ; i < array->length(); i++ )
1122         lst << SMESH::SelectionProxy( array[i].in() );
1123     }
1124   }
1125   return lst;
1126 }
1127
1128 /*!
1129   \brief Get element type (for group). For other mesh objects result is undefined.
1130   \return Group's element type.
1131 */
1132 SMESH::ElementType SMESH::SelectionProxy::groupElementType() const
1133 {
1134   SMESH::ElementType value = SMESH::ALL;
1135   if ( !isNull() )
1136   {
1137     SMESH::SMESH_GroupBase_var group = SMESH::SMESH_GroupBase::_narrow( myObject );
1138     if ( !CORBA::is_nil( group ) )
1139       value = group->GetType();
1140   }
1141   return value;
1142 }
1143
1144 /*!
1145   \brief Get color (for group). For other mesh objects result is undefined.
1146   \return Group's color.
1147 */
1148 QColor SMESH::SelectionProxy::color() const
1149 {
1150   QColor result;
1151   if ( !isNull() )
1152   {
1153     SMESH::SMESH_GroupBase_var group = SMESH::SMESH_GroupBase::_narrow( myObject );
1154     if ( !CORBA::is_nil( group ) )
1155     {
1156       SALOMEDS::Color c = group->GetColor();
1157       result = QColor::fromRgbF( c.R, c.G, c.B );
1158     }
1159   }
1160   return result;
1161 }
1162
1163 /*!
1164   \brief Get size (for group). For other mesh objects result is undefined.
1165   \param autoCompute Compute size if it is unavailable. Defaults to \c false.
1166   \return Group's size.
1167 */
1168 SMESH::smIdType SMESH::SelectionProxy::size( bool autoCompute ) const
1169 {
1170   // note: size is not computed for group on filter for performance reasons, see IPAL52831
1171   SMESH::smIdType result = -1;
1172   if ( !isNull() )
1173   {
1174     SMESH::SMESH_GroupBase_var group = SMESH::SMESH_GroupBase::_narrow( myObject );
1175     if ( !CORBA::is_nil( group ) )
1176     {
1177       if ( type() == GroupFilter )
1178         // for group on filter we check if value is already computed and cached
1179         autoCompute |= group->IsMeshInfoCorrect();
1180       else
1181         // for other groups we force autoCompute to true
1182         autoCompute = true;
1183       if ( autoCompute )
1184         result = group->Size();
1185     }
1186   }
1187   return result;
1188 }
1189
1190 /*!
1191   \brief Get number of underlying nodes (for group of elements). For other
1192   mesh objects result is undefined.
1193   \param autoCompute Compute size if it is unavailable. Defaults to \c false.
1194   \return Number of nodes contained in group.
1195 */
1196 SMESH::smIdType SMESH::SelectionProxy::nbNodes( bool autoCompute ) const
1197 {
1198   // note: nb of nodes is not computed automatically for performance reasons
1199   SMESH::smIdType result = -1;
1200   if ( !isNull() )
1201   {
1202     SMESH::SMESH_GroupBase_var group = SMESH::SMESH_GroupBase::_narrow( myObject );
1203     if ( !CORBA::is_nil( group ) && ( autoCompute || isMeshLoaded() ) )
1204     {
1205       int groupSize = size( autoCompute );
1206       if ( groupSize >= 0 )
1207       {
1208         int limit = SMESHGUI::resourceMgr()->integerValue( "SMESH", "info_groups_nodes_limit", 100000 );
1209         if ( group->IsNodeInfoAvailable() || limit <= 0 || groupSize <= limit )
1210           result = group->GetNumberOfNodes();
1211       }
1212     }
1213   }
1214   return result;
1215 }
1216
1217 /*!
1218   \brief Get list of nodes / elements IDs for the mesh group.
1219   \return List of IDs for group object; empty list for other types.
1220 */
1221 QSet<uint> SMESH::SelectionProxy::ids() const
1222 {
1223   QSet<uint> result;
1224   if ( !isNull() )
1225   {
1226     SMESH::SMESH_GroupBase_var group = SMESH::SMESH_GroupBase::_narrow( myObject );
1227     if ( !CORBA::is_nil( group ) )
1228     {
1229       SMESH::smIdType_array_var seq = group->GetListOfID();
1230       for ( int i = 0, n = seq->length(); i < n; i++ )
1231         result << (uint)seq[i];
1232     }
1233   }
1234   return result;
1235 }
1236
1237 ////////////////////////////////////////////////////////////////////////////////
1238 /// \class SMESH::MeshInfo
1239 /// \brief Store statistics on mesh object.
1240 ////////////////////////////////////////////////////////////////////////////////
1241
1242 /*!
1243   \brief Constructor.
1244 */
1245 SMESH::MeshInfo::MeshInfo()
1246 {
1247 }
1248
1249 /*!
1250   \brief Add information on given entity type.
1251   \param type Entity type.
1252   \param value Number of entities.
1253 */
1254 void SMESH::MeshInfo::addInfo( int type, long value )
1255 {
1256   myInfo[type] = value;
1257 }
1258
1259 /*!
1260   \brief Get number of entities of given type.
1261   \param type Entity type.
1262   \return Number of entities.
1263 */
1264 uint SMESH::MeshInfo::info( int type ) const
1265 {
1266   return myInfo.value( type, 0U );
1267 }
1268
1269 /*!
1270   \brief Access operator.
1271   \param type Entity type.
1272   \return Number of entities.
1273 */
1274 uint SMESH::MeshInfo::operator[] ( int type )
1275 {
1276   return (uint)info( type );
1277 }
1278
1279 /*!
1280   \brief Get total number of entities for types in given range.
1281   \param fromType Lower entity type.
1282   \param toType Upper entity type.
1283   \return Number of entities.
1284 */
1285 uint SMESH::MeshInfo::count( int fromType, int toType ) const
1286 {
1287   uint value = 0;
1288   for ( int type = fromType; type <= toType; type++ )
1289     value += info( type );
1290   return value;
1291 }
1292
1293 ////////////////////////////////////////////////////////////////////////////////
1294 /// \class SMESH::MedInfo
1295 /// \brief Provide operations over the selected object
1296 ////////////////////////////////////////////////////////////////////////////////
1297
1298 /*!
1299   \brief Constructor.
1300 */
1301 SMESH::MedInfo::MedInfo()
1302 {
1303 }
1304
1305 /*!
1306   \brief Get validity status.
1307
1308   MED file information is valid if at least stored file name is not null.
1309
1310   \return \c true if MED file info is valid; \c false otherwise.
1311 */
1312 bool SMESH::MedInfo::isValid() const
1313 {
1314   return !myFileName.isEmpty();
1315 }
1316
1317 /*!
1318   \brief Get file name for mesh imported from MED file.
1319   \return MED file name.
1320 */
1321 QString SMESH::MedInfo::fileName() const
1322 {
1323   return myFileName;
1324 }
1325
1326 /*!
1327   \brief Set file name for mesh imported from MED file.
1328   \param fileName MED file name.
1329 */
1330 void SMESH::MedInfo::setFileName( const QString& fileName )
1331 {
1332   myFileName = fileName;
1333 }
1334
1335 /*!
1336   \brief Get file size for mesh imported from MED file.
1337   \return MED file size.
1338 */
1339 uint SMESH::MedInfo::size() const
1340 {
1341   return mySize;
1342 }
1343
1344 /*!
1345   \brief Set file size for mesh imported from MED file.
1346   \param size MED file size.
1347 */
1348 void SMESH::MedInfo::setSize( uint size )
1349 {
1350   mySize = size;
1351 }
1352
1353 /*!
1354   \brief Get version of format for mesh imported from MED file.
1355   \return MED file format version.
1356 */
1357 QString SMESH::MedInfo::version() const
1358 {
1359   QString v = QString( "%1" ).arg( myMajor );
1360   if ( myMinor > 0 || myRelease > 0 ) v += QString( ".%1" ).arg( myMinor );
1361   else if ( myMajor > 0 ) v += ".0";
1362   if ( myRelease > 0 ) v += QString( ".%1" ).arg( myRelease );
1363   return v;
1364 }
1365
1366 /*!
1367   \brief Set version of format for mesh imported from MED file.
1368   \param major Major version number.
1369   \param minor Minor version number.
1370   \param release Release version number.
1371 */
1372 void SMESH::MedInfo::setVersion( uint major, uint minor, uint release )
1373 {
1374   myMajor = major;
1375   myMinor = minor;
1376   myRelease = release;
1377 }
1378
1379 ////////////////////////////////////////////////////////////////////////////////
1380 /// \class SMESH::Position
1381 /// \brief Describes position of mesh node or element on a reference shape.
1382 ////////////////////////////////////////////////////////////////////////////////
1383
1384 /*!
1385   \brief Constructor. Creates invalid position.
1386 */
1387 SMESH::Position::Position():
1388   myShapeId(-1), myShapeType(-1), myU(0), myV(0), myHasU(false), myHasV(false)
1389 {
1390 }
1391
1392 /*!
1393   \brief Check if position is valid.
1394   \return \c true if position is valid; \c false otherwise.
1395 */
1396 bool SMESH::Position::isValid() const
1397 {
1398   return myShapeId > 0 && myShapeType != -1;
1399 }
1400
1401 /*!
1402   \brief Get reference shape ID.
1403   \return Shape / sub-shape ID.
1404 */
1405 int SMESH::Position::shapeId() const
1406 {
1407   return myShapeId;
1408 }
1409
1410 /*!
1411   \brief Set reference shape ID.
1412   \param id Shape / sub-shape ID.
1413 */
1414 void SMESH::Position::setShapeId( int id )
1415 {
1416   myShapeId = id;
1417 }
1418
1419 /*!
1420   \brief Get reference shape type.
1421   \return Shape type.
1422 */
1423 int SMESH::Position::shapeType() const
1424 {
1425   return myShapeType;
1426 }
1427
1428 /*!
1429   \brief Set reference shape type.
1430   \param type Shape type.
1431 */
1432 void SMESH::Position::setShapeType( int type )
1433 {
1434   myShapeType = type;
1435 }
1436
1437 /*!
1438   \brief Check if there is U position on a shape.
1439   \return \c true if U position is valid; \c false otherwise.
1440 */
1441 bool SMESH::Position::hasU() const
1442 {
1443   return myHasU;
1444 }
1445
1446 /*!
1447   \brief Get U position on a shape.
1448   \return U position.
1449 */
1450 double SMESH::Position::u() const
1451 {
1452   return myU;
1453 }
1454
1455 /*!
1456   \brief Set U position on a shape.
1457   \parm u U position.
1458 */
1459 void SMESH::Position::setU( double u )
1460 {
1461   myU = u;
1462   myHasU = true;
1463 }
1464
1465 /*!
1466   \brief Check if there is V position on a shape.
1467   \return \c true if V position is valid; \c false otherwise.
1468 */
1469 bool SMESH::Position::hasV() const
1470 {
1471   return myHasV;
1472 }
1473
1474 /*!
1475   \brief Get V position on a shape.
1476   \return V position.
1477 */
1478 double SMESH::Position::v() const
1479 {
1480   return myV;
1481 }
1482
1483 /*!
1484   \brief Set V position on a shape.
1485   \parm v V position.
1486 */
1487 void SMESH::Position::setV( double v)
1488 {
1489   myV = v;
1490   myHasV = true;
1491 }
1492
1493 ////////////////////////////////////////////////////////////////////////////////
1494 /// \class SMESH::XYZ
1495 /// \brief Simple structure to manage 3D coordinate.
1496 ////////////////////////////////////////////////////////////////////////////////
1497
1498 /*!
1499   \brief Default constructor.
1500 */
1501 SMESH::XYZ::XYZ()
1502 {
1503   myX = myY = myZ = 0.0;
1504 }
1505
1506 /*!
1507   \brief Base constructor.
1508   \param parameter x X coordinate.
1509   \param parameter y Y coordinate.
1510   \param parameter z Z coordinate.
1511 */
1512 SMESH::XYZ::XYZ( double x, double y, double z )
1513 {
1514   myX = x;
1515   myY = y;
1516   myZ = z;
1517 }
1518
1519 /*!
1520   \brief Construction from geometrical point.
1521   \param parameter p Geometrical point.
1522 */
1523 SMESH::XYZ::XYZ( const gp_XYZ& p )
1524 {
1525   myX = p.X();
1526   myY = p.Y();
1527   myZ = p.Z();
1528 }
1529
1530 /*!
1531   \brief Add a point.
1532   \param parameter x X coordinate.
1533   \param parameter y Y coordinate.
1534   \param parameter z Z coordinate.
1535 */
1536 void SMESH::XYZ::add( double x, double y, double z )
1537 {
1538   myX += x;
1539   myY += y;
1540   myZ += z;
1541 }
1542
1543 /*!
1544   \brief Divide point to given coefficient.
1545   \param parameter a Divider coefficient.
1546 */
1547 void SMESH::XYZ::divide( double a )
1548 {
1549   if ( a != 0.)
1550   {
1551     myX /= a;
1552     myY /= a;
1553     myZ /= a;
1554   }
1555 }
1556
1557 /*!
1558   \brief Get X coordinate.
1559   \return X coordinate.
1560 */
1561 double SMESH::XYZ::x() const
1562 {
1563   return myX;
1564 }
1565
1566 /*!
1567   \brief Get Y coordinate.
1568   \return Y coordinate.
1569 */
1570 double SMESH::XYZ::y() const
1571 {
1572   return myY;
1573 }
1574
1575 /*!
1576   \brief Get Z coordinate.
1577   \return Z coordinate.
1578 */
1579 double SMESH::XYZ::z() const
1580 {
1581   return myZ;
1582 }
1583
1584 /*!
1585   \brief Conversion to geometrical point.
1586   \return Geometrical point.
1587 */
1588 SMESH::XYZ::operator gp_XYZ() const
1589 {
1590   return gp_XYZ( myX, myY, myZ );
1591 }