1 // Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
22 #include <Standard_Stream.hxx>
24 #include <GEOMImpl_IGroupOperations.hxx>
26 #include <GEOMImpl_Types.hxx>
28 #include <GEOM_Function.hxx>
29 #include <GEOM_ISubShape.hxx>
30 #include <GEOM_PythonDump.hxx>
32 #include "utilities.h"
34 #include <Utils_ExceptHandlers.hxx>
36 #include <TFunction_DriverTable.hxx>
37 #include <TFunction_Driver.hxx>
38 #include <TFunction_Logbook.hxx>
39 #include <TDF_Tool.hxx>
40 #include <TDataStd_Integer.hxx>
43 #include <TopExp_Explorer.hxx>
44 #include <TopTools_IndexedMapOfShape.hxx>
46 #include <TColStd_HArray1OfInteger.hxx>
47 #include <TColStd_MapOfInteger.hxx>
48 #include <TColStd_ListOfInteger.hxx>
49 #include <TColStd_ListIteratorOfListOfInteger.hxx>
51 //=============================================================================
55 //=============================================================================
56 GEOMImpl_IGroupOperations::GEOMImpl_IGroupOperations (GEOM_Engine* theEngine, int theDocID)
57 : GEOM_IOperations(theEngine, theDocID)
59 MESSAGE("GEOMImpl_IGroupOperations::GEOMImpl_IGroupOperations");
62 //=============================================================================
66 //=============================================================================
67 GEOMImpl_IGroupOperations::~GEOMImpl_IGroupOperations()
69 MESSAGE("GEOMImpl_IGroupOperations::~GEOMImpl_IGroupOperations");
73 //=============================================================================
77 //=============================================================================
78 Handle(GEOM_Object) GEOMImpl_IGroupOperations::CreateGroup
79 (Handle(GEOM_Object) theMainShape, TopAbs_ShapeEnum theShapeType)
83 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
84 anArray->SetValue(1, -1);
86 //Add a new Sub-shape object
87 Handle(GEOM_Object) aGroup = GetEngine()->AddSubShape(theMainShape, anArray);
90 aGroup->SetType(GEOM_GROUP);
92 //Set a sub-shape type
93 TDF_Label aFreeLabel = aGroup->GetFreeLabel();
94 TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)theShapeType);
96 //Make a Python command
97 Handle(GEOM_Function) aFunction = aGroup->GetFunction(1);
99 GEOM::TPythonDump(aFunction) << aGroup
100 << " = geompy.CreateGroup(" << theMainShape << ", " << theShapeType << ")";
106 //=============================================================================
110 //=============================================================================
111 void GEOMImpl_IGroupOperations::AddObject(Handle(GEOM_Object) theGroup, int theSubShapeID)
114 if(theGroup.IsNull()) return;
116 Handle(GEOM_Function) aFunction = theGroup->GetLastFunction();
117 if(aFunction.IsNull()) return;
119 GEOM_ISubShape aSSI (aFunction);
121 // Check sub-shape index validity
122 TDF_Label aLabel = aSSI.GetMainShape()->GetOwnerEntry();
123 if (aLabel.IsRoot()) return;
124 Handle(GEOM_Object) aMainObj = GEOM_Object::GetObject(aLabel);
125 if (aMainObj.IsNull()) return;
126 TopoDS_Shape aMainShape = aMainObj->GetValue();
127 if (aMainShape.IsNull()) return;
129 TopTools_IndexedMapOfShape aMapOfShapes;
130 TopExp::MapShapes(aMainShape, aMapOfShapes);
132 if (theSubShapeID < 1 || aMapOfShapes.Extent() < theSubShapeID) {
133 SetErrorCode("Invalid sub-shape index: out of range");
137 // Add sub-shape index
138 Handle(TColStd_HArray1OfInteger) aSeq = aSSI.GetIndices();
139 if(aSeq.IsNull()) return;
140 if(aSeq->Length() == 1 && aSeq->Value(1) == -1) {
141 aSeq->SetValue(1, theSubShapeID);
144 Standard_Integer aLength = aSeq->Length();
145 Handle(TColStd_HArray1OfInteger) aNewSeq = new TColStd_HArray1OfInteger(1, aLength+1);
146 for(Standard_Integer i = 1; i<=aLength; i++) {
147 aNewSeq->SetValue(i, aSeq->Value(i));
148 if(aSeq->Value(i) == theSubShapeID) {
149 SetErrorCode(ALREADY_PRESENT);
153 aNewSeq->SetValue(aLength+1, theSubShapeID);
154 if ( aFunction->IsLastFuntion() ) {
155 aSSI.SetIndices(aNewSeq);
158 aFunction = theGroup->AddFunction( GEOM_Object::GetSubShapeID(), 0, true );
159 GEOM_ISubShape aSSI2 (aFunction);
160 aSSI2.SetIndices(aNewSeq);
161 aSSI2.SetMainShape( aSSI.GetMainShape() );
165 // As we do not recompute here our group, lets mark it as Modified
166 Standard_Integer aTic = aMainObj->GetTic(); // tic of main shape
167 theGroup->SetTic(aTic - 1);
169 //Make a Python command
170 GEOM::TPythonDump(aFunction, /*append=*/true)
171 << "geompy.AddObject(" << theGroup << ", " << theSubShapeID << ")";
177 //=============================================================================
181 //=============================================================================
182 void GEOMImpl_IGroupOperations::RemoveObject (Handle(GEOM_Object) theGroup, int theSubShapeID)
185 if(theGroup.IsNull()) return;
187 Handle(GEOM_Function) aFunction = theGroup->GetLastFunction();
188 if(aFunction.IsNull()) return;
190 GEOM_ISubShape aSSI(aFunction);
191 Handle(TColStd_HArray1OfInteger) aSeq = aSSI.GetIndices();
192 if(aSeq.IsNull()) return;
194 if(aSeq->Length() == 1 && aSeq->Value(1) == -1) {
195 SetErrorCode(NOT_EXISTS);
199 Handle(TColStd_HArray1OfInteger) aNewSeq;
200 Standard_Integer aLength = aSeq->Length();
202 if(aSeq->Value(1) != theSubShapeID) {
203 SetErrorCode(NOT_EXISTS);
206 aNewSeq = new TColStd_HArray1OfInteger(1,1);
207 aNewSeq->SetValue(1, -1);
210 aNewSeq = new TColStd_HArray1OfInteger(1, aLength-1);
211 Standard_Boolean isFound = Standard_False;
212 for (Standard_Integer i = 1, k = 1; i <= aLength; i++) {
213 if (aSeq->Value(i) == theSubShapeID) {
214 isFound = Standard_True;
216 if (k < aLength) { // this check is to avoid sequence <aNewSeq> overflow
217 aNewSeq->SetValue(k, aSeq->Value(i));
224 SetErrorCode(NOT_EXISTS);
229 if ( aFunction->IsLastFuntion() ) {
230 aSSI.SetIndices(aNewSeq);
233 aFunction = theGroup->AddFunction( GEOM_Object::GetSubShapeID(), 0, true );
234 GEOM_ISubShape aSSI2 (aFunction);
235 aSSI2.SetIndices(aNewSeq);
236 aSSI2.SetMainShape( aSSI.GetMainShape() );
239 // As we do not recompute here our group, lets mark it as Modified
240 TDF_Label aLabel = aSSI.GetMainShape()->GetOwnerEntry();
241 if (aLabel.IsRoot()) return;
242 Handle(GEOM_Object) aMainObj = GEOM_Object::GetObject(aLabel);
243 if (aMainObj.IsNull()) return;
244 Standard_Integer aTic = aMainObj->GetTic(); // tic of main shape
245 theGroup->SetTic(aTic - 1);
247 //Make a Python command
248 GEOM::TPythonDump(aFunction, /*append=*/true)
249 << "geompy.RemoveObject(" << theGroup << ", " << theSubShapeID << ")";
255 //=============================================================================
259 //=============================================================================
260 void GEOMImpl_IGroupOperations::UnionList (Handle(GEOM_Object) theGroup,
261 const Handle(TColStd_HSequenceOfTransient)& theSubShapes)
264 if (theGroup.IsNull()) return;
266 Standard_Integer aLen = theSubShapes->Length();
268 //SetErrorCode("The list is empty");
273 Handle(GEOM_Function) aFunction = theGroup->GetLastFunction();
274 if (aFunction.IsNull()) return;
276 GEOM_ISubShape aSSI (aFunction);
278 // New contents of the group
279 TColStd_ListOfInteger aNewIDs;
280 TColStd_MapOfInteger mapIDs;
282 // Add current IDs to the list
283 Handle(TColStd_HArray1OfInteger) aSeq = aSSI.GetIndices();
284 if (aSeq.IsNull()) return;
285 Standard_Integer val_j, aLength = aSeq->Length();
287 for (Standard_Integer j = 1; j <= aLength; j++) {
288 val_j = aSeq->Value(j);
289 if (val_j > 0 && mapIDs.Add(val_j)) {
290 aNewIDs.Append(val_j);
295 Handle(GEOM_Function) aMainShapeFunc = aSSI.GetMainShape();
296 if (aMainShapeFunc.IsNull()) return;
297 TDF_Label aLabel = aMainShapeFunc->GetOwnerEntry();
298 if (aLabel.IsRoot()) return;
299 Handle(GEOM_Object) aMainObj = GEOM_Object::GetObject(aLabel);
300 if (aMainObj.IsNull()) return;
301 TopoDS_Shape aMainShape = aMainObj->GetValue();
302 if (aMainShape.IsNull()) return;
304 TopTools_IndexedMapOfShape mapIndices;
305 TopExp::MapShapes(aMainShape, mapIndices);
308 TopAbs_ShapeEnum aType = GetType(theGroup);
310 // Get IDs of sub-shapes to add
311 Standard_Integer i, new_id;
312 for (i = 1; i <= aLen; i++) {
313 Handle(GEOM_Object) anObj_i = Handle(GEOM_Object)::DownCast(theSubShapes->Value(i));
315 TopoDS_Shape aShape_i = anObj_i->GetValue();
316 if ( aShape_i.IsNull() ) continue;
317 TopAbs_ShapeEnum aType_i = aShape_i.ShapeType();
319 // 1. If aShape_i is sub-shape of aMainShape - add it
320 if (anObj_i->IsMainShape()) {
321 if (aType_i != aType && aType != TopAbs_SHAPE && aType != TopAbs_COMPOUND) {
322 SetErrorCode("Operation aborted: one of given objects has a wrong type");
325 if (!mapIndices.Contains(aShape_i)) {
326 SetErrorCode("Operation aborted: not a sub-shape given");
329 new_id = mapIndices.FindIndex(aShape_i);
330 if (mapIDs.Add(new_id)) {
331 aNewIDs.Append(new_id);
334 // 2. If type of group is not defined - add all sub-shapes of aShape_i
335 else if (aType == TopAbs_SHAPE || aType == TopAbs_COMPOUND) {
336 TopTools_IndexedMapOfShape mapIndices_i;
337 TopExp::MapShapes(aShape_i, mapIndices_i);
338 Standard_Integer ii = 1, nbSubSh = mapIndices_i.Extent();
339 Standard_Boolean someGood = Standard_False;
340 for (; ii <= nbSubSh; ii++) {
341 TopoDS_Shape aSubShape_i = mapIndices_i.FindKey(ii);
342 if (mapIndices.Contains(aSubShape_i)) {
343 someGood = Standard_True;
344 new_id = mapIndices.FindIndex(aSubShape_i);
345 if (mapIDs.Add(new_id)) {
346 aNewIDs.Append(new_id);
351 SetErrorCode("Operation aborted: not a sub-shape given");
355 // 3. If type of group is defined - add all sub-shapes of aShape_i of that type
357 TopExp_Explorer aSubShapes_i (aShape_i, aType);
358 for (; aSubShapes_i.More(); aSubShapes_i.Next()) {
359 TopoDS_Shape aSubShape_i = aSubShapes_i.Current();
360 if (!mapIndices.Contains(aSubShape_i)) {
361 SetErrorCode("Operation aborted: not a sub-shape given");
364 new_id = mapIndices.FindIndex(aSubShape_i);
365 if (mapIDs.Add(new_id)) {
366 aNewIDs.Append(new_id);
372 if (aNewIDs.Extent() > 0) {
373 Standard_Integer k = 1;
374 TColStd_ListIteratorOfListOfInteger aNewIDsIter (aNewIDs);
375 Handle(TColStd_HArray1OfInteger) aNewSeq = new TColStd_HArray1OfInteger(1, aNewIDs.Extent());
376 for (; aNewIDsIter.More(); aNewIDsIter.Next(), k++) {
377 aNewSeq->SetValue(k, aNewIDsIter.Value());
379 if ( aFunction->IsLastFuntion() ) {
380 aSSI.SetIndices(aNewSeq);
383 aFunction = theGroup->AddFunction( GEOM_Object::GetSubShapeID(), 0, true );
384 GEOM_ISubShape aSSI2 (aFunction);
385 aSSI2.SetIndices(aNewSeq);
386 aSSI2.SetMainShape(aMainShapeFunc);
388 // As we do not recompute here our group, lets mark it as Modified
389 Standard_Integer aTic = aMainObj->GetTic(); // tic of main shape
390 theGroup->SetTic(aTic - 1);
393 //Make a Python command
394 GEOM::TPythonDump pd (aFunction, /*append=*/true);
395 pd << "geompy.UnionList(" << theGroup << ", [";
397 for (i = 1; i <= aLen; i++) {
398 Handle(GEOM_Object) anObj_i = Handle(GEOM_Object)::DownCast(theSubShapes->Value(i));
399 pd << anObj_i << (( i < aLen ) ? ", " : "])");
405 //=============================================================================
409 //=============================================================================
410 void GEOMImpl_IGroupOperations::DifferenceList (Handle(GEOM_Object) theGroup,
411 const Handle(TColStd_HSequenceOfTransient)& theSubShapes)
414 if (theGroup.IsNull()) return;
416 Standard_Integer aLen = theSubShapes->Length();
418 //SetErrorCode("The list is empty");
423 Handle(GEOM_Function) aFunction = theGroup->GetLastFunction();
424 if (aFunction.IsNull()) return;
426 GEOM_ISubShape aSSI (aFunction);
428 // Map of IDs to be removed
429 TColStd_MapOfInteger mapIDsToRemove;
431 // Map of current IDs
432 Handle(TColStd_HArray1OfInteger) aSeq = aSSI.GetIndices();
433 if (aSeq.IsNull()) return;
434 Standard_Integer aLength = aSeq->Length();
436 // VSR 28/04/2011 commented to allow operation even for empty group
437 // if (aLength == 1 && aSeq->Value(1) == -1) // empty group
440 TColStd_MapOfInteger mapIDsCurrent;
441 Standard_Integer j = 1;
442 for (; j <= aLength; j++) {
443 mapIDsCurrent.Add(aSeq->Value(j));
447 Handle(GEOM_Function) aMainShapeFunc = aSSI.GetMainShape();
448 if (aMainShapeFunc.IsNull()) return;
449 TDF_Label aLabel = aMainShapeFunc->GetOwnerEntry();
450 if (aLabel.IsRoot()) return;
451 Handle(GEOM_Object) aMainObj = GEOM_Object::GetObject(aLabel);
452 if (aMainObj.IsNull()) return;
453 TopoDS_Shape aMainShape = aMainObj->GetValue();
454 if (aMainShape.IsNull()) return;
456 TopTools_IndexedMapOfShape mapIndices;
457 TopExp::MapShapes(aMainShape, mapIndices);
460 TopAbs_ShapeEnum aType = GetType(theGroup);
462 // Get IDs of sub-shapes to be removed
463 Standard_Integer i, rem_id;
464 for (i = 1; i <= aLen; i++) {
465 Handle(GEOM_Object) anObj_i = Handle(GEOM_Object)::DownCast(theSubShapes->Value(i));
467 TopoDS_Shape aShape_i = anObj_i->GetValue();
469 // 1. If aShape_i is sub-shape of aMainShape - remove it
470 if (mapIndices.Contains(aShape_i)) {
471 rem_id = mapIndices.FindIndex(aShape_i);
472 if (rem_id > 0 && mapIDsCurrent.Contains(rem_id)) {
473 mapIDsToRemove.Add(rem_id);
476 // 2. If type of group is not defined - remove all sub-shapes of aShape_i
477 else if (aType == TopAbs_SHAPE || aType == TopAbs_COMPOUND) {
478 TopTools_IndexedMapOfShape mapIndices_i;
479 TopExp::MapShapes(aShape_i, mapIndices_i);
480 Standard_Integer nbSubSh = mapIndices_i.Extent();
481 Standard_Integer ii = 1;
482 for (; ii <= nbSubSh; ii++) {
483 TopoDS_Shape aSubShape_i = mapIndices_i.FindKey(ii);
484 if (mapIndices.Contains(aSubShape_i)) {
485 rem_id = mapIndices.FindIndex(aSubShape_i);
486 if (rem_id > 0 && mapIDsCurrent.Contains(rem_id)) {
487 mapIDsToRemove.Add(rem_id);
492 // 3. If type of group is defined - remove all sub-shapes of aShape_i of that type
494 TopExp_Explorer aSubShapes_i (aShape_i, aType);
495 for (; aSubShapes_i.More(); aSubShapes_i.Next()) {
496 TopoDS_Shape aSubShape_i = aSubShapes_i.Current();
497 if (mapIndices.Contains(aSubShape_i)) {
498 rem_id = mapIndices.FindIndex(aSubShape_i);
499 if (rem_id > 0 && mapIDsCurrent.Contains(rem_id)) {
500 mapIDsToRemove.Add(rem_id);
507 if (mapIDsToRemove.Extent() > 0) {
508 Standard_Integer k = 1, aRemLength = mapIDsToRemove.Extent();
509 Handle(TColStd_HArray1OfInteger) aNewSeq;
510 if ( aLength - aRemLength > 0 ) {
511 aNewSeq = new TColStd_HArray1OfInteger(1, aLength - aRemLength);
512 for (j = 1; j <= aLength; j++) {
513 if (!mapIDsToRemove.Contains(aSeq->Value(j))) {
514 aNewSeq->SetValue(k, aSeq->Value(j));
520 aNewSeq = new TColStd_HArray1OfInteger(1,1);
521 aNewSeq->SetValue(1, -1);
524 if ( aFunction->IsLastFuntion() ) {
525 aSSI.SetIndices(aNewSeq);
528 aFunction = theGroup->AddFunction( GEOM_Object::GetSubShapeID(), 0, true );
529 GEOM_ISubShape aSSI2 (aFunction);
530 aSSI2.SetIndices(aNewSeq);
531 aSSI2.SetMainShape(aMainShapeFunc);
533 // As we do not recompute here our group, lets mark it as Modified
534 Standard_Integer aTic = aMainObj->GetTic(); // tic of main shape
535 theGroup->SetTic(aTic - 1);
538 //Make a Python command
539 GEOM::TPythonDump pd (aFunction, /*append=*/true);
540 pd << "geompy.DifferenceList(" << theGroup << ", [";
542 for (i = 1; i <= aLen; i++) {
543 Handle(GEOM_Object) anObj_i = Handle(GEOM_Object)::DownCast(theSubShapes->Value(i));
544 pd << anObj_i << (( i < aLen ) ? ", " : "])");
550 //=============================================================================
554 //=============================================================================
555 void GEOMImpl_IGroupOperations::UnionIDs (Handle(GEOM_Object) theGroup,
556 const Handle(TColStd_HSequenceOfInteger)& theSubShapes)
559 if (theGroup.IsNull()) return;
561 Standard_Integer aLen = theSubShapes->Length();
563 //SetErrorCode("The list is empty");
568 Handle(GEOM_Function) aFunction = theGroup->GetLastFunction();
569 if (aFunction.IsNull()) return;
571 GEOM_ISubShape aSSI (aFunction);
573 // New contents of the group
574 TColStd_ListOfInteger aNewIDs;
575 TColStd_MapOfInteger mapIDs;
577 // Add current IDs to the list
578 Handle(TColStd_HArray1OfInteger) aSeq = aSSI.GetIndices();
579 if (aSeq.IsNull()) return;
580 Standard_Integer val_j, aLength = aSeq->Length();
582 for (Standard_Integer j = 1; j <= aLength; j++) {
583 val_j = aSeq->Value(j);
584 if (val_j > 0 && mapIDs.Add(val_j)) {
585 aNewIDs.Append(val_j);
590 Handle(GEOM_Function) aMainShapeFunc = aSSI.GetMainShape();
591 if (aMainShapeFunc.IsNull()) return;
592 TDF_Label aLabel = aMainShapeFunc->GetOwnerEntry();
593 if (aLabel.IsRoot()) return;
594 Handle(GEOM_Object) aMainObj = GEOM_Object::GetObject(aLabel);
595 if (aMainObj.IsNull()) return;
596 TopoDS_Shape aMainShape = aMainObj->GetValue();
597 if (aMainShape.IsNull()) return;
599 TopTools_IndexedMapOfShape mapIndices;
600 TopExp::MapShapes(aMainShape, mapIndices);
603 TopAbs_ShapeEnum aType = GetType(theGroup);
605 // Get IDs of sub-shapes to add
606 Standard_Integer i, new_id;
607 for (i = 1; i <= aLen; i++) {
608 new_id = theSubShapes->Value(i);
610 if (0 < new_id && new_id <= mapIndices.Extent()) {
611 //if (mapIDs.Add(new_id)) { IPAL21297. Why we ignore invalid ids silently?
612 if (mapIDs.Add(new_id) && mapIndices(new_id).ShapeType()==aType ) {
613 aNewIDs.Append(new_id);
618 if (aNewIDs.Extent() > 0) {
619 Standard_Integer k = 1;
620 TColStd_ListIteratorOfListOfInteger aNewIDsIter (aNewIDs);
621 Handle(TColStd_HArray1OfInteger) aNewSeq = new TColStd_HArray1OfInteger(1, aNewIDs.Extent());
622 for (; aNewIDsIter.More(); aNewIDsIter.Next(), k++) {
623 aNewSeq->SetValue(k, aNewIDsIter.Value());
625 if ( aFunction->IsLastFuntion() ) {
626 aSSI.SetIndices(aNewSeq);
629 aFunction = theGroup->AddFunction( GEOM_Object::GetSubShapeID(), 0, true );
630 GEOM_ISubShape aSSI2 (aFunction);
631 aSSI2.SetIndices(aNewSeq);
632 aSSI2.SetMainShape(aMainShapeFunc);
634 // As we do not recompute here our group, lets mark it as Modified
635 Standard_Integer aTic = aMainObj->GetTic(); // tic of main shape
636 theGroup->SetTic(aTic - 1);
639 //Make a Python command
640 GEOM::TPythonDump pd (aFunction, /*append=*/true);
641 pd << "geompy.UnionIDs(" << theGroup << ", [";
642 for (i = 1; i < aLen; i++)
643 pd << theSubShapes->Value(i) << ", ";
644 pd << theSubShapes->Value(aLen) << "])";
649 //=============================================================================
653 //=============================================================================
654 void GEOMImpl_IGroupOperations::DifferenceIDs (Handle(GEOM_Object) theGroup,
655 const Handle(TColStd_HSequenceOfInteger)& theSubShapes)
658 if (theGroup.IsNull()) return;
660 Standard_Integer aLen = theSubShapes->Length();
662 //SetErrorCode("The list is empty");
667 Handle(GEOM_Function) aFunction = theGroup->GetLastFunction();
668 if (aFunction.IsNull()) return;
670 GEOM_ISubShape aSSI (aFunction);
672 // Map of IDs to be removed
673 TColStd_MapOfInteger mapIDsToRemove;
675 // Map of current IDs
676 Handle(TColStd_HArray1OfInteger) aSeq = aSSI.GetIndices();
677 if (aSeq.IsNull()) return;
678 Standard_Integer aLength = aSeq->Length();
680 // VSR 28/04/2011 commented to allow operation even for empty group
681 // if (aLength == 1 && aSeq->Value(1) == -1) // empty group
684 TColStd_MapOfInteger mapIDsCurrent;
685 Standard_Integer j = 1;
686 for (; j <= aLength; j++) {
687 mapIDsCurrent.Add(aSeq->Value(j));
691 Handle(GEOM_Function) aMainShapeFunc = aSSI.GetMainShape();
692 if (aMainShapeFunc.IsNull()) return;
693 TDF_Label aLabel = aMainShapeFunc->GetOwnerEntry();
694 if (aLabel.IsRoot()) return;
695 Handle(GEOM_Object) aMainObj = GEOM_Object::GetObject(aLabel);
696 if (aMainObj.IsNull()) return;
697 TopoDS_Shape aMainShape = aMainObj->GetValue();
698 if (aMainShape.IsNull()) return;
700 TopTools_IndexedMapOfShape mapIndices;
701 TopExp::MapShapes(aMainShape, mapIndices);
703 // Get IDs of sub-shapes to be removed
704 Standard_Integer i, rem_id;
705 for (i = 1; i <= aLen; i++) {
706 rem_id = theSubShapes->Value(i);
707 if (rem_id > 0 && mapIDsCurrent.Contains(rem_id)) {
708 mapIDsToRemove.Add(rem_id);
712 if (mapIDsToRemove.Extent() > 0) {
713 Standard_Integer k = 1, aRemLength = mapIDsToRemove.Extent();
714 Handle(TColStd_HArray1OfInteger) aNewSeq;
715 if ( aLength - aRemLength > 0 ) {
716 aNewSeq = new TColStd_HArray1OfInteger(1, aLength - aRemLength);
717 for (j = 1; j <= aLength; j++) {
718 if (!mapIDsToRemove.Contains(aSeq->Value(j))) {
719 aNewSeq->SetValue(k, aSeq->Value(j));
725 aNewSeq = new TColStd_HArray1OfInteger(1,1);
726 aNewSeq->SetValue(1, -1);
728 if ( aFunction->IsLastFuntion() ) {
729 aSSI.SetIndices(aNewSeq);
732 aFunction = theGroup->AddFunction( GEOM_Object::GetSubShapeID(), 0, true );
733 GEOM_ISubShape aSSI2 (aFunction);
734 aSSI2.SetIndices(aNewSeq);
735 aSSI2.SetMainShape(aMainShapeFunc);
737 // As we do not recompute here our group, lets mark it as Modified
738 Standard_Integer aTic = aMainObj->GetTic(); // tic of main shape
739 theGroup->SetTic(aTic - 1);
742 //Make a Python command
743 GEOM::TPythonDump pd (aFunction, /*append=*/true);
744 pd << "geompy.DifferenceIDs(" << theGroup << ", [";
745 for (i = 1; i < aLen; i++)
746 pd << theSubShapes->Value(i) << ", ";
747 pd << theSubShapes->Value(aLen) << "])";
752 //=============================================================================
756 //=============================================================================
757 Handle(GEOM_Object) GEOMImpl_IGroupOperations::UnionGroups (Handle(GEOM_Object) theGroup1,
758 Handle(GEOM_Object) theGroup2)
761 if (theGroup1.IsNull() || theGroup2.IsNull()) return NULL;
764 TopAbs_ShapeEnum aType1 = GetType(theGroup1);
765 TopAbs_ShapeEnum aType2 = GetType(theGroup2);
766 TopAbs_ShapeEnum aType = aType1;
767 if (aType1 != aType2) {
768 if (aType1 != TopAbs_SHAPE && aType1 != TopAbs_COMPOUND) {
769 if (aType2 == TopAbs_SHAPE || aType2 == TopAbs_COMPOUND)
772 SetErrorCode("Error: UnionGroups cannot be performed on groups of different type");
779 Handle(GEOM_Function) aFunction1 = theGroup1->GetLastFunction();
780 Handle(GEOM_Function) aFunction2 = theGroup2->GetLastFunction();
781 if (aFunction1.IsNull() || aFunction2.IsNull()) return NULL;
783 GEOM_ISubShape aSSI1 (aFunction1);
784 GEOM_ISubShape aSSI2 (aFunction2);
786 Handle(GEOM_Function) aMainShapeFunc1 = aSSI1.GetMainShape();
787 Handle(GEOM_Function) aMainShapeFunc2 = aSSI2.GetMainShape();
788 if (aMainShapeFunc1.IsNull() || aMainShapeFunc2.IsNull()) return NULL;
790 TDF_Label aLabel1 = aMainShapeFunc1->GetOwnerEntry();
791 TDF_Label aLabel2 = aMainShapeFunc2->GetOwnerEntry();
792 if (aLabel1.IsRoot() || aLabel2.IsRoot()) {
793 SetErrorCode("Error: UnionGroups can be performed only on groups");
797 if (aLabel1 != aLabel2) {
798 SetErrorCode("Error: UnionGroups cannot be performed on groups, built on different main shapes");
802 Handle(GEOM_Object) aMainObj = GEOM_Object::GetObject(aLabel1);
803 if (aMainObj.IsNull()) return NULL;
805 // New contents of the group
806 TColStd_ListOfInteger aNewIDs;
807 TColStd_MapOfInteger mapIDs;
809 Handle(TColStd_HArray1OfInteger) aSeq1 = aSSI1.GetIndices();
810 Handle(TColStd_HArray1OfInteger) aSeq2 = aSSI2.GetIndices();
811 if (aSeq1.IsNull() || aSeq2.IsNull()) return NULL;
813 Standard_Integer j, val_j;
814 Standard_Integer aLength1 = aSeq1->Length();
815 Standard_Integer aLength2 = aSeq2->Length();
817 for (j = 1; j <= aLength1; j++) {
818 val_j = aSeq1->Value(j);
819 if (val_j > 0 && mapIDs.Add(val_j)) {
820 aNewIDs.Append(val_j);
823 for (j = 1; j <= aLength2; j++) {
824 val_j = aSeq2->Value(j);
825 if (val_j > 0 && mapIDs.Add(val_j)) {
826 aNewIDs.Append(val_j);
830 if (aNewIDs.Extent() < 1) {
831 SetErrorCode("Error: UnionGroups cannot be performed on two empty groups");
835 // Put new indices from the list into an array
836 Standard_Integer k = 1;
837 TColStd_ListIteratorOfListOfInteger aNewIDsIter (aNewIDs);
838 Handle(TColStd_HArray1OfInteger) aNewArr = new TColStd_HArray1OfInteger (1, aNewIDs.Extent());
839 for (; aNewIDsIter.More(); aNewIDsIter.Next(), k++) {
840 aNewArr->SetValue(k, aNewIDsIter.Value());
844 Handle(GEOM_Object) aGroup = GetEngine()->AddSubShape(aMainObj, aNewArr);
845 aGroup->SetType(GEOM_GROUP);
846 TDF_Label aFreeLabel = aGroup->GetFreeLabel();
847 TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aType);
849 // Make a Python command
850 Handle(GEOM_Function) aFunction = aGroup->GetFunction(1);
851 GEOM::TPythonDump(aFunction) << aGroup << " = geompy.UnionGroups("
852 << theGroup1 << ", " << theGroup2 << ")";
858 //=============================================================================
862 //=============================================================================
863 Handle(GEOM_Object) GEOMImpl_IGroupOperations::IntersectGroups (Handle(GEOM_Object) theGroup1,
864 Handle(GEOM_Object) theGroup2)
867 if (theGroup1.IsNull() || theGroup2.IsNull()) return NULL;
870 TopAbs_ShapeEnum aType1 = GetType(theGroup1);
871 TopAbs_ShapeEnum aType2 = GetType(theGroup2);
872 TopAbs_ShapeEnum aType = aType1;
873 if (aType1 != aType2) {
874 if (aType1 != TopAbs_SHAPE && aType1 != TopAbs_COMPOUND) {
875 if (aType2 == TopAbs_SHAPE || aType2 == TopAbs_COMPOUND)
878 SetErrorCode("Error: IntersectGroups cannot be performed on groups of different type");
885 Handle(GEOM_Function) aFunction1 = theGroup1->GetLastFunction();
886 Handle(GEOM_Function) aFunction2 = theGroup2->GetLastFunction();
887 if (aFunction1.IsNull() || aFunction2.IsNull()) return NULL;
889 GEOM_ISubShape aSSI1 (aFunction1);
890 GEOM_ISubShape aSSI2 (aFunction2);
892 Handle(GEOM_Function) aMainShapeFunc1 = aSSI1.GetMainShape();
893 Handle(GEOM_Function) aMainShapeFunc2 = aSSI2.GetMainShape();
894 if (aMainShapeFunc1.IsNull() || aMainShapeFunc2.IsNull()) return NULL;
896 TDF_Label aLabel1 = aMainShapeFunc1->GetOwnerEntry();
897 TDF_Label aLabel2 = aMainShapeFunc2->GetOwnerEntry();
898 if (aLabel1.IsRoot() || aLabel2.IsRoot()) {
899 SetErrorCode("Error: UnionGroups can be performed only on groups");
903 if (aLabel1 != aLabel2) {
904 SetErrorCode("Error: IntersectGroups cannot be performed on groups, built on different main shapes");
908 Handle(GEOM_Object) aMainObj = GEOM_Object::GetObject(aLabel1);
909 if (aMainObj.IsNull()) return NULL;
911 // New contents of the group
912 TColStd_ListOfInteger aNewIDs;
913 TColStd_MapOfInteger mapIDs;
915 Handle(TColStd_HArray1OfInteger) aSeq1 = aSSI1.GetIndices();
916 Handle(TColStd_HArray1OfInteger) aSeq2 = aSSI2.GetIndices();
917 if (aSeq1.IsNull() || aSeq2.IsNull()) return NULL;
919 Standard_Integer j, val_j;
920 Standard_Integer aLength1 = aSeq1->Length();
921 Standard_Integer aLength2 = aSeq2->Length();
923 for (j = 1; j <= aLength1; j++) {
924 mapIDs.Add(aSeq1->Value(j));
926 for (j = 1; j <= aLength2; j++) {
927 val_j = aSeq2->Value(j);
928 if (val_j > 0 && !mapIDs.Add(val_j)) {
929 // add index, if it is in mapIDs (filled from Group_1)
930 aNewIDs.Append(val_j);
934 Handle(TColStd_HArray1OfInteger) aNewArr;
935 if (aNewIDs.Extent() < 1) {
936 aNewArr = new TColStd_HArray1OfInteger (1, 1);
937 aNewArr->SetValue(1, -1);
940 // Put new indices from the list into an array
941 Standard_Integer k = 1;
942 TColStd_ListIteratorOfListOfInteger aNewIDsIter (aNewIDs);
943 aNewArr = new TColStd_HArray1OfInteger (1, aNewIDs.Extent());
944 for (; aNewIDsIter.More(); aNewIDsIter.Next(), k++) {
945 aNewArr->SetValue(k, aNewIDsIter.Value());
950 Handle(GEOM_Object) aGroup = GetEngine()->AddSubShape(aMainObj, aNewArr);
951 aGroup->SetType(GEOM_GROUP);
952 TDF_Label aFreeLabel = aGroup->GetFreeLabel();
953 TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aType);
955 // Make a Python command
956 Handle(GEOM_Function) aFunction = aGroup->GetFunction(1);
957 GEOM::TPythonDump(aFunction) << aGroup << " = geompy.IntersectGroups("
958 << theGroup1 << ", " << theGroup2 << ")";
964 //=============================================================================
968 //=============================================================================
969 Handle(GEOM_Object) GEOMImpl_IGroupOperations::CutGroups (Handle(GEOM_Object) theGroup1,
970 Handle(GEOM_Object) theGroup2)
973 if (theGroup1.IsNull() || theGroup2.IsNull()) return NULL;
976 TopAbs_ShapeEnum aType1 = GetType(theGroup1);
977 TopAbs_ShapeEnum aType2 = GetType(theGroup2);
978 TopAbs_ShapeEnum aType = aType1;
979 if (aType1 != aType2) {
980 if (aType1 != TopAbs_SHAPE && aType1 != TopAbs_COMPOUND) {
981 if (aType2 == TopAbs_SHAPE || aType2 == TopAbs_COMPOUND)
984 SetErrorCode("Error: CutGroups cannot be performed on groups of different type");
991 Handle(GEOM_Function) aFunction1 = theGroup1->GetLastFunction();
992 Handle(GEOM_Function) aFunction2 = theGroup2->GetLastFunction();
993 if (aFunction1.IsNull() || aFunction2.IsNull()) return NULL;
995 GEOM_ISubShape aSSI1 (aFunction1);
996 GEOM_ISubShape aSSI2 (aFunction2);
998 Handle(GEOM_Function) aMainShapeFunc1 = aSSI1.GetMainShape();
999 Handle(GEOM_Function) aMainShapeFunc2 = aSSI2.GetMainShape();
1000 if (aMainShapeFunc1.IsNull() || aMainShapeFunc2.IsNull()) return NULL;
1002 TDF_Label aLabel1 = aMainShapeFunc1->GetOwnerEntry();
1003 TDF_Label aLabel2 = aMainShapeFunc2->GetOwnerEntry();
1004 if (aLabel1.IsRoot() || aLabel2.IsRoot()) {
1005 SetErrorCode("Error: UnionGroups can be performed only on groups");
1009 if (aLabel1 != aLabel2) {
1010 SetErrorCode("Error: CutGroups cannot be performed on groups, built on different main shapes");
1014 Handle(GEOM_Object) aMainObj = GEOM_Object::GetObject(aLabel1);
1015 if (aMainObj.IsNull()) return NULL;
1017 // New contents of the group
1018 TColStd_ListOfInteger aNewIDs;
1019 TColStd_MapOfInteger mapIDs;
1021 Handle(TColStd_HArray1OfInteger) aSeq1 = aSSI1.GetIndices();
1022 Handle(TColStd_HArray1OfInteger) aSeq2 = aSSI2.GetIndices();
1023 if (aSeq1.IsNull() || aSeq2.IsNull()) return NULL;
1025 Standard_Integer j, val_j;
1026 Standard_Integer aLength1 = aSeq1->Length();
1027 Standard_Integer aLength2 = aSeq2->Length();
1029 for (j = 1; j <= aLength2; j++) {
1030 mapIDs.Add(aSeq2->Value(j));
1032 for (j = 1; j <= aLength1; j++) {
1033 val_j = aSeq1->Value(j);
1034 if (val_j > 0 && mapIDs.Add(val_j)) {
1035 // add index, if it is not in mapIDs (filled from Group_2)
1036 aNewIDs.Append(val_j);
1040 Handle(TColStd_HArray1OfInteger) aNewArr;
1041 if (aNewIDs.Extent() < 1) {
1042 aNewArr = new TColStd_HArray1OfInteger (1, 1);
1043 aNewArr->SetValue(1, -1);
1046 // Put new indices from the list into an array
1047 Standard_Integer k = 1;
1048 TColStd_ListIteratorOfListOfInteger aNewIDsIter (aNewIDs);
1049 aNewArr = new TColStd_HArray1OfInteger (1, aNewIDs.Extent());
1050 for (; aNewIDsIter.More(); aNewIDsIter.Next(), k++) {
1051 aNewArr->SetValue(k, aNewIDsIter.Value());
1056 Handle(GEOM_Object) aGroup = GetEngine()->AddSubShape(aMainObj, aNewArr);
1057 aGroup->SetType(GEOM_GROUP);
1058 TDF_Label aFreeLabel = aGroup->GetFreeLabel();
1059 TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aType);
1061 // Make a Python command
1062 Handle(GEOM_Function) aFunction = aGroup->GetFunction(1);
1063 GEOM::TPythonDump(aFunction) << aGroup << " = geompy.CutGroups("
1064 << theGroup1 << ", " << theGroup2 << ")";
1070 //=============================================================================
1074 //=============================================================================
1075 Handle(GEOM_Object) GEOMImpl_IGroupOperations::UnionListOfGroups
1076 (const Handle(TColStd_HSequenceOfTransient)& theGList)
1079 if (theGList.IsNull()) return NULL;
1081 Standard_Integer i, aLen = theGList->Length();
1083 SetErrorCode("UnionListOfGroups error: the list of groups is empty");
1087 TopAbs_ShapeEnum aType, aType_i;
1088 TDF_Label aLabel, aLabel_i;
1089 TColStd_ListOfInteger aNewIDs;
1090 TColStd_MapOfInteger mapIDs;
1092 // Iterate on the initial groups
1093 for (i = 1; i <= aLen; i++) {
1094 Handle(GEOM_Object) aGr_i = Handle(GEOM_Object)::DownCast(theGList->Value(i));
1097 aType_i = GetType(aGr_i);
1101 if (aType_i != aType) {
1102 if (aType != TopAbs_SHAPE && aType != TopAbs_COMPOUND) {
1103 if (aType_i == TopAbs_SHAPE || aType_i == TopAbs_COMPOUND)
1106 SetErrorCode("Error: UnionListOfGroups cannot be performed on groups of different type");
1114 Handle(GEOM_Function) aFunction_i = aGr_i->GetLastFunction();
1115 if (aFunction_i.IsNull()) return NULL;
1116 GEOM_ISubShape aSSI (aFunction_i);
1117 Handle(GEOM_Function) aMainShapeFunc = aSSI.GetMainShape();
1118 if (aMainShapeFunc.IsNull()) return NULL;
1119 aLabel_i = aMainShapeFunc->GetOwnerEntry();
1120 if (aLabel_i.IsRoot()) {
1121 SetErrorCode("Error: UnionGroups can be performed only on groups");
1127 if (aLabel_i != aLabel) {
1128 SetErrorCode("Error: UnionListOfGroups cannot be performed on groups, built on different main shapes");
1133 // New contents of the group
1134 Handle(TColStd_HArray1OfInteger) aSeq = aSSI.GetIndices();
1135 if (aSeq.IsNull()) return NULL;
1137 Standard_Integer j, val_j, aLength = aSeq->Length();
1138 for (j = 1; j <= aLength; j++) {
1139 val_j = aSeq->Value(j);
1140 if (val_j > 0 && mapIDs.Add(val_j)) {
1141 aNewIDs.Append(val_j);
1146 // Check the resulting list of indices
1147 if (aNewIDs.Extent() < 1) {
1148 SetErrorCode("Error: UnionListOfGroups cannot be performed on all empty groups");
1152 Handle(GEOM_Object) aMainObj = GEOM_Object::GetObject(aLabel);
1153 if (aMainObj.IsNull()) return NULL;
1155 // Put new indices from the list into an array
1156 Standard_Integer k = 1;
1157 TColStd_ListIteratorOfListOfInteger aNewIDsIter (aNewIDs);
1158 Handle(TColStd_HArray1OfInteger) aNewArr = new TColStd_HArray1OfInteger (1, aNewIDs.Extent());
1159 for (; aNewIDsIter.More(); aNewIDsIter.Next(), k++) {
1160 aNewArr->SetValue(k, aNewIDsIter.Value());
1164 Handle(GEOM_Object) aGroup = GetEngine()->AddSubShape(aMainObj, aNewArr);
1165 aGroup->SetType(GEOM_GROUP);
1166 TDF_Label aFreeLabel = aGroup->GetFreeLabel();
1167 TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aType);
1169 //Make a Python command
1170 Handle(GEOM_Function) aFunction = aGroup->GetFunction(1);
1171 GEOM::TPythonDump pd (aFunction);
1172 pd << aGroup << " = geompy.UnionListOfGroups([";
1173 for (i = 1; i <= aLen; i++) {
1174 Handle(GEOM_Object) aGr_i = Handle(GEOM_Object)::DownCast(theGList->Value(i));
1175 pd << aGr_i << ((i < aLen) ? ", " : "])");
1182 //=============================================================================
1184 * IntersectListOfGroups
1186 //=============================================================================
1187 Handle(GEOM_Object) GEOMImpl_IGroupOperations::IntersectListOfGroups
1188 (const Handle(TColStd_HSequenceOfTransient)& theGList)
1191 if (theGList.IsNull()) return NULL;
1193 Standard_Integer i, aLen = theGList->Length();
1195 SetErrorCode("IntersectListOfGroups error: the list of groups is empty");
1199 TopAbs_ShapeEnum aType, aType_i;
1200 TDF_Label aLabel, aLabel_i;
1201 TColStd_ListOfInteger aNewIDs;
1202 TColStd_MapOfInteger mapIDs;
1204 // Iterate on the initial groups
1205 for (i = 1; i <= aLen; i++) {
1206 Handle(GEOM_Object) aGr_i = Handle(GEOM_Object)::DownCast(theGList->Value(i));
1209 aType_i = GetType(aGr_i);
1213 if (aType_i != aType) {
1214 if (aType != TopAbs_SHAPE && aType != TopAbs_COMPOUND) {
1215 if (aType_i == TopAbs_SHAPE || aType_i == TopAbs_COMPOUND)
1218 SetErrorCode("Error: IntersectListOfGroups cannot be performed on groups of different type");
1226 Handle(GEOM_Function) aFunction_i = aGr_i->GetLastFunction();
1227 if (aFunction_i.IsNull()) return NULL;
1228 GEOM_ISubShape aSSI (aFunction_i);
1229 Handle(GEOM_Function) aMainShapeFunc = aSSI.GetMainShape();
1230 if (aMainShapeFunc.IsNull()) return NULL;
1231 aLabel_i = aMainShapeFunc->GetOwnerEntry();
1232 if (aLabel_i.IsRoot()) {
1233 SetErrorCode("Error: UnionGroups can be performed only on groups");
1239 if (aLabel_i != aLabel) {
1240 SetErrorCode("Error: IntersectListOfGroups cannot be performed on groups, built on different main shapes");
1245 // New contents of the group
1246 Handle(TColStd_HArray1OfInteger) aSeq = aSSI.GetIndices();
1247 if (aSeq.IsNull()) return NULL;
1249 Standard_Integer j, val_j, aLength = aSeq->Length();
1250 for (j = 1; j <= aLength; j++) {
1251 val_j = aSeq->Value(j);
1254 // get all elements of the first group
1255 if (mapIDs.Add(val_j))
1256 aNewIDs.Append(val_j);
1259 // get only elements, present in all previously processed groups
1260 if (!mapIDs.Add(val_j))
1261 aNewIDs.Append(val_j);
1266 // refill the map with only validated elements
1269 TColStd_ListIteratorOfListOfInteger aNewIDsIter (aNewIDs);
1270 for (; aNewIDsIter.More(); aNewIDsIter.Next()) {
1271 mapIDs.Add(aNewIDsIter.Value());
1274 // clear the resulting list before starting the next sycle
1280 Handle(GEOM_Object) aMainObj = GEOM_Object::GetObject(aLabel);
1281 if (aMainObj.IsNull()) return NULL;
1283 Handle(TColStd_HArray1OfInteger) aNewArr;
1284 if (aNewIDs.Extent() < 1) {
1285 aNewArr = new TColStd_HArray1OfInteger (1, 1);
1286 aNewArr->SetValue(1, -1);
1289 // Put new indices from the list into an array
1290 Standard_Integer k = 1;
1291 TColStd_ListIteratorOfListOfInteger aNewIDsIter (aNewIDs);
1292 aNewArr = new TColStd_HArray1OfInteger (1, aNewIDs.Extent());
1293 for (; aNewIDsIter.More(); aNewIDsIter.Next(), k++) {
1294 aNewArr->SetValue(k, aNewIDsIter.Value());
1299 Handle(GEOM_Object) aGroup = GetEngine()->AddSubShape(aMainObj, aNewArr);
1300 aGroup->SetType(GEOM_GROUP);
1301 TDF_Label aFreeLabel = aGroup->GetFreeLabel();
1302 TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aType);
1304 //Make a Python command
1305 Handle(GEOM_Function) aFunction = aGroup->GetFunction(1);
1306 GEOM::TPythonDump pd (aFunction);
1307 pd << aGroup << " = geompy.IntersectListOfGroups([";
1308 for (i = 1; i <= aLen; i++) {
1309 Handle(GEOM_Object) aGr_i = Handle(GEOM_Object)::DownCast(theGList->Value(i));
1310 pd << aGr_i << ((i < aLen) ? ", " : "])");
1317 //=============================================================================
1321 //=============================================================================
1322 Handle(GEOM_Object) GEOMImpl_IGroupOperations::CutListOfGroups
1323 (const Handle(TColStd_HSequenceOfTransient)& theGList1,
1324 const Handle(TColStd_HSequenceOfTransient)& theGList2)
1327 if (theGList1.IsNull() || theGList2.IsNull()) return NULL;
1330 Standard_Integer aLen1 = theGList1->Length();
1331 Standard_Integer aLen2 = theGList2->Length();
1333 SetErrorCode("CutListOfGroups error: the first list of groups is empty");
1337 TopAbs_ShapeEnum aType, aType_i;
1338 TDF_Label aLabel, aLabel_i;
1339 TColStd_ListOfInteger aNewIDs;
1340 TColStd_MapOfInteger mapIDs;
1342 // 1. Collect indices to be excluded (from theGList2) into the mapIDs
1343 for (i = 1; i <= aLen2; i++) {
1344 Handle(GEOM_Object) aGr_i = Handle(GEOM_Object)::DownCast(theGList2->Value(i));
1347 aType_i = GetType(aGr_i);
1351 if (aType_i != aType) {
1352 if (aType != TopAbs_SHAPE && aType != TopAbs_COMPOUND) {
1353 if (aType_i == TopAbs_SHAPE || aType_i == TopAbs_COMPOUND)
1356 SetErrorCode("Error: CutListOfGroups cannot be performed on groups of different type");
1364 Handle(GEOM_Function) aFunction_i = aGr_i->GetLastFunction();
1365 if (aFunction_i.IsNull()) return NULL;
1366 GEOM_ISubShape aSSI (aFunction_i);
1367 Handle(GEOM_Function) aMainShapeFunc = aSSI.GetMainShape();
1368 if (aMainShapeFunc.IsNull()) return NULL;
1369 aLabel_i = aMainShapeFunc->GetOwnerEntry();
1370 if (aLabel_i.IsRoot()) {
1371 SetErrorCode("Error: UnionGroups can be performed only on groups");
1377 if (aLabel_i != aLabel) {
1378 SetErrorCode("Error: CutListOfGroups cannot be performed on groups, built on different main shapes");
1383 // Indiced to exclude
1384 Handle(TColStd_HArray1OfInteger) aSeq = aSSI.GetIndices();
1385 if (aSeq.IsNull()) return NULL;
1387 Standard_Integer j, aLength = aSeq->Length();
1388 for (j = 1; j <= aLength; j++) {
1389 mapIDs.Add(aSeq->Value(j));
1393 // 2. Collect indices from theGList1, avoiding indices from theGList2 (mapIDs)
1394 for (i = 1; i <= aLen1; i++) {
1395 Handle(GEOM_Object) aGr_i = Handle(GEOM_Object)::DownCast(theGList1->Value(i));
1398 aType_i = GetType(aGr_i);
1399 if (i == 1 && aLen2 < 1)
1402 if (aType_i != aType) {
1403 if (aType != TopAbs_SHAPE && aType != TopAbs_COMPOUND) {
1404 if (aType_i == TopAbs_SHAPE || aType_i == TopAbs_COMPOUND)
1407 SetErrorCode("Error: CutListOfGroups cannot be performed on groups of different type");
1415 Handle(GEOM_Function) aFunction_i = aGr_i->GetLastFunction();
1416 if (aFunction_i.IsNull()) return NULL;
1417 GEOM_ISubShape aSSI (aFunction_i);
1418 Handle(GEOM_Function) aMainShapeFunc = aSSI.GetMainShape();
1419 if (aMainShapeFunc.IsNull()) return NULL;
1420 aLabel_i = aMainShapeFunc->GetOwnerEntry();
1421 if (aLabel_i.IsRoot()) {
1422 SetErrorCode("Error: UnionGroups can be performed only on groups");
1425 if (i == 1 && aLen2 < 1)
1428 if (aLabel_i != aLabel) {
1429 SetErrorCode("Error: CutListOfGroups cannot be performed on groups, built on different main shapes");
1434 // New contents of the group
1435 Handle(TColStd_HArray1OfInteger) aSeq = aSSI.GetIndices();
1436 if (aSeq.IsNull()) return NULL;
1438 Standard_Integer j, val_j, aLength = aSeq->Length();
1439 for (j = 1; j <= aLength; j++) {
1440 val_j = aSeq->Value(j);
1441 if (val_j > 0 && mapIDs.Add(val_j)) {
1442 // get only elements, not present in mapIDs (theGList2)
1443 aNewIDs.Append(val_j);
1448 Handle(GEOM_Object) aMainObj = GEOM_Object::GetObject(aLabel);
1449 if (aMainObj.IsNull()) return NULL;
1451 Handle(TColStd_HArray1OfInteger) aNewArr;
1452 if (aNewIDs.Extent() < 1) {
1453 aNewArr = new TColStd_HArray1OfInteger (1, 1);
1454 aNewArr->SetValue(1, -1);
1457 // Put new indices from the list into an array
1458 Standard_Integer k = 1;
1459 TColStd_ListIteratorOfListOfInteger aNewIDsIter (aNewIDs);
1460 aNewArr = new TColStd_HArray1OfInteger (1, aNewIDs.Extent());
1461 for (; aNewIDsIter.More(); aNewIDsIter.Next(), k++) {
1462 aNewArr->SetValue(k, aNewIDsIter.Value());
1467 Handle(GEOM_Object) aGroup = GetEngine()->AddSubShape(aMainObj, aNewArr);
1468 aGroup->SetType(GEOM_GROUP);
1469 TDF_Label aFreeLabel = aGroup->GetFreeLabel();
1470 TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aType);
1472 //Make a Python command
1473 Handle(GEOM_Function) aFunction = aGroup->GetFunction(1);
1474 GEOM::TPythonDump pd (aFunction);
1475 pd << aGroup << " = geompy.CutListOfGroups([";
1476 for (i = 1; i <= aLen1; i++) {
1477 Handle(GEOM_Object) aGr_i = Handle(GEOM_Object)::DownCast(theGList1->Value(i));
1478 pd << aGr_i << ((i < aLen1) ? ", " : "], [");
1480 for (i = 1; i <= aLen2; i++) {
1481 Handle(GEOM_Object) aGr_i = Handle(GEOM_Object)::DownCast(theGList2->Value(i));
1482 pd << aGr_i << ((i < aLen2) ? ", " : "])");
1489 //=============================================================================
1493 //=============================================================================
1494 TopAbs_ShapeEnum GEOMImpl_IGroupOperations::GetType(Handle(GEOM_Object) theGroup)
1498 TDF_Label aFreeLabel = theGroup->GetFreeLabel();
1499 Handle(TDataStd_Integer) anAttrib;
1500 if(!aFreeLabel.FindAttribute(TDataStd_Integer::GetID(), anAttrib)) return TopAbs_SHAPE;
1503 return (TopAbs_ShapeEnum) anAttrib->Get();
1506 //=============================================================================
1510 //=============================================================================
1511 Handle(GEOM_Object) GEOMImpl_IGroupOperations::GetMainShape (Handle(GEOM_Object) theGroup)
1515 if(theGroup.IsNull()) return NULL;
1517 Handle(GEOM_Function) aGroupFunction = theGroup->GetFunction(1);
1518 if (aGroupFunction.IsNull()) return NULL;
1520 GEOM_ISubShape aSSI (aGroupFunction);
1521 Handle(GEOM_Function) aMainShapeFunction = aSSI.GetMainShape();
1522 if (aMainShapeFunction.IsNull()) return NULL;
1524 TDF_Label aLabel = aMainShapeFunction->GetOwnerEntry();
1525 Handle(GEOM_Object) aMainShape = GEOM_Object::GetObject(aLabel);
1526 if (aMainShape.IsNull()) return NULL;
1528 //Make a Python command
1529 //GEOM::TPythonDump(aGroupFunction, /*append=*/true)
1530 // << aMainShape << " = geompy.GetMainShape(" << theGroup << ")";
1536 //=============================================================================
1540 //=============================================================================
1541 Handle(TColStd_HArray1OfInteger) GEOMImpl_IGroupOperations::GetObjects(Handle(GEOM_Object) theGroup)
1545 if(theGroup.IsNull()) return NULL;
1547 Handle(GEOM_Function) aFunction = theGroup->GetLastFunction();
1548 if(aFunction.IsNull()) return NULL;
1550 GEOM_ISubShape aSSI(aFunction);
1551 Handle(TColStd_HArray1OfInteger) aSeq = aSSI.GetIndices();
1552 if(aSeq.IsNull()) return NULL;
1554 if(aSeq->Length() == 1 && aSeq->Value(1) == -1) {