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