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