1 // Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
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.
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.
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
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 #include <Standard_Stream.hxx>
25 #include <GEOMImpl_IGroupOperations.hxx>
27 #include <GEOMImpl_Types.hxx>
29 #include <GEOM_Function.hxx>
30 #include <GEOM_ISubShape.hxx>
31 #include <GEOM_PythonDump.hxx>
33 #include "utilities.h"
35 #include <Utils_ExceptHandlers.hxx>
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>
44 #include <TopExp_Explorer.hxx>
45 #include <TopTools_IndexedMapOfShape.hxx>
47 #include <TColStd_HArray1OfInteger.hxx>
48 #include <TColStd_MapOfInteger.hxx>
49 #include <TColStd_ListOfInteger.hxx>
50 #include <TColStd_ListIteratorOfListOfInteger.hxx>
52 //=============================================================================
56 //=============================================================================
57 GEOMImpl_IGroupOperations::GEOMImpl_IGroupOperations (GEOM_Engine* theEngine, int theDocID)
58 : GEOM_IOperations(theEngine, theDocID)
60 MESSAGE("GEOMImpl_IGroupOperations::GEOMImpl_IGroupOperations");
63 //=============================================================================
67 //=============================================================================
68 GEOMImpl_IGroupOperations::~GEOMImpl_IGroupOperations()
70 MESSAGE("GEOMImpl_IGroupOperations::~GEOMImpl_IGroupOperations");
74 //=============================================================================
78 //=============================================================================
79 Handle(GEOM_Object) GEOMImpl_IGroupOperations::CreateGroup
80 (Handle(GEOM_Object) theMainShape, TopAbs_ShapeEnum theShapeType)
84 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
85 anArray->SetValue(1, -1);
87 //Add a new Sub-shape object
88 Handle(GEOM_Object) aGroup = GetEngine()->AddSubShape(theMainShape, anArray);
91 aGroup->SetType(GEOM_GROUP);
93 //Set a sub-shape type
94 TDF_Label aFreeLabel = aGroup->GetFreeLabel();
95 TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)theShapeType);
97 //Make a Python command
98 Handle(GEOM_Function) aFunction = aGroup->GetFunction(1);
100 GEOM::TPythonDump(aFunction) << aGroup
101 << " = geompy.CreateGroup(" << theMainShape << ", " << theShapeType << ")";
107 //=============================================================================
111 //=============================================================================
112 void GEOMImpl_IGroupOperations::AddObject(Handle(GEOM_Object) theGroup, int theSubShapeID)
115 if(theGroup.IsNull()) return;
117 Handle(GEOM_Function) aFunction = theGroup->GetLastFunction();
118 if(aFunction.IsNull()) return;
120 GEOM_ISubShape aSSI (aFunction);
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;
130 TopTools_IndexedMapOfShape aMapOfShapes;
131 TopExp::MapShapes(aMainShape, aMapOfShapes);
133 if (theSubShapeID < 1 || aMapOfShapes.Extent() < theSubShapeID) {
134 SetErrorCode("Invalid sub-shape index: out of range");
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);
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);
154 aNewSeq->SetValue(aLength+1, theSubShapeID);
155 if ( aFunction->IsLastFuntion() ) {
156 aSSI.SetIndices(aNewSeq);
159 aFunction = theGroup->AddFunction( GEOM_Object::GetSubShapeID(), 0, true );
160 GEOM_ISubShape aSSI2 (aFunction);
161 aSSI2.SetIndices(aNewSeq);
162 aSSI2.SetMainShape( aSSI.GetMainShape() );
166 // As we do not recompute here our group, lets mark it as Modified
167 Standard_Integer aTic = aMainObj->GetTic(); // tic of main shape
168 theGroup->SetTic(aTic - 1);
170 //Make a Python command
171 GEOM::TPythonDump(aFunction, /*append=*/true)
172 << "geompy.AddObject(" << theGroup << ", " << theSubShapeID << ")";
178 //=============================================================================
182 //=============================================================================
183 void GEOMImpl_IGroupOperations::RemoveObject (Handle(GEOM_Object) theGroup, int theSubShapeID)
186 if(theGroup.IsNull()) return;
188 Handle(GEOM_Function) aFunction = theGroup->GetLastFunction();
189 if(aFunction.IsNull()) return;
191 GEOM_ISubShape aSSI(aFunction);
192 Handle(TColStd_HArray1OfInteger) aSeq = aSSI.GetIndices();
193 if(aSeq.IsNull()) return;
195 if(aSeq->Length() == 1 && aSeq->Value(1) == -1) {
196 SetErrorCode(NOT_EXISTS);
200 Handle(TColStd_HArray1OfInteger) aNewSeq;
201 Standard_Integer aLength = aSeq->Length();
203 if(aSeq->Value(1) != theSubShapeID) {
204 SetErrorCode(NOT_EXISTS);
207 aNewSeq = new TColStd_HArray1OfInteger(1,1);
208 aNewSeq->SetValue(1, -1);
211 aNewSeq = new TColStd_HArray1OfInteger(1, aLength-1);
212 Standard_Boolean isFound = Standard_False;
213 for (Standard_Integer i = 1, k = 1; i <= aLength; i++) {
214 if (aSeq->Value(i) == theSubShapeID) {
215 isFound = Standard_True;
217 if (k < aLength) { // this check is to avoid sequence <aNewSeq> overflow
218 aNewSeq->SetValue(k, aSeq->Value(i));
225 SetErrorCode(NOT_EXISTS);
230 if ( aFunction->IsLastFuntion() ) {
231 aSSI.SetIndices(aNewSeq);
234 aFunction = theGroup->AddFunction( GEOM_Object::GetSubShapeID(), 0, true );
235 GEOM_ISubShape aSSI2 (aFunction);
236 aSSI2.SetIndices(aNewSeq);
237 aSSI2.SetMainShape( aSSI.GetMainShape() );
240 // As we do not recompute here our group, lets mark it as Modified
241 TDF_Label aLabel = aSSI.GetMainShape()->GetOwnerEntry();
242 if (aLabel.IsRoot()) return;
243 Handle(GEOM_Object) aMainObj = GEOM_Object::GetObject(aLabel);
244 if (aMainObj.IsNull()) return;
245 Standard_Integer aTic = aMainObj->GetTic(); // tic of main shape
246 theGroup->SetTic(aTic - 1);
248 //Make a Python command
249 GEOM::TPythonDump(aFunction, /*append=*/true)
250 << "geompy.RemoveObject(" << theGroup << ", " << theSubShapeID << ")";
256 //=============================================================================
260 //=============================================================================
261 void GEOMImpl_IGroupOperations::UnionList (Handle(GEOM_Object) theGroup,
262 const Handle(TColStd_HSequenceOfTransient)& theSubShapes)
265 if (theGroup.IsNull()) return;
267 Standard_Integer aLen = theSubShapes->Length();
269 //SetErrorCode("The list is empty");
274 Handle(GEOM_Function) aFunction = theGroup->GetLastFunction();
275 if (aFunction.IsNull()) return;
277 GEOM_ISubShape aSSI (aFunction);
279 // New contents of the group
280 TColStd_ListOfInteger aNewIDs;
281 TColStd_MapOfInteger mapIDs;
283 // Add current IDs to the list
284 Handle(TColStd_HArray1OfInteger) aSeq = aSSI.GetIndices();
285 if (aSeq.IsNull()) return;
286 Standard_Integer val_j, aLength = aSeq->Length();
288 for (Standard_Integer j = 1; j <= aLength; j++) {
289 val_j = aSeq->Value(j);
290 if (val_j > 0 && mapIDs.Add(val_j)) {
291 aNewIDs.Append(val_j);
296 Handle(GEOM_Function) aMainShapeFunc = aSSI.GetMainShape();
297 if (aMainShapeFunc.IsNull()) return;
298 TDF_Label aLabel = aMainShapeFunc->GetOwnerEntry();
299 if (aLabel.IsRoot()) return;
300 Handle(GEOM_Object) aMainObj = GEOM_Object::GetObject(aLabel);
301 if (aMainObj.IsNull()) return;
302 TopoDS_Shape aMainShape = aMainObj->GetValue();
303 if (aMainShape.IsNull()) return;
305 TopTools_IndexedMapOfShape mapIndices;
306 TopExp::MapShapes(aMainShape, mapIndices);
309 TopAbs_ShapeEnum aType = GetType(theGroup);
311 // Get IDs of sub-shapes to add
312 Standard_Integer i, new_id;
313 for (i = 1; i <= aLen; i++) {
314 Handle(GEOM_Object) anObj_i = Handle(GEOM_Object)::DownCast(theSubShapes->Value(i));
316 TopoDS_Shape aShape_i = anObj_i->GetValue();
317 if ( aShape_i.IsNull() ) continue;
318 TopAbs_ShapeEnum aType_i = aShape_i.ShapeType();
320 // 1. If aShape_i is sub-shape of aMainShape - add it
321 if (anObj_i->IsMainShape()) {
322 if (aType_i != aType && aType != TopAbs_SHAPE && aType != TopAbs_COMPOUND) {
323 SetErrorCode("Operation aborted: one of given objects has a wrong type");
326 if (!mapIndices.Contains(aShape_i)) {
327 SetErrorCode("Operation aborted: not a sub-shape given");
330 new_id = mapIndices.FindIndex(aShape_i);
331 if (mapIDs.Add(new_id)) {
332 aNewIDs.Append(new_id);
335 // 2. If type of group is not defined - add all sub-shapes of aShape_i
336 else if (aType == TopAbs_SHAPE || aType == TopAbs_COMPOUND) {
337 TopTools_IndexedMapOfShape mapIndices_i;
338 TopExp::MapShapes(aShape_i, mapIndices_i);
339 Standard_Integer ii = 1, nbSubSh = mapIndices_i.Extent();
340 Standard_Boolean someGood = Standard_False;
341 for (; ii <= nbSubSh; ii++) {
342 TopoDS_Shape aSubShape_i = mapIndices_i.FindKey(ii);
343 if (mapIndices.Contains(aSubShape_i)) {
344 someGood = Standard_True;
345 new_id = mapIndices.FindIndex(aSubShape_i);
346 if (mapIDs.Add(new_id)) {
347 aNewIDs.Append(new_id);
352 SetErrorCode("Operation aborted: not a sub-shape given");
356 // 3. If type of group is defined - add all sub-shapes of aShape_i of that type
358 TopExp_Explorer aSubShapes_i (aShape_i, aType);
359 for (; aSubShapes_i.More(); aSubShapes_i.Next()) {
360 TopoDS_Shape aSubShape_i = aSubShapes_i.Current();
361 if (!mapIndices.Contains(aSubShape_i)) {
362 SetErrorCode("Operation aborted: not a sub-shape given");
365 new_id = mapIndices.FindIndex(aSubShape_i);
366 if (mapIDs.Add(new_id)) {
367 aNewIDs.Append(new_id);
373 if (aNewIDs.Extent() > 0) {
374 Standard_Integer k = 1;
375 TColStd_ListIteratorOfListOfInteger aNewIDsIter (aNewIDs);
376 Handle(TColStd_HArray1OfInteger) aNewSeq = new TColStd_HArray1OfInteger(1, aNewIDs.Extent());
377 for (; aNewIDsIter.More(); aNewIDsIter.Next(), k++) {
378 aNewSeq->SetValue(k, aNewIDsIter.Value());
380 if ( aFunction->IsLastFuntion() ) {
381 aSSI.SetIndices(aNewSeq);
384 aFunction = theGroup->AddFunction( GEOM_Object::GetSubShapeID(), 0, true );
385 GEOM_ISubShape aSSI2 (aFunction);
386 aSSI2.SetIndices(aNewSeq);
387 aSSI2.SetMainShape(aMainShapeFunc);
389 // As we do not recompute here our group, lets mark it as Modified
390 Standard_Integer aTic = aMainObj->GetTic(); // tic of main shape
391 theGroup->SetTic(aTic - 1);
394 //Make a Python command
395 GEOM::TPythonDump pd (aFunction, /*append=*/true);
396 pd << "geompy.UnionList(" << theGroup << ", [";
398 for (i = 1; i <= aLen; i++) {
399 Handle(GEOM_Object) anObj_i = Handle(GEOM_Object)::DownCast(theSubShapes->Value(i));
400 pd << anObj_i << (( i < aLen ) ? ", " : "])");
406 //=============================================================================
410 //=============================================================================
411 void GEOMImpl_IGroupOperations::DifferenceList (Handle(GEOM_Object) theGroup,
412 const Handle(TColStd_HSequenceOfTransient)& theSubShapes)
415 if (theGroup.IsNull()) return;
417 Standard_Integer aLen = theSubShapes->Length();
419 //SetErrorCode("The list is empty");
424 Handle(GEOM_Function) aFunction = theGroup->GetLastFunction();
425 if (aFunction.IsNull()) return;
427 GEOM_ISubShape aSSI (aFunction);
429 // Map of IDs to be removed
430 TColStd_MapOfInteger mapIDsToRemove;
432 // Map of current IDs
433 Handle(TColStd_HArray1OfInteger) aSeq = aSSI.GetIndices();
434 if (aSeq.IsNull()) return;
435 Standard_Integer aLength = aSeq->Length();
437 // VSR 28/04/2011 commented to allow operation even for empty group
438 // if (aLength == 1 && aSeq->Value(1) == -1) // empty group
441 TColStd_MapOfInteger mapIDsCurrent;
442 Standard_Integer j = 1;
443 for (; j <= aLength; j++) {
444 mapIDsCurrent.Add(aSeq->Value(j));
448 Handle(GEOM_Function) aMainShapeFunc = aSSI.GetMainShape();
449 if (aMainShapeFunc.IsNull()) return;
450 TDF_Label aLabel = aMainShapeFunc->GetOwnerEntry();
451 if (aLabel.IsRoot()) return;
452 Handle(GEOM_Object) aMainObj = GEOM_Object::GetObject(aLabel);
453 if (aMainObj.IsNull()) return;
454 TopoDS_Shape aMainShape = aMainObj->GetValue();
455 if (aMainShape.IsNull()) return;
457 TopTools_IndexedMapOfShape mapIndices;
458 TopExp::MapShapes(aMainShape, mapIndices);
461 TopAbs_ShapeEnum aType = GetType(theGroup);
463 // Get IDs of sub-shapes to be removed
464 Standard_Integer i, rem_id;
465 for (i = 1; i <= aLen; i++) {
466 Handle(GEOM_Object) anObj_i = Handle(GEOM_Object)::DownCast(theSubShapes->Value(i));
468 TopoDS_Shape aShape_i = anObj_i->GetValue();
470 // 1. If aShape_i is sub-shape of aMainShape - remove it
471 if (mapIndices.Contains(aShape_i)) {
472 rem_id = mapIndices.FindIndex(aShape_i);
473 if (rem_id > 0 && mapIDsCurrent.Contains(rem_id)) {
474 mapIDsToRemove.Add(rem_id);
477 // 2. If type of group is not defined - remove all sub-shapes of aShape_i
478 else if (aType == TopAbs_SHAPE || aType == TopAbs_COMPOUND) {
479 TopTools_IndexedMapOfShape mapIndices_i;
480 TopExp::MapShapes(aShape_i, mapIndices_i);
481 Standard_Integer nbSubSh = mapIndices_i.Extent();
482 Standard_Integer ii = 1;
483 for (; ii <= nbSubSh; ii++) {
484 TopoDS_Shape aSubShape_i = mapIndices_i.FindKey(ii);
485 if (mapIndices.Contains(aSubShape_i)) {
486 rem_id = mapIndices.FindIndex(aSubShape_i);
487 if (rem_id > 0 && mapIDsCurrent.Contains(rem_id)) {
488 mapIDsToRemove.Add(rem_id);
493 // 3. If type of group is defined - remove all sub-shapes of aShape_i of that type
495 TopExp_Explorer aSubShapes_i (aShape_i, aType);
496 for (; aSubShapes_i.More(); aSubShapes_i.Next()) {
497 TopoDS_Shape aSubShape_i = aSubShapes_i.Current();
498 if (mapIndices.Contains(aSubShape_i)) {
499 rem_id = mapIndices.FindIndex(aSubShape_i);
500 if (rem_id > 0 && mapIDsCurrent.Contains(rem_id)) {
501 mapIDsToRemove.Add(rem_id);
508 if (mapIDsToRemove.Extent() > 0) {
509 Standard_Integer k = 1, aRemLength = mapIDsToRemove.Extent();
510 Handle(TColStd_HArray1OfInteger) aNewSeq;
511 if ( aLength - aRemLength > 0 ) {
512 aNewSeq = new TColStd_HArray1OfInteger(1, aLength - aRemLength);
513 for (j = 1; j <= aLength; j++) {
514 if (!mapIDsToRemove.Contains(aSeq->Value(j))) {
515 aNewSeq->SetValue(k, aSeq->Value(j));
521 aNewSeq = new TColStd_HArray1OfInteger(1,1);
522 aNewSeq->SetValue(1, -1);
525 if ( aFunction->IsLastFuntion() ) {
526 aSSI.SetIndices(aNewSeq);
529 aFunction = theGroup->AddFunction( GEOM_Object::GetSubShapeID(), 0, true );
530 GEOM_ISubShape aSSI2 (aFunction);
531 aSSI2.SetIndices(aNewSeq);
532 aSSI2.SetMainShape(aMainShapeFunc);
534 // As we do not recompute here our group, lets mark it as Modified
535 Standard_Integer aTic = aMainObj->GetTic(); // tic of main shape
536 theGroup->SetTic(aTic - 1);
539 //Make a Python command
540 GEOM::TPythonDump pd (aFunction, /*append=*/true);
541 pd << "geompy.DifferenceList(" << theGroup << ", [";
543 for (i = 1; i <= aLen; i++) {
544 Handle(GEOM_Object) anObj_i = Handle(GEOM_Object)::DownCast(theSubShapes->Value(i));
545 pd << anObj_i << (( i < aLen ) ? ", " : "])");
551 //=============================================================================
555 //=============================================================================
556 void GEOMImpl_IGroupOperations::UnionIDs (Handle(GEOM_Object) theGroup,
557 const Handle(TColStd_HSequenceOfInteger)& theSubShapes)
560 if (theGroup.IsNull()) return;
562 Standard_Integer aLen = theSubShapes->Length();
564 //SetErrorCode("The list is empty");
569 Handle(GEOM_Function) aFunction = theGroup->GetLastFunction();
570 if (aFunction.IsNull()) return;
572 GEOM_ISubShape aSSI (aFunction);
574 // New contents of the group
575 TColStd_ListOfInteger aNewIDs;
576 TColStd_MapOfInteger mapIDs;
578 // Add current IDs to the list
579 Handle(TColStd_HArray1OfInteger) aSeq = aSSI.GetIndices();
580 if (aSeq.IsNull()) return;
581 Standard_Integer val_j, aLength = aSeq->Length();
583 for (Standard_Integer j = 1; j <= aLength; j++) {
584 val_j = aSeq->Value(j);
585 if (val_j > 0 && mapIDs.Add(val_j)) {
586 aNewIDs.Append(val_j);
591 Handle(GEOM_Function) aMainShapeFunc = aSSI.GetMainShape();
592 if (aMainShapeFunc.IsNull()) return;
593 TDF_Label aLabel = aMainShapeFunc->GetOwnerEntry();
594 if (aLabel.IsRoot()) return;
595 Handle(GEOM_Object) aMainObj = GEOM_Object::GetObject(aLabel);
596 if (aMainObj.IsNull()) return;
597 TopoDS_Shape aMainShape = aMainObj->GetValue();
598 if (aMainShape.IsNull()) return;
600 TopTools_IndexedMapOfShape mapIndices;
601 TopExp::MapShapes(aMainShape, mapIndices);
604 TopAbs_ShapeEnum aType = GetType(theGroup);
606 // Get IDs of sub-shapes to add
607 Standard_Integer i, new_id;
608 for (i = 1; i <= aLen; i++) {
609 new_id = theSubShapes->Value(i);
611 if (0 < new_id && new_id <= mapIndices.Extent()) {
612 //if (mapIDs.Add(new_id)) { IPAL21297. Why we ignore invalid ids silently?
613 if (mapIDs.Add(new_id) && mapIndices(new_id).ShapeType()==aType ) {
614 aNewIDs.Append(new_id);
619 if (aNewIDs.Extent() > 0) {
620 Standard_Integer k = 1;
621 TColStd_ListIteratorOfListOfInteger aNewIDsIter (aNewIDs);
622 Handle(TColStd_HArray1OfInteger) aNewSeq = new TColStd_HArray1OfInteger(1, aNewIDs.Extent());
623 for (; aNewIDsIter.More(); aNewIDsIter.Next(), k++) {
624 aNewSeq->SetValue(k, aNewIDsIter.Value());
626 if ( aFunction->IsLastFuntion() ) {
627 aSSI.SetIndices(aNewSeq);
630 aFunction = theGroup->AddFunction( GEOM_Object::GetSubShapeID(), 0, true );
631 GEOM_ISubShape aSSI2 (aFunction);
632 aSSI2.SetIndices(aNewSeq);
633 aSSI2.SetMainShape(aMainShapeFunc);
635 // As we do not recompute here our group, lets mark it as Modified
636 Standard_Integer aTic = aMainObj->GetTic(); // tic of main shape
637 theGroup->SetTic(aTic - 1);
640 //Make a Python command
641 GEOM::TPythonDump pd (aFunction, /*append=*/true);
642 pd << "geompy.UnionIDs(" << theGroup << ", [";
643 for (i = 1; i < aLen; i++)
644 pd << theSubShapes->Value(i) << ", ";
645 pd << theSubShapes->Value(aLen) << "])";
650 //=============================================================================
654 //=============================================================================
655 void GEOMImpl_IGroupOperations::DifferenceIDs (Handle(GEOM_Object) theGroup,
656 const Handle(TColStd_HSequenceOfInteger)& theSubShapes)
659 if (theGroup.IsNull()) return;
661 Standard_Integer aLen = theSubShapes->Length();
663 //SetErrorCode("The list is empty");
668 Handle(GEOM_Function) aFunction = theGroup->GetLastFunction();
669 if (aFunction.IsNull()) return;
671 GEOM_ISubShape aSSI (aFunction);
673 // Map of IDs to be removed
674 TColStd_MapOfInteger mapIDsToRemove;
676 // Map of current IDs
677 Handle(TColStd_HArray1OfInteger) aSeq = aSSI.GetIndices();
678 if (aSeq.IsNull()) return;
679 Standard_Integer aLength = aSeq->Length();
681 // VSR 28/04/2011 commented to allow operation even for empty group
682 // if (aLength == 1 && aSeq->Value(1) == -1) // empty group
685 TColStd_MapOfInteger mapIDsCurrent;
686 Standard_Integer j = 1;
687 for (; j <= aLength; j++) {
688 mapIDsCurrent.Add(aSeq->Value(j));
692 Handle(GEOM_Function) aMainShapeFunc = aSSI.GetMainShape();
693 if (aMainShapeFunc.IsNull()) return;
694 TDF_Label aLabel = aMainShapeFunc->GetOwnerEntry();
695 if (aLabel.IsRoot()) return;
696 Handle(GEOM_Object) aMainObj = GEOM_Object::GetObject(aLabel);
697 if (aMainObj.IsNull()) return;
698 TopoDS_Shape aMainShape = aMainObj->GetValue();
699 if (aMainShape.IsNull()) return;
701 TopTools_IndexedMapOfShape mapIndices;
702 TopExp::MapShapes(aMainShape, mapIndices);
704 // Get IDs of sub-shapes to be removed
705 Standard_Integer i, rem_id;
706 for (i = 1; i <= aLen; i++) {
707 rem_id = theSubShapes->Value(i);
708 if (rem_id > 0 && mapIDsCurrent.Contains(rem_id)) {
709 mapIDsToRemove.Add(rem_id);
713 if (mapIDsToRemove.Extent() > 0) {
714 Standard_Integer k = 1, aRemLength = mapIDsToRemove.Extent();
715 Handle(TColStd_HArray1OfInteger) aNewSeq;
716 if ( aLength - aRemLength > 0 ) {
717 aNewSeq = new TColStd_HArray1OfInteger(1, aLength - aRemLength);
718 for (j = 1; j <= aLength; j++) {
719 if (!mapIDsToRemove.Contains(aSeq->Value(j))) {
720 aNewSeq->SetValue(k, aSeq->Value(j));
726 aNewSeq = new TColStd_HArray1OfInteger(1,1);
727 aNewSeq->SetValue(1, -1);
729 if ( aFunction->IsLastFuntion() ) {
730 aSSI.SetIndices(aNewSeq);
733 aFunction = theGroup->AddFunction( GEOM_Object::GetSubShapeID(), 0, true );
734 GEOM_ISubShape aSSI2 (aFunction);
735 aSSI2.SetIndices(aNewSeq);
736 aSSI2.SetMainShape(aMainShapeFunc);
738 // As we do not recompute here our group, lets mark it as Modified
739 Standard_Integer aTic = aMainObj->GetTic(); // tic of main shape
740 theGroup->SetTic(aTic - 1);
743 //Make a Python command
744 GEOM::TPythonDump pd (aFunction, /*append=*/true);
745 pd << "geompy.DifferenceIDs(" << theGroup << ", [";
746 for (i = 1; i < aLen; i++)
747 pd << theSubShapes->Value(i) << ", ";
748 pd << theSubShapes->Value(aLen) << "])";
753 //=============================================================================
757 //=============================================================================
758 TopAbs_ShapeEnum GEOMImpl_IGroupOperations::GetType(Handle(GEOM_Object) theGroup)
762 TDF_Label aFreeLabel = theGroup->GetFreeLabel();
763 Handle(TDataStd_Integer) anAttrib;
764 if(!aFreeLabel.FindAttribute(TDataStd_Integer::GetID(), anAttrib)) return TopAbs_SHAPE;
767 return (TopAbs_ShapeEnum) anAttrib->Get();
770 //=============================================================================
774 //=============================================================================
775 Handle(GEOM_Object) GEOMImpl_IGroupOperations::GetMainShape (Handle(GEOM_Object) theGroup)
779 if(theGroup.IsNull()) return NULL;
781 Handle(GEOM_Function) aGroupFunction = theGroup->GetFunction(1);
782 if (aGroupFunction.IsNull()) return NULL;
784 GEOM_ISubShape aSSI (aGroupFunction);
785 Handle(GEOM_Function) aMainShapeFunction = aSSI.GetMainShape();
786 if (aMainShapeFunction.IsNull()) return NULL;
788 TDF_Label aLabel = aMainShapeFunction->GetOwnerEntry();
789 Handle(GEOM_Object) aMainShape = GEOM_Object::GetObject(aLabel);
790 if (aMainShape.IsNull()) return NULL;
792 //Make a Python command
793 //GEOM::TPythonDump(aGroupFunction, /*append=*/true)
794 // << aMainShape << " = geompy.GetMainShape(" << theGroup << ")";
800 //=============================================================================
804 //=============================================================================
805 Handle(TColStd_HArray1OfInteger) GEOMImpl_IGroupOperations::GetObjects(Handle(GEOM_Object) theGroup)
809 if(theGroup.IsNull()) return NULL;
811 Handle(GEOM_Function) aFunction = theGroup->GetLastFunction();
812 if(aFunction.IsNull()) return NULL;
814 GEOM_ISubShape aSSI(aFunction);
815 Handle(TColStd_HArray1OfInteger) aSeq = aSSI.GetIndices();
816 if(aSeq.IsNull()) return NULL;
818 if(aSeq->Length() == 1 && aSeq->Value(1) == -1) {