Salome HOME
Merge from OCC_development_generic_2006
[modules/geom.git] / src / GEOMImpl / GEOMImpl_IGroupOperations.cxx
1 // Copyright (C) 2005  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
2 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
3 // 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either 
7 // version 2.1 of the License.
8 // 
9 // This library is distributed in the hope that it will be useful 
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
12 // Lesser General Public License for more details.
13 //
14 // You should have received a copy of the GNU Lesser General Public  
15 // License along with this library; if not, write to the Free Software 
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
17 //
18 // See http://www.salome-platform.org/
19 //
20 #include <Standard_Stream.hxx>
21
22 #include <GEOMImpl_IGroupOperations.hxx>
23
24 #include <GEOMImpl_Types.hxx>
25
26 #include <GEOM_Function.hxx>
27 #include <GEOM_ISubShape.hxx>
28 #include <GEOM_PythonDump.hxx>
29
30 #include "utilities.h"
31 #include <OpUtil.hxx>
32 #include <Utils_ExceptHandlers.hxx>
33
34 #include <TFunction_DriverTable.hxx>
35 #include <TFunction_Driver.hxx>
36 #include <TFunction_Logbook.hxx>
37 #include <TDF_Tool.hxx>
38 #include <TDataStd_Integer.hxx>
39
40 #include <TopExp.hxx>
41 #include <TopTools_IndexedMapOfShape.hxx>
42
43 #include <TColStd_HArray1OfInteger.hxx>
44 #include <TColStd_MapOfInteger.hxx>
45 #include <TColStd_ListOfInteger.hxx>
46 #include <TColStd_ListIteratorOfListOfInteger.hxx>
47
48 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
49
50 //=============================================================================
51 /*!
52  *   constructor:
53  */
54 //=============================================================================
55 GEOMImpl_IGroupOperations::GEOMImpl_IGroupOperations (GEOM_Engine* theEngine, int theDocID) 
56 : GEOM_IOperations(theEngine, theDocID)
57 {
58   MESSAGE("GEOMImpl_IGroupOperations::GEOMImpl_IGroupOperations");
59 }
60
61 //=============================================================================
62 /*!
63  *  destructor
64  */
65 //=============================================================================
66 GEOMImpl_IGroupOperations::~GEOMImpl_IGroupOperations()
67 {
68   MESSAGE("GEOMImpl_IGroupOperations::~GEOMImpl_IGroupOperations");
69 }
70
71
72 //=============================================================================
73 /*!
74  *  CreateGroup
75  */
76 //=============================================================================
77 Handle(GEOM_Object) GEOMImpl_IGroupOperations::CreateGroup
78        (Handle(GEOM_Object) theMainShape, TopAbs_ShapeEnum  theShapeType)
79 {
80   SetErrorCode(KO);
81
82   Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
83   anArray->SetValue(1, -1);
84
85   //Add a new Fillet object
86   Handle(GEOM_Object) aGroup = GetEngine()->AddSubShape(theMainShape, anArray);
87
88   //Set a GROUP type
89   aGroup->SetType(GEOM_GROUP);
90
91   //Set a sub shape type
92   TDF_Label aFreeLabel = aGroup->GetFreeLabel();
93   TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)theShapeType);
94
95   //Make a Python command
96   Handle(GEOM_Function) aFunction = aGroup->GetFunction(1);
97   //TCollection_AsciiString anOldDescr = aFunction->GetDescription();
98
99   //GEOM::TPythonDump(aFunction) << anOldDescr.ToCString() << "\n\t" << aGroup
100   GEOM::TPythonDump(aFunction) << aGroup
101     << " = geompy.CreateGroup(" << theMainShape << ", " << (int)theShapeType << ")";
102
103   SetErrorCode(OK);
104   return aGroup; 
105 }
106
107 //=============================================================================
108 /*!
109  *  AddObject
110  */
111 //=============================================================================
112 void GEOMImpl_IGroupOperations::AddObject(Handle(GEOM_Object) theGroup, int theSubShapeID)
113 {
114   SetErrorCode(KO);
115   if(theGroup.IsNull()) return;
116
117   Handle(GEOM_Function) aFunction = theGroup->GetFunction(1);
118   if(aFunction.IsNull()) return;
119
120   GEOM_ISubShape aSSI (aFunction);
121
122   // Check sub-shape index validity
123   TDF_Label aLabel = aSSI.GetMainShape()->GetOwnerEntry();
124   if (aLabel.IsRoot()) return;
125   Handle(GEOM_Object) anObj = GEOM_Object::GetObject(aLabel);
126   if (anObj.IsNull()) return;
127   TopoDS_Shape aMainShape = anObj->GetValue();
128   if (aMainShape.IsNull()) return;
129
130   TopTools_IndexedMapOfShape aMapOfShapes;
131   TopExp::MapShapes(aMainShape, aMapOfShapes);
132
133   if (theSubShapeID < 1 || aMapOfShapes.Extent() < theSubShapeID) {
134     SetErrorCode("Invalid sub-shape index: out of range");
135     return;
136   }
137
138   // Add sub-shape index
139   Handle(TColStd_HArray1OfInteger) aSeq = aSSI.GetIndices();
140   if(aSeq.IsNull()) return;
141   if(aSeq->Length() == 1 && aSeq->Value(1) == -1) {
142     aSeq->SetValue(1, theSubShapeID);
143   }
144   else {
145     Standard_Integer aLength = aSeq->Length();
146     Handle(TColStd_HArray1OfInteger) aNewSeq = new TColStd_HArray1OfInteger(1, aLength+1);
147     for(Standard_Integer i = 1; i<=aLength; i++) {
148       aNewSeq->SetValue(i, aSeq->Value(i));
149       if(aSeq->Value(i) == theSubShapeID) {
150         SetErrorCode(ALREADY_PRESENT);
151         return; //
152       }
153     }
154     aNewSeq->SetValue(aLength+1, theSubShapeID);
155     aSSI.SetIndices(aNewSeq);
156   }
157
158   //Make a Python command
159   TCollection_AsciiString anOldDescr = aFunction->GetDescription();
160
161   GEOM::TPythonDump(aFunction) << anOldDescr.ToCString() << "\n\t"
162     << "geompy.AddObject(" << theGroup << ", " << theSubShapeID << ")";
163
164   SetErrorCode(OK);
165   return;
166 }
167
168 //=============================================================================
169 /*!
170  *  RemoveObject
171  */
172 //=============================================================================
173 void GEOMImpl_IGroupOperations::RemoveObject (Handle(GEOM_Object) theGroup, int theSubShapeID)
174 {
175   SetErrorCode(KO);
176   if(theGroup.IsNull()) return;
177
178   Handle(GEOM_Function) aFunction = theGroup->GetFunction(1);
179   if(aFunction.IsNull()) return;
180
181   GEOM_ISubShape aSSI(aFunction);
182   Handle(TColStd_HArray1OfInteger) aSeq = aSSI.GetIndices();
183   if(aSeq.IsNull()) return;
184   if(aSeq->Length() == 1 && aSeq->Value(1) == -1) {
185     SetErrorCode(NOT_EXISTS);
186     return;
187   }
188   else {
189     Handle(TColStd_HArray1OfInteger) aNewSeq;
190     Standard_Integer aLength = aSeq->Length();
191     if(aLength == 1) {
192       if(aSeq->Value(1) != theSubShapeID) {
193         SetErrorCode(NOT_EXISTS);
194         return;         
195       }
196       aNewSeq = new TColStd_HArray1OfInteger(1,1);
197       aNewSeq->SetValue(1, -1);
198     }
199     else {
200       aNewSeq = new TColStd_HArray1OfInteger(1, aLength-1);
201       Standard_Boolean isFound = Standard_False;
202       for(Standard_Integer i = 1, k=1; i<=aLength; i++) {
203         if(i == aLength && !isFound) {
204           SetErrorCode(NOT_EXISTS);
205           return; 
206         }
207         if(aSeq->Value(i) == theSubShapeID) {
208           isFound = Standard_True;
209           continue;
210         }
211         aNewSeq->SetValue(k, aSeq->Value(i));
212         k++;
213       }
214
215       if(!isFound) {
216         SetErrorCode(NOT_EXISTS);
217         return; 
218       }
219     }
220
221     aSSI.SetIndices(aNewSeq);
222   }
223
224   //Make a Python command 
225   TCollection_AsciiString anOldDescr = aFunction->GetDescription();
226
227   GEOM::TPythonDump(aFunction) << anOldDescr.ToCString() << "\n\t"
228     << "geompy.RemoveObject(" << theGroup << ", " << theSubShapeID << ")";
229
230   SetErrorCode(OK);
231   return; 
232 }
233
234 //=============================================================================
235 /*!
236  *  UnionList
237  */
238 //=============================================================================
239 void GEOMImpl_IGroupOperations::UnionList (Handle(GEOM_Object) theGroup,
240                                            const Handle(TColStd_HSequenceOfTransient)& theSubShapes)
241 {
242   SetErrorCode(KO);
243   if (theGroup.IsNull()) return;
244
245   Handle(GEOM_Function) aFunction = theGroup->GetFunction(1);
246   if (aFunction.IsNull()) return;
247
248   GEOM_ISubShape aSSI (aFunction);
249
250   // New contents of the group
251   TColStd_ListOfInteger aNewIDs;
252   TColStd_MapOfInteger mapIDs;
253
254   // Add current IDs to the list
255   Handle(TColStd_HArray1OfInteger) aSeq = aSSI.GetIndices();
256   if (aSeq.IsNull()) return;
257   Standard_Integer val_j, aLength = aSeq->Length();
258
259   for (Standard_Integer j = 1; j <= aLength; j++) {
260     val_j = aSeq->Value(j);
261     if (val_j > 0 && mapIDs.Add(val_j)) {
262       aNewIDs.Append(val_j);
263     }
264   }
265
266   // Get Main Shape
267   Handle(GEOM_Function) aMainShapeFunc = aSSI.GetMainShape();
268   if (aMainShapeFunc.IsNull()) return;
269   TDF_Label aLabel = aMainShapeFunc->GetOwnerEntry();
270   if (aLabel.IsRoot()) return;
271   Handle(GEOM_Object) aMainObj = GEOM_Object::GetObject(aLabel);
272   if (aMainObj.IsNull()) return;
273   TopoDS_Shape aMainShape = aMainObj->GetValue();
274   if (aMainShape.IsNull()) return;
275
276   TopTools_IndexedMapOfShape mapIndices;
277   TopExp::MapShapes(aMainShape, mapIndices);
278
279   // Get IDs of sub-shapes to add
280   Standard_Integer i, new_id, aLen = theSubShapes->Length();
281   for (i = 1; i <= aLen; i++) {
282     Handle(GEOM_Object) anObj_i = Handle(GEOM_Object)::DownCast(theSubShapes->Value(i));
283
284     if (anObj_i->IsMainShape()) {
285       TopoDS_Shape aShape_i = anObj_i->GetValue();
286       if (mapIndices.Contains(aShape_i)) {
287         new_id = mapIndices.FindIndex(aShape_i);
288         if (mapIDs.Add(new_id)) {
289           aNewIDs.Append(new_id);
290         }
291       } else {
292         SetErrorCode("One of given objects can not be added to the group, because it is not a sub-shape of the group's main shape");
293         return;
294       }
295     } else {
296       // Check main shape of sub-shape to add
297       Handle(GEOM_Function) aFunc_i = anObj_i->GetFunction(1);
298       if (aFunc_i.IsNull()) return;
299
300       GEOM_ISubShape aSSI_i (aFunc_i);
301
302       Handle(GEOM_Function) aMainShapeFunc_i = aSSI_i.GetMainShape();
303       if (aMainShapeFunc_i.IsNull()) return;
304       TDF_Label aLabel_i = aMainShapeFunc_i->GetOwnerEntry();
305       if (aLabel_i.IsRoot()) return;
306       Handle(GEOM_Object) aMainObj_i = GEOM_Object::GetObject(aLabel);
307       if (aMainObj_i.IsNull()) return;
308       TopoDS_Shape aMainShape_i = aMainObj_i->GetValue();
309       if (aMainShape_i.IsNull()) return;
310
311       if (aMainShape_i.IsSame(aMainShape)) {
312         // add all sub-shape IDs to the list
313
314         // Get IDs
315         Handle(TColStd_HArray1OfInteger) aSeq_i = aSSI_i.GetIndices();
316         if (aSeq_i.IsNull()) return;
317         Standard_Integer aLength_i = aSeq_i->Length();
318
319         for (Standard_Integer i_j = 1; i_j <= aLength_i; i_j++) {
320           new_id = aSeq_i->Value(i_j);
321           if (new_id > 0) {
322             if (mapIDs.Add(new_id)) {
323               aNewIDs.Append(new_id);
324             }
325           }
326         }
327
328       } else if (mapIndices.Contains(aMainShape_i)) {
329         // compute new IDs and add them to the list
330         TopTools_IndexedMapOfShape mapIndices_i;
331         TopExp::MapShapes(aMainShape_i, mapIndices_i);
332
333         // Get IDs
334         Handle(TColStd_HArray1OfInteger) aSeq_i = aSSI_i.GetIndices();
335         if (aSeq_i.IsNull()) return;
336         Standard_Integer aLength_i = aSeq_i->Length();
337
338         for (Standard_Integer i_j = 1; i_j <= aLength_i; i_j++) {
339           if (aSeq_i->Value(i_j) > 0) {
340             TopoDS_Shape aShape_i_j = mapIndices_i.FindKey(i_j);
341             new_id = mapIndices.FindIndex(aShape_i_j);
342             if (mapIDs.Add(new_id)) {
343               aNewIDs.Append(new_id);
344             }
345           }
346         }
347
348       } else {
349         SetErrorCode("One of given objects can not be added to the group, because it is not a sub-shape of the group's main shape");
350         return;
351       }
352     }
353   }
354
355   if (aNewIDs.Extent() > 0) {
356     Standard_Integer k = 1;
357     TColStd_ListIteratorOfListOfInteger aNewIDsIter (aNewIDs);
358     Handle(TColStd_HArray1OfInteger) aNewSeq = new TColStd_HArray1OfInteger(1, aNewIDs.Extent());
359     for (; aNewIDsIter.More(); aNewIDsIter.Next(), k++) {
360       aNewSeq->SetValue(k, aNewIDsIter.Value());
361     }
362
363     aSSI.SetIndices(aNewSeq);
364   }
365
366   //Make a Python command 
367   TCollection_AsciiString anOldDescr = aFunction->GetDescription();
368
369   GEOM::TPythonDump pd (aFunction);
370   pd << anOldDescr.ToCString() << "\n\t" << "geompy.UnionList(" << theGroup << ", [";
371
372   for (i = 1; i <= aLen; i++) {
373     Handle(GEOM_Object) anObj_i = Handle(GEOM_Object)::DownCast(theSubShapes->Value(i));
374     pd << anObj_i << (( i < aLen ) ? ", " : "])");
375   }
376
377   SetErrorCode(OK);
378 }
379
380 //=============================================================================
381 /*!
382  *  DifferenceList
383  */
384 //=============================================================================
385 void GEOMImpl_IGroupOperations::DifferenceList (Handle(GEOM_Object) theGroup,
386                                                 const Handle(TColStd_HSequenceOfTransient)& theSubShapes)
387 {
388   SetErrorCode(KO);
389   if (theGroup.IsNull()) return;
390
391   Handle(GEOM_Function) aFunction = theGroup->GetFunction(1);
392   if (aFunction.IsNull()) return;
393
394   GEOM_ISubShape aSSI (aFunction);
395
396   // Map of IDs to be removed
397   TColStd_MapOfInteger mapIDsToRemove;
398
399   // Map of current IDs
400   Handle(TColStd_HArray1OfInteger) aSeq = aSSI.GetIndices();
401   if (aSeq.IsNull()) return;
402   Standard_Integer aLength = aSeq->Length();
403
404   if (aLength == 1 && aSeq->Value(1) == -1) // empty group
405     return;
406
407   TColStd_MapOfInteger mapIDsCurrent;
408   Standard_Integer j = 1;
409   for (; j <= aLength; j++) {
410     mapIDsCurrent.Add(aSeq->Value(j));
411   }
412
413   // Get Main Shape
414   Handle(GEOM_Function) aMainShapeFunc = aSSI.GetMainShape();
415   if (aMainShapeFunc.IsNull()) return;
416   TDF_Label aLabel = aMainShapeFunc->GetOwnerEntry();
417   if (aLabel.IsRoot()) return;
418   Handle(GEOM_Object) aMainObj = GEOM_Object::GetObject(aLabel);
419   if (aMainObj.IsNull()) return;
420   TopoDS_Shape aMainShape = aMainObj->GetValue();
421   if (aMainShape.IsNull()) return;
422
423   TopTools_IndexedMapOfShape mapIndices;
424   TopExp::MapShapes(aMainShape, mapIndices);
425
426   // Get IDs of sub-shapes to be removed
427   Standard_Integer i, rem_id, aLen = theSubShapes->Length();
428   for (i = 1; i <= aLen; i++) {
429     Handle(GEOM_Object) anObj_i = Handle(GEOM_Object)::DownCast(theSubShapes->Value(i));
430
431     if (anObj_i->IsMainShape()) {
432       TopoDS_Shape aShape_i = anObj_i->GetValue();
433       if (mapIndices.Contains(aShape_i)) {
434         rem_id = mapIndices.FindIndex(aShape_i);
435         if (mapIDsCurrent.Contains(rem_id)) {
436           mapIDsToRemove.Add(rem_id);
437         }
438       } else {
439         SetErrorCode("One of given objects can not be removed from the group, because it is not a sub-shape of the group's main shape");
440         return;
441       }
442     } else {
443       // Check main shape of sub-shape to be removed
444       Handle(GEOM_Function) aFunc_i = anObj_i->GetFunction(1);
445       if (aFunc_i.IsNull()) return;
446
447       GEOM_ISubShape aSSI_i (aFunc_i);
448
449       Handle(GEOM_Function) aMainShapeFunc_i = aSSI_i.GetMainShape();
450       if (aMainShapeFunc_i.IsNull()) return;
451       TDF_Label aLabel_i = aMainShapeFunc_i->GetOwnerEntry();
452       if (aLabel_i.IsRoot()) return;
453       Handle(GEOM_Object) aMainObj_i = GEOM_Object::GetObject(aLabel);
454       if (aMainObj_i.IsNull()) return;
455       TopoDS_Shape aMainShape_i = aMainObj_i->GetValue();
456       if (aMainShape_i.IsNull()) return;
457
458       if (aMainShape_i.IsSame(aMainShape)) {
459         // remove all sub-shapes
460
461         // Get IDs
462         Handle(TColStd_HArray1OfInteger) aSeq_i = aSSI_i.GetIndices();
463         if (aSeq_i.IsNull()) return;
464         Standard_Integer aLength_i = aSeq_i->Length();
465
466         for (Standard_Integer i_j = 1; i_j <= aLength_i; i_j++) {
467           rem_id = aSeq_i->Value(i_j);
468           if (rem_id > 0) {
469             if (mapIDsCurrent.Contains(rem_id)) {
470               mapIDsToRemove.Add(rem_id);
471             }
472           }
473         }
474
475       } else if (mapIndices.Contains(aMainShape_i)) {
476         // compute new IDs and add them to the map of ids to be removed
477         TopTools_IndexedMapOfShape mapIndices_i;
478         TopExp::MapShapes(aMainShape_i, mapIndices_i);
479
480         // Get IDs
481         Handle(TColStd_HArray1OfInteger) aSeq_i = aSSI_i.GetIndices();
482         if (aSeq_i.IsNull()) return;
483         Standard_Integer aLength_i = aSeq_i->Length();
484
485         for (Standard_Integer i_j = 1; i_j <= aLength_i; i_j++) {
486           if (aSeq_i->Value(i_j) > 0) {
487             TopoDS_Shape aShape_i_j = mapIndices_i.FindKey(i_j);
488             rem_id = mapIndices.FindIndex(aShape_i_j);
489             if (mapIDsCurrent.Contains(rem_id)) {
490               mapIDsToRemove.Add(rem_id);
491             }
492           }
493         }
494
495       } else {
496         SetErrorCode("One of given objects can not be removed from the group, because it is not a sub-shape of the group's main shape");
497         return;
498       }
499     }
500   }
501
502   if (mapIDsToRemove.Extent() > 0) {
503     Standard_Integer k = 1, aRemLength = mapIDsToRemove.Extent();
504     Handle(TColStd_HArray1OfInteger) aNewSeq = new TColStd_HArray1OfInteger(1, aLength - aRemLength);
505
506     for (j = 1; j <= aLength; j++) {
507       if (!mapIDsToRemove.Contains(aSeq->Value(j))) {
508         aNewSeq->SetValue(k, aSeq->Value(j));
509         k++;
510       }
511     }
512
513     aSSI.SetIndices(aNewSeq);
514   }
515
516   //Make a Python command
517   TCollection_AsciiString anOldDescr = aFunction->GetDescription();
518
519   GEOM::TPythonDump pd (aFunction);
520   pd << anOldDescr.ToCString() << "\n\t" << "geompy.DifferenceList(" << theGroup << ", [";
521
522   for (i = 1; i <= aLen; i++) {
523     Handle(GEOM_Object) anObj_i = Handle(GEOM_Object)::DownCast(theSubShapes->Value(i));
524     pd << anObj_i << (( i < aLen ) ? ", " : "])");
525   }
526
527   SetErrorCode(OK);
528 }
529 //=============================================================================
530 /*!
531  *  UnionIDs
532  */
533 //=============================================================================
534 void GEOMImpl_IGroupOperations::UnionIDs (Handle(GEOM_Object) theGroup,
535                                           const Handle(TColStd_HSequenceOfInteger)& theSubShapes)
536 {
537   SetErrorCode(KO);
538   if (theGroup.IsNull()) return;
539
540   Handle(GEOM_Function) aFunction = theGroup->GetFunction(1);
541   if (aFunction.IsNull()) return;
542
543   GEOM_ISubShape aSSI (aFunction);
544
545   // New contents of the group
546   TColStd_ListOfInteger aNewIDs;
547   TColStd_MapOfInteger mapIDs;
548
549   // Add current IDs to the list
550   Handle(TColStd_HArray1OfInteger) aSeq = aSSI.GetIndices();
551   if (aSeq.IsNull()) return;
552   Standard_Integer val_j, aLength = aSeq->Length();
553
554   for (Standard_Integer j = 1; j <= aLength; j++) {
555     val_j = aSeq->Value(j);
556     if (val_j > 0 && mapIDs.Add(val_j)) {
557       aNewIDs.Append(val_j);
558     }
559   }
560
561   // Get Main Shape
562   Handle(GEOM_Function) aMainShapeFunc = aSSI.GetMainShape();
563   if (aMainShapeFunc.IsNull()) return;
564   TDF_Label aLabel = aMainShapeFunc->GetOwnerEntry();
565   if (aLabel.IsRoot()) return;
566   Handle(GEOM_Object) aMainObj = GEOM_Object::GetObject(aLabel);
567   if (aMainObj.IsNull()) return;
568   TopoDS_Shape aMainShape = aMainObj->GetValue();
569   if (aMainShape.IsNull()) return;
570
571   TopTools_IndexedMapOfShape mapIndices;
572   TopExp::MapShapes(aMainShape, mapIndices);
573
574   // Get IDs of sub-shapes to add
575   Standard_Integer i, new_id, aLen = theSubShapes->Length();
576   for (i = 1; i <= aLen; i++) {
577     new_id = theSubShapes->Value(i);
578
579     if (0 < new_id && new_id <= mapIndices.Extent()) {
580       if (mapIDs.Add(new_id)) {
581         aNewIDs.Append(new_id);
582       }
583     }
584   }
585
586   if (aNewIDs.Extent() > 0) {
587     Standard_Integer k = 1;
588     TColStd_ListIteratorOfListOfInteger aNewIDsIter (aNewIDs);
589     Handle(TColStd_HArray1OfInteger) aNewSeq = new TColStd_HArray1OfInteger(1, aNewIDs.Extent());
590     for (; aNewIDsIter.More(); aNewIDsIter.Next(), k++) {
591       aNewSeq->SetValue(k, aNewIDsIter.Value());
592     }
593
594     aSSI.SetIndices(aNewSeq);
595   }
596
597   SetErrorCode(OK);
598 }
599
600 //=============================================================================
601 /*!
602  *  DifferenceIDs
603  */
604 //=============================================================================
605 void GEOMImpl_IGroupOperations::DifferenceIDs (Handle(GEOM_Object) theGroup,
606                                                const Handle(TColStd_HSequenceOfInteger)& theSubShapes)
607 {
608   SetErrorCode(KO);
609   if (theGroup.IsNull()) return;
610
611   Handle(GEOM_Function) aFunction = theGroup->GetFunction(1);
612   if (aFunction.IsNull()) return;
613
614   GEOM_ISubShape aSSI (aFunction);
615
616   // Map of IDs to be removed
617   TColStd_MapOfInteger mapIDsToRemove;
618
619   // Map of current IDs
620   Handle(TColStd_HArray1OfInteger) aSeq = aSSI.GetIndices();
621   if (aSeq.IsNull()) return;
622   Standard_Integer aLength = aSeq->Length();
623
624   if (aLength == 1 && aSeq->Value(1) == -1) // empty group
625     return;
626
627   TColStd_MapOfInteger mapIDsCurrent;
628   Standard_Integer j = 1;
629   for (; j <= aLength; j++) {
630     mapIDsCurrent.Add(aSeq->Value(j));
631   }
632
633   // Get Main Shape
634   Handle(GEOM_Function) aMainShapeFunc = aSSI.GetMainShape();
635   if (aMainShapeFunc.IsNull()) return;
636   TDF_Label aLabel = aMainShapeFunc->GetOwnerEntry();
637   if (aLabel.IsRoot()) return;
638   Handle(GEOM_Object) aMainObj = GEOM_Object::GetObject(aLabel);
639   if (aMainObj.IsNull()) return;
640   TopoDS_Shape aMainShape = aMainObj->GetValue();
641   if (aMainShape.IsNull()) return;
642
643   TopTools_IndexedMapOfShape mapIndices;
644   TopExp::MapShapes(aMainShape, mapIndices);
645
646   // Get IDs of sub-shapes to be removed
647   Standard_Integer i, rem_id, aLen = theSubShapes->Length();
648   for (i = 1; i <= aLen; i++) {
649     rem_id = theSubShapes->Value(i);
650     if (mapIDsCurrent.Contains(rem_id)) {
651       mapIDsToRemove.Add(rem_id);
652     }
653   }
654
655   if (mapIDsToRemove.Extent() > 0) {
656     Standard_Integer k = 1, aRemLength = mapIDsToRemove.Extent();
657     Handle(TColStd_HArray1OfInteger) aNewSeq = new TColStd_HArray1OfInteger(1, aLength - aRemLength);
658
659     for (j = 1; j <= aLength; j++) {
660       if (!mapIDsToRemove.Contains(aSeq->Value(j))) {
661         aNewSeq->SetValue(k, aSeq->Value(j));
662         k++;
663       }
664     }
665
666     aSSI.SetIndices(aNewSeq);
667   }
668
669   SetErrorCode(OK);
670 }
671
672 //=============================================================================
673 /*!
674  *  GetType
675  */
676 //=============================================================================
677 TopAbs_ShapeEnum GEOMImpl_IGroupOperations::GetType(Handle(GEOM_Object) theGroup)
678 {
679   SetErrorCode(KO);
680
681   TDF_Label aFreeLabel = theGroup->GetFreeLabel();
682   Handle(TDataStd_Integer) anAttrib;
683   if(!aFreeLabel.FindAttribute(TDataStd_Integer::GetID(), anAttrib)) return TopAbs_SHAPE;
684  
685   SetErrorCode(OK);
686   return (TopAbs_ShapeEnum) anAttrib->Get(); 
687 }
688
689 //=============================================================================
690 /*!
691  *  GetMainShape
692  */
693 //=============================================================================
694 Handle(GEOM_Object) GEOMImpl_IGroupOperations::GetMainShape (Handle(GEOM_Object) theGroup)
695 {
696   SetErrorCode(KO);
697
698   if(theGroup.IsNull()) return NULL;
699
700   Handle(GEOM_Function) aGroupFunction = theGroup->GetFunction(1);
701   if (aGroupFunction.IsNull()) return NULL;
702
703   GEOM_ISubShape aSSI (aGroupFunction);
704   Handle(GEOM_Function) aMainShapeFunction = aSSI.GetMainShape();
705   if (aMainShapeFunction.IsNull()) return NULL;
706
707   TDF_Label aLabel = aMainShapeFunction->GetOwnerEntry();
708   Handle(GEOM_Object) aMainShape = GEOM_Object::GetObject(aLabel);
709   if (aMainShape.IsNull()) return NULL;
710
711   //Make a Python command
712   TCollection_AsciiString anOldDescr = aGroupFunction->GetDescription();
713
714   GEOM::TPythonDump(aGroupFunction) << anOldDescr.ToCString() << "\n\t"
715     << aMainShape << " = geompy.GetMainShape(" << theGroup << ")";
716
717   SetErrorCode(OK);
718   return aMainShape; 
719 }
720
721 //=============================================================================
722 /*!
723  *  GetObjects
724  */
725 //=============================================================================
726 Handle(TColStd_HArray1OfInteger) GEOMImpl_IGroupOperations::GetObjects(Handle(GEOM_Object) theGroup)
727 {
728   SetErrorCode(KO);
729   
730    if(theGroup.IsNull()) return NULL;
731
732   Handle(GEOM_Function) aFunction = theGroup->GetFunction(1);
733   if(aFunction.IsNull()) return NULL;
734   
735   GEOM_ISubShape aSSI(aFunction);
736   Handle(TColStd_HArray1OfInteger) aSeq = aSSI.GetIndices();
737   if(aSeq.IsNull()) return NULL;
738
739   if(aSeq->Length() == 1 && aSeq->Value(1) == -1) {
740     SetErrorCode(OK);
741     return NULL;
742   }
743
744   SetErrorCode(OK);
745   return aSeq;
746 }