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