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