1 // Copyright (C) 2007-2022 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, or (at your option) any later version.
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"
34 #include <Utils_ExceptHandlers.hxx>
36 #include <TFunction_DriverTable.hxx>
37 #include <TFunction_Driver.hxx>
38 #include <TDF_Tool.hxx>
39 #include <TDataStd_Integer.hxx>
42 #include <TopExp_Explorer.hxx>
43 #include <TopTools_IndexedMapOfShape.hxx>
45 #include <TColStd_HArray1OfInteger.hxx>
46 #include <TColStd_MapOfInteger.hxx>
47 #include <TColStd_ListOfInteger.hxx>
48 #include <TColStd_ListIteratorOfListOfInteger.hxx>
50 //=============================================================================
54 //=============================================================================
55 GEOMImpl_IGroupOperations::GEOMImpl_IGroupOperations (GEOM_Engine* theEngine)
56 : GEOM_IOperations(theEngine)
58 MESSAGE("GEOMImpl_IGroupOperations::GEOMImpl_IGroupOperations");
61 //=============================================================================
65 //=============================================================================
66 GEOMImpl_IGroupOperations::~GEOMImpl_IGroupOperations()
68 MESSAGE("GEOMImpl_IGroupOperations::~GEOMImpl_IGroupOperations");
72 //=============================================================================
76 //=============================================================================
77 Handle(GEOM_Object) GEOMImpl_IGroupOperations::CreateGroup
78 (Handle(GEOM_Object) theMainShape, TopAbs_ShapeEnum theShapeType)
82 if ( theShapeType != TopAbs_VERTEX && theShapeType != TopAbs_EDGE &&
83 theShapeType != TopAbs_FACE && theShapeType != TopAbs_SOLID ) {
84 SetErrorCode( "Error: You could create group of only next type: vertex, edge, face or solid" );
88 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
89 anArray->SetValue(1, -1);
91 //Add a new Sub-shape object
92 Handle(GEOM_Object) aGroup = GetEngine()->AddSubShape(theMainShape, anArray);
95 aGroup->SetType(GEOM_GROUP);
97 //Set a sub-shape type
98 TDF_Label aFreeLabel = aGroup->GetFreeLabel();
99 TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)theShapeType);
101 //Make a Python command
102 Handle(GEOM_Function) aFunction = aGroup->GetFunction(1);
104 GEOM::TPythonDump(aFunction) << aGroup
105 << " = geompy.CreateGroup(" << theMainShape << ", " << theShapeType << ")";
111 //=============================================================================
115 //=============================================================================
116 void GEOMImpl_IGroupOperations::AddObject(Handle(GEOM_Object) theGroup, int theSubShapeID)
119 if(theGroup.IsNull()) return;
121 if ( theGroup->GetType() != GEOM_GROUP ) {
122 SetErrorCode( "Error: You could perform this operation only with group. Please select a group." );
126 Handle(GEOM_Function) aFunction = theGroup->GetLastFunction();
127 if(aFunction.IsNull()) return;
129 GEOM_ISubShape aSSI (aFunction);
131 // Check sub-shape index validity
132 TDF_Label aLabel = aSSI.GetMainShape()->GetOwnerEntry();
133 if (aLabel.IsRoot()) return;
134 Handle(GEOM_Object) aMainObj = GEOM_Object::GetObject(aLabel);
135 if (aMainObj.IsNull()) return;
136 TopoDS_Shape aMainShape = aMainObj->GetValue();
137 if (aMainShape.IsNull()) return;
139 TopTools_IndexedMapOfShape aMapOfShapes;
140 TopExp::MapShapes(aMainShape, aMapOfShapes);
142 TopAbs_ShapeEnum aGroupType = GetType(theGroup);
143 TopAbs_ShapeEnum aShapeType = aMapOfShapes.FindKey(theSubShapeID).ShapeType();
144 if ( aGroupType != aShapeType ) {
145 SetErrorCode( "Error: You could perform this operation only with object the same type as the type of group." );
149 if (theSubShapeID < 1 || aMapOfShapes.Extent() < theSubShapeID) {
150 SetErrorCode("Invalid sub-shape index: out of range");
154 // Add sub-shape index
155 Handle(TColStd_HArray1OfInteger) aSeq = aSSI.GetIndices();
156 if(aSeq.IsNull()) return;
157 if(aSeq->Length() == 1 && aSeq->Value(1) == -1) {
158 aSeq->SetValue(1, theSubShapeID);
161 Standard_Integer aLength = aSeq->Length();
162 Handle(TColStd_HArray1OfInteger) aNewSeq = new TColStd_HArray1OfInteger(1, aLength+1);
163 for(Standard_Integer i = 1; i<=aLength; i++) {
164 aNewSeq->SetValue(i, aSeq->Value(i));
165 if(aSeq->Value(i) == theSubShapeID) {
166 SetErrorCode(ALREADY_PRESENT);
170 aNewSeq->SetValue(aLength+1, theSubShapeID);
171 if ( aFunction->IsLastFuntion() ) {
172 aSSI.SetIndices(aNewSeq);
175 aFunction = theGroup->AddFunction( GEOM_Object::GetSubShapeID(), 0, true );
176 GEOM_ISubShape aSSI2 (aFunction);
177 aSSI2.SetIndices(aNewSeq);
178 aSSI2.SetMainShape( aSSI.GetMainShape() );
182 // As we do not recompute here our group, lets mark it as Modified
183 Standard_Integer aTic = aMainObj->GetTic(); // tic of main shape
184 theGroup->SetTic(aTic - 1);
186 //Make a Python command
187 GEOM::TPythonDump(aFunction, /*append=*/true)
188 << "geompy.AddObject(" << theGroup << ", " << theSubShapeID << ")";
194 //=============================================================================
198 //=============================================================================
199 void GEOMImpl_IGroupOperations::RemoveObject (Handle(GEOM_Object) theGroup, int theSubShapeID)
202 if(theGroup.IsNull()) return;
204 if ( theGroup->GetType() != GEOM_GROUP ) {
205 SetErrorCode( "Error: You could perform this operation only with group. Please select a group." );
209 Handle(GEOM_Function) aFunction = theGroup->GetLastFunction();
210 if(aFunction.IsNull()) return;
212 GEOM_ISubShape aSSI(aFunction);
213 Handle(TColStd_HArray1OfInteger) aSeq = aSSI.GetIndices();
214 if(aSeq.IsNull()) return;
216 if(aSeq->Length() == 1 && aSeq->Value(1) == -1) {
217 SetErrorCode(NOT_EXISTS);
221 Handle(TColStd_HArray1OfInteger) aNewSeq;
222 Standard_Integer aLength = aSeq->Length();
224 if(aSeq->Value(1) != theSubShapeID) {
225 SetErrorCode(NOT_EXISTS);
228 aNewSeq = new TColStd_HArray1OfInteger(1,1);
229 aNewSeq->SetValue(1, -1);
232 aNewSeq = new TColStd_HArray1OfInteger(1, aLength-1);
233 Standard_Boolean isFound = Standard_False;
234 for (Standard_Integer i = 1, k = 1; i <= aLength; i++) {
235 if (aSeq->Value(i) == theSubShapeID) {
236 isFound = Standard_True;
238 if (k < aLength) { // this check is to avoid sequence <aNewSeq> overflow
239 aNewSeq->SetValue(k, aSeq->Value(i));
246 SetErrorCode(NOT_EXISTS);
251 if ( aFunction->IsLastFuntion() ) {
252 aSSI.SetIndices(aNewSeq);
255 aFunction = theGroup->AddFunction( GEOM_Object::GetSubShapeID(), 0, true );
256 GEOM_ISubShape aSSI2 (aFunction);
257 aSSI2.SetIndices(aNewSeq);
258 aSSI2.SetMainShape( aSSI.GetMainShape() );
261 // As we do not recompute here our group, lets mark it as Modified
262 TDF_Label aLabel = aSSI.GetMainShape()->GetOwnerEntry();
263 if (aLabel.IsRoot()) return;
264 Handle(GEOM_Object) aMainObj = GEOM_Object::GetObject(aLabel);
265 if (aMainObj.IsNull()) return;
266 Standard_Integer aTic = aMainObj->GetTic(); // tic of main shape
267 theGroup->SetTic(aTic - 1);
269 //Make a Python command
270 GEOM::TPythonDump(aFunction, /*append=*/true)
271 << "geompy.RemoveObject(" << theGroup << ", " << theSubShapeID << ")";
277 //=============================================================================
281 //=============================================================================
282 void GEOMImpl_IGroupOperations::UnionList (Handle(GEOM_Object) theGroup,
283 const Handle(TColStd_HSequenceOfTransient)& theSubShapes)
286 if (theGroup.IsNull()) return;
288 if ( theGroup->GetType() != GEOM_GROUP ) {
289 SetErrorCode( "Error: You could perform this operation only with group. Please select a group." );
293 Standard_Integer aLen = theSubShapes->Length();
295 //SetErrorCode("The list is empty");
300 Handle(GEOM_Function) aFunction = theGroup->GetLastFunction();
301 if (aFunction.IsNull()) return;
303 GEOM_ISubShape aSSI (aFunction);
305 // New contents of the group
306 TColStd_ListOfInteger aNewIDs;
307 TColStd_MapOfInteger mapIDs;
309 // Add current IDs to the list
310 Handle(TColStd_HArray1OfInteger) aSeq = aSSI.GetIndices();
311 if (aSeq.IsNull()) return;
312 Standard_Integer val_j, aLength = aSeq->Length();
314 for (Standard_Integer j = 1; j <= aLength; j++) {
315 val_j = aSeq->Value(j);
316 if (val_j > 0 && mapIDs.Add(val_j)) {
317 aNewIDs.Append(val_j);
322 Handle(GEOM_Function) aMainShapeFunc = aSSI.GetMainShape();
323 if (aMainShapeFunc.IsNull()) return;
324 TDF_Label aLabel = aMainShapeFunc->GetOwnerEntry();
325 if (aLabel.IsRoot()) return;
326 Handle(GEOM_Object) aMainObj = GEOM_Object::GetObject(aLabel);
327 if (aMainObj.IsNull()) return;
328 TopoDS_Shape aMainShape = aMainObj->GetValue();
329 if (aMainShape.IsNull()) return;
331 TopTools_IndexedMapOfShape mapIndices;
332 TopExp::MapShapes(aMainShape, mapIndices);
335 TopAbs_ShapeEnum aType = GetType(theGroup);
337 // Get IDs of sub-shapes to add
338 Standard_Integer i, new_id;
339 for (i = 1; i <= aLen; i++) {
340 Handle(GEOM_Object) anObj_i = Handle(GEOM_Object)::DownCast(theSubShapes->Value(i));
342 TopoDS_Shape aShape_i = anObj_i->GetValue();
343 if ( aShape_i.IsNull() ) continue;
344 TopAbs_ShapeEnum aType_i = aShape_i.ShapeType();
346 // 1. If aShape_i is sub-shape of aMainShape - add it
347 if (anObj_i->IsMainShape()) {
348 if (aType_i != aType && aType != TopAbs_SHAPE && aType != TopAbs_COMPOUND) {
349 SetErrorCode("Operation aborted: one of given objects has a wrong type");
352 if (!mapIndices.Contains(aShape_i)) {
353 SetErrorCode("Operation aborted: not a sub-shape given");
356 new_id = mapIndices.FindIndex(aShape_i);
357 if (mapIDs.Add(new_id)) {
358 aNewIDs.Append(new_id);
361 // 2. If type of group is not defined - add all sub-shapes of aShape_i
362 else if (aType == TopAbs_SHAPE || aType == TopAbs_COMPOUND) {
363 TopTools_IndexedMapOfShape mapIndices_i;
364 TopExp::MapShapes(aShape_i, mapIndices_i);
365 Standard_Integer ii = 1, nbSubSh = mapIndices_i.Extent();
366 Standard_Boolean someGood = Standard_False;
367 for (; ii <= nbSubSh; ii++) {
368 TopoDS_Shape aSubShape_i = mapIndices_i.FindKey(ii);
369 if (mapIndices.Contains(aSubShape_i)) {
370 someGood = Standard_True;
371 new_id = mapIndices.FindIndex(aSubShape_i);
372 if (mapIDs.Add(new_id)) {
373 aNewIDs.Append(new_id);
378 SetErrorCode("Operation aborted: not a sub-shape given");
382 // 3. If type of group is defined - add all sub-shapes of aShape_i of that type
384 TopExp_Explorer aSubShapes_i (aShape_i, aType);
385 for (; aSubShapes_i.More(); aSubShapes_i.Next()) {
386 TopoDS_Shape aSubShape_i = aSubShapes_i.Current();
387 if (!mapIndices.Contains(aSubShape_i)) {
388 SetErrorCode("Operation aborted: not a sub-shape given");
391 new_id = mapIndices.FindIndex(aSubShape_i);
392 if (mapIDs.Add(new_id)) {
393 aNewIDs.Append(new_id);
399 if (aNewIDs.Extent() > 0) {
400 Standard_Integer k = 1;
401 TColStd_ListIteratorOfListOfInteger aNewIDsIter (aNewIDs);
402 Handle(TColStd_HArray1OfInteger) aNewSeq = new TColStd_HArray1OfInteger(1, aNewIDs.Extent());
403 for (; aNewIDsIter.More(); aNewIDsIter.Next(), k++) {
404 aNewSeq->SetValue(k, aNewIDsIter.Value());
406 if ( aFunction->IsLastFuntion() ) {
407 aSSI.SetIndices(aNewSeq);
410 aFunction = theGroup->AddFunction( GEOM_Object::GetSubShapeID(), 0, true );
411 GEOM_ISubShape aSSI2 (aFunction);
412 aSSI2.SetIndices(aNewSeq);
413 aSSI2.SetMainShape(aMainShapeFunc);
415 // As we do not recompute here our group, lets mark it as Modified
416 Standard_Integer aTic = aMainObj->GetTic(); // tic of main shape
417 theGroup->SetTic(aTic - 1);
420 //Make a Python command
421 GEOM::TPythonDump pd (aFunction, /*append=*/true);
422 pd << "geompy.UnionList(" << theGroup << ", [";
424 for (i = 1; i <= aLen; i++) {
425 Handle(GEOM_Object) anObj_i = Handle(GEOM_Object)::DownCast(theSubShapes->Value(i));
426 pd << anObj_i << (( i < aLen ) ? ", " : "])");
432 //=============================================================================
436 //=============================================================================
437 void GEOMImpl_IGroupOperations::DifferenceList (Handle(GEOM_Object) theGroup,
438 const Handle(TColStd_HSequenceOfTransient)& theSubShapes)
441 if (theGroup.IsNull()) return;
443 if ( theGroup->GetType() != GEOM_GROUP ) {
444 SetErrorCode( "Error: You could perform this operation only with group. Please select a group." );
448 Standard_Integer aLen = theSubShapes->Length();
450 //SetErrorCode("The list is empty");
455 Handle(GEOM_Function) aFunction = theGroup->GetLastFunction();
456 if (aFunction.IsNull()) return;
458 GEOM_ISubShape aSSI (aFunction);
460 // Map of IDs to be removed
461 TColStd_MapOfInteger mapIDsToRemove;
463 // Map of current IDs
464 Handle(TColStd_HArray1OfInteger) aSeq = aSSI.GetIndices();
465 if (aSeq.IsNull()) return;
466 Standard_Integer aLength = aSeq->Length();
468 // VSR 28/04/2011 commented to allow operation even for empty group
469 // if (aLength == 1 && aSeq->Value(1) == -1) // empty group
472 TColStd_MapOfInteger mapIDsCurrent;
473 Standard_Integer j = 1;
474 for (; j <= aLength; j++) {
475 mapIDsCurrent.Add(aSeq->Value(j));
479 Handle(GEOM_Function) aMainShapeFunc = aSSI.GetMainShape();
480 if (aMainShapeFunc.IsNull()) return;
481 TDF_Label aLabel = aMainShapeFunc->GetOwnerEntry();
482 if (aLabel.IsRoot()) return;
483 Handle(GEOM_Object) aMainObj = GEOM_Object::GetObject(aLabel);
484 if (aMainObj.IsNull()) return;
485 TopoDS_Shape aMainShape = aMainObj->GetValue();
486 if (aMainShape.IsNull()) return;
488 TopTools_IndexedMapOfShape mapIndices;
489 TopExp::MapShapes(aMainShape, mapIndices);
492 TopAbs_ShapeEnum aType = GetType(theGroup);
494 // Get IDs of sub-shapes to be removed
495 Standard_Integer i, rem_id;
496 for (i = 1; i <= aLen; i++) {
497 Handle(GEOM_Object) anObj_i = Handle(GEOM_Object)::DownCast(theSubShapes->Value(i));
499 TopoDS_Shape aShape_i = anObj_i->GetValue();
501 // 1. If aShape_i is sub-shape of aMainShape - remove it
502 if (mapIndices.Contains(aShape_i)) {
503 rem_id = mapIndices.FindIndex(aShape_i);
504 if (rem_id > 0 && mapIDsCurrent.Contains(rem_id)) {
505 mapIDsToRemove.Add(rem_id);
508 // 2. If type of group is not defined - remove all sub-shapes of aShape_i
509 else if (aType == TopAbs_SHAPE || aType == TopAbs_COMPOUND) {
510 TopTools_IndexedMapOfShape mapIndices_i;
511 TopExp::MapShapes(aShape_i, mapIndices_i);
512 Standard_Integer nbSubSh = mapIndices_i.Extent();
513 Standard_Integer ii = 1;
514 for (; ii <= nbSubSh; ii++) {
515 TopoDS_Shape aSubShape_i = mapIndices_i.FindKey(ii);
516 if (mapIndices.Contains(aSubShape_i)) {
517 rem_id = mapIndices.FindIndex(aSubShape_i);
518 if (rem_id > 0 && mapIDsCurrent.Contains(rem_id)) {
519 mapIDsToRemove.Add(rem_id);
524 // 3. If type of group is defined - remove all sub-shapes of aShape_i of that type
526 TopExp_Explorer aSubShapes_i (aShape_i, aType);
527 for (; aSubShapes_i.More(); aSubShapes_i.Next()) {
528 TopoDS_Shape aSubShape_i = aSubShapes_i.Current();
529 if (mapIndices.Contains(aSubShape_i)) {
530 rem_id = mapIndices.FindIndex(aSubShape_i);
531 if (rem_id > 0 && mapIDsCurrent.Contains(rem_id)) {
532 mapIDsToRemove.Add(rem_id);
539 if (mapIDsToRemove.Extent() > 0) {
540 Standard_Integer k = 1, aRemLength = mapIDsToRemove.Extent();
541 Handle(TColStd_HArray1OfInteger) aNewSeq;
542 if ( aLength - aRemLength > 0 ) {
543 aNewSeq = new TColStd_HArray1OfInteger(1, aLength - aRemLength);
544 for (j = 1; j <= aLength; j++) {
545 if (!mapIDsToRemove.Contains(aSeq->Value(j))) {
546 aNewSeq->SetValue(k, aSeq->Value(j));
552 aNewSeq = new TColStd_HArray1OfInteger(1,1);
553 aNewSeq->SetValue(1, -1);
556 if ( aFunction->IsLastFuntion() ) {
557 aSSI.SetIndices(aNewSeq);
560 aFunction = theGroup->AddFunction( GEOM_Object::GetSubShapeID(), 0, true );
561 GEOM_ISubShape aSSI2 (aFunction);
562 aSSI2.SetIndices(aNewSeq);
563 aSSI2.SetMainShape(aMainShapeFunc);
565 // As we do not recompute here our group, lets mark it as Modified
566 Standard_Integer aTic = aMainObj->GetTic(); // tic of main shape
567 theGroup->SetTic(aTic - 1);
570 //Make a Python command
571 GEOM::TPythonDump pd (aFunction, /*append=*/true);
572 pd << "geompy.DifferenceList(" << theGroup << ", [";
574 for (i = 1; i <= aLen; i++) {
575 Handle(GEOM_Object) anObj_i = Handle(GEOM_Object)::DownCast(theSubShapes->Value(i));
576 pd << anObj_i << (( i < aLen ) ? ", " : "])");
582 //=============================================================================
586 //=============================================================================
587 void GEOMImpl_IGroupOperations::UnionIDs (Handle(GEOM_Object) theGroup,
588 const Handle(TColStd_HSequenceOfInteger)& theSubShapes)
591 if (theGroup.IsNull()) return;
593 if ( theGroup->GetType() != GEOM_GROUP ) {
594 SetErrorCode( "Error: You could perform this operation only with group. Please select a group." );
598 Standard_Integer aLen = theSubShapes->Length();
600 //SetErrorCode("The list is empty");
605 Handle(GEOM_Function) aFunction = theGroup->GetLastFunction();
606 if (aFunction.IsNull()) return;
608 GEOM_ISubShape aSSI (aFunction);
610 // New contents of the group
611 TColStd_ListOfInteger aNewIDs;
612 TColStd_MapOfInteger mapIDs;
614 // Add current IDs to the list
615 Handle(TColStd_HArray1OfInteger) aSeq = aSSI.GetIndices();
616 if (aSeq.IsNull()) return;
617 Standard_Integer val_j, aLength = aSeq->Length();
619 for (Standard_Integer j = 1; j <= aLength; j++) {
620 val_j = aSeq->Value(j);
621 if (val_j > 0 && mapIDs.Add(val_j)) {
622 aNewIDs.Append(val_j);
627 Handle(GEOM_Function) aMainShapeFunc = aSSI.GetMainShape();
628 if (aMainShapeFunc.IsNull()) return;
629 TDF_Label aLabel = aMainShapeFunc->GetOwnerEntry();
630 if (aLabel.IsRoot()) return;
631 Handle(GEOM_Object) aMainObj = GEOM_Object::GetObject(aLabel);
632 if (aMainObj.IsNull()) return;
633 TopoDS_Shape aMainShape = aMainObj->GetValue();
634 if (aMainShape.IsNull()) return;
636 TopTools_IndexedMapOfShape mapIndices;
637 TopExp::MapShapes(aMainShape, mapIndices);
640 TopAbs_ShapeEnum aType = GetType(theGroup);
642 // Get IDs of sub-shapes to add
643 Standard_Integer i, new_id;
644 for (i = 1; i <= aLen; i++) {
645 new_id = theSubShapes->Value(i);
647 if (0 < new_id && new_id <= mapIndices.Extent()) {
648 //if (mapIDs.Add(new_id)) { IPAL21297. Why we ignore invalid ids silently?
649 if (mapIDs.Add(new_id) && mapIndices(new_id).ShapeType()==aType ) {
650 aNewIDs.Append(new_id);
655 if (aNewIDs.Extent() > 0) {
656 Standard_Integer k = 1;
657 TColStd_ListIteratorOfListOfInteger aNewIDsIter (aNewIDs);
658 Handle(TColStd_HArray1OfInteger) aNewSeq = new TColStd_HArray1OfInteger(1, aNewIDs.Extent());
659 for (; aNewIDsIter.More(); aNewIDsIter.Next(), k++) {
660 aNewSeq->SetValue(k, aNewIDsIter.Value());
662 if ( aFunction->IsLastFuntion() ) {
663 aSSI.SetIndices(aNewSeq);
666 aFunction = theGroup->AddFunction( GEOM_Object::GetSubShapeID(), 0, true );
667 GEOM_ISubShape aSSI2 (aFunction);
668 aSSI2.SetIndices(aNewSeq);
669 aSSI2.SetMainShape(aMainShapeFunc);
671 // As we do not recompute here our group, lets mark it as Modified
672 Standard_Integer aTic = aMainObj->GetTic(); // tic of main shape
673 theGroup->SetTic(aTic - 1);
676 //Make a Python command
677 GEOM::TPythonDump pd (aFunction, /*append=*/true);
678 pd << "geompy.UnionIDs(" << theGroup << ", [";
679 for (i = 1; i < aLen; i++)
680 pd << theSubShapes->Value(i) << ", ";
681 pd << theSubShapes->Value(aLen) << "])";
686 //=============================================================================
690 //=============================================================================
691 void GEOMImpl_IGroupOperations::DifferenceIDs (Handle(GEOM_Object) theGroup,
692 const Handle(TColStd_HSequenceOfInteger)& theSubShapes)
695 if (theGroup.IsNull()) return;
697 if ( theGroup->GetType() != GEOM_GROUP ) {
698 SetErrorCode( "Error: You could perform this operation only with group. Please select a group." );
702 Standard_Integer aLen = theSubShapes->Length();
704 //SetErrorCode("The list is empty");
709 Handle(GEOM_Function) aFunction = theGroup->GetLastFunction();
710 if (aFunction.IsNull()) return;
712 GEOM_ISubShape aSSI (aFunction);
714 // Map of IDs to be removed
715 TColStd_MapOfInteger mapIDsToRemove;
717 // Map of current IDs
718 Handle(TColStd_HArray1OfInteger) aSeq = aSSI.GetIndices();
719 if (aSeq.IsNull()) return;
720 Standard_Integer aLength = aSeq->Length();
722 // VSR 28/04/2011 commented to allow operation even for empty group
723 // if (aLength == 1 && aSeq->Value(1) == -1) // empty group
726 TColStd_MapOfInteger mapIDsCurrent;
727 Standard_Integer j = 1;
728 for (; j <= aLength; j++) {
729 mapIDsCurrent.Add(aSeq->Value(j));
733 Handle(GEOM_Function) aMainShapeFunc = aSSI.GetMainShape();
734 if (aMainShapeFunc.IsNull()) return;
735 TDF_Label aLabel = aMainShapeFunc->GetOwnerEntry();
736 if (aLabel.IsRoot()) return;
737 Handle(GEOM_Object) aMainObj = GEOM_Object::GetObject(aLabel);
738 if (aMainObj.IsNull()) return;
739 TopoDS_Shape aMainShape = aMainObj->GetValue();
740 if (aMainShape.IsNull()) return;
742 TopTools_IndexedMapOfShape mapIndices;
743 TopExp::MapShapes(aMainShape, mapIndices);
745 // Get IDs of sub-shapes to be removed
746 Standard_Integer i, rem_id;
747 for (i = 1; i <= aLen; i++) {
748 rem_id = theSubShapes->Value(i);
749 if (rem_id > 0 && mapIDsCurrent.Contains(rem_id)) {
750 mapIDsToRemove.Add(rem_id);
754 if (mapIDsToRemove.Extent() > 0) {
755 Standard_Integer k = 1, aRemLength = mapIDsToRemove.Extent();
756 Handle(TColStd_HArray1OfInteger) aNewSeq;
757 if ( aLength - aRemLength > 0 ) {
758 aNewSeq = new TColStd_HArray1OfInteger(1, aLength - aRemLength);
759 for (j = 1; j <= aLength; j++) {
760 if (!mapIDsToRemove.Contains(aSeq->Value(j))) {
761 aNewSeq->SetValue(k, aSeq->Value(j));
767 aNewSeq = new TColStd_HArray1OfInteger(1,1);
768 aNewSeq->SetValue(1, -1);
770 if ( aFunction->IsLastFuntion() ) {
771 aSSI.SetIndices(aNewSeq);
774 aFunction = theGroup->AddFunction( GEOM_Object::GetSubShapeID(), 0, true );
775 GEOM_ISubShape aSSI2 (aFunction);
776 aSSI2.SetIndices(aNewSeq);
777 aSSI2.SetMainShape(aMainShapeFunc);
779 // As we do not recompute here our group, lets mark it as Modified
780 Standard_Integer aTic = aMainObj->GetTic(); // tic of main shape
781 theGroup->SetTic(aTic - 1);
784 //Make a Python command
785 GEOM::TPythonDump pd (aFunction, /*append=*/true);
786 pd << "geompy.DifferenceIDs(" << theGroup << ", [";
787 for (i = 1; i < aLen; i++)
788 pd << theSubShapes->Value(i) << ", ";
789 pd << theSubShapes->Value(aLen) << "])";
794 //=============================================================================
798 //=============================================================================
799 Handle(GEOM_Object) GEOMImpl_IGroupOperations::UnionGroups (Handle(GEOM_Object) theGroup1,
800 Handle(GEOM_Object) theGroup2)
803 if (theGroup1.IsNull() || theGroup2.IsNull()) return NULL;
805 if ( theGroup1->GetType() != GEOM_GROUP || theGroup2->GetType() != GEOM_GROUP ) {
806 SetErrorCode( "Error: You could perform this operation only with group. Please select a group." );
811 TopAbs_ShapeEnum aType1 = GetType(theGroup1);
812 TopAbs_ShapeEnum aType2 = GetType(theGroup2);
813 TopAbs_ShapeEnum aType = aType1;
814 if (aType1 != aType2) {
815 if (aType1 != TopAbs_SHAPE && aType1 != TopAbs_COMPOUND) {
816 if (aType2 == TopAbs_SHAPE || aType2 == TopAbs_COMPOUND)
819 SetErrorCode("Error: UnionGroups cannot be performed on groups of different type");
826 Handle(GEOM_Function) aFunction1 = theGroup1->GetLastFunction();
827 Handle(GEOM_Function) aFunction2 = theGroup2->GetLastFunction();
828 if (aFunction1.IsNull() || aFunction2.IsNull()) return NULL;
830 GEOM_ISubShape aSSI1 (aFunction1);
831 GEOM_ISubShape aSSI2 (aFunction2);
833 Handle(GEOM_Function) aMainShapeFunc1 = aSSI1.GetMainShape();
834 Handle(GEOM_Function) aMainShapeFunc2 = aSSI2.GetMainShape();
835 if (aMainShapeFunc1.IsNull() || aMainShapeFunc2.IsNull()) return NULL;
837 TDF_Label aLabel1 = aMainShapeFunc1->GetOwnerEntry();
838 TDF_Label aLabel2 = aMainShapeFunc2->GetOwnerEntry();
839 if (aLabel1.IsRoot() || aLabel2.IsRoot()) {
840 SetErrorCode("Error: UnionGroups can be performed only on groups");
844 if (aLabel1 != aLabel2) {
845 SetErrorCode("Error: UnionGroups cannot be performed on groups, built on different main shapes");
849 Handle(GEOM_Object) aMainObj = GEOM_Object::GetObject(aLabel1);
850 if (aMainObj.IsNull()) return NULL;
852 // New contents of the group
853 TColStd_ListOfInteger aNewIDs;
854 TColStd_MapOfInteger mapIDs;
856 Handle(TColStd_HArray1OfInteger) aSeq1 = aSSI1.GetIndices();
857 Handle(TColStd_HArray1OfInteger) aSeq2 = aSSI2.GetIndices();
858 if (aSeq1.IsNull() || aSeq2.IsNull()) return NULL;
860 Standard_Integer j, val_j;
861 Standard_Integer aLength1 = aSeq1->Length();
862 Standard_Integer aLength2 = aSeq2->Length();
864 for (j = 1; j <= aLength1; j++) {
865 val_j = aSeq1->Value(j);
866 if (val_j > 0 && mapIDs.Add(val_j)) {
867 aNewIDs.Append(val_j);
870 for (j = 1; j <= aLength2; j++) {
871 val_j = aSeq2->Value(j);
872 if (val_j > 0 && mapIDs.Add(val_j)) {
873 aNewIDs.Append(val_j);
877 if (aNewIDs.Extent() < 1) {
878 SetErrorCode("Error: UnionGroups cannot be performed on two empty groups");
882 // Put new indices from the list into an array
883 Standard_Integer k = 1;
884 TColStd_ListIteratorOfListOfInteger aNewIDsIter (aNewIDs);
885 Handle(TColStd_HArray1OfInteger) aNewArr = new TColStd_HArray1OfInteger (1, aNewIDs.Extent());
886 for (; aNewIDsIter.More(); aNewIDsIter.Next(), k++) {
887 aNewArr->SetValue(k, aNewIDsIter.Value());
891 Handle(GEOM_Object) aGroup = GetEngine()->AddSubShape(aMainObj, aNewArr);
892 aGroup->SetType(GEOM_GROUP);
893 TDF_Label aFreeLabel = aGroup->GetFreeLabel();
894 TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aType);
896 // Make a Python command
897 Handle(GEOM_Function) aFunction = aGroup->GetFunction(1);
898 GEOM::TPythonDump(aFunction) << aGroup << " = geompy.UnionGroups("
899 << theGroup1 << ", " << theGroup2 << ")";
905 //=============================================================================
909 //=============================================================================
910 Handle(GEOM_Object) GEOMImpl_IGroupOperations::IntersectGroups (Handle(GEOM_Object) theGroup1,
911 Handle(GEOM_Object) theGroup2)
914 if (theGroup1.IsNull() || theGroup2.IsNull()) return NULL;
916 if ( theGroup1->GetType() != GEOM_GROUP || theGroup2->GetType() != GEOM_GROUP ) {
917 SetErrorCode( "Error: You could perform this operation only with group. Please select a group." );
922 TopAbs_ShapeEnum aType1 = GetType(theGroup1);
923 TopAbs_ShapeEnum aType2 = GetType(theGroup2);
924 TopAbs_ShapeEnum aType = aType1;
925 if (aType1 != aType2) {
926 if (aType1 != TopAbs_SHAPE && aType1 != TopAbs_COMPOUND) {
927 if (aType2 == TopAbs_SHAPE || aType2 == TopAbs_COMPOUND)
930 SetErrorCode("Error: IntersectGroups cannot be performed on groups of different type");
937 Handle(GEOM_Function) aFunction1 = theGroup1->GetLastFunction();
938 Handle(GEOM_Function) aFunction2 = theGroup2->GetLastFunction();
939 if (aFunction1.IsNull() || aFunction2.IsNull()) return NULL;
941 GEOM_ISubShape aSSI1 (aFunction1);
942 GEOM_ISubShape aSSI2 (aFunction2);
944 Handle(GEOM_Function) aMainShapeFunc1 = aSSI1.GetMainShape();
945 Handle(GEOM_Function) aMainShapeFunc2 = aSSI2.GetMainShape();
946 if (aMainShapeFunc1.IsNull() || aMainShapeFunc2.IsNull()) return NULL;
948 TDF_Label aLabel1 = aMainShapeFunc1->GetOwnerEntry();
949 TDF_Label aLabel2 = aMainShapeFunc2->GetOwnerEntry();
950 if (aLabel1.IsRoot() || aLabel2.IsRoot()) {
951 SetErrorCode("Error: UnionGroups can be performed only on groups");
955 if (aLabel1 != aLabel2) {
956 SetErrorCode("Error: IntersectGroups cannot be performed on groups, built on different main shapes");
960 Handle(GEOM_Object) aMainObj = GEOM_Object::GetObject(aLabel1);
961 if (aMainObj.IsNull()) return NULL;
963 // New contents of the group
964 TColStd_ListOfInteger aNewIDs;
965 TColStd_MapOfInteger mapIDs;
967 Handle(TColStd_HArray1OfInteger) aSeq1 = aSSI1.GetIndices();
968 Handle(TColStd_HArray1OfInteger) aSeq2 = aSSI2.GetIndices();
969 if (aSeq1.IsNull() || aSeq2.IsNull()) return NULL;
971 Standard_Integer j, val_j;
972 Standard_Integer aLength1 = aSeq1->Length();
973 Standard_Integer aLength2 = aSeq2->Length();
975 for (j = 1; j <= aLength1; j++) {
976 mapIDs.Add(aSeq1->Value(j));
978 for (j = 1; j <= aLength2; j++) {
979 val_j = aSeq2->Value(j);
980 if (val_j > 0 && !mapIDs.Add(val_j)) {
981 // add index, if it is in mapIDs (filled from Group_1)
982 aNewIDs.Append(val_j);
986 Handle(TColStd_HArray1OfInteger) aNewArr;
987 if (aNewIDs.Extent() < 1) {
988 aNewArr = new TColStd_HArray1OfInteger (1, 1);
989 aNewArr->SetValue(1, -1);
992 // Put new indices from the list into an array
993 Standard_Integer k = 1;
994 TColStd_ListIteratorOfListOfInteger aNewIDsIter (aNewIDs);
995 aNewArr = new TColStd_HArray1OfInteger (1, aNewIDs.Extent());
996 for (; aNewIDsIter.More(); aNewIDsIter.Next(), k++) {
997 aNewArr->SetValue(k, aNewIDsIter.Value());
1002 Handle(GEOM_Object) aGroup = GetEngine()->AddSubShape(aMainObj, aNewArr);
1003 aGroup->SetType(GEOM_GROUP);
1004 TDF_Label aFreeLabel = aGroup->GetFreeLabel();
1005 TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aType);
1007 // Make a Python command
1008 Handle(GEOM_Function) aFunction = aGroup->GetFunction(1);
1009 GEOM::TPythonDump(aFunction) << aGroup << " = geompy.IntersectGroups("
1010 << theGroup1 << ", " << theGroup2 << ")";
1016 //=============================================================================
1020 //=============================================================================
1021 Handle(GEOM_Object) GEOMImpl_IGroupOperations::CutGroups (Handle(GEOM_Object) theGroup1,
1022 Handle(GEOM_Object) theGroup2)
1025 if (theGroup1.IsNull() || theGroup2.IsNull()) return NULL;
1027 if ( theGroup1->GetType() != GEOM_GROUP || theGroup2->GetType() != GEOM_GROUP ) {
1028 SetErrorCode( "Error: You could perform this operation only with group. Please select a group." );
1033 TopAbs_ShapeEnum aType1 = GetType(theGroup1);
1034 TopAbs_ShapeEnum aType2 = GetType(theGroup2);
1035 TopAbs_ShapeEnum aType = aType1;
1036 if (aType1 != aType2) {
1037 if (aType1 != TopAbs_SHAPE && aType1 != TopAbs_COMPOUND) {
1038 if (aType2 == TopAbs_SHAPE || aType2 == TopAbs_COMPOUND)
1041 SetErrorCode("Error: CutGroups cannot be performed on groups of different type");
1048 Handle(GEOM_Function) aFunction1 = theGroup1->GetLastFunction();
1049 Handle(GEOM_Function) aFunction2 = theGroup2->GetLastFunction();
1050 if (aFunction1.IsNull() || aFunction2.IsNull()) return NULL;
1052 GEOM_ISubShape aSSI1 (aFunction1);
1053 GEOM_ISubShape aSSI2 (aFunction2);
1055 Handle(GEOM_Function) aMainShapeFunc1 = aSSI1.GetMainShape();
1056 Handle(GEOM_Function) aMainShapeFunc2 = aSSI2.GetMainShape();
1057 if (aMainShapeFunc1.IsNull() || aMainShapeFunc2.IsNull()) return NULL;
1059 TDF_Label aLabel1 = aMainShapeFunc1->GetOwnerEntry();
1060 TDF_Label aLabel2 = aMainShapeFunc2->GetOwnerEntry();
1061 if (aLabel1.IsRoot() || aLabel2.IsRoot()) {
1062 SetErrorCode("Error: UnionGroups can be performed only on groups");
1066 if (aLabel1 != aLabel2) {
1067 SetErrorCode("Error: CutGroups cannot be performed on groups, built on different main shapes");
1071 Handle(GEOM_Object) aMainObj = GEOM_Object::GetObject(aLabel1);
1072 if (aMainObj.IsNull()) return NULL;
1074 // New contents of the group
1075 TColStd_ListOfInteger aNewIDs;
1076 TColStd_MapOfInteger mapIDs;
1078 Handle(TColStd_HArray1OfInteger) aSeq1 = aSSI1.GetIndices();
1079 Handle(TColStd_HArray1OfInteger) aSeq2 = aSSI2.GetIndices();
1080 if (aSeq1.IsNull() || aSeq2.IsNull()) return NULL;
1082 Standard_Integer j, val_j;
1083 Standard_Integer aLength1 = aSeq1->Length();
1084 Standard_Integer aLength2 = aSeq2->Length();
1086 for (j = 1; j <= aLength2; j++) {
1087 mapIDs.Add(aSeq2->Value(j));
1089 for (j = 1; j <= aLength1; j++) {
1090 val_j = aSeq1->Value(j);
1091 if (val_j > 0 && mapIDs.Add(val_j)) {
1092 // add index, if it is not in mapIDs (filled from Group_2)
1093 aNewIDs.Append(val_j);
1097 Handle(TColStd_HArray1OfInteger) aNewArr;
1098 if (aNewIDs.Extent() < 1) {
1099 aNewArr = new TColStd_HArray1OfInteger (1, 1);
1100 aNewArr->SetValue(1, -1);
1103 // Put new indices from the list into an array
1104 Standard_Integer k = 1;
1105 TColStd_ListIteratorOfListOfInteger aNewIDsIter (aNewIDs);
1106 aNewArr = new TColStd_HArray1OfInteger (1, aNewIDs.Extent());
1107 for (; aNewIDsIter.More(); aNewIDsIter.Next(), k++) {
1108 aNewArr->SetValue(k, aNewIDsIter.Value());
1113 Handle(GEOM_Object) aGroup = GetEngine()->AddSubShape(aMainObj, aNewArr);
1114 aGroup->SetType(GEOM_GROUP);
1115 TDF_Label aFreeLabel = aGroup->GetFreeLabel();
1116 TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aType);
1118 // Make a Python command
1119 Handle(GEOM_Function) aFunction = aGroup->GetFunction(1);
1120 GEOM::TPythonDump(aFunction) << aGroup << " = geompy.CutGroups("
1121 << theGroup1 << ", " << theGroup2 << ")";
1127 //=============================================================================
1131 //=============================================================================
1132 Handle(GEOM_Object) GEOMImpl_IGroupOperations::UnionListOfGroups
1133 (const Handle(TColStd_HSequenceOfTransient)& theGList)
1136 if (theGList.IsNull()) return NULL;
1138 Standard_Integer i, aLen = theGList->Length();
1140 SetErrorCode("UnionListOfGroups error: the list of groups is empty");
1144 TopAbs_ShapeEnum aType = TopAbs_SHAPE, aType_i; // todo: refactor: aType must be initialized to avoid warning (see below)
1145 TDF_Label aLabel, aLabel_i;
1146 TColStd_ListOfInteger aNewIDs;
1147 TColStd_MapOfInteger mapIDs;
1149 // Iterate on the initial groups
1150 for (i = 1; i <= aLen; i++) {
1151 Handle(GEOM_Object) aGr_i = Handle(GEOM_Object)::DownCast(theGList->Value(i));
1152 if ( aGr_i->GetType() != GEOM_GROUP ) {
1153 SetErrorCode( "Error: You could perform this operation only with group. Please select a group." );
1157 aType_i = GetType(aGr_i);
1161 if (aType_i != aType) {
1162 if (aType != TopAbs_SHAPE && aType != TopAbs_COMPOUND) { // todo: refactor: aType must be initialized to avoid warning (see above)
1163 if (aType_i == TopAbs_SHAPE || aType_i == TopAbs_COMPOUND)
1166 SetErrorCode("Error: UnionListOfGroups cannot be performed on groups of different type");
1174 Handle(GEOM_Function) aFunction_i = aGr_i->GetLastFunction();
1175 if (aFunction_i.IsNull()) return NULL;
1176 GEOM_ISubShape aSSI (aFunction_i);
1177 Handle(GEOM_Function) aMainShapeFunc = aSSI.GetMainShape();
1178 if (aMainShapeFunc.IsNull()) return NULL;
1179 aLabel_i = aMainShapeFunc->GetOwnerEntry();
1180 if (aLabel_i.IsRoot()) {
1181 SetErrorCode("Error: UnionGroups can be performed only on groups");
1187 if (aLabel_i != aLabel) {
1188 SetErrorCode("Error: UnionListOfGroups cannot be performed on groups, built on different main shapes");
1193 // New contents of the group
1194 Handle(TColStd_HArray1OfInteger) aSeq = aSSI.GetIndices();
1195 if (aSeq.IsNull()) return NULL;
1197 Standard_Integer j, val_j, aLength = aSeq->Length();
1198 for (j = 1; j <= aLength; j++) {
1199 val_j = aSeq->Value(j);
1200 if (val_j > 0 && mapIDs.Add(val_j)) {
1201 aNewIDs.Append(val_j);
1206 // Check the resulting list of indices
1207 if (aNewIDs.Extent() < 1) {
1208 SetErrorCode("Error: UnionListOfGroups cannot be performed on all empty groups");
1212 Handle(GEOM_Object) aMainObj = GEOM_Object::GetObject(aLabel);
1213 if (aMainObj.IsNull()) return NULL;
1215 // Put new indices from the list into an array
1216 Standard_Integer k = 1;
1217 TColStd_ListIteratorOfListOfInteger aNewIDsIter (aNewIDs);
1218 Handle(TColStd_HArray1OfInteger) aNewArr = new TColStd_HArray1OfInteger (1, aNewIDs.Extent());
1219 for (; aNewIDsIter.More(); aNewIDsIter.Next(), k++) {
1220 aNewArr->SetValue(k, aNewIDsIter.Value());
1224 Handle(GEOM_Object) aGroup = GetEngine()->AddSubShape(aMainObj, aNewArr);
1225 aGroup->SetType(GEOM_GROUP);
1226 TDF_Label aFreeLabel = aGroup->GetFreeLabel();
1227 TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aType);
1229 //Make a Python command
1230 Handle(GEOM_Function) aFunction = aGroup->GetFunction(1);
1231 GEOM::TPythonDump pd (aFunction);
1232 pd << aGroup << " = geompy.UnionListOfGroups([";
1233 for (i = 1; i <= aLen; i++) {
1234 Handle(GEOM_Object) aGr_i = Handle(GEOM_Object)::DownCast(theGList->Value(i));
1235 pd << aGr_i << ((i < aLen) ? ", " : "])");
1242 //=============================================================================
1244 * IntersectListOfGroups
1246 //=============================================================================
1247 Handle(GEOM_Object) GEOMImpl_IGroupOperations::IntersectListOfGroups
1248 (const Handle(TColStd_HSequenceOfTransient)& theGList)
1251 if (theGList.IsNull()) return NULL;
1253 Standard_Integer i, aLen = theGList->Length();
1255 SetErrorCode("IntersectListOfGroups error: the list of groups is empty");
1259 TopAbs_ShapeEnum aType = TopAbs_SHAPE, aType_i; // todo: refactor: aType must be initialized to avoid warning (see below)
1260 TDF_Label aLabel, aLabel_i;
1261 TColStd_ListOfInteger aNewIDs;
1262 TColStd_MapOfInteger mapIDs;
1264 // Iterate on the initial groups
1265 for (i = 1; i <= aLen; i++) {
1266 Handle(GEOM_Object) aGr_i = Handle(GEOM_Object)::DownCast(theGList->Value(i));
1267 if ( aGr_i->GetType() != GEOM_GROUP ) {
1268 SetErrorCode( "Error: You could perform this operation only with group. Please select a group." );
1272 aType_i = GetType(aGr_i);
1276 if (aType_i != aType) {
1277 if (aType != TopAbs_SHAPE && aType != TopAbs_COMPOUND) { // todo: refactor: aType must be initialized to avoid warning (see above)
1278 if (aType_i == TopAbs_SHAPE || aType_i == TopAbs_COMPOUND)
1281 SetErrorCode("Error: IntersectListOfGroups cannot be performed on groups of different type");
1289 Handle(GEOM_Function) aFunction_i = aGr_i->GetLastFunction();
1290 if (aFunction_i.IsNull()) return NULL;
1291 GEOM_ISubShape aSSI (aFunction_i);
1292 Handle(GEOM_Function) aMainShapeFunc = aSSI.GetMainShape();
1293 if (aMainShapeFunc.IsNull()) return NULL;
1294 aLabel_i = aMainShapeFunc->GetOwnerEntry();
1295 if (aLabel_i.IsRoot()) {
1296 SetErrorCode("Error: UnionGroups can be performed only on groups");
1302 if (aLabel_i != aLabel) {
1303 SetErrorCode("Error: IntersectListOfGroups cannot be performed on groups, built on different main shapes");
1308 // New contents of the group
1309 Handle(TColStd_HArray1OfInteger) aSeq = aSSI.GetIndices();
1310 if (aSeq.IsNull()) return NULL;
1312 Standard_Integer j, val_j, aLength = aSeq->Length();
1313 for (j = 1; j <= aLength; j++) {
1314 val_j = aSeq->Value(j);
1317 // get all elements of the first group
1318 if (mapIDs.Add(val_j))
1319 aNewIDs.Append(val_j);
1322 // get only elements, present in all previously processed groups
1323 if (!mapIDs.Add(val_j))
1324 aNewIDs.Append(val_j);
1329 // refill the map with only validated elements
1332 TColStd_ListIteratorOfListOfInteger aNewIDsIter (aNewIDs);
1333 for (; aNewIDsIter.More(); aNewIDsIter.Next()) {
1334 mapIDs.Add(aNewIDsIter.Value());
1337 // clear the resulting list before starting the next sycle
1343 Handle(GEOM_Object) aMainObj = GEOM_Object::GetObject(aLabel);
1344 if (aMainObj.IsNull()) return NULL;
1346 Handle(TColStd_HArray1OfInteger) aNewArr;
1347 if (aNewIDs.Extent() < 1) {
1348 aNewArr = new TColStd_HArray1OfInteger (1, 1);
1349 aNewArr->SetValue(1, -1);
1352 // Put new indices from the list into an array
1353 Standard_Integer k = 1;
1354 TColStd_ListIteratorOfListOfInteger aNewIDsIter (aNewIDs);
1355 aNewArr = new TColStd_HArray1OfInteger (1, aNewIDs.Extent());
1356 for (; aNewIDsIter.More(); aNewIDsIter.Next(), k++) {
1357 aNewArr->SetValue(k, aNewIDsIter.Value());
1362 Handle(GEOM_Object) aGroup = GetEngine()->AddSubShape(aMainObj, aNewArr);
1363 aGroup->SetType(GEOM_GROUP);
1364 TDF_Label aFreeLabel = aGroup->GetFreeLabel();
1365 TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aType);
1367 //Make a Python command
1368 Handle(GEOM_Function) aFunction = aGroup->GetFunction(1);
1369 GEOM::TPythonDump pd (aFunction);
1370 pd << aGroup << " = geompy.IntersectListOfGroups([";
1371 for (i = 1; i <= aLen; i++) {
1372 Handle(GEOM_Object) aGr_i = Handle(GEOM_Object)::DownCast(theGList->Value(i));
1373 pd << aGr_i << ((i < aLen) ? ", " : "])");
1380 //=============================================================================
1384 //=============================================================================
1385 Handle(GEOM_Object) GEOMImpl_IGroupOperations::CutListOfGroups
1386 (const Handle(TColStd_HSequenceOfTransient)& theGList1,
1387 const Handle(TColStd_HSequenceOfTransient)& theGList2)
1390 if (theGList1.IsNull() || theGList2.IsNull()) return NULL;
1393 Standard_Integer aLen1 = theGList1->Length();
1394 Standard_Integer aLen2 = theGList2->Length();
1396 SetErrorCode("CutListOfGroups error: the first list of groups is empty");
1400 TopAbs_ShapeEnum aType = TopAbs_SHAPE, aType_i; // todo: refactor: aType must be initialized to avoid warning (see below)
1401 TDF_Label aLabel, aLabel_i;
1402 TColStd_ListOfInteger aNewIDs;
1403 TColStd_MapOfInteger mapIDs;
1405 // 1. Collect indices to be excluded (from theGList2) into the mapIDs
1406 for (i = 1; i <= aLen2; i++) {
1407 Handle(GEOM_Object) aGr_i = Handle(GEOM_Object)::DownCast(theGList2->Value(i));
1408 if ( aGr_i->GetType() != GEOM_GROUP ) {
1409 SetErrorCode( "Error: You could perform this operation only with group. Please select a group." );
1413 aType_i = GetType(aGr_i);
1417 if (aType_i != aType) {
1418 if (aType != TopAbs_SHAPE && aType != TopAbs_COMPOUND) {
1419 if (aType_i == TopAbs_SHAPE || aType_i == TopAbs_COMPOUND)
1422 SetErrorCode("Error: CutListOfGroups cannot be performed on groups of different type");
1430 Handle(GEOM_Function) aFunction_i = aGr_i->GetLastFunction();
1431 if (aFunction_i.IsNull()) return NULL;
1432 GEOM_ISubShape aSSI (aFunction_i);
1433 Handle(GEOM_Function) aMainShapeFunc = aSSI.GetMainShape();
1434 if (aMainShapeFunc.IsNull()) return NULL;
1435 aLabel_i = aMainShapeFunc->GetOwnerEntry();
1436 if (aLabel_i.IsRoot()) {
1437 SetErrorCode("Error: UnionGroups can be performed only on groups");
1443 if (aLabel_i != aLabel) {
1444 SetErrorCode("Error: CutListOfGroups cannot be performed on groups, built on different main shapes");
1449 // Indiced to exclude
1450 Handle(TColStd_HArray1OfInteger) aSeq = aSSI.GetIndices();
1451 if (aSeq.IsNull()) return NULL;
1453 Standard_Integer j, aLength = aSeq->Length();
1454 for (j = 1; j <= aLength; j++) {
1455 mapIDs.Add(aSeq->Value(j));
1459 // 2. Collect indices from theGList1, avoiding indices from theGList2 (mapIDs)
1460 for (i = 1; i <= aLen1; i++) {
1461 Handle(GEOM_Object) aGr_i = Handle(GEOM_Object)::DownCast(theGList1->Value(i));
1462 if ( aGr_i->GetType() != GEOM_GROUP ) {
1463 SetErrorCode( "Error: You could perform this operation only with group. Please select a group." );
1467 aType_i = GetType(aGr_i);
1468 if (i == 1 && aLen2 < 1)
1471 if (aType_i != aType) {
1472 if (aType != TopAbs_SHAPE && aType != TopAbs_COMPOUND) { // todo: refactor: aType must be initialized to avoid warning (see above)
1473 if (aType_i == TopAbs_SHAPE || aType_i == TopAbs_COMPOUND)
1476 SetErrorCode("Error: CutListOfGroups cannot be performed on groups of different type");
1484 Handle(GEOM_Function) aFunction_i = aGr_i->GetLastFunction();
1485 if (aFunction_i.IsNull()) return NULL;
1486 GEOM_ISubShape aSSI (aFunction_i);
1487 Handle(GEOM_Function) aMainShapeFunc = aSSI.GetMainShape();
1488 if (aMainShapeFunc.IsNull()) return NULL;
1489 aLabel_i = aMainShapeFunc->GetOwnerEntry();
1490 if (aLabel_i.IsRoot()) {
1491 SetErrorCode("Error: UnionGroups can be performed only on groups");
1494 if (i == 1 && aLen2 < 1)
1497 if (aLabel_i != aLabel) {
1498 SetErrorCode("Error: CutListOfGroups cannot be performed on groups, built on different main shapes");
1503 // New contents of the group
1504 Handle(TColStd_HArray1OfInteger) aSeq = aSSI.GetIndices();
1505 if (aSeq.IsNull()) return NULL;
1507 Standard_Integer j, val_j, aLength = aSeq->Length();
1508 for (j = 1; j <= aLength; j++) {
1509 val_j = aSeq->Value(j);
1510 if (val_j > 0 && mapIDs.Add(val_j)) {
1511 // get only elements, not present in mapIDs (theGList2)
1512 aNewIDs.Append(val_j);
1517 Handle(GEOM_Object) aMainObj = GEOM_Object::GetObject(aLabel);
1518 if (aMainObj.IsNull()) return NULL;
1520 Handle(TColStd_HArray1OfInteger) aNewArr;
1521 if (aNewIDs.Extent() < 1) {
1522 aNewArr = new TColStd_HArray1OfInteger (1, 1);
1523 aNewArr->SetValue(1, -1);
1526 // Put new indices from the list into an array
1527 Standard_Integer k = 1;
1528 TColStd_ListIteratorOfListOfInteger aNewIDsIter (aNewIDs);
1529 aNewArr = new TColStd_HArray1OfInteger (1, aNewIDs.Extent());
1530 for (; aNewIDsIter.More(); aNewIDsIter.Next(), k++) {
1531 aNewArr->SetValue(k, aNewIDsIter.Value());
1536 Handle(GEOM_Object) aGroup = GetEngine()->AddSubShape(aMainObj, aNewArr);
1537 aGroup->SetType(GEOM_GROUP);
1538 TDF_Label aFreeLabel = aGroup->GetFreeLabel();
1539 TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aType);
1541 //Make a Python command
1542 Handle(GEOM_Function) aFunction = aGroup->GetFunction(1);
1543 GEOM::TPythonDump pd (aFunction);
1544 pd << aGroup << " = geompy.CutListOfGroups([";
1545 for (i = 1; i <= aLen1; i++) {
1546 Handle(GEOM_Object) aGr_i = Handle(GEOM_Object)::DownCast(theGList1->Value(i));
1547 pd << aGr_i << ((i < aLen1) ? ", " : "], [");
1549 for (i = 1; i <= aLen2; i++) {
1550 Handle(GEOM_Object) aGr_i = Handle(GEOM_Object)::DownCast(theGList2->Value(i));
1551 pd << aGr_i << ((i < aLen2) ? ", " : "])");
1558 //=============================================================================
1562 //=============================================================================
1563 TopAbs_ShapeEnum GEOMImpl_IGroupOperations::GetType(Handle(GEOM_Object) theGroup)
1567 TDF_Label aFreeLabel = theGroup->GetFreeLabel();
1568 Handle(TDataStd_Integer) anAttrib;
1569 if(!aFreeLabel.FindAttribute(TDataStd_Integer::GetID(), anAttrib)) return TopAbs_SHAPE;
1572 return (TopAbs_ShapeEnum) anAttrib->Get();
1575 //=============================================================================
1579 //=============================================================================
1580 Handle(GEOM_Object) GEOMImpl_IGroupOperations::GetMainShape (Handle(GEOM_Object) theGroup)
1584 if (theGroup.IsNull()) return NULL;
1585 if (theGroup->GetType() != GEOM_GROUP &&
1586 theGroup->GetType() != GEOM_SUBSHAPE) {
1587 SetErrorCode("Error: You could perform this operation only with a group or a sub-shape.");
1591 Handle(GEOM_Function) aGroupFunction = theGroup->GetFunction(1);
1592 if (aGroupFunction.IsNull()) return NULL;
1594 GEOM_ISubShape aSSI (aGroupFunction);
1595 Handle(GEOM_Function) aMainShapeFunction = aSSI.GetMainShape();
1596 if (aMainShapeFunction.IsNull()) return NULL;
1598 TDF_Label aLabel = aMainShapeFunction->GetOwnerEntry();
1599 Handle(GEOM_Object) aMainShape = GEOM_Object::GetObject(aLabel);
1600 if (aMainShape.IsNull()) return NULL;
1602 //Make a Python command
1603 //GEOM::TPythonDump(aGroupFunction, /*append=*/true)
1604 // << aMainShape << " = geompy.GetMainShape(" << theGroup << ")";
1610 //=============================================================================
1614 //=============================================================================
1615 Handle(TColStd_HArray1OfInteger) GEOMImpl_IGroupOperations::GetObjects(Handle(GEOM_Object) theGroup)
1619 if(theGroup.IsNull()) return NULL;
1620 if ( theGroup->GetType() != GEOM_GROUP ) {
1621 SetErrorCode( "Error: You could perform this operation only with group. Please select a group." );
1624 Handle(GEOM_Function) aFunction = theGroup->GetLastFunction();
1625 if(aFunction.IsNull()) return NULL;
1627 GEOM_ISubShape aSSI(aFunction);
1628 Handle(TColStd_HArray1OfInteger) aSeq = aSSI.GetIndices();
1629 if(aSeq.IsNull()) return NULL;
1631 if(aSeq->Length() == 1 && aSeq->Value(1) == -1) {