1 // Copyright (C) 2007-2015 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"
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 if ( theShapeType != TopAbs_VERTEX && theShapeType != TopAbs_EDGE &&
85 theShapeType != TopAbs_FACE && theShapeType != TopAbs_SOLID ) {
86 SetErrorCode( "Error: You could create group of only next type: vertex, edge, face or solid" );
90 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
91 anArray->SetValue(1, -1);
93 //Add a new Sub-shape object
94 Handle(GEOM_Object) aGroup = GetEngine()->AddSubShape(theMainShape, anArray);
97 aGroup->SetType(GEOM_GROUP);
99 //Set a sub-shape type
100 TDF_Label aFreeLabel = aGroup->GetFreeLabel();
101 TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)theShapeType);
103 //Make a Python command
104 Handle(GEOM_Function) aFunction = aGroup->GetFunction(1);
106 GEOM::TPythonDump(aFunction) << aGroup
107 << " = geompy.CreateGroup(" << theMainShape << ", " << theShapeType << ")";
113 //=============================================================================
117 //=============================================================================
118 void GEOMImpl_IGroupOperations::AddObject(Handle(GEOM_Object) theGroup, int theSubShapeID)
121 if(theGroup.IsNull()) return;
123 if ( theGroup->GetType() != GEOM_GROUP ) {
124 SetErrorCode( "Error: You could perform this operation only with group. Please select a group." );
128 Handle(GEOM_Function) aFunction = theGroup->GetLastFunction();
129 if(aFunction.IsNull()) return;
131 GEOM_ISubShape aSSI (aFunction);
133 // Check sub-shape index validity
134 TDF_Label aLabel = aSSI.GetMainShape()->GetOwnerEntry();
135 if (aLabel.IsRoot()) return;
136 Handle(GEOM_Object) aMainObj = GEOM_Object::GetObject(aLabel);
137 if (aMainObj.IsNull()) return;
138 TopoDS_Shape aMainShape = aMainObj->GetValue();
139 if (aMainShape.IsNull()) return;
141 TopTools_IndexedMapOfShape aMapOfShapes;
142 TopExp::MapShapes(aMainShape, aMapOfShapes);
144 TopAbs_ShapeEnum aGroupType = GetType(theGroup);
145 TopAbs_ShapeEnum aShapeType = aMapOfShapes.FindKey(theSubShapeID).ShapeType();
146 if ( aGroupType != aShapeType ) {
147 SetErrorCode( "Error: You could perform this operation only with object the same type as the type of group." );
151 if (theSubShapeID < 1 || aMapOfShapes.Extent() < theSubShapeID) {
152 SetErrorCode("Invalid sub-shape index: out of range");
156 // Add sub-shape index
157 Handle(TColStd_HArray1OfInteger) aSeq = aSSI.GetIndices();
158 if(aSeq.IsNull()) return;
159 if(aSeq->Length() == 1 && aSeq->Value(1) == -1) {
160 aSeq->SetValue(1, theSubShapeID);
163 Standard_Integer aLength = aSeq->Length();
164 Handle(TColStd_HArray1OfInteger) aNewSeq = new TColStd_HArray1OfInteger(1, aLength+1);
165 for(Standard_Integer i = 1; i<=aLength; i++) {
166 aNewSeq->SetValue(i, aSeq->Value(i));
167 if(aSeq->Value(i) == theSubShapeID) {
168 SetErrorCode(ALREADY_PRESENT);
172 aNewSeq->SetValue(aLength+1, theSubShapeID);
173 if ( aFunction->IsLastFuntion() ) {
174 aSSI.SetIndices(aNewSeq);
177 aFunction = theGroup->AddFunction( GEOM_Object::GetSubShapeID(), 0, true );
178 GEOM_ISubShape aSSI2 (aFunction);
179 aSSI2.SetIndices(aNewSeq);
180 aSSI2.SetMainShape( aSSI.GetMainShape() );
184 // As we do not recompute here our group, lets mark it as Modified
185 Standard_Integer aTic = aMainObj->GetTic(); // tic of main shape
186 theGroup->SetTic(aTic - 1);
188 //Make a Python command
189 GEOM::TPythonDump(aFunction, /*append=*/true)
190 << "geompy.AddObject(" << theGroup << ", " << theSubShapeID << ")";
196 //=============================================================================
200 //=============================================================================
201 void GEOMImpl_IGroupOperations::RemoveObject (Handle(GEOM_Object) theGroup, int theSubShapeID)
204 if(theGroup.IsNull()) return;
206 if ( theGroup->GetType() != GEOM_GROUP ) {
207 SetErrorCode( "Error: You could perform this operation only with group. Please select a group." );
211 Handle(GEOM_Function) aFunction = theGroup->GetLastFunction();
212 if(aFunction.IsNull()) return;
214 GEOM_ISubShape aSSI(aFunction);
215 Handle(TColStd_HArray1OfInteger) aSeq = aSSI.GetIndices();
216 if(aSeq.IsNull()) return;
218 if(aSeq->Length() == 1 && aSeq->Value(1) == -1) {
219 SetErrorCode(NOT_EXISTS);
223 Handle(TColStd_HArray1OfInteger) aNewSeq;
224 Standard_Integer aLength = aSeq->Length();
226 if(aSeq->Value(1) != theSubShapeID) {
227 SetErrorCode(NOT_EXISTS);
230 aNewSeq = new TColStd_HArray1OfInteger(1,1);
231 aNewSeq->SetValue(1, -1);
234 aNewSeq = new TColStd_HArray1OfInteger(1, aLength-1);
235 Standard_Boolean isFound = Standard_False;
236 for (Standard_Integer i = 1, k = 1; i <= aLength; i++) {
237 if (aSeq->Value(i) == theSubShapeID) {
238 isFound = Standard_True;
240 if (k < aLength) { // this check is to avoid sequence <aNewSeq> overflow
241 aNewSeq->SetValue(k, aSeq->Value(i));
248 SetErrorCode(NOT_EXISTS);
253 if ( aFunction->IsLastFuntion() ) {
254 aSSI.SetIndices(aNewSeq);
257 aFunction = theGroup->AddFunction( GEOM_Object::GetSubShapeID(), 0, true );
258 GEOM_ISubShape aSSI2 (aFunction);
259 aSSI2.SetIndices(aNewSeq);
260 aSSI2.SetMainShape( aSSI.GetMainShape() );
263 // As we do not recompute here our group, lets mark it as Modified
264 TDF_Label aLabel = aSSI.GetMainShape()->GetOwnerEntry();
265 if (aLabel.IsRoot()) return;
266 Handle(GEOM_Object) aMainObj = GEOM_Object::GetObject(aLabel);
267 if (aMainObj.IsNull()) return;
268 Standard_Integer aTic = aMainObj->GetTic(); // tic of main shape
269 theGroup->SetTic(aTic - 1);
271 //Make a Python command
272 GEOM::TPythonDump(aFunction, /*append=*/true)
273 << "geompy.RemoveObject(" << theGroup << ", " << theSubShapeID << ")";
279 //=============================================================================
283 //=============================================================================
284 void GEOMImpl_IGroupOperations::UnionList (Handle(GEOM_Object) theGroup,
285 const Handle(TColStd_HSequenceOfTransient)& theSubShapes)
288 if (theGroup.IsNull()) return;
290 if ( theGroup->GetType() != GEOM_GROUP ) {
291 SetErrorCode( "Error: You could perform this operation only with group. Please select a group." );
295 Standard_Integer aLen = theSubShapes->Length();
297 //SetErrorCode("The list is empty");
302 Handle(GEOM_Function) aFunction = theGroup->GetLastFunction();
303 if (aFunction.IsNull()) return;
305 GEOM_ISubShape aSSI (aFunction);
307 // New contents of the group
308 TColStd_ListOfInteger aNewIDs;
309 TColStd_MapOfInteger mapIDs;
311 // Add current IDs to the list
312 Handle(TColStd_HArray1OfInteger) aSeq = aSSI.GetIndices();
313 if (aSeq.IsNull()) return;
314 Standard_Integer val_j, aLength = aSeq->Length();
316 for (Standard_Integer j = 1; j <= aLength; j++) {
317 val_j = aSeq->Value(j);
318 if (val_j > 0 && mapIDs.Add(val_j)) {
319 aNewIDs.Append(val_j);
324 Handle(GEOM_Function) aMainShapeFunc = aSSI.GetMainShape();
325 if (aMainShapeFunc.IsNull()) return;
326 TDF_Label aLabel = aMainShapeFunc->GetOwnerEntry();
327 if (aLabel.IsRoot()) return;
328 Handle(GEOM_Object) aMainObj = GEOM_Object::GetObject(aLabel);
329 if (aMainObj.IsNull()) return;
330 TopoDS_Shape aMainShape = aMainObj->GetValue();
331 if (aMainShape.IsNull()) return;
333 TopTools_IndexedMapOfShape mapIndices;
334 TopExp::MapShapes(aMainShape, mapIndices);
337 TopAbs_ShapeEnum aType = GetType(theGroup);
339 // Get IDs of sub-shapes to add
340 Standard_Integer i, new_id;
341 for (i = 1; i <= aLen; i++) {
342 Handle(GEOM_Object) anObj_i = Handle(GEOM_Object)::DownCast(theSubShapes->Value(i));
344 TopoDS_Shape aShape_i = anObj_i->GetValue();
345 if ( aShape_i.IsNull() ) continue;
346 TopAbs_ShapeEnum aType_i = aShape_i.ShapeType();
348 // 1. If aShape_i is sub-shape of aMainShape - add it
349 if (anObj_i->IsMainShape()) {
350 if (aType_i != aType && aType != TopAbs_SHAPE && aType != TopAbs_COMPOUND) {
351 SetErrorCode("Operation aborted: one of given objects has a wrong type");
354 if (!mapIndices.Contains(aShape_i)) {
355 SetErrorCode("Operation aborted: not a sub-shape given");
358 new_id = mapIndices.FindIndex(aShape_i);
359 if (mapIDs.Add(new_id)) {
360 aNewIDs.Append(new_id);
363 // 2. If type of group is not defined - add all sub-shapes of aShape_i
364 else if (aType == TopAbs_SHAPE || aType == TopAbs_COMPOUND) {
365 TopTools_IndexedMapOfShape mapIndices_i;
366 TopExp::MapShapes(aShape_i, mapIndices_i);
367 Standard_Integer ii = 1, nbSubSh = mapIndices_i.Extent();
368 Standard_Boolean someGood = Standard_False;
369 for (; ii <= nbSubSh; ii++) {
370 TopoDS_Shape aSubShape_i = mapIndices_i.FindKey(ii);
371 if (mapIndices.Contains(aSubShape_i)) {
372 someGood = Standard_True;
373 new_id = mapIndices.FindIndex(aSubShape_i);
374 if (mapIDs.Add(new_id)) {
375 aNewIDs.Append(new_id);
380 SetErrorCode("Operation aborted: not a sub-shape given");
384 // 3. If type of group is defined - add all sub-shapes of aShape_i of that type
386 TopExp_Explorer aSubShapes_i (aShape_i, aType);
387 for (; aSubShapes_i.More(); aSubShapes_i.Next()) {
388 TopoDS_Shape aSubShape_i = aSubShapes_i.Current();
389 if (!mapIndices.Contains(aSubShape_i)) {
390 SetErrorCode("Operation aborted: not a sub-shape given");
393 new_id = mapIndices.FindIndex(aSubShape_i);
394 if (mapIDs.Add(new_id)) {
395 aNewIDs.Append(new_id);
401 if (aNewIDs.Extent() > 0) {
402 Standard_Integer k = 1;
403 TColStd_ListIteratorOfListOfInteger aNewIDsIter (aNewIDs);
404 Handle(TColStd_HArray1OfInteger) aNewSeq = new TColStd_HArray1OfInteger(1, aNewIDs.Extent());
405 for (; aNewIDsIter.More(); aNewIDsIter.Next(), k++) {
406 aNewSeq->SetValue(k, aNewIDsIter.Value());
408 if ( aFunction->IsLastFuntion() ) {
409 aSSI.SetIndices(aNewSeq);
412 aFunction = theGroup->AddFunction( GEOM_Object::GetSubShapeID(), 0, true );
413 GEOM_ISubShape aSSI2 (aFunction);
414 aSSI2.SetIndices(aNewSeq);
415 aSSI2.SetMainShape(aMainShapeFunc);
417 // As we do not recompute here our group, lets mark it as Modified
418 Standard_Integer aTic = aMainObj->GetTic(); // tic of main shape
419 theGroup->SetTic(aTic - 1);
422 //Make a Python command
423 GEOM::TPythonDump pd (aFunction, /*append=*/true);
424 pd << "geompy.UnionList(" << theGroup << ", [";
426 for (i = 1; i <= aLen; i++) {
427 Handle(GEOM_Object) anObj_i = Handle(GEOM_Object)::DownCast(theSubShapes->Value(i));
428 pd << anObj_i << (( i < aLen ) ? ", " : "])");
434 //=============================================================================
438 //=============================================================================
439 void GEOMImpl_IGroupOperations::DifferenceList (Handle(GEOM_Object) theGroup,
440 const Handle(TColStd_HSequenceOfTransient)& theSubShapes)
443 if (theGroup.IsNull()) return;
445 if ( theGroup->GetType() != GEOM_GROUP ) {
446 SetErrorCode( "Error: You could perform this operation only with group. Please select a group." );
450 Standard_Integer aLen = theSubShapes->Length();
452 //SetErrorCode("The list is empty");
457 Handle(GEOM_Function) aFunction = theGroup->GetLastFunction();
458 if (aFunction.IsNull()) return;
460 GEOM_ISubShape aSSI (aFunction);
462 // Map of IDs to be removed
463 TColStd_MapOfInteger mapIDsToRemove;
465 // Map of current IDs
466 Handle(TColStd_HArray1OfInteger) aSeq = aSSI.GetIndices();
467 if (aSeq.IsNull()) return;
468 Standard_Integer aLength = aSeq->Length();
470 // VSR 28/04/2011 commented to allow operation even for empty group
471 // if (aLength == 1 && aSeq->Value(1) == -1) // empty group
474 TColStd_MapOfInteger mapIDsCurrent;
475 Standard_Integer j = 1;
476 for (; j <= aLength; j++) {
477 mapIDsCurrent.Add(aSeq->Value(j));
481 Handle(GEOM_Function) aMainShapeFunc = aSSI.GetMainShape();
482 if (aMainShapeFunc.IsNull()) return;
483 TDF_Label aLabel = aMainShapeFunc->GetOwnerEntry();
484 if (aLabel.IsRoot()) return;
485 Handle(GEOM_Object) aMainObj = GEOM_Object::GetObject(aLabel);
486 if (aMainObj.IsNull()) return;
487 TopoDS_Shape aMainShape = aMainObj->GetValue();
488 if (aMainShape.IsNull()) return;
490 TopTools_IndexedMapOfShape mapIndices;
491 TopExp::MapShapes(aMainShape, mapIndices);
494 TopAbs_ShapeEnum aType = GetType(theGroup);
496 // Get IDs of sub-shapes to be removed
497 Standard_Integer i, rem_id;
498 for (i = 1; i <= aLen; i++) {
499 Handle(GEOM_Object) anObj_i = Handle(GEOM_Object)::DownCast(theSubShapes->Value(i));
501 TopoDS_Shape aShape_i = anObj_i->GetValue();
503 // 1. If aShape_i is sub-shape of aMainShape - remove it
504 if (mapIndices.Contains(aShape_i)) {
505 rem_id = mapIndices.FindIndex(aShape_i);
506 if (rem_id > 0 && mapIDsCurrent.Contains(rem_id)) {
507 mapIDsToRemove.Add(rem_id);
510 // 2. If type of group is not defined - remove all sub-shapes of aShape_i
511 else if (aType == TopAbs_SHAPE || aType == TopAbs_COMPOUND) {
512 TopTools_IndexedMapOfShape mapIndices_i;
513 TopExp::MapShapes(aShape_i, mapIndices_i);
514 Standard_Integer nbSubSh = mapIndices_i.Extent();
515 Standard_Integer ii = 1;
516 for (; ii <= nbSubSh; ii++) {
517 TopoDS_Shape aSubShape_i = mapIndices_i.FindKey(ii);
518 if (mapIndices.Contains(aSubShape_i)) {
519 rem_id = mapIndices.FindIndex(aSubShape_i);
520 if (rem_id > 0 && mapIDsCurrent.Contains(rem_id)) {
521 mapIDsToRemove.Add(rem_id);
526 // 3. If type of group is defined - remove all sub-shapes of aShape_i of that type
528 TopExp_Explorer aSubShapes_i (aShape_i, aType);
529 for (; aSubShapes_i.More(); aSubShapes_i.Next()) {
530 TopoDS_Shape aSubShape_i = aSubShapes_i.Current();
531 if (mapIndices.Contains(aSubShape_i)) {
532 rem_id = mapIndices.FindIndex(aSubShape_i);
533 if (rem_id > 0 && mapIDsCurrent.Contains(rem_id)) {
534 mapIDsToRemove.Add(rem_id);
541 if (mapIDsToRemove.Extent() > 0) {
542 Standard_Integer k = 1, aRemLength = mapIDsToRemove.Extent();
543 Handle(TColStd_HArray1OfInteger) aNewSeq;
544 if ( aLength - aRemLength > 0 ) {
545 aNewSeq = new TColStd_HArray1OfInteger(1, aLength - aRemLength);
546 for (j = 1; j <= aLength; j++) {
547 if (!mapIDsToRemove.Contains(aSeq->Value(j))) {
548 aNewSeq->SetValue(k, aSeq->Value(j));
554 aNewSeq = new TColStd_HArray1OfInteger(1,1);
555 aNewSeq->SetValue(1, -1);
558 if ( aFunction->IsLastFuntion() ) {
559 aSSI.SetIndices(aNewSeq);
562 aFunction = theGroup->AddFunction( GEOM_Object::GetSubShapeID(), 0, true );
563 GEOM_ISubShape aSSI2 (aFunction);
564 aSSI2.SetIndices(aNewSeq);
565 aSSI2.SetMainShape(aMainShapeFunc);
567 // As we do not recompute here our group, lets mark it as Modified
568 Standard_Integer aTic = aMainObj->GetTic(); // tic of main shape
569 theGroup->SetTic(aTic - 1);
572 //Make a Python command
573 GEOM::TPythonDump pd (aFunction, /*append=*/true);
574 pd << "geompy.DifferenceList(" << theGroup << ", [";
576 for (i = 1; i <= aLen; i++) {
577 Handle(GEOM_Object) anObj_i = Handle(GEOM_Object)::DownCast(theSubShapes->Value(i));
578 pd << anObj_i << (( i < aLen ) ? ", " : "])");
584 //=============================================================================
588 //=============================================================================
589 void GEOMImpl_IGroupOperations::UnionIDs (Handle(GEOM_Object) theGroup,
590 const Handle(TColStd_HSequenceOfInteger)& theSubShapes)
593 if (theGroup.IsNull()) return;
595 if ( theGroup->GetType() != GEOM_GROUP ) {
596 SetErrorCode( "Error: You could perform this operation only with group. Please select a group." );
600 Standard_Integer aLen = theSubShapes->Length();
602 //SetErrorCode("The list is empty");
607 Handle(GEOM_Function) aFunction = theGroup->GetLastFunction();
608 if (aFunction.IsNull()) return;
610 GEOM_ISubShape aSSI (aFunction);
612 // New contents of the group
613 TColStd_ListOfInteger aNewIDs;
614 TColStd_MapOfInteger mapIDs;
616 // Add current IDs to the list
617 Handle(TColStd_HArray1OfInteger) aSeq = aSSI.GetIndices();
618 if (aSeq.IsNull()) return;
619 Standard_Integer val_j, aLength = aSeq->Length();
621 for (Standard_Integer j = 1; j <= aLength; j++) {
622 val_j = aSeq->Value(j);
623 if (val_j > 0 && mapIDs.Add(val_j)) {
624 aNewIDs.Append(val_j);
629 Handle(GEOM_Function) aMainShapeFunc = aSSI.GetMainShape();
630 if (aMainShapeFunc.IsNull()) return;
631 TDF_Label aLabel = aMainShapeFunc->GetOwnerEntry();
632 if (aLabel.IsRoot()) return;
633 Handle(GEOM_Object) aMainObj = GEOM_Object::GetObject(aLabel);
634 if (aMainObj.IsNull()) return;
635 TopoDS_Shape aMainShape = aMainObj->GetValue();
636 if (aMainShape.IsNull()) return;
638 TopTools_IndexedMapOfShape mapIndices;
639 TopExp::MapShapes(aMainShape, mapIndices);
642 TopAbs_ShapeEnum aType = GetType(theGroup);
644 // Get IDs of sub-shapes to add
645 Standard_Integer i, new_id;
646 for (i = 1; i <= aLen; i++) {
647 new_id = theSubShapes->Value(i);
649 if (0 < new_id && new_id <= mapIndices.Extent()) {
650 //if (mapIDs.Add(new_id)) { IPAL21297. Why we ignore invalid ids silently?
651 if (mapIDs.Add(new_id) && mapIndices(new_id).ShapeType()==aType ) {
652 aNewIDs.Append(new_id);
657 if (aNewIDs.Extent() > 0) {
658 Standard_Integer k = 1;
659 TColStd_ListIteratorOfListOfInteger aNewIDsIter (aNewIDs);
660 Handle(TColStd_HArray1OfInteger) aNewSeq = new TColStd_HArray1OfInteger(1, aNewIDs.Extent());
661 for (; aNewIDsIter.More(); aNewIDsIter.Next(), k++) {
662 aNewSeq->SetValue(k, aNewIDsIter.Value());
664 if ( aFunction->IsLastFuntion() ) {
665 aSSI.SetIndices(aNewSeq);
668 aFunction = theGroup->AddFunction( GEOM_Object::GetSubShapeID(), 0, true );
669 GEOM_ISubShape aSSI2 (aFunction);
670 aSSI2.SetIndices(aNewSeq);
671 aSSI2.SetMainShape(aMainShapeFunc);
673 // As we do not recompute here our group, lets mark it as Modified
674 Standard_Integer aTic = aMainObj->GetTic(); // tic of main shape
675 theGroup->SetTic(aTic - 1);
678 //Make a Python command
679 GEOM::TPythonDump pd (aFunction, /*append=*/true);
680 pd << "geompy.UnionIDs(" << theGroup << ", [";
681 for (i = 1; i < aLen; i++)
682 pd << theSubShapes->Value(i) << ", ";
683 pd << theSubShapes->Value(aLen) << "])";
688 //=============================================================================
692 //=============================================================================
693 void GEOMImpl_IGroupOperations::DifferenceIDs (Handle(GEOM_Object) theGroup,
694 const Handle(TColStd_HSequenceOfInteger)& theSubShapes)
697 if (theGroup.IsNull()) return;
699 if ( theGroup->GetType() != GEOM_GROUP ) {
700 SetErrorCode( "Error: You could perform this operation only with group. Please select a group." );
704 Standard_Integer aLen = theSubShapes->Length();
706 //SetErrorCode("The list is empty");
711 Handle(GEOM_Function) aFunction = theGroup->GetLastFunction();
712 if (aFunction.IsNull()) return;
714 GEOM_ISubShape aSSI (aFunction);
716 // Map of IDs to be removed
717 TColStd_MapOfInteger mapIDsToRemove;
719 // Map of current IDs
720 Handle(TColStd_HArray1OfInteger) aSeq = aSSI.GetIndices();
721 if (aSeq.IsNull()) return;
722 Standard_Integer aLength = aSeq->Length();
724 // VSR 28/04/2011 commented to allow operation even for empty group
725 // if (aLength == 1 && aSeq->Value(1) == -1) // empty group
728 TColStd_MapOfInteger mapIDsCurrent;
729 Standard_Integer j = 1;
730 for (; j <= aLength; j++) {
731 mapIDsCurrent.Add(aSeq->Value(j));
735 Handle(GEOM_Function) aMainShapeFunc = aSSI.GetMainShape();
736 if (aMainShapeFunc.IsNull()) return;
737 TDF_Label aLabel = aMainShapeFunc->GetOwnerEntry();
738 if (aLabel.IsRoot()) return;
739 Handle(GEOM_Object) aMainObj = GEOM_Object::GetObject(aLabel);
740 if (aMainObj.IsNull()) return;
741 TopoDS_Shape aMainShape = aMainObj->GetValue();
742 if (aMainShape.IsNull()) return;
744 TopTools_IndexedMapOfShape mapIndices;
745 TopExp::MapShapes(aMainShape, mapIndices);
747 // Get IDs of sub-shapes to be removed
748 Standard_Integer i, rem_id;
749 for (i = 1; i <= aLen; i++) {
750 rem_id = theSubShapes->Value(i);
751 if (rem_id > 0 && mapIDsCurrent.Contains(rem_id)) {
752 mapIDsToRemove.Add(rem_id);
756 if (mapIDsToRemove.Extent() > 0) {
757 Standard_Integer k = 1, aRemLength = mapIDsToRemove.Extent();
758 Handle(TColStd_HArray1OfInteger) aNewSeq;
759 if ( aLength - aRemLength > 0 ) {
760 aNewSeq = new TColStd_HArray1OfInteger(1, aLength - aRemLength);
761 for (j = 1; j <= aLength; j++) {
762 if (!mapIDsToRemove.Contains(aSeq->Value(j))) {
763 aNewSeq->SetValue(k, aSeq->Value(j));
769 aNewSeq = new TColStd_HArray1OfInteger(1,1);
770 aNewSeq->SetValue(1, -1);
772 if ( aFunction->IsLastFuntion() ) {
773 aSSI.SetIndices(aNewSeq);
776 aFunction = theGroup->AddFunction( GEOM_Object::GetSubShapeID(), 0, true );
777 GEOM_ISubShape aSSI2 (aFunction);
778 aSSI2.SetIndices(aNewSeq);
779 aSSI2.SetMainShape(aMainShapeFunc);
781 // As we do not recompute here our group, lets mark it as Modified
782 Standard_Integer aTic = aMainObj->GetTic(); // tic of main shape
783 theGroup->SetTic(aTic - 1);
786 //Make a Python command
787 GEOM::TPythonDump pd (aFunction, /*append=*/true);
788 pd << "geompy.DifferenceIDs(" << theGroup << ", [";
789 for (i = 1; i < aLen; i++)
790 pd << theSubShapes->Value(i) << ", ";
791 pd << theSubShapes->Value(aLen) << "])";
796 //=============================================================================
800 //=============================================================================
801 Handle(GEOM_Object) GEOMImpl_IGroupOperations::UnionGroups (Handle(GEOM_Object) theGroup1,
802 Handle(GEOM_Object) theGroup2)
805 if (theGroup1.IsNull() || theGroup2.IsNull()) return NULL;
807 if ( theGroup1->GetType() != GEOM_GROUP || theGroup2->GetType() != GEOM_GROUP ) {
808 SetErrorCode( "Error: You could perform this operation only with group. Please select a group." );
813 TopAbs_ShapeEnum aType1 = GetType(theGroup1);
814 TopAbs_ShapeEnum aType2 = GetType(theGroup2);
815 TopAbs_ShapeEnum aType = aType1;
816 if (aType1 != aType2) {
817 if (aType1 != TopAbs_SHAPE && aType1 != TopAbs_COMPOUND) {
818 if (aType2 == TopAbs_SHAPE || aType2 == TopAbs_COMPOUND)
821 SetErrorCode("Error: UnionGroups cannot be performed on groups of different type");
828 Handle(GEOM_Function) aFunction1 = theGroup1->GetLastFunction();
829 Handle(GEOM_Function) aFunction2 = theGroup2->GetLastFunction();
830 if (aFunction1.IsNull() || aFunction2.IsNull()) return NULL;
832 GEOM_ISubShape aSSI1 (aFunction1);
833 GEOM_ISubShape aSSI2 (aFunction2);
835 Handle(GEOM_Function) aMainShapeFunc1 = aSSI1.GetMainShape();
836 Handle(GEOM_Function) aMainShapeFunc2 = aSSI2.GetMainShape();
837 if (aMainShapeFunc1.IsNull() || aMainShapeFunc2.IsNull()) return NULL;
839 TDF_Label aLabel1 = aMainShapeFunc1->GetOwnerEntry();
840 TDF_Label aLabel2 = aMainShapeFunc2->GetOwnerEntry();
841 if (aLabel1.IsRoot() || aLabel2.IsRoot()) {
842 SetErrorCode("Error: UnionGroups can be performed only on groups");
846 if (aLabel1 != aLabel2) {
847 SetErrorCode("Error: UnionGroups cannot be performed on groups, built on different main shapes");
851 Handle(GEOM_Object) aMainObj = GEOM_Object::GetObject(aLabel1);
852 if (aMainObj.IsNull()) return NULL;
854 // New contents of the group
855 TColStd_ListOfInteger aNewIDs;
856 TColStd_MapOfInteger mapIDs;
858 Handle(TColStd_HArray1OfInteger) aSeq1 = aSSI1.GetIndices();
859 Handle(TColStd_HArray1OfInteger) aSeq2 = aSSI2.GetIndices();
860 if (aSeq1.IsNull() || aSeq2.IsNull()) return NULL;
862 Standard_Integer j, val_j;
863 Standard_Integer aLength1 = aSeq1->Length();
864 Standard_Integer aLength2 = aSeq2->Length();
866 for (j = 1; j <= aLength1; j++) {
867 val_j = aSeq1->Value(j);
868 if (val_j > 0 && mapIDs.Add(val_j)) {
869 aNewIDs.Append(val_j);
872 for (j = 1; j <= aLength2; j++) {
873 val_j = aSeq2->Value(j);
874 if (val_j > 0 && mapIDs.Add(val_j)) {
875 aNewIDs.Append(val_j);
879 if (aNewIDs.Extent() < 1) {
880 SetErrorCode("Error: UnionGroups cannot be performed on two empty groups");
884 // Put new indices from the list into an array
885 Standard_Integer k = 1;
886 TColStd_ListIteratorOfListOfInteger aNewIDsIter (aNewIDs);
887 Handle(TColStd_HArray1OfInteger) aNewArr = new TColStd_HArray1OfInteger (1, aNewIDs.Extent());
888 for (; aNewIDsIter.More(); aNewIDsIter.Next(), k++) {
889 aNewArr->SetValue(k, aNewIDsIter.Value());
893 Handle(GEOM_Object) aGroup = GetEngine()->AddSubShape(aMainObj, aNewArr);
894 aGroup->SetType(GEOM_GROUP);
895 TDF_Label aFreeLabel = aGroup->GetFreeLabel();
896 TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aType);
898 // Make a Python command
899 Handle(GEOM_Function) aFunction = aGroup->GetFunction(1);
900 GEOM::TPythonDump(aFunction) << aGroup << " = geompy.UnionGroups("
901 << theGroup1 << ", " << theGroup2 << ")";
907 //=============================================================================
911 //=============================================================================
912 Handle(GEOM_Object) GEOMImpl_IGroupOperations::IntersectGroups (Handle(GEOM_Object) theGroup1,
913 Handle(GEOM_Object) theGroup2)
916 if (theGroup1.IsNull() || theGroup2.IsNull()) return NULL;
918 if ( theGroup1->GetType() != GEOM_GROUP || theGroup2->GetType() != GEOM_GROUP ) {
919 SetErrorCode( "Error: You could perform this operation only with group. Please select a group." );
924 TopAbs_ShapeEnum aType1 = GetType(theGroup1);
925 TopAbs_ShapeEnum aType2 = GetType(theGroup2);
926 TopAbs_ShapeEnum aType = aType1;
927 if (aType1 != aType2) {
928 if (aType1 != TopAbs_SHAPE && aType1 != TopAbs_COMPOUND) {
929 if (aType2 == TopAbs_SHAPE || aType2 == TopAbs_COMPOUND)
932 SetErrorCode("Error: IntersectGroups cannot be performed on groups of different type");
939 Handle(GEOM_Function) aFunction1 = theGroup1->GetLastFunction();
940 Handle(GEOM_Function) aFunction2 = theGroup2->GetLastFunction();
941 if (aFunction1.IsNull() || aFunction2.IsNull()) return NULL;
943 GEOM_ISubShape aSSI1 (aFunction1);
944 GEOM_ISubShape aSSI2 (aFunction2);
946 Handle(GEOM_Function) aMainShapeFunc1 = aSSI1.GetMainShape();
947 Handle(GEOM_Function) aMainShapeFunc2 = aSSI2.GetMainShape();
948 if (aMainShapeFunc1.IsNull() || aMainShapeFunc2.IsNull()) return NULL;
950 TDF_Label aLabel1 = aMainShapeFunc1->GetOwnerEntry();
951 TDF_Label aLabel2 = aMainShapeFunc2->GetOwnerEntry();
952 if (aLabel1.IsRoot() || aLabel2.IsRoot()) {
953 SetErrorCode("Error: UnionGroups can be performed only on groups");
957 if (aLabel1 != aLabel2) {
958 SetErrorCode("Error: IntersectGroups cannot be performed on groups, built on different main shapes");
962 Handle(GEOM_Object) aMainObj = GEOM_Object::GetObject(aLabel1);
963 if (aMainObj.IsNull()) return NULL;
965 // New contents of the group
966 TColStd_ListOfInteger aNewIDs;
967 TColStd_MapOfInteger mapIDs;
969 Handle(TColStd_HArray1OfInteger) aSeq1 = aSSI1.GetIndices();
970 Handle(TColStd_HArray1OfInteger) aSeq2 = aSSI2.GetIndices();
971 if (aSeq1.IsNull() || aSeq2.IsNull()) return NULL;
973 Standard_Integer j, val_j;
974 Standard_Integer aLength1 = aSeq1->Length();
975 Standard_Integer aLength2 = aSeq2->Length();
977 for (j = 1; j <= aLength1; j++) {
978 mapIDs.Add(aSeq1->Value(j));
980 for (j = 1; j <= aLength2; j++) {
981 val_j = aSeq2->Value(j);
982 if (val_j > 0 && !mapIDs.Add(val_j)) {
983 // add index, if it is in mapIDs (filled from Group_1)
984 aNewIDs.Append(val_j);
988 Handle(TColStd_HArray1OfInteger) aNewArr;
989 if (aNewIDs.Extent() < 1) {
990 aNewArr = new TColStd_HArray1OfInteger (1, 1);
991 aNewArr->SetValue(1, -1);
994 // Put new indices from the list into an array
995 Standard_Integer k = 1;
996 TColStd_ListIteratorOfListOfInteger aNewIDsIter (aNewIDs);
997 aNewArr = new TColStd_HArray1OfInteger (1, aNewIDs.Extent());
998 for (; aNewIDsIter.More(); aNewIDsIter.Next(), k++) {
999 aNewArr->SetValue(k, aNewIDsIter.Value());
1004 Handle(GEOM_Object) aGroup = GetEngine()->AddSubShape(aMainObj, aNewArr);
1005 aGroup->SetType(GEOM_GROUP);
1006 TDF_Label aFreeLabel = aGroup->GetFreeLabel();
1007 TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aType);
1009 // Make a Python command
1010 Handle(GEOM_Function) aFunction = aGroup->GetFunction(1);
1011 GEOM::TPythonDump(aFunction) << aGroup << " = geompy.IntersectGroups("
1012 << theGroup1 << ", " << theGroup2 << ")";
1018 //=============================================================================
1022 //=============================================================================
1023 Handle(GEOM_Object) GEOMImpl_IGroupOperations::CutGroups (Handle(GEOM_Object) theGroup1,
1024 Handle(GEOM_Object) theGroup2)
1027 if (theGroup1.IsNull() || theGroup2.IsNull()) return NULL;
1029 if ( theGroup1->GetType() != GEOM_GROUP || theGroup2->GetType() != GEOM_GROUP ) {
1030 SetErrorCode( "Error: You could perform this operation only with group. Please select a group." );
1035 TopAbs_ShapeEnum aType1 = GetType(theGroup1);
1036 TopAbs_ShapeEnum aType2 = GetType(theGroup2);
1037 TopAbs_ShapeEnum aType = aType1;
1038 if (aType1 != aType2) {
1039 if (aType1 != TopAbs_SHAPE && aType1 != TopAbs_COMPOUND) {
1040 if (aType2 == TopAbs_SHAPE || aType2 == TopAbs_COMPOUND)
1043 SetErrorCode("Error: CutGroups cannot be performed on groups of different type");
1050 Handle(GEOM_Function) aFunction1 = theGroup1->GetLastFunction();
1051 Handle(GEOM_Function) aFunction2 = theGroup2->GetLastFunction();
1052 if (aFunction1.IsNull() || aFunction2.IsNull()) return NULL;
1054 GEOM_ISubShape aSSI1 (aFunction1);
1055 GEOM_ISubShape aSSI2 (aFunction2);
1057 Handle(GEOM_Function) aMainShapeFunc1 = aSSI1.GetMainShape();
1058 Handle(GEOM_Function) aMainShapeFunc2 = aSSI2.GetMainShape();
1059 if (aMainShapeFunc1.IsNull() || aMainShapeFunc2.IsNull()) return NULL;
1061 TDF_Label aLabel1 = aMainShapeFunc1->GetOwnerEntry();
1062 TDF_Label aLabel2 = aMainShapeFunc2->GetOwnerEntry();
1063 if (aLabel1.IsRoot() || aLabel2.IsRoot()) {
1064 SetErrorCode("Error: UnionGroups can be performed only on groups");
1068 if (aLabel1 != aLabel2) {
1069 SetErrorCode("Error: CutGroups cannot be performed on groups, built on different main shapes");
1073 Handle(GEOM_Object) aMainObj = GEOM_Object::GetObject(aLabel1);
1074 if (aMainObj.IsNull()) return NULL;
1076 // New contents of the group
1077 TColStd_ListOfInteger aNewIDs;
1078 TColStd_MapOfInteger mapIDs;
1080 Handle(TColStd_HArray1OfInteger) aSeq1 = aSSI1.GetIndices();
1081 Handle(TColStd_HArray1OfInteger) aSeq2 = aSSI2.GetIndices();
1082 if (aSeq1.IsNull() || aSeq2.IsNull()) return NULL;
1084 Standard_Integer j, val_j;
1085 Standard_Integer aLength1 = aSeq1->Length();
1086 Standard_Integer aLength2 = aSeq2->Length();
1088 for (j = 1; j <= aLength2; j++) {
1089 mapIDs.Add(aSeq2->Value(j));
1091 for (j = 1; j <= aLength1; j++) {
1092 val_j = aSeq1->Value(j);
1093 if (val_j > 0 && mapIDs.Add(val_j)) {
1094 // add index, if it is not in mapIDs (filled from Group_2)
1095 aNewIDs.Append(val_j);
1099 Handle(TColStd_HArray1OfInteger) aNewArr;
1100 if (aNewIDs.Extent() < 1) {
1101 aNewArr = new TColStd_HArray1OfInteger (1, 1);
1102 aNewArr->SetValue(1, -1);
1105 // Put new indices from the list into an array
1106 Standard_Integer k = 1;
1107 TColStd_ListIteratorOfListOfInteger aNewIDsIter (aNewIDs);
1108 aNewArr = new TColStd_HArray1OfInteger (1, aNewIDs.Extent());
1109 for (; aNewIDsIter.More(); aNewIDsIter.Next(), k++) {
1110 aNewArr->SetValue(k, aNewIDsIter.Value());
1115 Handle(GEOM_Object) aGroup = GetEngine()->AddSubShape(aMainObj, aNewArr);
1116 aGroup->SetType(GEOM_GROUP);
1117 TDF_Label aFreeLabel = aGroup->GetFreeLabel();
1118 TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aType);
1120 // Make a Python command
1121 Handle(GEOM_Function) aFunction = aGroup->GetFunction(1);
1122 GEOM::TPythonDump(aFunction) << aGroup << " = geompy.CutGroups("
1123 << theGroup1 << ", " << theGroup2 << ")";
1129 //=============================================================================
1133 //=============================================================================
1134 Handle(GEOM_Object) GEOMImpl_IGroupOperations::UnionListOfGroups
1135 (const Handle(TColStd_HSequenceOfTransient)& theGList)
1138 if (theGList.IsNull()) return NULL;
1140 Standard_Integer i, aLen = theGList->Length();
1142 SetErrorCode("UnionListOfGroups error: the list of groups is empty");
1146 TopAbs_ShapeEnum aType, aType_i;
1147 TDF_Label aLabel, aLabel_i;
1148 TColStd_ListOfInteger aNewIDs;
1149 TColStd_MapOfInteger mapIDs;
1151 // Iterate on the initial groups
1152 for (i = 1; i <= aLen; i++) {
1153 Handle(GEOM_Object) aGr_i = Handle(GEOM_Object)::DownCast(theGList->Value(i));
1154 if ( aGr_i->GetType() != GEOM_GROUP ) {
1155 SetErrorCode( "Error: You could perform this operation only with group. Please select a group." );
1159 aType_i = GetType(aGr_i);
1163 if (aType_i != aType) {
1164 if (aType != TopAbs_SHAPE && aType != TopAbs_COMPOUND) {
1165 if (aType_i == TopAbs_SHAPE || aType_i == TopAbs_COMPOUND)
1168 SetErrorCode("Error: UnionListOfGroups cannot be performed on groups of different type");
1176 Handle(GEOM_Function) aFunction_i = aGr_i->GetLastFunction();
1177 if (aFunction_i.IsNull()) return NULL;
1178 GEOM_ISubShape aSSI (aFunction_i);
1179 Handle(GEOM_Function) aMainShapeFunc = aSSI.GetMainShape();
1180 if (aMainShapeFunc.IsNull()) return NULL;
1181 aLabel_i = aMainShapeFunc->GetOwnerEntry();
1182 if (aLabel_i.IsRoot()) {
1183 SetErrorCode("Error: UnionGroups can be performed only on groups");
1189 if (aLabel_i != aLabel) {
1190 SetErrorCode("Error: UnionListOfGroups cannot be performed on groups, built on different main shapes");
1195 // New contents of the group
1196 Handle(TColStd_HArray1OfInteger) aSeq = aSSI.GetIndices();
1197 if (aSeq.IsNull()) return NULL;
1199 Standard_Integer j, val_j, aLength = aSeq->Length();
1200 for (j = 1; j <= aLength; j++) {
1201 val_j = aSeq->Value(j);
1202 if (val_j > 0 && mapIDs.Add(val_j)) {
1203 aNewIDs.Append(val_j);
1208 // Check the resulting list of indices
1209 if (aNewIDs.Extent() < 1) {
1210 SetErrorCode("Error: UnionListOfGroups cannot be performed on all empty groups");
1214 Handle(GEOM_Object) aMainObj = GEOM_Object::GetObject(aLabel);
1215 if (aMainObj.IsNull()) return NULL;
1217 // Put new indices from the list into an array
1218 Standard_Integer k = 1;
1219 TColStd_ListIteratorOfListOfInteger aNewIDsIter (aNewIDs);
1220 Handle(TColStd_HArray1OfInteger) aNewArr = new TColStd_HArray1OfInteger (1, aNewIDs.Extent());
1221 for (; aNewIDsIter.More(); aNewIDsIter.Next(), k++) {
1222 aNewArr->SetValue(k, aNewIDsIter.Value());
1226 Handle(GEOM_Object) aGroup = GetEngine()->AddSubShape(aMainObj, aNewArr);
1227 aGroup->SetType(GEOM_GROUP);
1228 TDF_Label aFreeLabel = aGroup->GetFreeLabel();
1229 TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aType);
1231 //Make a Python command
1232 Handle(GEOM_Function) aFunction = aGroup->GetFunction(1);
1233 GEOM::TPythonDump pd (aFunction);
1234 pd << aGroup << " = geompy.UnionListOfGroups([";
1235 for (i = 1; i <= aLen; i++) {
1236 Handle(GEOM_Object) aGr_i = Handle(GEOM_Object)::DownCast(theGList->Value(i));
1237 pd << aGr_i << ((i < aLen) ? ", " : "])");
1244 //=============================================================================
1246 * IntersectListOfGroups
1248 //=============================================================================
1249 Handle(GEOM_Object) GEOMImpl_IGroupOperations::IntersectListOfGroups
1250 (const Handle(TColStd_HSequenceOfTransient)& theGList)
1253 if (theGList.IsNull()) return NULL;
1255 Standard_Integer i, aLen = theGList->Length();
1257 SetErrorCode("IntersectListOfGroups error: the list of groups is empty");
1261 TopAbs_ShapeEnum aType, aType_i;
1262 TDF_Label aLabel, aLabel_i;
1263 TColStd_ListOfInteger aNewIDs;
1264 TColStd_MapOfInteger mapIDs;
1266 // Iterate on the initial groups
1267 for (i = 1; i <= aLen; i++) {
1268 Handle(GEOM_Object) aGr_i = Handle(GEOM_Object)::DownCast(theGList->Value(i));
1269 if ( aGr_i->GetType() != GEOM_GROUP ) {
1270 SetErrorCode( "Error: You could perform this operation only with group. Please select a group." );
1274 aType_i = GetType(aGr_i);
1278 if (aType_i != aType) {
1279 if (aType != TopAbs_SHAPE && aType != TopAbs_COMPOUND) {
1280 if (aType_i == TopAbs_SHAPE || aType_i == TopAbs_COMPOUND)
1283 SetErrorCode("Error: IntersectListOfGroups cannot be performed on groups of different type");
1291 Handle(GEOM_Function) aFunction_i = aGr_i->GetLastFunction();
1292 if (aFunction_i.IsNull()) return NULL;
1293 GEOM_ISubShape aSSI (aFunction_i);
1294 Handle(GEOM_Function) aMainShapeFunc = aSSI.GetMainShape();
1295 if (aMainShapeFunc.IsNull()) return NULL;
1296 aLabel_i = aMainShapeFunc->GetOwnerEntry();
1297 if (aLabel_i.IsRoot()) {
1298 SetErrorCode("Error: UnionGroups can be performed only on groups");
1304 if (aLabel_i != aLabel) {
1305 SetErrorCode("Error: IntersectListOfGroups cannot be performed on groups, built on different main shapes");
1310 // New contents of the group
1311 Handle(TColStd_HArray1OfInteger) aSeq = aSSI.GetIndices();
1312 if (aSeq.IsNull()) return NULL;
1314 Standard_Integer j, val_j, aLength = aSeq->Length();
1315 for (j = 1; j <= aLength; j++) {
1316 val_j = aSeq->Value(j);
1319 // get all elements of the first group
1320 if (mapIDs.Add(val_j))
1321 aNewIDs.Append(val_j);
1324 // get only elements, present in all previously processed groups
1325 if (!mapIDs.Add(val_j))
1326 aNewIDs.Append(val_j);
1331 // refill the map with only validated elements
1334 TColStd_ListIteratorOfListOfInteger aNewIDsIter (aNewIDs);
1335 for (; aNewIDsIter.More(); aNewIDsIter.Next()) {
1336 mapIDs.Add(aNewIDsIter.Value());
1339 // clear the resulting list before starting the next sycle
1345 Handle(GEOM_Object) aMainObj = GEOM_Object::GetObject(aLabel);
1346 if (aMainObj.IsNull()) return NULL;
1348 Handle(TColStd_HArray1OfInteger) aNewArr;
1349 if (aNewIDs.Extent() < 1) {
1350 aNewArr = new TColStd_HArray1OfInteger (1, 1);
1351 aNewArr->SetValue(1, -1);
1354 // Put new indices from the list into an array
1355 Standard_Integer k = 1;
1356 TColStd_ListIteratorOfListOfInteger aNewIDsIter (aNewIDs);
1357 aNewArr = new TColStd_HArray1OfInteger (1, aNewIDs.Extent());
1358 for (; aNewIDsIter.More(); aNewIDsIter.Next(), k++) {
1359 aNewArr->SetValue(k, aNewIDsIter.Value());
1364 Handle(GEOM_Object) aGroup = GetEngine()->AddSubShape(aMainObj, aNewArr);
1365 aGroup->SetType(GEOM_GROUP);
1366 TDF_Label aFreeLabel = aGroup->GetFreeLabel();
1367 TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aType);
1369 //Make a Python command
1370 Handle(GEOM_Function) aFunction = aGroup->GetFunction(1);
1371 GEOM::TPythonDump pd (aFunction);
1372 pd << aGroup << " = geompy.IntersectListOfGroups([";
1373 for (i = 1; i <= aLen; i++) {
1374 Handle(GEOM_Object) aGr_i = Handle(GEOM_Object)::DownCast(theGList->Value(i));
1375 pd << aGr_i << ((i < aLen) ? ", " : "])");
1382 //=============================================================================
1386 //=============================================================================
1387 Handle(GEOM_Object) GEOMImpl_IGroupOperations::CutListOfGroups
1388 (const Handle(TColStd_HSequenceOfTransient)& theGList1,
1389 const Handle(TColStd_HSequenceOfTransient)& theGList2)
1392 if (theGList1.IsNull() || theGList2.IsNull()) return NULL;
1395 Standard_Integer aLen1 = theGList1->Length();
1396 Standard_Integer aLen2 = theGList2->Length();
1398 SetErrorCode("CutListOfGroups error: the first list of groups is empty");
1402 TopAbs_ShapeEnum aType, aType_i;
1403 TDF_Label aLabel, aLabel_i;
1404 TColStd_ListOfInteger aNewIDs;
1405 TColStd_MapOfInteger mapIDs;
1407 // 1. Collect indices to be excluded (from theGList2) into the mapIDs
1408 for (i = 1; i <= aLen2; i++) {
1409 Handle(GEOM_Object) aGr_i = Handle(GEOM_Object)::DownCast(theGList2->Value(i));
1410 if ( aGr_i->GetType() != GEOM_GROUP ) {
1411 SetErrorCode( "Error: You could perform this operation only with group. Please select a group." );
1415 aType_i = GetType(aGr_i);
1419 if (aType_i != aType) {
1420 if (aType != TopAbs_SHAPE && aType != TopAbs_COMPOUND) {
1421 if (aType_i == TopAbs_SHAPE || aType_i == TopAbs_COMPOUND)
1424 SetErrorCode("Error: CutListOfGroups cannot be performed on groups of different type");
1432 Handle(GEOM_Function) aFunction_i = aGr_i->GetLastFunction();
1433 if (aFunction_i.IsNull()) return NULL;
1434 GEOM_ISubShape aSSI (aFunction_i);
1435 Handle(GEOM_Function) aMainShapeFunc = aSSI.GetMainShape();
1436 if (aMainShapeFunc.IsNull()) return NULL;
1437 aLabel_i = aMainShapeFunc->GetOwnerEntry();
1438 if (aLabel_i.IsRoot()) {
1439 SetErrorCode("Error: UnionGroups can be performed only on groups");
1445 if (aLabel_i != aLabel) {
1446 SetErrorCode("Error: CutListOfGroups cannot be performed on groups, built on different main shapes");
1451 // Indiced to exclude
1452 Handle(TColStd_HArray1OfInteger) aSeq = aSSI.GetIndices();
1453 if (aSeq.IsNull()) return NULL;
1455 Standard_Integer j, aLength = aSeq->Length();
1456 for (j = 1; j <= aLength; j++) {
1457 mapIDs.Add(aSeq->Value(j));
1461 // 2. Collect indices from theGList1, avoiding indices from theGList2 (mapIDs)
1462 for (i = 1; i <= aLen1; i++) {
1463 Handle(GEOM_Object) aGr_i = Handle(GEOM_Object)::DownCast(theGList1->Value(i));
1464 if ( aGr_i->GetType() != GEOM_GROUP ) {
1465 SetErrorCode( "Error: You could perform this operation only with group. Please select a group." );
1469 aType_i = GetType(aGr_i);
1470 if (i == 1 && aLen2 < 1)
1473 if (aType_i != aType) {
1474 if (aType != TopAbs_SHAPE && aType != TopAbs_COMPOUND) {
1475 if (aType_i == TopAbs_SHAPE || aType_i == TopAbs_COMPOUND)
1478 SetErrorCode("Error: CutListOfGroups cannot be performed on groups of different type");
1486 Handle(GEOM_Function) aFunction_i = aGr_i->GetLastFunction();
1487 if (aFunction_i.IsNull()) return NULL;
1488 GEOM_ISubShape aSSI (aFunction_i);
1489 Handle(GEOM_Function) aMainShapeFunc = aSSI.GetMainShape();
1490 if (aMainShapeFunc.IsNull()) return NULL;
1491 aLabel_i = aMainShapeFunc->GetOwnerEntry();
1492 if (aLabel_i.IsRoot()) {
1493 SetErrorCode("Error: UnionGroups can be performed only on groups");
1496 if (i == 1 && aLen2 < 1)
1499 if (aLabel_i != aLabel) {
1500 SetErrorCode("Error: CutListOfGroups cannot be performed on groups, built on different main shapes");
1505 // New contents of the group
1506 Handle(TColStd_HArray1OfInteger) aSeq = aSSI.GetIndices();
1507 if (aSeq.IsNull()) return NULL;
1509 Standard_Integer j, val_j, aLength = aSeq->Length();
1510 for (j = 1; j <= aLength; j++) {
1511 val_j = aSeq->Value(j);
1512 if (val_j > 0 && mapIDs.Add(val_j)) {
1513 // get only elements, not present in mapIDs (theGList2)
1514 aNewIDs.Append(val_j);
1519 Handle(GEOM_Object) aMainObj = GEOM_Object::GetObject(aLabel);
1520 if (aMainObj.IsNull()) return NULL;
1522 Handle(TColStd_HArray1OfInteger) aNewArr;
1523 if (aNewIDs.Extent() < 1) {
1524 aNewArr = new TColStd_HArray1OfInteger (1, 1);
1525 aNewArr->SetValue(1, -1);
1528 // Put new indices from the list into an array
1529 Standard_Integer k = 1;
1530 TColStd_ListIteratorOfListOfInteger aNewIDsIter (aNewIDs);
1531 aNewArr = new TColStd_HArray1OfInteger (1, aNewIDs.Extent());
1532 for (; aNewIDsIter.More(); aNewIDsIter.Next(), k++) {
1533 aNewArr->SetValue(k, aNewIDsIter.Value());
1538 Handle(GEOM_Object) aGroup = GetEngine()->AddSubShape(aMainObj, aNewArr);
1539 aGroup->SetType(GEOM_GROUP);
1540 TDF_Label aFreeLabel = aGroup->GetFreeLabel();
1541 TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aType);
1543 //Make a Python command
1544 Handle(GEOM_Function) aFunction = aGroup->GetFunction(1);
1545 GEOM::TPythonDump pd (aFunction);
1546 pd << aGroup << " = geompy.CutListOfGroups([";
1547 for (i = 1; i <= aLen1; i++) {
1548 Handle(GEOM_Object) aGr_i = Handle(GEOM_Object)::DownCast(theGList1->Value(i));
1549 pd << aGr_i << ((i < aLen1) ? ", " : "], [");
1551 for (i = 1; i <= aLen2; i++) {
1552 Handle(GEOM_Object) aGr_i = Handle(GEOM_Object)::DownCast(theGList2->Value(i));
1553 pd << aGr_i << ((i < aLen2) ? ", " : "])");
1560 //=============================================================================
1564 //=============================================================================
1565 TopAbs_ShapeEnum GEOMImpl_IGroupOperations::GetType(Handle(GEOM_Object) theGroup)
1569 TDF_Label aFreeLabel = theGroup->GetFreeLabel();
1570 Handle(TDataStd_Integer) anAttrib;
1571 if(!aFreeLabel.FindAttribute(TDataStd_Integer::GetID(), anAttrib)) return TopAbs_SHAPE;
1574 return (TopAbs_ShapeEnum) anAttrib->Get();
1577 //=============================================================================
1581 //=============================================================================
1582 Handle(GEOM_Object) GEOMImpl_IGroupOperations::GetMainShape (Handle(GEOM_Object) theGroup)
1586 if (theGroup.IsNull()) return NULL;
1587 if (theGroup->GetType() != GEOM_GROUP &&
1588 theGroup->GetType() != GEOM_SUBSHAPE) {
1589 SetErrorCode("Error: You could perform this operation only with a group or a sub-shape.");
1593 Handle(GEOM_Function) aGroupFunction = theGroup->GetFunction(1);
1594 if (aGroupFunction.IsNull()) return NULL;
1596 GEOM_ISubShape aSSI (aGroupFunction);
1597 Handle(GEOM_Function) aMainShapeFunction = aSSI.GetMainShape();
1598 if (aMainShapeFunction.IsNull()) return NULL;
1600 TDF_Label aLabel = aMainShapeFunction->GetOwnerEntry();
1601 Handle(GEOM_Object) aMainShape = GEOM_Object::GetObject(aLabel);
1602 if (aMainShape.IsNull()) return NULL;
1604 //Make a Python command
1605 //GEOM::TPythonDump(aGroupFunction, /*append=*/true)
1606 // << aMainShape << " = geompy.GetMainShape(" << theGroup << ")";
1612 //=============================================================================
1616 //=============================================================================
1617 Handle(TColStd_HArray1OfInteger) GEOMImpl_IGroupOperations::GetObjects(Handle(GEOM_Object) theGroup)
1621 if(theGroup.IsNull()) return NULL;
1622 if ( theGroup->GetType() != GEOM_GROUP ) {
1623 SetErrorCode( "Error: You could perform this operation only with group. Please select a group." );
1626 Handle(GEOM_Function) aFunction = theGroup->GetLastFunction();
1627 if(aFunction.IsNull()) return NULL;
1629 GEOM_ISubShape aSSI(aFunction);
1630 Handle(TColStd_HArray1OfInteger) aSeq = aSSI.GetIndices();
1631 if(aSeq.IsNull()) return NULL;
1633 if(aSeq->Length() == 1 && aSeq->Value(1) == -1) {