]> SALOME platform Git repositories - modules/geom.git/blob - src/GEOMImpl/GEOMImpl_IGroupOperations.cxx
Salome HOME
Merge from V6_5_BR 05/06/2012
[modules/geom.git] / src / GEOMImpl / GEOMImpl_IGroupOperations.cxx
1 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 #include <Standard_Stream.hxx>
24
25 #include <GEOMImpl_IGroupOperations.hxx>
26
27 #include <GEOMImpl_Types.hxx>
28
29 #include <GEOM_Function.hxx>
30 #include <GEOM_ISubShape.hxx>
31 #include <GEOM_PythonDump.hxx>
32
33 #include "utilities.h"
34 #include <OpUtil.hxx>
35 #include <Utils_ExceptHandlers.hxx>
36
37 #include <TFunction_DriverTable.hxx>
38 #include <TFunction_Driver.hxx>
39 #include <TFunction_Logbook.hxx>
40 #include <TDF_Tool.hxx>
41 #include <TDataStd_Integer.hxx>
42
43 #include <TopExp.hxx>
44 #include <TopExp_Explorer.hxx>
45 #include <TopTools_IndexedMapOfShape.hxx>
46
47 #include <TColStd_HArray1OfInteger.hxx>
48 #include <TColStd_MapOfInteger.hxx>
49 #include <TColStd_ListOfInteger.hxx>
50 #include <TColStd_ListIteratorOfListOfInteger.hxx>
51
52 //=============================================================================
53 /*!
54  *   constructor:
55  */
56 //=============================================================================
57 GEOMImpl_IGroupOperations::GEOMImpl_IGroupOperations (GEOM_Engine* theEngine, int theDocID)
58 : GEOM_IOperations(theEngine, theDocID)
59 {
60   MESSAGE("GEOMImpl_IGroupOperations::GEOMImpl_IGroupOperations");
61 }
62
63 //=============================================================================
64 /*!
65  *  destructor
66  */
67 //=============================================================================
68 GEOMImpl_IGroupOperations::~GEOMImpl_IGroupOperations()
69 {
70   MESSAGE("GEOMImpl_IGroupOperations::~GEOMImpl_IGroupOperations");
71 }
72
73
74 //=============================================================================
75 /*!
76  *  CreateGroup
77  */
78 //=============================================================================
79 Handle(GEOM_Object) GEOMImpl_IGroupOperations::CreateGroup
80        (Handle(GEOM_Object) theMainShape, TopAbs_ShapeEnum theShapeType)
81 {
82   SetErrorCode(KO);
83
84   Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
85   anArray->SetValue(1, -1);
86
87   //Add a new Sub-shape object
88   Handle(GEOM_Object) aGroup = GetEngine()->AddSubShape(theMainShape, anArray);
89
90   //Set a GROUP type
91   aGroup->SetType(GEOM_GROUP);
92
93   //Set a sub-shape type
94   TDF_Label aFreeLabel = aGroup->GetFreeLabel();
95   TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)theShapeType);
96
97   //Make a Python command
98   Handle(GEOM_Function) aFunction = aGroup->GetFunction(1);
99
100   GEOM::TPythonDump(aFunction) << aGroup
101     << " = geompy.CreateGroup(" << theMainShape << ", " << 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) aMainObj = GEOM_Object::GetObject(aLabel);
126   if (aMainObj.IsNull()) return;
127   TopoDS_Shape aMainShape = aMainObj->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   // As we do not recompute here our group, lets mark it as Modified
159   Standard_Integer aTic = aMainObj->GetTic(); // tic of main shape
160   theGroup->SetTic(aTic - 1);
161
162   //Make a Python command
163   GEOM::TPythonDump(aFunction, /*append=*/true)
164     << "geompy.AddObject(" << theGroup << ", " << theSubShapeID << ")";
165
166   SetErrorCode(OK);
167   return;
168 }
169
170 //=============================================================================
171 /*!
172  *  RemoveObject
173  */
174 //=============================================================================
175 void GEOMImpl_IGroupOperations::RemoveObject (Handle(GEOM_Object) theGroup, int theSubShapeID)
176 {
177   SetErrorCode(KO);
178   if(theGroup.IsNull()) return;
179
180   Handle(GEOM_Function) aFunction = theGroup->GetFunction(1);
181   if(aFunction.IsNull()) return;
182
183   GEOM_ISubShape aSSI(aFunction);
184   Handle(TColStd_HArray1OfInteger) aSeq = aSSI.GetIndices();
185   if(aSeq.IsNull()) return;
186
187   if(aSeq->Length() == 1 && aSeq->Value(1) == -1) {
188     SetErrorCode(NOT_EXISTS);
189     return;
190   }
191
192   Handle(TColStd_HArray1OfInteger) aNewSeq;
193   Standard_Integer aLength = aSeq->Length();
194   if(aLength == 1) {
195     if(aSeq->Value(1) != theSubShapeID) {
196       SetErrorCode(NOT_EXISTS);
197       return;
198     }
199     aNewSeq = new TColStd_HArray1OfInteger(1,1);
200     aNewSeq->SetValue(1, -1);
201   }
202   else {
203     aNewSeq = new TColStd_HArray1OfInteger(1, aLength-1);
204     Standard_Boolean isFound = Standard_False;
205     for (Standard_Integer i = 1, k = 1; i <= aLength; i++) {
206       if (aSeq->Value(i) == theSubShapeID) {
207         isFound = Standard_True;
208       } else {
209         if (k < aLength) { // this check is to avoid sequence <aNewSeq> overflow
210           aNewSeq->SetValue(k, aSeq->Value(i));
211           k++;
212         }
213       }
214     }
215
216     if (!isFound) {
217       SetErrorCode(NOT_EXISTS);
218       return;
219     }
220   }
221
222   aSSI.SetIndices(aNewSeq);
223
224   // As we do not recompute here our group, lets mark it as Modified
225   TDF_Label aLabel = aSSI.GetMainShape()->GetOwnerEntry();
226   if (aLabel.IsRoot()) return;
227   Handle(GEOM_Object) aMainObj = GEOM_Object::GetObject(aLabel);
228   if (aMainObj.IsNull()) return;
229   Standard_Integer aTic = aMainObj->GetTic(); // tic of main shape
230   theGroup->SetTic(aTic - 1);
231
232   //Make a Python command
233   GEOM::TPythonDump(aFunction, /*append=*/true)
234     << "geompy.RemoveObject(" << theGroup << ", " << theSubShapeID << ")";
235
236   SetErrorCode(OK);
237   return;
238 }
239
240 //=============================================================================
241 /*!
242  *  UnionList
243  */
244 //=============================================================================
245 void GEOMImpl_IGroupOperations::UnionList (Handle(GEOM_Object) theGroup,
246                                            const Handle(TColStd_HSequenceOfTransient)& theSubShapes)
247 {
248   SetErrorCode(KO);
249   if (theGroup.IsNull()) return;
250
251   Standard_Integer aLen = theSubShapes->Length();
252   if (aLen < 1) {
253     //SetErrorCode("The list is empty");
254     SetErrorCode(OK);
255     return;
256   }
257
258   Handle(GEOM_Function) aFunction = theGroup->GetFunction(1);
259   if (aFunction.IsNull()) return;
260
261   GEOM_ISubShape aSSI (aFunction);
262
263   // New contents of the group
264   TColStd_ListOfInteger aNewIDs;
265   TColStd_MapOfInteger mapIDs;
266
267   // Add current IDs to the list
268   Handle(TColStd_HArray1OfInteger) aSeq = aSSI.GetIndices();
269   if (aSeq.IsNull()) return;
270   Standard_Integer val_j, aLength = aSeq->Length();
271
272   for (Standard_Integer j = 1; j <= aLength; j++) {
273     val_j = aSeq->Value(j);
274     if (val_j > 0 && mapIDs.Add(val_j)) {
275       aNewIDs.Append(val_j);
276     }
277   }
278
279   // Get Main Shape
280   Handle(GEOM_Function) aMainShapeFunc = aSSI.GetMainShape();
281   if (aMainShapeFunc.IsNull()) return;
282   TDF_Label aLabel = aMainShapeFunc->GetOwnerEntry();
283   if (aLabel.IsRoot()) return;
284   Handle(GEOM_Object) aMainObj = GEOM_Object::GetObject(aLabel);
285   if (aMainObj.IsNull()) return;
286   TopoDS_Shape aMainShape = aMainObj->GetValue();
287   if (aMainShape.IsNull()) return;
288
289   TopTools_IndexedMapOfShape mapIndices;
290   TopExp::MapShapes(aMainShape, mapIndices);
291
292   // Get group type
293   TopAbs_ShapeEnum aType = GetType(theGroup);
294
295   // Get IDs of sub-shapes to add
296   Standard_Integer i, new_id;
297   for (i = 1; i <= aLen; i++) {
298     Handle(GEOM_Object) anObj_i = Handle(GEOM_Object)::DownCast(theSubShapes->Value(i));
299
300     TopoDS_Shape aShape_i = anObj_i->GetValue();
301     if ( aShape_i.IsNull() ) continue;
302     TopAbs_ShapeEnum aType_i = aShape_i.ShapeType();
303
304     // 1. If aShape_i is sub-shape of aMainShape - add it
305     if (anObj_i->IsMainShape()) {
306       if (aType_i != aType && aType != TopAbs_SHAPE && aType != TopAbs_COMPOUND) {
307         SetErrorCode("Operation aborted: one of given objects has a wrong type");
308         return;
309       }
310       if (!mapIndices.Contains(aShape_i)) {
311         SetErrorCode("Operation aborted: not a sub-shape given");
312         return;
313       }
314       new_id = mapIndices.FindIndex(aShape_i);
315       if (mapIDs.Add(new_id)) {
316         aNewIDs.Append(new_id);
317       }
318     }
319     // 2. If type of group is not defined - add all sub-shapes of aShape_i
320     else if (aType == TopAbs_SHAPE || aType == TopAbs_COMPOUND) {
321       TopTools_IndexedMapOfShape mapIndices_i;
322       TopExp::MapShapes(aShape_i, mapIndices_i);
323       Standard_Integer ii = 1, nbSubSh = mapIndices_i.Extent();
324       Standard_Boolean someGood = Standard_False;
325       for (; ii <= nbSubSh; ii++) {
326         TopoDS_Shape aSubShape_i = mapIndices_i.FindKey(ii);
327         if (mapIndices.Contains(aSubShape_i)) {
328           someGood = Standard_True;
329           new_id = mapIndices.FindIndex(aSubShape_i);
330           if (mapIDs.Add(new_id)) {
331             aNewIDs.Append(new_id);
332           }
333         }
334       }
335       if (!someGood) {
336         SetErrorCode("Operation aborted: not a sub-shape given");
337         return;
338       }
339     }
340     // 3. If type of group is defined - add all sub-shapes of aShape_i of that type
341     else {
342       TopExp_Explorer aSubShapes_i (aShape_i, aType);
343       for (; aSubShapes_i.More(); aSubShapes_i.Next()) {
344         TopoDS_Shape aSubShape_i = aSubShapes_i.Current();
345         if (!mapIndices.Contains(aSubShape_i)) {
346           SetErrorCode("Operation aborted: not a sub-shape given");
347           return;
348         }
349         new_id = mapIndices.FindIndex(aSubShape_i);
350         if (mapIDs.Add(new_id)) {
351           aNewIDs.Append(new_id);
352         }
353       }
354     }
355   }
356
357   if (aNewIDs.Extent() > 0) {
358     Standard_Integer k = 1;
359     TColStd_ListIteratorOfListOfInteger aNewIDsIter (aNewIDs);
360     Handle(TColStd_HArray1OfInteger) aNewSeq = new TColStd_HArray1OfInteger(1, aNewIDs.Extent());
361     for (; aNewIDsIter.More(); aNewIDsIter.Next(), k++) {
362       aNewSeq->SetValue(k, aNewIDsIter.Value());
363     }
364
365     aSSI.SetIndices(aNewSeq);
366
367     // As we do not recompute here our group, lets mark it as Modified
368     Standard_Integer aTic = aMainObj->GetTic(); // tic of main shape
369     theGroup->SetTic(aTic - 1);
370   }
371
372   //Make a Python command
373   Handle(GEOM_Object) aLatest = GEOM::GetCreatedLast(theSubShapes);
374   aLatest = GEOM::GetCreatedLast(aLatest, theGroup);
375   Handle(GEOM_Function) aLastFunc = aLatest->GetLastFunction();
376
377   GEOM::TPythonDump pd (aLastFunc, /*append=*/true);
378   pd << "geompy.UnionList(" << theGroup << ", [";
379
380   for (i = 1; i <= aLen; i++) {
381     Handle(GEOM_Object) anObj_i = Handle(GEOM_Object)::DownCast(theSubShapes->Value(i));
382     pd << anObj_i << (( i < aLen ) ? ", " : "])");
383   }
384
385   SetErrorCode(OK);
386 }
387
388 //=============================================================================
389 /*!
390  *  DifferenceList
391  */
392 //=============================================================================
393 void GEOMImpl_IGroupOperations::DifferenceList (Handle(GEOM_Object) theGroup,
394                                                 const Handle(TColStd_HSequenceOfTransient)& theSubShapes)
395 {
396   SetErrorCode(KO);
397   if (theGroup.IsNull()) return;
398
399   Standard_Integer aLen = theSubShapes->Length();
400   if (aLen < 1) {
401     //SetErrorCode("The list is empty");
402     SetErrorCode(OK);
403     return;
404   }
405
406   Handle(GEOM_Function) aFunction = theGroup->GetFunction(1);
407   if (aFunction.IsNull()) return;
408
409   GEOM_ISubShape aSSI (aFunction);
410
411   // Map of IDs to be removed
412   TColStd_MapOfInteger mapIDsToRemove;
413
414   // Map of current IDs
415   Handle(TColStd_HArray1OfInteger) aSeq = aSSI.GetIndices();
416   if (aSeq.IsNull()) return;
417   Standard_Integer aLength = aSeq->Length();
418
419   // VSR 28/04/2011 commented to allow operation even for empty group
420   //   if (aLength == 1 && aSeq->Value(1) == -1) // empty group
421   //     return;
422
423   TColStd_MapOfInteger mapIDsCurrent;
424   Standard_Integer j = 1;
425   for (; j <= aLength; j++) {
426     mapIDsCurrent.Add(aSeq->Value(j));
427   }
428
429   // Get Main Shape
430   Handle(GEOM_Function) aMainShapeFunc = aSSI.GetMainShape();
431   if (aMainShapeFunc.IsNull()) return;
432   TDF_Label aLabel = aMainShapeFunc->GetOwnerEntry();
433   if (aLabel.IsRoot()) return;
434   Handle(GEOM_Object) aMainObj = GEOM_Object::GetObject(aLabel);
435   if (aMainObj.IsNull()) return;
436   TopoDS_Shape aMainShape = aMainObj->GetValue();
437   if (aMainShape.IsNull()) return;
438
439   TopTools_IndexedMapOfShape mapIndices;
440   TopExp::MapShapes(aMainShape, mapIndices);
441
442   // Get group type
443   TopAbs_ShapeEnum aType = GetType(theGroup);
444
445   // Get IDs of sub-shapes to be removed
446   Standard_Integer i, rem_id;
447   for (i = 1; i <= aLen; i++) {
448     Handle(GEOM_Object) anObj_i = Handle(GEOM_Object)::DownCast(theSubShapes->Value(i));
449
450     TopoDS_Shape aShape_i = anObj_i->GetValue();
451
452     // 1. If aShape_i is sub-shape of aMainShape - remove it
453     if (mapIndices.Contains(aShape_i)) {
454       rem_id = mapIndices.FindIndex(aShape_i);
455       if (rem_id > 0 && mapIDsCurrent.Contains(rem_id)) {
456         mapIDsToRemove.Add(rem_id);
457       }
458     }
459     // 2. If type of group is not defined - remove all sub-shapes of aShape_i
460     else if (aType == TopAbs_SHAPE || aType == TopAbs_COMPOUND) {
461       TopTools_IndexedMapOfShape mapIndices_i;
462       TopExp::MapShapes(aShape_i, mapIndices_i);
463       Standard_Integer nbSubSh = mapIndices_i.Extent();
464       Standard_Integer ii = 1;
465       for (; ii <= nbSubSh; ii++) {
466         TopoDS_Shape aSubShape_i = mapIndices_i.FindKey(ii);
467         if (mapIndices.Contains(aSubShape_i)) {
468           rem_id = mapIndices.FindIndex(aSubShape_i);
469           if (rem_id > 0 && mapIDsCurrent.Contains(rem_id)) {
470             mapIDsToRemove.Add(rem_id);
471           }
472         }
473       }
474     }
475     // 3. If type of group is defined - remove all sub-shapes of aShape_i of that type
476     else {
477       TopExp_Explorer aSubShapes_i (aShape_i, aType);
478       for (; aSubShapes_i.More(); aSubShapes_i.Next()) {
479         TopoDS_Shape aSubShape_i = aSubShapes_i.Current();
480         if (mapIndices.Contains(aSubShape_i)) {
481           rem_id = mapIndices.FindIndex(aSubShape_i);
482           if (rem_id > 0 && mapIDsCurrent.Contains(rem_id)) {
483             mapIDsToRemove.Add(rem_id);
484           }
485         }
486       }
487     }
488   }
489
490   if (mapIDsToRemove.Extent() > 0) {
491     Standard_Integer k = 1, aRemLength = mapIDsToRemove.Extent();
492     Handle(TColStd_HArray1OfInteger) aNewSeq;
493     if ( aLength - aRemLength > 0 ) {
494       aNewSeq = new TColStd_HArray1OfInteger(1, aLength - aRemLength);
495       for (j = 1; j <= aLength; j++) {
496         if (!mapIDsToRemove.Contains(aSeq->Value(j))) {
497           aNewSeq->SetValue(k, aSeq->Value(j));
498           k++;
499         }
500       }
501     }
502     else {
503       aNewSeq = new TColStd_HArray1OfInteger(1,1);
504       aNewSeq->SetValue(1, -1);
505     }
506
507     aSSI.SetIndices(aNewSeq);
508
509     // As we do not recompute here our group, lets mark it as Modified
510     Standard_Integer aTic = aMainObj->GetTic(); // tic of main shape
511     theGroup->SetTic(aTic - 1);
512   }
513
514   //Make a Python command
515   Handle(GEOM_Object) aLatest = GEOM::GetCreatedLast(theSubShapes);
516   aLatest = GEOM::GetCreatedLast(aLatest, theGroup);
517   Handle(GEOM_Function) aLastFunc = aLatest->GetLastFunction();
518
519   GEOM::TPythonDump pd (aLastFunc, /*append=*/true);
520   pd << "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 /*!
532  *  UnionIDs
533  */
534 //=============================================================================
535 void GEOMImpl_IGroupOperations::UnionIDs (Handle(GEOM_Object) theGroup,
536                                           const Handle(TColStd_HSequenceOfInteger)& theSubShapes)
537 {
538   SetErrorCode(KO);
539   if (theGroup.IsNull()) return;
540
541   Standard_Integer aLen = theSubShapes->Length();
542   if (aLen < 1) {
543     //SetErrorCode("The list is empty");
544     SetErrorCode(OK);
545     return;
546   }
547
548   Handle(GEOM_Function) aFunction = theGroup->GetFunction(1);
549   if (aFunction.IsNull()) return;
550
551   GEOM_ISubShape aSSI (aFunction);
552
553   // New contents of the group
554   TColStd_ListOfInteger aNewIDs;
555   TColStd_MapOfInteger mapIDs;
556
557   // Add current IDs to the list
558   Handle(TColStd_HArray1OfInteger) aSeq = aSSI.GetIndices();
559   if (aSeq.IsNull()) return;
560   Standard_Integer val_j, aLength = aSeq->Length();
561
562   for (Standard_Integer j = 1; j <= aLength; j++) {
563     val_j = aSeq->Value(j);
564     if (val_j > 0 && mapIDs.Add(val_j)) {
565       aNewIDs.Append(val_j);
566     }
567   }
568
569   // Get Main Shape
570   Handle(GEOM_Function) aMainShapeFunc = aSSI.GetMainShape();
571   if (aMainShapeFunc.IsNull()) return;
572   TDF_Label aLabel = aMainShapeFunc->GetOwnerEntry();
573   if (aLabel.IsRoot()) return;
574   Handle(GEOM_Object) aMainObj = GEOM_Object::GetObject(aLabel);
575   if (aMainObj.IsNull()) return;
576   TopoDS_Shape aMainShape = aMainObj->GetValue();
577   if (aMainShape.IsNull()) return;
578
579   TopTools_IndexedMapOfShape mapIndices;
580   TopExp::MapShapes(aMainShape, mapIndices);
581
582   // Get group type
583   TopAbs_ShapeEnum aType = GetType(theGroup);
584
585   // Get IDs of sub-shapes to add
586   Standard_Integer i, new_id;
587   for (i = 1; i <= aLen; i++) {
588     new_id = theSubShapes->Value(i);
589
590     if (0 < new_id && new_id <= mapIndices.Extent()) {
591       //if (mapIDs.Add(new_id)) { IPAL21297. Why we ignore invalid ids silently?
592       if (mapIDs.Add(new_id) && mapIndices(new_id).ShapeType()==aType ) {
593         aNewIDs.Append(new_id);
594       }
595     }
596   }
597
598   if (aNewIDs.Extent() > 0) {
599     Standard_Integer k = 1;
600     TColStd_ListIteratorOfListOfInteger aNewIDsIter (aNewIDs);
601     Handle(TColStd_HArray1OfInteger) aNewSeq = new TColStd_HArray1OfInteger(1, aNewIDs.Extent());
602     for (; aNewIDsIter.More(); aNewIDsIter.Next(), k++) {
603       aNewSeq->SetValue(k, aNewIDsIter.Value());
604     }
605
606     aSSI.SetIndices(aNewSeq);
607
608     // As we do not recompute here our group, lets mark it as Modified
609     Standard_Integer aTic = aMainObj->GetTic(); // tic of main shape
610     theGroup->SetTic(aTic - 1);
611   }
612
613   //Make a Python command
614   GEOM::TPythonDump pd (aFunction, /*append=*/true);
615   pd << "geompy.UnionIDs(" << theGroup << ", [";
616   for (i = 1; i < aLen; i++)
617     pd << theSubShapes->Value(i) << ", ";
618   pd << theSubShapes->Value(aLen) << "])";
619
620   SetErrorCode(OK);
621 }
622
623 //=============================================================================
624 /*!
625  *  DifferenceIDs
626  */
627 //=============================================================================
628 void GEOMImpl_IGroupOperations::DifferenceIDs (Handle(GEOM_Object) theGroup,
629                                                const Handle(TColStd_HSequenceOfInteger)& theSubShapes)
630 {
631   SetErrorCode(KO);
632   if (theGroup.IsNull()) return;
633
634   Standard_Integer aLen = theSubShapes->Length();
635   if (aLen < 1) {
636     //SetErrorCode("The list is empty");
637     SetErrorCode(OK);
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   // VSR 28/04/2011 commented to allow operation even for empty group
655   //   if (aLength == 1 && aSeq->Value(1) == -1) // empty group
656   //     return;
657
658   TColStd_MapOfInteger mapIDsCurrent;
659   Standard_Integer j = 1;
660   for (; j <= aLength; j++) {
661     mapIDsCurrent.Add(aSeq->Value(j));
662   }
663
664   // Get Main Shape
665   Handle(GEOM_Function) aMainShapeFunc = aSSI.GetMainShape();
666   if (aMainShapeFunc.IsNull()) return;
667   TDF_Label aLabel = aMainShapeFunc->GetOwnerEntry();
668   if (aLabel.IsRoot()) return;
669   Handle(GEOM_Object) aMainObj = GEOM_Object::GetObject(aLabel);
670   if (aMainObj.IsNull()) return;
671   TopoDS_Shape aMainShape = aMainObj->GetValue();
672   if (aMainShape.IsNull()) return;
673
674   TopTools_IndexedMapOfShape mapIndices;
675   TopExp::MapShapes(aMainShape, mapIndices);
676
677   // Get IDs of sub-shapes to be removed
678   Standard_Integer i, rem_id;
679   for (i = 1; i <= aLen; i++) {
680     rem_id = theSubShapes->Value(i);
681     if (rem_id > 0 && mapIDsCurrent.Contains(rem_id)) {
682       mapIDsToRemove.Add(rem_id);
683     }
684   }
685
686   if (mapIDsToRemove.Extent() > 0) {
687     Standard_Integer k = 1, aRemLength = mapIDsToRemove.Extent();
688     Handle(TColStd_HArray1OfInteger) aNewSeq;
689     if ( aLength - aRemLength > 0 ) {
690       aNewSeq = new TColStd_HArray1OfInteger(1, aLength - aRemLength);
691       for (j = 1; j <= aLength; j++) {
692         if (!mapIDsToRemove.Contains(aSeq->Value(j))) {
693           aNewSeq->SetValue(k, aSeq->Value(j));
694           k++;
695         }
696       }
697     }
698     else {
699       aNewSeq = new TColStd_HArray1OfInteger(1,1);
700       aNewSeq->SetValue(1, -1);
701     }
702
703     aSSI.SetIndices(aNewSeq);
704
705     // As we do not recompute here our group, lets mark it as Modified
706     Standard_Integer aTic = aMainObj->GetTic(); // tic of main shape
707     theGroup->SetTic(aTic - 1);
708   }
709
710   //Make a Python command
711   GEOM::TPythonDump pd (aFunction, /*append=*/true);
712   pd << "geompy.DifferenceIDs(" << theGroup << ", [";
713   for (i = 1; i < aLen; i++)
714     pd << theSubShapes->Value(i) << ", ";
715   pd << theSubShapes->Value(aLen) << "])";
716
717   SetErrorCode(OK);
718 }
719
720 //=============================================================================
721 /*!
722  *  GetType
723  */
724 //=============================================================================
725 TopAbs_ShapeEnum GEOMImpl_IGroupOperations::GetType(Handle(GEOM_Object) theGroup)
726 {
727   SetErrorCode(KO);
728
729   TDF_Label aFreeLabel = theGroup->GetFreeLabel();
730   Handle(TDataStd_Integer) anAttrib;
731   if(!aFreeLabel.FindAttribute(TDataStd_Integer::GetID(), anAttrib)) return TopAbs_SHAPE;
732
733   SetErrorCode(OK);
734   return (TopAbs_ShapeEnum) anAttrib->Get();
735 }
736
737 //=============================================================================
738 /*!
739  *  GetMainShape
740  */
741 //=============================================================================
742 Handle(GEOM_Object) GEOMImpl_IGroupOperations::GetMainShape (Handle(GEOM_Object) theGroup)
743 {
744   SetErrorCode(KO);
745
746   if(theGroup.IsNull()) return NULL;
747
748   Handle(GEOM_Function) aGroupFunction = theGroup->GetFunction(1);
749   if (aGroupFunction.IsNull()) return NULL;
750
751   GEOM_ISubShape aSSI (aGroupFunction);
752   Handle(GEOM_Function) aMainShapeFunction = aSSI.GetMainShape();
753   if (aMainShapeFunction.IsNull()) return NULL;
754
755   TDF_Label aLabel = aMainShapeFunction->GetOwnerEntry();
756   Handle(GEOM_Object) aMainShape = GEOM_Object::GetObject(aLabel);
757   if (aMainShape.IsNull()) return NULL;
758
759   //Make a Python command
760   //GEOM::TPythonDump(aGroupFunction, /*append=*/true)
761   //  << aMainShape << " = geompy.GetMainShape(" << theGroup << ")";
762
763   SetErrorCode(OK);
764   return aMainShape;
765 }
766
767 //=============================================================================
768 /*!
769  *  GetObjects
770  */
771 //=============================================================================
772 Handle(TColStd_HArray1OfInteger) GEOMImpl_IGroupOperations::GetObjects(Handle(GEOM_Object) theGroup)
773 {
774   SetErrorCode(KO);
775
776   if(theGroup.IsNull()) return NULL;
777
778   Handle(GEOM_Function) aFunction = theGroup->GetFunction(1);
779   if(aFunction.IsNull()) return NULL;
780
781   GEOM_ISubShape aSSI(aFunction);
782   Handle(TColStd_HArray1OfInteger) aSeq = aSSI.GetIndices();
783   if(aSeq.IsNull()) return NULL;
784
785   if(aSeq->Length() == 1 && aSeq->Value(1) == -1) {
786     SetErrorCode(OK);
787     return NULL;
788   }
789
790   SetErrorCode(OK);
791   return aSeq;
792 }