Back to index

salome-geom  6.5.0
GEOMImpl_IGroupOperations.cxx
Go to the documentation of this file.
00001 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
00002 //
00003 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
00004 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
00005 //
00006 // This library is free software; you can redistribute it and/or
00007 // modify it under the terms of the GNU Lesser General Public
00008 // License as published by the Free Software Foundation; either
00009 // version 2.1 of the License.
00010 //
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 // Lesser General Public License for more details.
00015 //
00016 // You should have received a copy of the GNU Lesser General Public
00017 // License along with this library; if not, write to the Free Software
00018 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00019 //
00020 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
00021 //
00022 
00023 #include <Standard_Stream.hxx>
00024 
00025 #include <GEOMImpl_IGroupOperations.hxx>
00026 
00027 #include <GEOMImpl_Types.hxx>
00028 
00029 #include <GEOM_Function.hxx>
00030 #include <GEOM_ISubShape.hxx>
00031 #include <GEOM_PythonDump.hxx>
00032 
00033 #include "utilities.h"
00034 #include <OpUtil.hxx>
00035 #include <Utils_ExceptHandlers.hxx>
00036 
00037 #include <TFunction_DriverTable.hxx>
00038 #include <TFunction_Driver.hxx>
00039 #include <TFunction_Logbook.hxx>
00040 #include <TDF_Tool.hxx>
00041 #include <TDataStd_Integer.hxx>
00042 
00043 #include <TopExp.hxx>
00044 #include <TopExp_Explorer.hxx>
00045 #include <TopTools_IndexedMapOfShape.hxx>
00046 
00047 #include <TColStd_HArray1OfInteger.hxx>
00048 #include <TColStd_MapOfInteger.hxx>
00049 #include <TColStd_ListOfInteger.hxx>
00050 #include <TColStd_ListIteratorOfListOfInteger.hxx>
00051 
00052 //=============================================================================
00056 //=============================================================================
00057 GEOMImpl_IGroupOperations::GEOMImpl_IGroupOperations (GEOM_Engine* theEngine, int theDocID)
00058 : GEOM_IOperations(theEngine, theDocID)
00059 {
00060   MESSAGE("GEOMImpl_IGroupOperations::GEOMImpl_IGroupOperations");
00061 }
00062 
00063 //=============================================================================
00067 //=============================================================================
00068 GEOMImpl_IGroupOperations::~GEOMImpl_IGroupOperations()
00069 {
00070   MESSAGE("GEOMImpl_IGroupOperations::~GEOMImpl_IGroupOperations");
00071 }
00072 
00073 
00074 //=============================================================================
00078 //=============================================================================
00079 Handle(GEOM_Object) GEOMImpl_IGroupOperations::CreateGroup
00080        (Handle(GEOM_Object) theMainShape, TopAbs_ShapeEnum theShapeType)
00081 {
00082   SetErrorCode(KO);
00083 
00084   Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
00085   anArray->SetValue(1, -1);
00086 
00087   //Add a new Sub-shape object
00088   Handle(GEOM_Object) aGroup = GetEngine()->AddSubShape(theMainShape, anArray);
00089 
00090   //Set a GROUP type
00091   aGroup->SetType(GEOM_GROUP);
00092 
00093   //Set a sub-shape type
00094   TDF_Label aFreeLabel = aGroup->GetFreeLabel();
00095   TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)theShapeType);
00096 
00097   //Make a Python command
00098   Handle(GEOM_Function) aFunction = aGroup->GetFunction(1);
00099 
00100   GEOM::TPythonDump(aFunction) << aGroup
00101     << " = geompy.CreateGroup(" << theMainShape << ", " << theShapeType << ")";
00102 
00103   SetErrorCode(OK);
00104   return aGroup;
00105 }
00106 
00107 //=============================================================================
00111 //=============================================================================
00112 void GEOMImpl_IGroupOperations::AddObject(Handle(GEOM_Object) theGroup, int theSubShapeID)
00113 {
00114   SetErrorCode(KO);
00115   if(theGroup.IsNull()) return;
00116 
00117   Handle(GEOM_Function) aFunction = theGroup->GetFunction(1);
00118   if(aFunction.IsNull()) return;
00119 
00120   GEOM_ISubShape aSSI (aFunction);
00121 
00122   // Check sub-shape index validity
00123   TDF_Label aLabel = aSSI.GetMainShape()->GetOwnerEntry();
00124   if (aLabel.IsRoot()) return;
00125   Handle(GEOM_Object) aMainObj = GEOM_Object::GetObject(aLabel);
00126   if (aMainObj.IsNull()) return;
00127   TopoDS_Shape aMainShape = aMainObj->GetValue();
00128   if (aMainShape.IsNull()) return;
00129 
00130   TopTools_IndexedMapOfShape aMapOfShapes;
00131   TopExp::MapShapes(aMainShape, aMapOfShapes);
00132 
00133   if (theSubShapeID < 1 || aMapOfShapes.Extent() < theSubShapeID) {
00134     SetErrorCode("Invalid sub-shape index: out of range");
00135     return;
00136   }
00137 
00138   // Add sub-shape index
00139   Handle(TColStd_HArray1OfInteger) aSeq = aSSI.GetIndices();
00140   if(aSeq.IsNull()) return;
00141   if(aSeq->Length() == 1 && aSeq->Value(1) == -1) {
00142     aSeq->SetValue(1, theSubShapeID);
00143   }
00144   else {
00145     Standard_Integer aLength = aSeq->Length();
00146     Handle(TColStd_HArray1OfInteger) aNewSeq = new TColStd_HArray1OfInteger(1, aLength+1);
00147     for(Standard_Integer i = 1; i<=aLength; i++) {
00148       aNewSeq->SetValue(i, aSeq->Value(i));
00149       if(aSeq->Value(i) == theSubShapeID) {
00150         SetErrorCode(ALREADY_PRESENT);
00151         return; //
00152       }
00153     }
00154     aNewSeq->SetValue(aLength+1, theSubShapeID);
00155     aSSI.SetIndices(aNewSeq);
00156   }
00157 
00158   // As we do not recompute here our group, lets mark it as Modified
00159   Standard_Integer aTic = aMainObj->GetTic(); // tic of main shape
00160   theGroup->SetTic(aTic - 1);
00161 
00162   //Make a Python command
00163   GEOM::TPythonDump(aFunction, /*append=*/true)
00164     << "geompy.AddObject(" << theGroup << ", " << theSubShapeID << ")";
00165 
00166   SetErrorCode(OK);
00167   return;
00168 }
00169 
00170 //=============================================================================
00174 //=============================================================================
00175 void GEOMImpl_IGroupOperations::RemoveObject (Handle(GEOM_Object) theGroup, int theSubShapeID)
00176 {
00177   SetErrorCode(KO);
00178   if(theGroup.IsNull()) return;
00179 
00180   Handle(GEOM_Function) aFunction = theGroup->GetFunction(1);
00181   if(aFunction.IsNull()) return;
00182 
00183   GEOM_ISubShape aSSI(aFunction);
00184   Handle(TColStd_HArray1OfInteger) aSeq = aSSI.GetIndices();
00185   if(aSeq.IsNull()) return;
00186 
00187   if(aSeq->Length() == 1 && aSeq->Value(1) == -1) {
00188     SetErrorCode(NOT_EXISTS);
00189     return;
00190   }
00191 
00192   Handle(TColStd_HArray1OfInteger) aNewSeq;
00193   Standard_Integer aLength = aSeq->Length();
00194   if(aLength == 1) {
00195     if(aSeq->Value(1) != theSubShapeID) {
00196       SetErrorCode(NOT_EXISTS);
00197       return;
00198     }
00199     aNewSeq = new TColStd_HArray1OfInteger(1,1);
00200     aNewSeq->SetValue(1, -1);
00201   }
00202   else {
00203     aNewSeq = new TColStd_HArray1OfInteger(1, aLength-1);
00204     Standard_Boolean isFound = Standard_False;
00205     for (Standard_Integer i = 1, k = 1; i <= aLength; i++) {
00206       if (aSeq->Value(i) == theSubShapeID) {
00207         isFound = Standard_True;
00208       } else {
00209         if (k < aLength) { // this check is to avoid sequence <aNewSeq> overflow
00210           aNewSeq->SetValue(k, aSeq->Value(i));
00211           k++;
00212         }
00213       }
00214     }
00215 
00216     if (!isFound) {
00217       SetErrorCode(NOT_EXISTS);
00218       return;
00219     }
00220   }
00221 
00222   aSSI.SetIndices(aNewSeq);
00223 
00224   // As we do not recompute here our group, lets mark it as Modified
00225   TDF_Label aLabel = aSSI.GetMainShape()->GetOwnerEntry();
00226   if (aLabel.IsRoot()) return;
00227   Handle(GEOM_Object) aMainObj = GEOM_Object::GetObject(aLabel);
00228   if (aMainObj.IsNull()) return;
00229   Standard_Integer aTic = aMainObj->GetTic(); // tic of main shape
00230   theGroup->SetTic(aTic - 1);
00231 
00232   //Make a Python command
00233   GEOM::TPythonDump(aFunction, /*append=*/true)
00234     << "geompy.RemoveObject(" << theGroup << ", " << theSubShapeID << ")";
00235 
00236   SetErrorCode(OK);
00237   return;
00238 }
00239 
00240 //=============================================================================
00244 //=============================================================================
00245 void GEOMImpl_IGroupOperations::UnionList (Handle(GEOM_Object) theGroup,
00246                                            const Handle(TColStd_HSequenceOfTransient)& theSubShapes)
00247 {
00248   SetErrorCode(KO);
00249   if (theGroup.IsNull()) return;
00250 
00251   Standard_Integer aLen = theSubShapes->Length();
00252   if (aLen < 1) {
00253     //SetErrorCode("The list is empty");
00254     SetErrorCode(OK);
00255     return;
00256   }
00257 
00258   Handle(GEOM_Function) aFunction = theGroup->GetFunction(1);
00259   if (aFunction.IsNull()) return;
00260 
00261   GEOM_ISubShape aSSI (aFunction);
00262 
00263   // New contents of the group
00264   TColStd_ListOfInteger aNewIDs;
00265   TColStd_MapOfInteger mapIDs;
00266 
00267   // Add current IDs to the list
00268   Handle(TColStd_HArray1OfInteger) aSeq = aSSI.GetIndices();
00269   if (aSeq.IsNull()) return;
00270   Standard_Integer val_j, aLength = aSeq->Length();
00271 
00272   for (Standard_Integer j = 1; j <= aLength; j++) {
00273     val_j = aSeq->Value(j);
00274     if (val_j > 0 && mapIDs.Add(val_j)) {
00275       aNewIDs.Append(val_j);
00276     }
00277   }
00278 
00279   // Get Main Shape
00280   Handle(GEOM_Function) aMainShapeFunc = aSSI.GetMainShape();
00281   if (aMainShapeFunc.IsNull()) return;
00282   TDF_Label aLabel = aMainShapeFunc->GetOwnerEntry();
00283   if (aLabel.IsRoot()) return;
00284   Handle(GEOM_Object) aMainObj = GEOM_Object::GetObject(aLabel);
00285   if (aMainObj.IsNull()) return;
00286   TopoDS_Shape aMainShape = aMainObj->GetValue();
00287   if (aMainShape.IsNull()) return;
00288 
00289   TopTools_IndexedMapOfShape mapIndices;
00290   TopExp::MapShapes(aMainShape, mapIndices);
00291 
00292   // Get group type
00293   TopAbs_ShapeEnum aType = GetType(theGroup);
00294 
00295   // Get IDs of sub-shapes to add
00296   Standard_Integer i, new_id;
00297   for (i = 1; i <= aLen; i++) {
00298     Handle(GEOM_Object) anObj_i = Handle(GEOM_Object)::DownCast(theSubShapes->Value(i));
00299 
00300     TopoDS_Shape aShape_i = anObj_i->GetValue();
00301     if ( aShape_i.IsNull() ) continue;
00302     TopAbs_ShapeEnum aType_i = aShape_i.ShapeType();
00303 
00304     // 1. If aShape_i is sub-shape of aMainShape - add it
00305     if (anObj_i->IsMainShape()) {
00306       if (aType_i != aType && aType != TopAbs_SHAPE && aType != TopAbs_COMPOUND) {
00307         SetErrorCode("Operation aborted: one of given objects has a wrong type");
00308         return;
00309       }
00310       if (!mapIndices.Contains(aShape_i)) {
00311         SetErrorCode("Operation aborted: not a sub-shape given");
00312         return;
00313       }
00314       new_id = mapIndices.FindIndex(aShape_i);
00315       if (mapIDs.Add(new_id)) {
00316         aNewIDs.Append(new_id);
00317       }
00318     }
00319     // 2. If type of group is not defined - add all sub-shapes of aShape_i
00320     else if (aType == TopAbs_SHAPE || aType == TopAbs_COMPOUND) {
00321       TopTools_IndexedMapOfShape mapIndices_i;
00322       TopExp::MapShapes(aShape_i, mapIndices_i);
00323       Standard_Integer ii = 1, nbSubSh = mapIndices_i.Extent();
00324       Standard_Boolean someGood = Standard_False;
00325       for (; ii <= nbSubSh; ii++) {
00326         TopoDS_Shape aSubShape_i = mapIndices_i.FindKey(ii);
00327         if (mapIndices.Contains(aSubShape_i)) {
00328           someGood = Standard_True;
00329           new_id = mapIndices.FindIndex(aSubShape_i);
00330           if (mapIDs.Add(new_id)) {
00331             aNewIDs.Append(new_id);
00332           }
00333         }
00334       }
00335       if (!someGood) {
00336         SetErrorCode("Operation aborted: not a sub-shape given");
00337         return;
00338       }
00339     }
00340     // 3. If type of group is defined - add all sub-shapes of aShape_i of that type
00341     else {
00342       TopExp_Explorer aSubShapes_i (aShape_i, aType);
00343       for (; aSubShapes_i.More(); aSubShapes_i.Next()) {
00344         TopoDS_Shape aSubShape_i = aSubShapes_i.Current();
00345         if (!mapIndices.Contains(aSubShape_i)) {
00346           SetErrorCode("Operation aborted: not a sub-shape given");
00347           return;
00348         }
00349         new_id = mapIndices.FindIndex(aSubShape_i);
00350         if (mapIDs.Add(new_id)) {
00351           aNewIDs.Append(new_id);
00352         }
00353       }
00354     }
00355   }
00356 
00357   if (aNewIDs.Extent() > 0) {
00358     Standard_Integer k = 1;
00359     TColStd_ListIteratorOfListOfInteger aNewIDsIter (aNewIDs);
00360     Handle(TColStd_HArray1OfInteger) aNewSeq = new TColStd_HArray1OfInteger(1, aNewIDs.Extent());
00361     for (; aNewIDsIter.More(); aNewIDsIter.Next(), k++) {
00362       aNewSeq->SetValue(k, aNewIDsIter.Value());
00363     }
00364 
00365     aSSI.SetIndices(aNewSeq);
00366 
00367     // As we do not recompute here our group, lets mark it as Modified
00368     Standard_Integer aTic = aMainObj->GetTic(); // tic of main shape
00369     theGroup->SetTic(aTic - 1);
00370   }
00371 
00372   //Make a Python command
00373   Handle(GEOM_Object) aLatest = GEOM::GetCreatedLast(theSubShapes);
00374   aLatest = GEOM::GetCreatedLast(aLatest, theGroup);
00375   Handle(GEOM_Function) aLastFunc = aLatest->GetLastFunction();
00376 
00377   GEOM::TPythonDump pd (aLastFunc, /*append=*/true);
00378   pd << "geompy.UnionList(" << theGroup << ", [";
00379 
00380   for (i = 1; i <= aLen; i++) {
00381     Handle(GEOM_Object) anObj_i = Handle(GEOM_Object)::DownCast(theSubShapes->Value(i));
00382     pd << anObj_i << (( i < aLen ) ? ", " : "])");
00383   }
00384 
00385   SetErrorCode(OK);
00386 }
00387 
00388 //=============================================================================
00392 //=============================================================================
00393 void GEOMImpl_IGroupOperations::DifferenceList (Handle(GEOM_Object) theGroup,
00394                                                 const Handle(TColStd_HSequenceOfTransient)& theSubShapes)
00395 {
00396   SetErrorCode(KO);
00397   if (theGroup.IsNull()) return;
00398 
00399   Standard_Integer aLen = theSubShapes->Length();
00400   if (aLen < 1) {
00401     //SetErrorCode("The list is empty");
00402     SetErrorCode(OK);
00403     return;
00404   }
00405 
00406   Handle(GEOM_Function) aFunction = theGroup->GetFunction(1);
00407   if (aFunction.IsNull()) return;
00408 
00409   GEOM_ISubShape aSSI (aFunction);
00410 
00411   // Map of IDs to be removed
00412   TColStd_MapOfInteger mapIDsToRemove;
00413 
00414   // Map of current IDs
00415   Handle(TColStd_HArray1OfInteger) aSeq = aSSI.GetIndices();
00416   if (aSeq.IsNull()) return;
00417   Standard_Integer aLength = aSeq->Length();
00418 
00419   // VSR 28/04/2011 commented to allow operation even for empty group
00420   //   if (aLength == 1 && aSeq->Value(1) == -1) // empty group
00421   //     return;
00422 
00423   TColStd_MapOfInteger mapIDsCurrent;
00424   Standard_Integer j = 1;
00425   for (; j <= aLength; j++) {
00426     mapIDsCurrent.Add(aSeq->Value(j));
00427   }
00428 
00429   // Get Main Shape
00430   Handle(GEOM_Function) aMainShapeFunc = aSSI.GetMainShape();
00431   if (aMainShapeFunc.IsNull()) return;
00432   TDF_Label aLabel = aMainShapeFunc->GetOwnerEntry();
00433   if (aLabel.IsRoot()) return;
00434   Handle(GEOM_Object) aMainObj = GEOM_Object::GetObject(aLabel);
00435   if (aMainObj.IsNull()) return;
00436   TopoDS_Shape aMainShape = aMainObj->GetValue();
00437   if (aMainShape.IsNull()) return;
00438 
00439   TopTools_IndexedMapOfShape mapIndices;
00440   TopExp::MapShapes(aMainShape, mapIndices);
00441 
00442   // Get group type
00443   TopAbs_ShapeEnum aType = GetType(theGroup);
00444 
00445   // Get IDs of sub-shapes to be removed
00446   Standard_Integer i, rem_id;
00447   for (i = 1; i <= aLen; i++) {
00448     Handle(GEOM_Object) anObj_i = Handle(GEOM_Object)::DownCast(theSubShapes->Value(i));
00449 
00450     TopoDS_Shape aShape_i = anObj_i->GetValue();
00451 
00452     // 1. If aShape_i is sub-shape of aMainShape - remove it
00453     if (mapIndices.Contains(aShape_i)) {
00454       rem_id = mapIndices.FindIndex(aShape_i);
00455       if (rem_id > 0 && mapIDsCurrent.Contains(rem_id)) {
00456         mapIDsToRemove.Add(rem_id);
00457       }
00458     }
00459     // 2. If type of group is not defined - remove all sub-shapes of aShape_i
00460     else if (aType == TopAbs_SHAPE || aType == TopAbs_COMPOUND) {
00461       TopTools_IndexedMapOfShape mapIndices_i;
00462       TopExp::MapShapes(aShape_i, mapIndices_i);
00463       Standard_Integer nbSubSh = mapIndices_i.Extent();
00464       Standard_Integer ii = 1;
00465       for (; ii <= nbSubSh; ii++) {
00466         TopoDS_Shape aSubShape_i = mapIndices_i.FindKey(ii);
00467         if (mapIndices.Contains(aSubShape_i)) {
00468           rem_id = mapIndices.FindIndex(aSubShape_i);
00469           if (rem_id > 0 && mapIDsCurrent.Contains(rem_id)) {
00470             mapIDsToRemove.Add(rem_id);
00471           }
00472         }
00473       }
00474     }
00475     // 3. If type of group is defined - remove all sub-shapes of aShape_i of that type
00476     else {
00477       TopExp_Explorer aSubShapes_i (aShape_i, aType);
00478       for (; aSubShapes_i.More(); aSubShapes_i.Next()) {
00479         TopoDS_Shape aSubShape_i = aSubShapes_i.Current();
00480         if (mapIndices.Contains(aSubShape_i)) {
00481           rem_id = mapIndices.FindIndex(aSubShape_i);
00482           if (rem_id > 0 && mapIDsCurrent.Contains(rem_id)) {
00483             mapIDsToRemove.Add(rem_id);
00484           }
00485         }
00486       }
00487     }
00488   }
00489 
00490   if (mapIDsToRemove.Extent() > 0) {
00491     Standard_Integer k = 1, aRemLength = mapIDsToRemove.Extent();
00492     Handle(TColStd_HArray1OfInteger) aNewSeq;
00493     if ( aLength - aRemLength > 0 ) {
00494       aNewSeq = new TColStd_HArray1OfInteger(1, aLength - aRemLength);
00495       for (j = 1; j <= aLength; j++) {
00496        if (!mapIDsToRemove.Contains(aSeq->Value(j))) {
00497          aNewSeq->SetValue(k, aSeq->Value(j));
00498          k++;
00499        }
00500       }
00501     }
00502     else {
00503       aNewSeq = new TColStd_HArray1OfInteger(1,1);
00504       aNewSeq->SetValue(1, -1);
00505     }
00506 
00507     aSSI.SetIndices(aNewSeq);
00508 
00509     // As we do not recompute here our group, lets mark it as Modified
00510     Standard_Integer aTic = aMainObj->GetTic(); // tic of main shape
00511     theGroup->SetTic(aTic - 1);
00512   }
00513 
00514   //Make a Python command
00515   Handle(GEOM_Object) aLatest = GEOM::GetCreatedLast(theSubShapes);
00516   aLatest = GEOM::GetCreatedLast(aLatest, theGroup);
00517   Handle(GEOM_Function) aLastFunc = aLatest->GetLastFunction();
00518 
00519   GEOM::TPythonDump pd (aLastFunc, /*append=*/true);
00520   pd << "geompy.DifferenceList(" << theGroup << ", [";
00521 
00522   for (i = 1; i <= aLen; i++) {
00523     Handle(GEOM_Object) anObj_i = Handle(GEOM_Object)::DownCast(theSubShapes->Value(i));
00524     pd << anObj_i << (( i < aLen ) ? ", " : "])");
00525   }
00526 
00527   SetErrorCode(OK);
00528 }
00529 
00530 //=============================================================================
00534 //=============================================================================
00535 void GEOMImpl_IGroupOperations::UnionIDs (Handle(GEOM_Object) theGroup,
00536                                           const Handle(TColStd_HSequenceOfInteger)& theSubShapes)
00537 {
00538   SetErrorCode(KO);
00539   if (theGroup.IsNull()) return;
00540 
00541   Standard_Integer aLen = theSubShapes->Length();
00542   if (aLen < 1) {
00543     //SetErrorCode("The list is empty");
00544     SetErrorCode(OK);
00545     return;
00546   }
00547 
00548   Handle(GEOM_Function) aFunction = theGroup->GetFunction(1);
00549   if (aFunction.IsNull()) return;
00550 
00551   GEOM_ISubShape aSSI (aFunction);
00552 
00553   // New contents of the group
00554   TColStd_ListOfInteger aNewIDs;
00555   TColStd_MapOfInteger mapIDs;
00556 
00557   // Add current IDs to the list
00558   Handle(TColStd_HArray1OfInteger) aSeq = aSSI.GetIndices();
00559   if (aSeq.IsNull()) return;
00560   Standard_Integer val_j, aLength = aSeq->Length();
00561 
00562   for (Standard_Integer j = 1; j <= aLength; j++) {
00563     val_j = aSeq->Value(j);
00564     if (val_j > 0 && mapIDs.Add(val_j)) {
00565       aNewIDs.Append(val_j);
00566     }
00567   }
00568 
00569   // Get Main Shape
00570   Handle(GEOM_Function) aMainShapeFunc = aSSI.GetMainShape();
00571   if (aMainShapeFunc.IsNull()) return;
00572   TDF_Label aLabel = aMainShapeFunc->GetOwnerEntry();
00573   if (aLabel.IsRoot()) return;
00574   Handle(GEOM_Object) aMainObj = GEOM_Object::GetObject(aLabel);
00575   if (aMainObj.IsNull()) return;
00576   TopoDS_Shape aMainShape = aMainObj->GetValue();
00577   if (aMainShape.IsNull()) return;
00578 
00579   TopTools_IndexedMapOfShape mapIndices;
00580   TopExp::MapShapes(aMainShape, mapIndices);
00581 
00582   // Get group type
00583   TopAbs_ShapeEnum aType = GetType(theGroup);
00584 
00585   // Get IDs of sub-shapes to add
00586   Standard_Integer i, new_id;
00587   for (i = 1; i <= aLen; i++) {
00588     new_id = theSubShapes->Value(i);
00589 
00590     if (0 < new_id && new_id <= mapIndices.Extent()) {
00591       //if (mapIDs.Add(new_id)) { IPAL21297. Why we ignore invalid ids silently?
00592       if (mapIDs.Add(new_id) && mapIndices(new_id).ShapeType()==aType ) {
00593         aNewIDs.Append(new_id);
00594       }
00595     }
00596   }
00597 
00598   if (aNewIDs.Extent() > 0) {
00599     Standard_Integer k = 1;
00600     TColStd_ListIteratorOfListOfInteger aNewIDsIter (aNewIDs);
00601     Handle(TColStd_HArray1OfInteger) aNewSeq = new TColStd_HArray1OfInteger(1, aNewIDs.Extent());
00602     for (; aNewIDsIter.More(); aNewIDsIter.Next(), k++) {
00603       aNewSeq->SetValue(k, aNewIDsIter.Value());
00604     }
00605 
00606     aSSI.SetIndices(aNewSeq);
00607 
00608     // As we do not recompute here our group, lets mark it as Modified
00609     Standard_Integer aTic = aMainObj->GetTic(); // tic of main shape
00610     theGroup->SetTic(aTic - 1);
00611   }
00612 
00613   //Make a Python command
00614   GEOM::TPythonDump pd (aFunction, /*append=*/true);
00615   pd << "geompy.UnionIDs(" << theGroup << ", [";
00616   for (i = 1; i < aLen; i++)
00617     pd << theSubShapes->Value(i) << ", ";
00618   pd << theSubShapes->Value(aLen) << "])";
00619 
00620   SetErrorCode(OK);
00621 }
00622 
00623 //=============================================================================
00627 //=============================================================================
00628 void GEOMImpl_IGroupOperations::DifferenceIDs (Handle(GEOM_Object) theGroup,
00629                                                const Handle(TColStd_HSequenceOfInteger)& theSubShapes)
00630 {
00631   SetErrorCode(KO);
00632   if (theGroup.IsNull()) return;
00633 
00634   Standard_Integer aLen = theSubShapes->Length();
00635   if (aLen < 1) {
00636     //SetErrorCode("The list is empty");
00637     SetErrorCode(OK);
00638     return;
00639   }
00640 
00641   Handle(GEOM_Function) aFunction = theGroup->GetFunction(1);
00642   if (aFunction.IsNull()) return;
00643 
00644   GEOM_ISubShape aSSI (aFunction);
00645 
00646   // Map of IDs to be removed
00647   TColStd_MapOfInteger mapIDsToRemove;
00648 
00649   // Map of current IDs
00650   Handle(TColStd_HArray1OfInteger) aSeq = aSSI.GetIndices();
00651   if (aSeq.IsNull()) return;
00652   Standard_Integer aLength = aSeq->Length();
00653 
00654   // VSR 28/04/2011 commented to allow operation even for empty group
00655   //   if (aLength == 1 && aSeq->Value(1) == -1) // empty group
00656   //     return;
00657 
00658   TColStd_MapOfInteger mapIDsCurrent;
00659   Standard_Integer j = 1;
00660   for (; j <= aLength; j++) {
00661     mapIDsCurrent.Add(aSeq->Value(j));
00662   }
00663 
00664   // Get Main Shape
00665   Handle(GEOM_Function) aMainShapeFunc = aSSI.GetMainShape();
00666   if (aMainShapeFunc.IsNull()) return;
00667   TDF_Label aLabel = aMainShapeFunc->GetOwnerEntry();
00668   if (aLabel.IsRoot()) return;
00669   Handle(GEOM_Object) aMainObj = GEOM_Object::GetObject(aLabel);
00670   if (aMainObj.IsNull()) return;
00671   TopoDS_Shape aMainShape = aMainObj->GetValue();
00672   if (aMainShape.IsNull()) return;
00673 
00674   TopTools_IndexedMapOfShape mapIndices;
00675   TopExp::MapShapes(aMainShape, mapIndices);
00676 
00677   // Get IDs of sub-shapes to be removed
00678   Standard_Integer i, rem_id;
00679   for (i = 1; i <= aLen; i++) {
00680     rem_id = theSubShapes->Value(i);
00681     if (rem_id > 0 && mapIDsCurrent.Contains(rem_id)) {
00682       mapIDsToRemove.Add(rem_id);
00683     }
00684   }
00685 
00686   if (mapIDsToRemove.Extent() > 0) {
00687     Standard_Integer k = 1, aRemLength = mapIDsToRemove.Extent();
00688     Handle(TColStd_HArray1OfInteger) aNewSeq;
00689     if ( aLength - aRemLength > 0 ) {
00690       aNewSeq = new TColStd_HArray1OfInteger(1, aLength - aRemLength);
00691       for (j = 1; j <= aLength; j++) {
00692        if (!mapIDsToRemove.Contains(aSeq->Value(j))) {
00693          aNewSeq->SetValue(k, aSeq->Value(j));
00694          k++;
00695        }
00696       }
00697     }
00698     else {
00699       aNewSeq = new TColStd_HArray1OfInteger(1,1);
00700       aNewSeq->SetValue(1, -1);
00701     }
00702 
00703     aSSI.SetIndices(aNewSeq);
00704 
00705     // As we do not recompute here our group, lets mark it as Modified
00706     Standard_Integer aTic = aMainObj->GetTic(); // tic of main shape
00707     theGroup->SetTic(aTic - 1);
00708   }
00709 
00710   //Make a Python command
00711   GEOM::TPythonDump pd (aFunction, /*append=*/true);
00712   pd << "geompy.DifferenceIDs(" << theGroup << ", [";
00713   for (i = 1; i < aLen; i++)
00714     pd << theSubShapes->Value(i) << ", ";
00715   pd << theSubShapes->Value(aLen) << "])";
00716 
00717   SetErrorCode(OK);
00718 }
00719 
00720 //=============================================================================
00724 //=============================================================================
00725 TopAbs_ShapeEnum GEOMImpl_IGroupOperations::GetType(Handle(GEOM_Object) theGroup)
00726 {
00727   SetErrorCode(KO);
00728 
00729   TDF_Label aFreeLabel = theGroup->GetFreeLabel();
00730   Handle(TDataStd_Integer) anAttrib;
00731   if(!aFreeLabel.FindAttribute(TDataStd_Integer::GetID(), anAttrib)) return TopAbs_SHAPE;
00732 
00733   SetErrorCode(OK);
00734   return (TopAbs_ShapeEnum) anAttrib->Get();
00735 }
00736 
00737 //=============================================================================
00741 //=============================================================================
00742 Handle(GEOM_Object) GEOMImpl_IGroupOperations::GetMainShape (Handle(GEOM_Object) theGroup)
00743 {
00744   SetErrorCode(KO);
00745 
00746   if(theGroup.IsNull()) return NULL;
00747 
00748   Handle(GEOM_Function) aGroupFunction = theGroup->GetFunction(1);
00749   if (aGroupFunction.IsNull()) return NULL;
00750 
00751   GEOM_ISubShape aSSI (aGroupFunction);
00752   Handle(GEOM_Function) aMainShapeFunction = aSSI.GetMainShape();
00753   if (aMainShapeFunction.IsNull()) return NULL;
00754 
00755   TDF_Label aLabel = aMainShapeFunction->GetOwnerEntry();
00756   Handle(GEOM_Object) aMainShape = GEOM_Object::GetObject(aLabel);
00757   if (aMainShape.IsNull()) return NULL;
00758 
00759   //Make a Python command
00760   //GEOM::TPythonDump(aGroupFunction, /*append=*/true)
00761   //  << aMainShape << " = geompy.GetMainShape(" << theGroup << ")";
00762 
00763   SetErrorCode(OK);
00764   return aMainShape;
00765 }
00766 
00767 //=============================================================================
00771 //=============================================================================
00772 Handle(TColStd_HArray1OfInteger) GEOMImpl_IGroupOperations::GetObjects(Handle(GEOM_Object) theGroup)
00773 {
00774   SetErrorCode(KO);
00775 
00776   if(theGroup.IsNull()) return NULL;
00777 
00778   Handle(GEOM_Function) aFunction = theGroup->GetFunction(1);
00779   if(aFunction.IsNull()) return NULL;
00780 
00781   GEOM_ISubShape aSSI(aFunction);
00782   Handle(TColStd_HArray1OfInteger) aSeq = aSSI.GetIndices();
00783   if(aSeq.IsNull()) return NULL;
00784 
00785   if(aSeq->Length() == 1 && aSeq->Value(1) == -1) {
00786     SetErrorCode(OK);
00787     return NULL;
00788   }
00789 
00790   SetErrorCode(OK);
00791   return aSeq;
00792 }