]> SALOME platform Git repositories - modules/geom.git/blob - src/GEOMImpl/GEOMImpl_IGroupOperations.cxx
Salome HOME
Join modifications from branch OCC_development_for_3_2_0a2
[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
98   GEOM::TPythonDump(aFunction) << aGroup
99     << " = geompy.CreateGroup(" << theMainShape << ", " << theShapeType << ")";
100
101   SetErrorCode(OK);
102   return aGroup;
103 }
104
105 //=============================================================================
106 /*!
107  *  AddObject
108  */
109 //=============================================================================
110 void GEOMImpl_IGroupOperations::AddObject(Handle(GEOM_Object) theGroup, int theSubShapeID)
111 {
112   SetErrorCode(KO);
113   if(theGroup.IsNull()) return;
114
115   Handle(GEOM_Function) aFunction = theGroup->GetFunction(1);
116   if(aFunction.IsNull()) return;
117
118   GEOM_ISubShape aSSI (aFunction);
119
120   // Check sub-shape index validity
121   TDF_Label aLabel = aSSI.GetMainShape()->GetOwnerEntry();
122   if (aLabel.IsRoot()) return;
123   Handle(GEOM_Object) anObj = GEOM_Object::GetObject(aLabel);
124   if (anObj.IsNull()) return;
125   TopoDS_Shape aMainShape = anObj->GetValue();
126   if (aMainShape.IsNull()) return;
127
128   TopTools_IndexedMapOfShape aMapOfShapes;
129   TopExp::MapShapes(aMainShape, aMapOfShapes);
130
131   if (theSubShapeID < 1 || aMapOfShapes.Extent() < theSubShapeID) {
132     SetErrorCode("Invalid sub-shape index: out of range");
133     return;
134   }
135
136   // Add sub-shape index
137   Handle(TColStd_HArray1OfInteger) aSeq = aSSI.GetIndices();
138   if(aSeq.IsNull()) return;
139   if(aSeq->Length() == 1 && aSeq->Value(1) == -1) {
140     aSeq->SetValue(1, theSubShapeID);
141   }
142   else {
143     Standard_Integer aLength = aSeq->Length();
144     Handle(TColStd_HArray1OfInteger) aNewSeq = new TColStd_HArray1OfInteger(1, aLength+1);
145     for(Standard_Integer i = 1; i<=aLength; i++) {
146       aNewSeq->SetValue(i, aSeq->Value(i));
147       if(aSeq->Value(i) == theSubShapeID) {
148         SetErrorCode(ALREADY_PRESENT);
149         return; //
150       }
151     }
152     aNewSeq->SetValue(aLength+1, theSubShapeID);
153     aSSI.SetIndices(aNewSeq);
154   }
155
156   //Make a Python command
157   GEOM::TPythonDump(aFunction, /*append=*/true)
158     << "geompy.AddObject(" << theGroup << ", " << theSubShapeID << ")";
159
160   SetErrorCode(OK);
161   return;
162 }
163
164 //=============================================================================
165 /*!
166  *  RemoveObject
167  */
168 //=============================================================================
169 void GEOMImpl_IGroupOperations::RemoveObject (Handle(GEOM_Object) theGroup, int theSubShapeID)
170 {
171   SetErrorCode(KO);
172   if(theGroup.IsNull()) return;
173
174   Handle(GEOM_Function) aFunction = theGroup->GetFunction(1);
175   if(aFunction.IsNull()) return;
176
177   GEOM_ISubShape aSSI(aFunction);
178   Handle(TColStd_HArray1OfInteger) aSeq = aSSI.GetIndices();
179   if(aSeq.IsNull()) return;
180   if(aSeq->Length() == 1 && aSeq->Value(1) == -1) {
181     SetErrorCode(NOT_EXISTS);
182     return;
183   }
184   else {
185     Handle(TColStd_HArray1OfInteger) aNewSeq;
186     Standard_Integer aLength = aSeq->Length();
187     if(aLength == 1) {
188       if(aSeq->Value(1) != theSubShapeID) {
189         SetErrorCode(NOT_EXISTS);
190         return;         
191       }
192       aNewSeq = new TColStd_HArray1OfInteger(1,1);
193       aNewSeq->SetValue(1, -1);
194     }
195     else {
196       aNewSeq = new TColStd_HArray1OfInteger(1, aLength-1);
197       Standard_Boolean isFound = Standard_False;
198       for(Standard_Integer i = 1, k=1; i<=aLength; i++) {
199         if(i == aLength && !isFound) {
200           SetErrorCode(NOT_EXISTS);
201           return; 
202         }
203         if(aSeq->Value(i) == theSubShapeID) {
204           isFound = Standard_True;
205           continue;
206         }
207         aNewSeq->SetValue(k, aSeq->Value(i));
208         k++;
209       }
210
211       if(!isFound) {
212         SetErrorCode(NOT_EXISTS);
213         return; 
214       }
215     }
216
217     aSSI.SetIndices(aNewSeq);
218   }
219
220   //Make a Python command 
221   GEOM::TPythonDump(aFunction, /*append=*/true)
222     << "geompy.RemoveObject(" << theGroup << ", " << theSubShapeID << ")";
223
224   SetErrorCode(OK);
225   return; 
226 }
227
228 //=============================================================================
229 /*!
230  *  UnionList
231  */
232 //=============================================================================
233 void GEOMImpl_IGroupOperations::UnionList (Handle(GEOM_Object) theGroup,
234                                            const Handle(TColStd_HSequenceOfTransient)& theSubShapes)
235 {
236   SetErrorCode(KO);
237   if (theGroup.IsNull()) return;
238
239   Standard_Integer aLen = theSubShapes->Length();
240   if (aLen < 1) {
241     SetErrorCode("The list is empty");
242     return;
243   }
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;
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   Handle(GEOM_Object) aLatest = GEOM::GetCreatedLast(theSubShapes);
368   aLatest = GEOM::GetCreatedLast(aLatest, theGroup);
369   Handle(GEOM_Function) aLastFunc = aLatest->GetLastFunction();
370
371   GEOM::TPythonDump pd (aLastFunc, /*append=*/true);
372   pd << "geompy.UnionList(" << theGroup << ", [";
373
374   for (i = 1; i <= aLen; i++) {
375     Handle(GEOM_Object) anObj_i = Handle(GEOM_Object)::DownCast(theSubShapes->Value(i));
376     pd << anObj_i << (( i < aLen ) ? ", " : "])");
377   }
378
379   SetErrorCode(OK);
380 }
381
382 //=============================================================================
383 /*!
384  *  DifferenceList
385  */
386 //=============================================================================
387 void GEOMImpl_IGroupOperations::DifferenceList (Handle(GEOM_Object) theGroup,
388                                                 const Handle(TColStd_HSequenceOfTransient)& theSubShapes)
389 {
390   SetErrorCode(KO);
391   if (theGroup.IsNull()) return;
392
393   Standard_Integer aLen = theSubShapes->Length();
394   if (aLen < 1) {
395     SetErrorCode("The list is empty");
396     return;
397   }
398
399   Handle(GEOM_Function) aFunction = theGroup->GetFunction(1);
400   if (aFunction.IsNull()) return;
401
402   GEOM_ISubShape aSSI (aFunction);
403
404   // Map of IDs to be removed
405   TColStd_MapOfInteger mapIDsToRemove;
406
407   // Map of current IDs
408   Handle(TColStd_HArray1OfInteger) aSeq = aSSI.GetIndices();
409   if (aSeq.IsNull()) return;
410   Standard_Integer aLength = aSeq->Length();
411
412   if (aLength == 1 && aSeq->Value(1) == -1) // empty group
413     return;
414
415   TColStd_MapOfInteger mapIDsCurrent;
416   Standard_Integer j = 1;
417   for (; j <= aLength; j++) {
418     mapIDsCurrent.Add(aSeq->Value(j));
419   }
420
421   // Get Main Shape
422   Handle(GEOM_Function) aMainShapeFunc = aSSI.GetMainShape();
423   if (aMainShapeFunc.IsNull()) return;
424   TDF_Label aLabel = aMainShapeFunc->GetOwnerEntry();
425   if (aLabel.IsRoot()) return;
426   Handle(GEOM_Object) aMainObj = GEOM_Object::GetObject(aLabel);
427   if (aMainObj.IsNull()) return;
428   TopoDS_Shape aMainShape = aMainObj->GetValue();
429   if (aMainShape.IsNull()) return;
430
431   TopTools_IndexedMapOfShape mapIndices;
432   TopExp::MapShapes(aMainShape, mapIndices);
433
434   // Get IDs of sub-shapes to be removed
435   Standard_Integer i, rem_id;
436   for (i = 1; i <= aLen; i++) {
437     Handle(GEOM_Object) anObj_i = Handle(GEOM_Object)::DownCast(theSubShapes->Value(i));
438
439     if (anObj_i->IsMainShape()) {
440       TopoDS_Shape aShape_i = anObj_i->GetValue();
441       if (mapIndices.Contains(aShape_i)) {
442         rem_id = mapIndices.FindIndex(aShape_i);
443         if (mapIDsCurrent.Contains(rem_id)) {
444           mapIDsToRemove.Add(rem_id);
445         }
446       } else {
447         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");
448         return;
449       }
450     } else {
451       // Check main shape of sub-shape to be removed
452       Handle(GEOM_Function) aFunc_i = anObj_i->GetFunction(1);
453       if (aFunc_i.IsNull()) return;
454
455       GEOM_ISubShape aSSI_i (aFunc_i);
456
457       Handle(GEOM_Function) aMainShapeFunc_i = aSSI_i.GetMainShape();
458       if (aMainShapeFunc_i.IsNull()) return;
459       TDF_Label aLabel_i = aMainShapeFunc_i->GetOwnerEntry();
460       if (aLabel_i.IsRoot()) return;
461       Handle(GEOM_Object) aMainObj_i = GEOM_Object::GetObject(aLabel);
462       if (aMainObj_i.IsNull()) return;
463       TopoDS_Shape aMainShape_i = aMainObj_i->GetValue();
464       if (aMainShape_i.IsNull()) return;
465
466       if (aMainShape_i.IsSame(aMainShape)) {
467         // remove all sub-shapes
468
469         // Get IDs
470         Handle(TColStd_HArray1OfInteger) aSeq_i = aSSI_i.GetIndices();
471         if (aSeq_i.IsNull()) return;
472         Standard_Integer aLength_i = aSeq_i->Length();
473
474         for (Standard_Integer i_j = 1; i_j <= aLength_i; i_j++) {
475           rem_id = aSeq_i->Value(i_j);
476           if (rem_id > 0) {
477             if (mapIDsCurrent.Contains(rem_id)) {
478               mapIDsToRemove.Add(rem_id);
479             }
480           }
481         }
482
483       } else if (mapIndices.Contains(aMainShape_i)) {
484         // compute new IDs and add them to the map of ids to be removed
485         TopTools_IndexedMapOfShape mapIndices_i;
486         TopExp::MapShapes(aMainShape_i, mapIndices_i);
487
488         // Get IDs
489         Handle(TColStd_HArray1OfInteger) aSeq_i = aSSI_i.GetIndices();
490         if (aSeq_i.IsNull()) return;
491         Standard_Integer aLength_i = aSeq_i->Length();
492
493         for (Standard_Integer i_j = 1; i_j <= aLength_i; i_j++) {
494           if (aSeq_i->Value(i_j) > 0) {
495             TopoDS_Shape aShape_i_j = mapIndices_i.FindKey(i_j);
496             rem_id = mapIndices.FindIndex(aShape_i_j);
497             if (mapIDsCurrent.Contains(rem_id)) {
498               mapIDsToRemove.Add(rem_id);
499             }
500           }
501         }
502
503       } else {
504         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");
505         return;
506       }
507     }
508   }
509
510   if (mapIDsToRemove.Extent() > 0) {
511     Standard_Integer k = 1, aRemLength = mapIDsToRemove.Extent();
512     Handle(TColStd_HArray1OfInteger) aNewSeq = new TColStd_HArray1OfInteger(1, aLength - aRemLength);
513
514     for (j = 1; j <= aLength; j++) {
515       if (!mapIDsToRemove.Contains(aSeq->Value(j))) {
516         aNewSeq->SetValue(k, aSeq->Value(j));
517         k++;
518       }
519     }
520
521     aSSI.SetIndices(aNewSeq);
522   }
523
524   //Make a Python command
525   Handle(GEOM_Object) aLatest = GEOM::GetCreatedLast(theSubShapes);
526   aLatest = GEOM::GetCreatedLast(aLatest, theGroup);
527   Handle(GEOM_Function) aLastFunc = aLatest->GetLastFunction();
528
529   GEOM::TPythonDump pd (aLastFunc, /*append=*/true);
530   pd << "geompy.DifferenceList(" << theGroup << ", [";
531
532   for (i = 1; i <= aLen; i++) {
533     Handle(GEOM_Object) anObj_i = Handle(GEOM_Object)::DownCast(theSubShapes->Value(i));
534     pd << anObj_i << (( i < aLen ) ? ", " : "])");
535   }
536
537   SetErrorCode(OK);
538 }
539
540 //=============================================================================
541 /*!
542  *  UnionIDs
543  */
544 //=============================================================================
545 void GEOMImpl_IGroupOperations::UnionIDs (Handle(GEOM_Object) theGroup,
546                                           const Handle(TColStd_HSequenceOfInteger)& theSubShapes)
547 {
548   SetErrorCode(KO);
549   if (theGroup.IsNull()) return;
550
551   Standard_Integer aLen = theSubShapes->Length();
552   if (aLen < 1) {
553     SetErrorCode("The list is empty");
554     return;
555   }
556
557   Handle(GEOM_Function) aFunction = theGroup->GetFunction(1);
558   if (aFunction.IsNull()) return;
559
560   GEOM_ISubShape aSSI (aFunction);
561
562   // New contents of the group
563   TColStd_ListOfInteger aNewIDs;
564   TColStd_MapOfInteger mapIDs;
565
566   // Add current IDs to the list
567   Handle(TColStd_HArray1OfInteger) aSeq = aSSI.GetIndices();
568   if (aSeq.IsNull()) return;
569   Standard_Integer val_j, aLength = aSeq->Length();
570
571   for (Standard_Integer j = 1; j <= aLength; j++) {
572     val_j = aSeq->Value(j);
573     if (val_j > 0 && mapIDs.Add(val_j)) {
574       aNewIDs.Append(val_j);
575     }
576   }
577
578   // Get Main Shape
579   Handle(GEOM_Function) aMainShapeFunc = aSSI.GetMainShape();
580   if (aMainShapeFunc.IsNull()) return;
581   TDF_Label aLabel = aMainShapeFunc->GetOwnerEntry();
582   if (aLabel.IsRoot()) return;
583   Handle(GEOM_Object) aMainObj = GEOM_Object::GetObject(aLabel);
584   if (aMainObj.IsNull()) return;
585   TopoDS_Shape aMainShape = aMainObj->GetValue();
586   if (aMainShape.IsNull()) return;
587
588   TopTools_IndexedMapOfShape mapIndices;
589   TopExp::MapShapes(aMainShape, mapIndices);
590
591   // Get IDs of sub-shapes to add
592   Standard_Integer i, new_id;
593   for (i = 1; i <= aLen; i++) {
594     new_id = theSubShapes->Value(i);
595
596     if (0 < new_id && new_id <= mapIndices.Extent()) {
597       if (mapIDs.Add(new_id)) {
598         aNewIDs.Append(new_id);
599       }
600     }
601   }
602
603   if (aNewIDs.Extent() > 0) {
604     Standard_Integer k = 1;
605     TColStd_ListIteratorOfListOfInteger aNewIDsIter (aNewIDs);
606     Handle(TColStd_HArray1OfInteger) aNewSeq = new TColStd_HArray1OfInteger(1, aNewIDs.Extent());
607     for (; aNewIDsIter.More(); aNewIDsIter.Next(), k++) {
608       aNewSeq->SetValue(k, aNewIDsIter.Value());
609     }
610
611     aSSI.SetIndices(aNewSeq);
612   }
613
614   //Make a Python command
615   GEOM::TPythonDump pd (aFunction, /*append=*/true);
616   pd << "geompy.UnionIDs(" << theGroup << ", [";
617   for (i = 1; i < aLen; i++)
618     pd << theSubShapes->Value(i) << ", ";
619   pd << theSubShapes->Value(aLen) << "])";
620
621   SetErrorCode(OK);
622 }
623
624 //=============================================================================
625 /*!
626  *  DifferenceIDs
627  */
628 //=============================================================================
629 void GEOMImpl_IGroupOperations::DifferenceIDs (Handle(GEOM_Object) theGroup,
630                                                const Handle(TColStd_HSequenceOfInteger)& theSubShapes)
631 {
632   SetErrorCode(KO);
633   if (theGroup.IsNull()) return;
634
635   Standard_Integer aLen = theSubShapes->Length();
636   if (aLen < 1) {
637     SetErrorCode("The list is empty");
638     return;
639   }
640
641   Handle(GEOM_Function) aFunction = theGroup->GetFunction(1);
642   if (aFunction.IsNull()) return;
643
644   GEOM_ISubShape aSSI (aFunction);
645
646   // Map of IDs to be removed
647   TColStd_MapOfInteger mapIDsToRemove;
648
649   // Map of current IDs
650   Handle(TColStd_HArray1OfInteger) aSeq = aSSI.GetIndices();
651   if (aSeq.IsNull()) return;
652   Standard_Integer aLength = aSeq->Length();
653
654   if (aLength == 1 && aSeq->Value(1) == -1) // empty group
655     return;
656
657   TColStd_MapOfInteger mapIDsCurrent;
658   Standard_Integer j = 1;
659   for (; j <= aLength; j++) {
660     mapIDsCurrent.Add(aSeq->Value(j));
661   }
662
663   // Get Main Shape
664   Handle(GEOM_Function) aMainShapeFunc = aSSI.GetMainShape();
665   if (aMainShapeFunc.IsNull()) return;
666   TDF_Label aLabel = aMainShapeFunc->GetOwnerEntry();
667   if (aLabel.IsRoot()) return;
668   Handle(GEOM_Object) aMainObj = GEOM_Object::GetObject(aLabel);
669   if (aMainObj.IsNull()) return;
670   TopoDS_Shape aMainShape = aMainObj->GetValue();
671   if (aMainShape.IsNull()) return;
672
673   TopTools_IndexedMapOfShape mapIndices;
674   TopExp::MapShapes(aMainShape, mapIndices);
675
676   // Get IDs of sub-shapes to be removed
677   Standard_Integer i, rem_id;
678   for (i = 1; i <= aLen; i++) {
679     rem_id = theSubShapes->Value(i);
680     if (mapIDsCurrent.Contains(rem_id)) {
681       mapIDsToRemove.Add(rem_id);
682     }
683   }
684
685   if (mapIDsToRemove.Extent() > 0) {
686     Standard_Integer k = 1, aRemLength = mapIDsToRemove.Extent();
687     Handle(TColStd_HArray1OfInteger) aNewSeq = new TColStd_HArray1OfInteger(1, aLength - aRemLength);
688
689     for (j = 1; j <= aLength; j++) {
690       if (!mapIDsToRemove.Contains(aSeq->Value(j))) {
691         aNewSeq->SetValue(k, aSeq->Value(j));
692         k++;
693       }
694     }
695
696     aSSI.SetIndices(aNewSeq);
697   }
698
699   //Make a Python command
700   GEOM::TPythonDump pd (aFunction, /*append=*/true);
701   pd << "geompy.DifferenceIDs(" << theGroup << ", [";
702   for (i = 1; i < aLen; i++)
703     pd << theSubShapes->Value(i) << ", ";
704   pd << theSubShapes->Value(aLen) << "])";
705
706   SetErrorCode(OK);
707 }
708
709 //=============================================================================
710 /*!
711  *  GetType
712  */
713 //=============================================================================
714 TopAbs_ShapeEnum GEOMImpl_IGroupOperations::GetType(Handle(GEOM_Object) theGroup)
715 {
716   SetErrorCode(KO);
717
718   TDF_Label aFreeLabel = theGroup->GetFreeLabel();
719   Handle(TDataStd_Integer) anAttrib;
720   if(!aFreeLabel.FindAttribute(TDataStd_Integer::GetID(), anAttrib)) return TopAbs_SHAPE;
721  
722   SetErrorCode(OK);
723   return (TopAbs_ShapeEnum) anAttrib->Get(); 
724 }
725
726 //=============================================================================
727 /*!
728  *  GetMainShape
729  */
730 //=============================================================================
731 Handle(GEOM_Object) GEOMImpl_IGroupOperations::GetMainShape (Handle(GEOM_Object) theGroup)
732 {
733   SetErrorCode(KO);
734
735   if(theGroup.IsNull()) return NULL;
736
737   Handle(GEOM_Function) aGroupFunction = theGroup->GetFunction(1);
738   if (aGroupFunction.IsNull()) return NULL;
739
740   GEOM_ISubShape aSSI (aGroupFunction);
741   Handle(GEOM_Function) aMainShapeFunction = aSSI.GetMainShape();
742   if (aMainShapeFunction.IsNull()) return NULL;
743
744   TDF_Label aLabel = aMainShapeFunction->GetOwnerEntry();
745   Handle(GEOM_Object) aMainShape = GEOM_Object::GetObject(aLabel);
746   if (aMainShape.IsNull()) return NULL;
747
748   //Make a Python command
749   GEOM::TPythonDump(aGroupFunction, /*append=*/true)
750     << aMainShape << " = geompy.GetMainShape(" << theGroup << ")";
751
752   SetErrorCode(OK);
753   return aMainShape; 
754 }
755
756 //=============================================================================
757 /*!
758  *  GetObjects
759  */
760 //=============================================================================
761 Handle(TColStd_HArray1OfInteger) GEOMImpl_IGroupOperations::GetObjects(Handle(GEOM_Object) theGroup)
762 {
763   SetErrorCode(KO);
764
765   if(theGroup.IsNull()) return NULL;
766
767   Handle(GEOM_Function) aFunction = theGroup->GetFunction(1);
768   if(aFunction.IsNull()) return NULL;
769
770   GEOM_ISubShape aSSI(aFunction);
771   Handle(TColStd_HArray1OfInteger) aSeq = aSSI.GetIndices();
772   if(aSeq.IsNull()) return NULL;
773
774   if(aSeq->Length() == 1 && aSeq->Value(1) == -1) {
775     SetErrorCode(OK);
776     return NULL;
777   }
778
779   SetErrorCode(OK);
780   return aSeq;
781 }