Salome HOME
Merge from V6_3_BR 06/06/2011
[modules/smesh.git] / src / SMESHGUI / SMESHGUI_Selection.cxx
1 // Copyright (C) 2007-2011  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.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 // SMESH SMESHGUI_Selection
24 // File   : SMESHGUI_Selection.cxx
25 // Author : Alexander SOLOVYOV, Open CASCADE S.A.S.
26 // SMESH includes
27 //
28 #include "SMESHGUI_Selection.h"
29
30 #include "SMESHGUI_Utils.h"
31 #include "SMESHGUI_VTKUtils.h"
32 #include "SMESHGUI_GEOMGenUtils.h"
33 #include "SMESHGUI_ComputeDlg.h"
34
35 #include <SMESH_Type.h>
36 #include <SMESH_Actor.h>
37 #include <SMESH_ScalarBarActor.h>
38
39 // SALOME GUI includes
40 #include <SalomeApp_Study.h>
41 #include <LightApp_VTKSelector.h>
42 #include <SVTK_ViewWindow.h>
43
44 // IDL includes
45 #include <SALOMEconfig.h>
46 #include CORBA_CLIENT_HEADER(SMESH_Gen)
47 #include CORBA_CLIENT_HEADER(SMESH_Mesh)
48 #include CORBA_CLIENT_HEADER(SMESH_Group)
49
50 //=======================================================================
51 //function : SMESHGUI_Selection
52 //purpose  : 
53 //=======================================================================
54 SMESHGUI_Selection::SMESHGUI_Selection()
55 : LightApp_Selection()
56 {
57 }
58
59 //=======================================================================
60 //function : ~SMESHGUI_Selection
61 //purpose  : 
62 //=======================================================================
63 SMESHGUI_Selection::~SMESHGUI_Selection()
64 {
65 }
66
67 //=======================================================================
68 //function : init
69 //purpose  : 
70 //=======================================================================
71 void SMESHGUI_Selection::init( const QString& client, LightApp_SelectionMgr* mgr )
72 {
73   LightApp_Selection::init( client, mgr );
74
75   if( mgr && study() )
76   {
77     SalomeApp_Study* aSStudy = dynamic_cast<SalomeApp_Study*>(study());
78     if (!aSStudy)
79       return;
80     _PTR(Study) aStudy = aSStudy->studyDS();
81
82     for( int i=0, n=count(); i<n; i++ )
83       myTypes.append( typeName( type( entry( i ), aStudy ) ) );
84   }
85 }
86
87 //=======================================================================
88 //function : processOwner
89 //purpose  : 
90 //=======================================================================
91 bool SMESHGUI_Selection::processOwner( const LightApp_DataOwner* ow )
92 {
93   const LightApp_SVTKDataOwner* owner =
94     dynamic_cast<const LightApp_SVTKDataOwner*> ( ow );
95   if( owner )
96     myActors.append( dynamic_cast<SMESH_Actor*>( owner->GetActor() ) );
97   else
98     myActors.append( 0 );
99   return true;
100 }
101
102 //=======================================================================
103 //function : parameter
104 //purpose  : 
105 //=======================================================================
106 QVariant SMESHGUI_Selection::parameter( const int ind, const QString& p ) const
107 {
108   QVariant val;
109   if      ( p=="client" )        val = QVariant( LightApp_Selection::parameter( p ) );
110   else if ( p=="type" )          val = QVariant( myTypes[ind] );
111   else if ( p=="elemTypes" )     val = QVariant( elemTypes( ind ) );
112   else if ( p=="isAutoColor" )   val = QVariant( isAutoColor( ind ) );
113   else if ( p=="numberOfNodes" ) val = QVariant( numberOfNodes( ind ) );
114   else if ( p=="labeledTypes" )  val = QVariant( labeledTypes( ind ) );
115   else if ( p=="shrinkMode" )    val = QVariant( shrinkMode( ind ) );
116   else if ( p=="entityMode" )    val = QVariant( entityMode( ind ) );
117   else if ( p=="controlMode" )   val = QVariant( controlMode( ind ) );
118   else if ( p=="isNumFunctor" )  val = QVariant( isNumFunctor( ind ) );
119   else if ( p=="displayMode" )   val = QVariant( displayMode( ind ) );
120   else if ( p=="isComputable" )  val = QVariant( isComputable( ind ) );
121   else if ( p=="isPreComputable" )  val = QVariant( isPreComputable( ind ) );
122   else if ( p=="hasReference" )  val = QVariant( hasReference( ind ) );
123   else if ( p=="isImported" )    val = QVariant( isImported( ind ) );
124   else if ( p=="facesOrientationMode" ) val = QVariant( facesOrientationMode( ind ) );
125   else if ( p=="groupType" )     val = QVariant( groupType( ind ) );
126   else if ( p=="quadratic2DMode") val =  QVariant(quadratic2DMode(ind));
127   else if ( p=="isDistributionVisible") val = QVariant(isDistributionVisible(ind));
128
129   if( val.isValid() )
130     return val;
131   else
132     return LightApp_Selection::parameter( ind, p );
133 }
134
135 //=======================================================================
136 //function : getVtkOwner
137 //purpose  : 
138 //=======================================================================
139
140 SMESH_Actor* SMESHGUI_Selection::getActor( int ind ) const
141 {
142   if( ind >= 0 && ind < count() )
143     return myActors.isEmpty() ? 0 : myActors.at( ind );
144   else
145     return 0;
146 }
147
148 //=======================================================================
149 //function : elemTypes
150 //purpose  : may return {'Elem0d' 'Edge' 'Face' 'Volume'} at most
151 //=======================================================================
152
153 QList<QVariant> SMESHGUI_Selection::elemTypes( int ind ) const
154 {
155   QList<QVariant> types;
156   SMESH_Actor* actor = getActor( ind );
157   if ( actor ) {
158     TVisualObjPtr object = actor->GetObject();
159     if ( object ) {
160       if ( object->GetNbEntities( SMDSAbs_0DElement )) types.append( "Elem0d" );
161       if ( object->GetNbEntities( SMDSAbs_Edge )) types.append( "Edge" );
162       if ( object->GetNbEntities( SMDSAbs_Face )) types.append( "Face" );
163       if ( object->GetNbEntities( SMDSAbs_Volume )) types.append( "Volume" );
164     }
165   }
166   return types;
167 }
168
169 //=======================================================================
170 //function : labeledTypes
171 //purpose  : may return {'Point' 'Cell'} at most
172 //=======================================================================
173
174 QList<QVariant> SMESHGUI_Selection::labeledTypes( int ind ) const
175 {
176   QList<QVariant> types;
177   SMESH_Actor* actor = getActor( ind );
178   if ( actor ) {
179     if ( actor->GetPointsLabeled()) types.append( "Point" );
180     if ( actor->GetCellsLabeled()) types.append( "Cell" );
181   }
182   return types;
183 }
184
185 //=======================================================================
186 //function : displayMode
187 //purpose  : return SMESH_Actor::EReperesent
188 //=======================================================================
189
190 QString SMESHGUI_Selection::displayMode( int ind ) const
191 {
192   SMESH_Actor* actor = getActor( ind );
193   if ( actor ) {
194     switch( actor->GetRepresentation() ) {
195     case SMESH_Actor::eEdge:    return "eEdge";
196     case SMESH_Actor::eSurface: return "eSurface";
197     case SMESH_Actor::ePoint:   return "ePoint";
198     default: break;
199     }
200   }
201   return "Unknown";
202 }
203
204
205 //=======================================================================
206 //function : quadratic2DMode
207 //purpose  : return SMESH_Actor::EQuadratic2DRepresentation
208 //=======================================================================
209 QString SMESHGUI_Selection::quadratic2DMode( int ind ) const
210 {
211   SMESH_Actor* actor = getActor( ind );
212   if ( actor ) {
213     switch( actor->GetQuadratic2DRepresentation() ) {
214     case SMESH_Actor::eLines:    return "eLines";
215     case SMESH_Actor::eArcs: return "eArcs";
216     default: break;
217     }
218   }
219   return "Unknown";
220 }
221
222 //=======================================================================
223 //function : isDistributionVisible
224 //purpose  : Visible/Invisible distribution of the ScalarBar Actor
225 //=======================================================================
226
227 bool SMESHGUI_Selection::isDistributionVisible(int ind) const {
228   SMESH_Actor* actor = getActor( ind );
229   return (actor && actor->GetScalarBarActor() && actor->GetScalarBarActor()->GetDistributionVisibility());
230
231
232 //=======================================================================
233 //function : shrinkMode
234 //purpose  : return either 'IsSrunk', 'IsNotShrunk' or 'IsNotShrinkable'
235 //=======================================================================
236
237 QString SMESHGUI_Selection::shrinkMode( int ind ) const
238 {
239   SMESH_Actor* actor = getActor( ind );
240   if ( actor && actor->IsShrunkable() ) {
241     if ( actor->IsShrunk() )
242       return "IsShrunk";
243     return "IsNotShrunk";
244   }
245   return "IsNotShrinkable";
246 }
247
248 //=======================================================================
249 //function : entityMode
250 //purpose  : may return {'Elem0d' 'Edge' 'Face' 'Volume'} at most
251 //=======================================================================
252
253 QList<QVariant> SMESHGUI_Selection::entityMode( int ind ) const
254 {
255   QList<QVariant> types;
256   SMESH_Actor* actor = getActor( ind );
257   if ( actor ) {
258     unsigned int aMode = actor->GetEntityMode();
259     if ( aMode & SMESH_Actor::eVolumes    ) types.append( "Volume" );
260     if ( aMode & SMESH_Actor::eFaces      ) types.append( "Face"   );
261     if ( aMode & SMESH_Actor::eEdges      ) types.append( "Edge"   );
262     if ( aMode & SMESH_Actor::e0DElements ) types.append( "Elem0d" );
263   }
264   return types;
265 }
266
267 //=======================================================================
268 //function : controlMode
269 //purpose  : return SMESH_Actor::eControl
270 //=======================================================================
271
272 QString SMESHGUI_Selection::controlMode( int ind ) const
273 {
274   SMESH_Actor* actor = getActor( ind );
275   QString mode = "eNone";
276   if ( actor ) {
277     switch( actor->GetControlMode() ) {
278     case SMESH_Actor::eLength:                mode = "eLength";                break;
279     case SMESH_Actor::eLength2D:              mode = "eLength2D";              break;
280     case SMESH_Actor::eFreeEdges:             mode = "eFreeEdges";             break;
281     case SMESH_Actor::eFreeNodes:             mode = "eFreeNodes";             break;
282     case SMESH_Actor::eFreeBorders:           mode = "eFreeBorders";           break;
283     case SMESH_Actor::eFreeFaces:             mode = "eFreeFaces";             break;
284     case SMESH_Actor::eMultiConnection:       mode = "eMultiConnection";       break;
285     case SMESH_Actor::eMultiConnection2D:     mode = "eMultiConnection2D";     break;
286     case SMESH_Actor::eArea:                  mode = "eArea";                  break;
287     case SMESH_Actor::eVolume3D:              mode = "eVolume3D";              break;
288     case SMESH_Actor::eMaxElementLength2D:    mode = "eMaxElementLength2D";    break;
289     case SMESH_Actor::eMaxElementLength3D:    mode = "eMaxElementLength3D";    break;
290     case SMESH_Actor::eTaper:                 mode = "eTaper";                 break;
291     case SMESH_Actor::eAspectRatio:           mode = "eAspectRatio";           break;
292     case SMESH_Actor::eAspectRatio3D:         mode = "eAspectRatio3D";         break;
293     case SMESH_Actor::eMinimumAngle:          mode = "eMinimumAngle";          break;
294     case SMESH_Actor::eWarping:               mode = "eWarping";               break;
295     case SMESH_Actor::eSkew:                  mode = "eSkew";                  break;
296     case SMESH_Actor::eBareBorderFace:        mode = "eBareBorderFace";        break;
297     case SMESH_Actor::eBareBorderVolume:      mode = "eBareBorderVolume";      break;
298     case SMESH_Actor::eOverConstrainedFace:   mode = "eOverConstrainedFace";   break;
299     case SMESH_Actor::eOverConstrainedVolume: mode = "eOverConstrainedVolume"; break;
300     default:break;
301     }
302   }
303   return mode;
304 }
305
306 bool SMESHGUI_Selection::isNumFunctor( int ind ) const
307 {
308   bool result = false;
309   SMESH_Actor* actor = getActor( ind );
310   if ( actor ) {
311     switch( actor->GetControlMode() ) {
312     case SMESH_Actor::eLength:
313     case SMESH_Actor::eLength2D:
314     case SMESH_Actor::eMultiConnection:
315     case SMESH_Actor::eMultiConnection2D:
316     case SMESH_Actor::eArea:
317     case SMESH_Actor::eVolume3D:
318     case SMESH_Actor::eMaxElementLength2D:
319     case SMESH_Actor::eMaxElementLength3D:
320     case SMESH_Actor::eTaper:
321     case SMESH_Actor::eAspectRatio:
322     case SMESH_Actor::eAspectRatio3D:
323     case SMESH_Actor::eMinimumAngle:
324     case SMESH_Actor::eWarping:
325     case SMESH_Actor::eSkew:
326       result = true;
327       break;
328     default:
329       break;
330     }
331   }
332   return result;
333 }
334
335 //=======================================================================
336 //function : facesOrientationMode
337 //purpose  : 
338 //=======================================================================
339
340 QString SMESHGUI_Selection::facesOrientationMode( int ind ) const
341 {
342   SMESH_Actor* actor = getActor( ind );
343   if ( actor ) {
344     if ( actor->GetFacesOriented() )
345       return "IsOriented";
346     return "IsNotOriented";
347   }
348   return "Unknown";
349 }
350
351 //=======================================================================
352 //function : isAutoColor
353 //purpose  : 
354 //=======================================================================
355
356 bool SMESHGUI_Selection::isAutoColor( int ind ) const
357 {
358   if ( ind >= 0 && ind < myTypes.count() && myTypes[ind] != "Unknown" )
359   {
360     _PTR(SObject) sobj = SMESH::GetActiveStudyDocument()->FindObjectID( entry( ind ).toLatin1().data() );
361     CORBA::Object_var obj = SMESH::SObjectToObject( sobj, SMESH::GetActiveStudyDocument() );
362
363     if ( ! CORBA::is_nil( obj )) {
364       SMESH::SMESH_Mesh_var mesh = SMESH::SMESH_Mesh::_narrow( obj );
365       if ( ! mesh->_is_nil() )
366         return mesh->GetAutoColor();
367     }
368   }
369   return false;
370 }
371
372 //=======================================================================
373 //function : numberOfNodes
374 //purpose  : 
375 //=======================================================================
376
377 int SMESHGUI_Selection::numberOfNodes( int ind ) const
378 {
379   if ( ind >= 0 && ind < myTypes.count() && myTypes[ind] != "Unknown" )
380   {
381     _PTR(SObject) sobj = SMESH::GetActiveStudyDocument()->FindObjectID( entry( ind ).toLatin1().data() );
382     CORBA::Object_var obj = SMESH::SObjectToObject( sobj, SMESH::GetActiveStudyDocument() );
383
384     if ( ! CORBA::is_nil( obj )) {
385       SMESH::SMESH_Mesh_var mesh = SMESH::SMESH_Mesh::_narrow( obj );
386       if ( ! mesh->_is_nil() )
387         return mesh->NbNodes();
388       SMESH::SMESH_subMesh_var aSubMeshObj = SMESH::SMESH_subMesh::_narrow( obj );
389       if ( !aSubMeshObj->_is_nil() )
390         return aSubMeshObj->GetNumberOfNodes(true);
391       SMESH::SMESH_GroupBase_var aGroupObj = SMESH::SMESH_GroupBase::_narrow( obj );
392       if ( !aGroupObj->_is_nil() )
393         return aGroupObj->Size();
394     }
395   }
396   return 0;
397 }
398
399 //=======================================================================
400 //function : isComputable
401 //purpose  : 
402 //=======================================================================
403
404 QVariant SMESHGUI_Selection::isComputable( int ind ) const
405 {
406   if ( ind >= 0 && ind < myTypes.count() && myTypes[ind] != "Unknown" )
407   {
408 /*    Handle(SALOME_InteractiveObject) io =
409       static_cast<LightApp_DataOwner*>( myDataOwners[ ind ].get() )->IO();
410     if ( !io.IsNull() ) {
411       SMESH::SMESH_Mesh_var mesh = SMESH::GetMeshByIO(io); // m,sm,gr->m
412       if ( !mesh->_is_nil() ) {*/
413         _PTR(SObject) so = SMESH::GetActiveStudyDocument()->FindObjectID( entry( ind ).toLatin1().data() );
414         //FindSObject( mesh );
415         if ( so ) {
416           CORBA::Object_var obj = SMESH::SObjectToObject(so, SMESH::GetActiveStudyDocument());
417           if(!CORBA::is_nil(obj)){
418             SMESH::SMESH_Mesh_var mesh = SMESH::SMESH_Mesh::_narrow( obj );
419             if (!mesh->_is_nil()){
420               if(mesh->HasShapeToMesh()) {
421                 GEOM::GEOM_Object_var shape = SMESH::GetShapeOnMeshOrSubMesh( so );
422                 return QVariant( !shape->_is_nil() );
423               }
424               else
425               {
426                 return QVariant(!mesh->NbFaces()==0);
427               }
428             }
429             else
430             {
431               GEOM::GEOM_Object_var shape = SMESH::GetShapeOnMeshOrSubMesh( so );
432               return QVariant( !shape->_is_nil() );
433             }
434           }
435         }
436 //      }
437 //    }
438   }
439   return QVariant( false );
440 }
441
442 //=======================================================================
443 //function : isPreComputable
444 //purpose  : 
445 //=======================================================================
446
447 QVariant SMESHGUI_Selection::isPreComputable( int ind ) const
448 {
449   if ( ind >= 0 && ind < myTypes.count() && myTypes[ind] != "Unknown" )
450   {
451     QMap<int,int> modeMap;
452     _PTR(SObject) pMesh = SMESH::GetActiveStudyDocument()->FindObjectID( entry( ind ).toLatin1().data() );
453     SMESHGUI_PrecomputeOp::getAssignedAlgos( pMesh, modeMap );
454     return QVariant( modeMap.size() > 1 );
455   }
456   return QVariant( false );
457 }
458
459 //=======================================================================
460 //function : hasReference
461 //purpose  : 
462 //=======================================================================
463
464 QVariant SMESHGUI_Selection::hasReference( int ind ) const
465 {
466   return QVariant( isReference( ind ) );
467 }
468
469 //=======================================================================
470 //function : isVisible
471 //purpose  : 
472 //=======================================================================
473
474 QVariant SMESHGUI_Selection::isVisible( int ind ) const
475 {
476   if ( ind >= 0 && ind < myTypes.count() && myTypes[ind] != "Unknown" )
477   {
478     QString ent = entry( ind );
479     SMESH_Actor* actor = SMESH::FindActorByEntry( ent.toLatin1().data() );
480     if ( actor && actor->hasIO() ) {
481       if(SVTK_ViewWindow* aViewWindow = SMESH::GetCurrentVtkView())
482         return QVariant( aViewWindow->isVisible( actor->getIO() ) );
483     }
484   }
485   return QVariant( false );
486 }
487
488 //=======================================================================
489 //function : type
490 //purpose  : 
491 //=======================================================================
492
493 int SMESHGUI_Selection::type( const QString& entry, _PTR(Study) study )
494 {
495   _PTR(SObject) obj (study->FindObjectID(entry.toLatin1().data()));
496   if( !obj )
497     return -1;
498
499   _PTR(SObject) ref;
500   if( obj->ReferencedObject( ref ) )
501     obj = ref;
502
503   _PTR(SObject) objFather = obj->GetFather();
504   _PTR(SComponent) objComponent = obj->GetFatherComponent();
505
506   if( objComponent->ComponentDataType()!="SMESH" )
507     return -1;
508
509   if( objComponent->GetIOR()==obj->GetIOR() )
510     return COMPONENT;
511
512   int aLevel = obj->Depth() - objComponent->Depth(),
513       aFTag = objFather->Tag(),
514       anOTag = obj->Tag(),
515       res = -1;
516
517   switch (aLevel)
518   {
519   case 1:
520     if (anOTag >= SMESH::Tag_FirstMeshRoot)
521       res = MESH;
522     break;
523   case 2:
524     switch (aFTag)
525     {
526     case SMESH::Tag_HypothesisRoot:
527       res = HYPOTHESIS;
528       break;
529     case SMESH::Tag_AlgorithmsRoot:
530       res = ALGORITHM;
531       break;
532     }
533     break;
534   case 3:
535     switch (aFTag)
536     {
537     case SMESH::Tag_SubMeshOnVertex:
538       res = SUBMESH_VERTEX;
539       break;
540     case SMESH::Tag_SubMeshOnEdge:
541       res = SUBMESH_EDGE;
542       break;
543     case SMESH::Tag_SubMeshOnFace:
544       res = SUBMESH_FACE;
545       break;
546     case SMESH::Tag_SubMeshOnSolid:
547       res = SUBMESH_SOLID;
548       break;
549     case SMESH::Tag_SubMeshOnCompound:
550       res = SUBMESH_COMPOUND;
551       break;
552     default:
553       if (aFTag >= SMESH::Tag_FirstGroup)
554         res = GROUP;
555       else
556         res = SUBMESH;
557     }
558     break;
559   }
560
561   return res;
562 }
563
564 //=======================================================================
565 //function : typeName
566 //purpose  : 
567 //=======================================================================
568
569 QString SMESHGUI_Selection::typeName( const int t )
570 {
571   switch( t )
572   {
573   case HYPOTHESIS:
574     return "Hypothesis";
575   case ALGORITHM:
576     return "Algorithm";
577   case MESH:
578     return "Mesh";
579   case SUBMESH:
580     return "SubMesh";
581   case MESHorSUBMESH:
582     return "Mesh or submesh";
583   case SUBMESH_VERTEX:
584     return "Mesh vertex";
585   case SUBMESH_EDGE:
586     return "Mesh edge";
587   case SUBMESH_FACE:
588     return "Mesh face";
589   case SUBMESH_SOLID:
590     return "Mesh solid";
591   case SUBMESH_COMPOUND:
592     return "Mesh compound";
593   case GROUP:
594     return "Group";
595   case COMPONENT:
596     return "Component";
597   default:
598     return "Unknown";
599   }
600 }
601
602 bool SMESHGUI_Selection::isImported( const int ind ) const
603 {
604   QString e = entry( ind );
605   _PTR(SObject) SO = SMESH::GetActiveStudyDocument()->FindObjectID( e.toLatin1().constData() );
606   bool res = false;
607   if( SO )
608   {
609     SMESH::SMESH_Mesh_var aMesh = SMESH::SMESH_Mesh::_narrow( SMESH::SObjectToObject( SO ) );
610     if( !aMesh->_is_nil() )
611     {
612       SALOME_MED::MedFileInfo* inf = aMesh->GetMEDFileInfo();
613       res = strlen( (char*)inf->fileName ) > 0;
614     }
615   }
616   return res;
617 }
618
619 //=======================================================================
620 //function : groupType
621 //purpose  : 
622 //=======================================================================
623
624 QString SMESHGUI_Selection::groupType( int ind ) const
625 {
626   QString e = entry( ind );
627   _PTR(SObject) SO = SMESH::GetActiveStudyDocument()->FindObjectID( e.toLatin1().constData() );
628   QString type;
629   if( SO )
630   {
631     CORBA::Object_var obj = SMESH::SObjectToObject( SO );
632   
633     SMESH::SMESH_Group_var aGroup = SMESH::SMESH_Group::_narrow( obj );
634     SMESH::SMESH_GroupOnGeom_var aGroupOnGeom = SMESH::SMESH_GroupOnGeom::_narrow( obj );
635     if( !aGroup->_is_nil() )
636       type = QString( "Group" );
637     else if ( !aGroupOnGeom->_is_nil() )
638       type = QString( "GroupOnGeom" );
639   }
640   return type;
641 }