From 00621ab4f35ece96476fc358acf598d78ec0a95d Mon Sep 17 00:00:00 2001 From: jfa Date: Mon, 24 Sep 2012 11:54:41 +0000 Subject: [PATCH] Mantis issue 0021703: [CEA 577] Boolean operations on groups. --- doc/salome/gui/GEOM/images/groups_cut_dlg.png | Bin 0 -> 18001 bytes .../gui/GEOM/images/groups_intersect_dlg.png | Bin 0 -> 15774 bytes .../gui/GEOM/images/groups_union_dlg.png | Bin 0 -> 14922 bytes doc/salome/gui/GEOM/input/tui_test_others.doc | 3 + .../GEOM/input/tui_working_with_groups.doc | 110 ++- .../gui/GEOM/input/working_with_groups.doc | 107 ++- idl/GEOM_Gen.idl | 59 ++ src/GEOMGUI/GEOM_images.ts | 12 + src/GEOMGUI/GEOM_msg_en.ts | 75 ++ src/GEOMGUI/GeometryGUI.cxx | 15 +- src/GEOMGUI/GeometryGUI_Operations.h | 3 + src/GEOMImpl/GEOMImpl_IGroupOperations.cxx | 754 +++++++++++++++++- src/GEOMImpl/GEOMImpl_IGroupOperations.hxx | 17 +- src/GEOM_I/GEOM_IGroupOperations_i.cc | 173 +++- src/GEOM_I/GEOM_IGroupOperations_i.hh | 19 +- src/GEOM_SWIG/GEOM_TestOthers.py | 37 + src/GEOM_SWIG/geompyDC.py | 150 ++++ src/GroupGUI/GroupGUI.cxx | 59 +- src/GroupGUI/GroupGUI_BooleanDlg.cxx | 320 ++++++++ src/GroupGUI/GroupGUI_BooleanDlg.h | 76 ++ src/GroupGUI/Makefile.am | 12 +- 21 files changed, 1938 insertions(+), 63 deletions(-) create mode 100644 doc/salome/gui/GEOM/images/groups_cut_dlg.png create mode 100644 doc/salome/gui/GEOM/images/groups_intersect_dlg.png create mode 100644 doc/salome/gui/GEOM/images/groups_union_dlg.png create mode 100644 src/GroupGUI/GroupGUI_BooleanDlg.cxx create mode 100644 src/GroupGUI/GroupGUI_BooleanDlg.h diff --git a/doc/salome/gui/GEOM/images/groups_cut_dlg.png b/doc/salome/gui/GEOM/images/groups_cut_dlg.png new file mode 100644 index 0000000000000000000000000000000000000000..248eebaa567d35b2d08c44c8230323f58ceceb8e GIT binary patch literal 18001 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 W9W}`?5$M{7D9Ncmt&n*c@;?B9S}vae literal 0 HcmV?d00001 diff --git a/doc/salome/gui/GEOM/images/groups_union_dlg.png b/doc/salome/gui/GEOM/images/groups_union_dlg.png new file mode 100644 index 0000000000000000000000000000000000000000..9df9cd651a9c7f123a87c5da66f63fd2c8b2a2cc GIT binary patch literal 14922 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

Creation of a group

+
+\anchor tui_create_groups_anchor +

Creation of a group

\code import geompy @@ -42,6 +44,8 @@ gg.createAndDisplayGO(id_group1) salome.sg.updateObjBrowser(1) \endcode +\anchor tui_edit_groups_anchor +

Adding an object to the group

\code @@ -107,4 +111,108 @@ gg.createAndDisplayGO(id_group1) salome.sg.updateObjBrowser(1) \endcode +
+\anchor tui_union_groups_anchor +

Union Groups

+ +\code +import geompy +import salome + +# create a box and some groups of faces on it +Box_1 = geompy.MakeBoxDXDYDZ(200, 200, 200) +Group_1 = geompy.CreateGroup(Box_1, geompy.ShapeType["FACE"]) +geompy.UnionIDs(Group_1, [13, 23]) +Group_2 = geompy.CreateGroup(Box_1, geompy.ShapeType["FACE"]) +geompy.UnionIDs(Group_2, [3, 27]) +Group_3 = geompy.CreateGroup(Box_1, geompy.ShapeType["FACE"]) +geompy.UnionIDs(Group_3, [33, 23]) +Group_4 = geompy.CreateGroup(Box_1, geompy.ShapeType["FACE"]) +geompy.UnionIDs(Group_4, [31, 27]) + +# union groups +Group_U_1_2 = geompy.UnionGroups(Group_1, Group_2) +Group_UL_3_4 = geompy.UnionListOfGroups([Group_3, Group_4]) + +# publish shapes +geompy.addToStudy(Box_1, 'Box_1') +geompy.addToStudyInFather(Box_1, Group_1, 'Group_1') +geompy.addToStudyInFather(Box_1, Group_2, 'Group_2') +geompy.addToStudyInFather(Box_1, Group_3, 'Group_3') +geompy.addToStudyInFather(Box_1, Group_4, 'Group_4') +geompy.addToStudyInFather(Box_1, Group_U_1_2, 'Group_U_1_2') +geompy.addToStudyInFather(Box_1, Group_UL_3_4, 'Group_UL_3_4') +salome.sg.updateObjBrowser(1) +\endcode + +
+\anchor tui_intersect_groups_anchor +

Intersect Groups

+ +\code +import geompy +import salome + +# create a box and some groups of faces on it +Box_1 = geompy.MakeBoxDXDYDZ(200, 200, 200) +Group_1 = geompy.CreateGroup(Box_1, geompy.ShapeType["FACE"]) +geompy.UnionIDs(Group_1, [13, 23]) +Group_2 = geompy.CreateGroup(Box_1, geompy.ShapeType["FACE"]) +geompy.UnionIDs(Group_2, [3, 27]) +Group_3 = geompy.CreateGroup(Box_1, geompy.ShapeType["FACE"]) +geompy.UnionIDs(Group_3, [33, 23]) +Group_4 = geompy.CreateGroup(Box_1, geompy.ShapeType["FACE"]) +geompy.UnionIDs(Group_4, [31, 27]) + +# intersect groups +Group_I_1_3 = geompy.IntersectGroups(Group_1, Group_3) +Group_IL_1_3 = geompy.IntersectListOfGroups([Group_1, Group_3]) + +# publish shapes +geompy.addToStudy(Box_1, 'Box_1') +geompy.addToStudyInFather(Box_1, Group_1, 'Group_1') +geompy.addToStudyInFather(Box_1, Group_2, 'Group_2') +geompy.addToStudyInFather(Box_1, Group_3, 'Group_3') +geompy.addToStudyInFather(Box_1, Group_4, 'Group_4') +geompy.addToStudyInFather(Box_1, Group_I_1_3, 'Group_I_1_3') +geompy.addToStudyInFather(Box_1, Group_IL_1_3, 'Group_IL_1_3') +salome.sg.updateObjBrowser(1) + +\endcode + +
+\anchor tui_cut_groups_anchor +

Cut Groups

+ +\code +import geompy +import salome + +# create a box and some groups of faces on it +Box_1 = geompy.MakeBoxDXDYDZ(200, 200, 200) +Group_1 = geompy.CreateGroup(Box_1, geompy.ShapeType["FACE"]) +geompy.UnionIDs(Group_1, [13, 23]) +Group_2 = geompy.CreateGroup(Box_1, geompy.ShapeType["FACE"]) +geompy.UnionIDs(Group_2, [3, 27]) +Group_3 = geompy.CreateGroup(Box_1, geompy.ShapeType["FACE"]) +geompy.UnionIDs(Group_3, [33, 23]) +Group_4 = geompy.CreateGroup(Box_1, geompy.ShapeType["FACE"]) +geompy.UnionIDs(Group_4, [31, 27]) + +# cut groups +Group_C_2_4 = geompy.CutGroups(Group_2, Group_4) +Group_CL_2_4 = geompy.CutListOfGroups([Group_2], [Group_4]) + +# publish shapes +geompy.addToStudy(Box_1, 'Box_1') +geompy.addToStudyInFather(Box_1, Group_1, 'Group_1') +geompy.addToStudyInFather(Box_1, Group_2, 'Group_2') +geompy.addToStudyInFather(Box_1, Group_3, 'Group_3') +geompy.addToStudyInFather(Box_1, Group_4, 'Group_4') +geompy.addToStudyInFather(Box_1, Group_C_2_4, 'Group_C_2_4') +geompy.addToStudyInFather(Box_1, Group_CL_2_4, 'Group_CL_2_4') +salome.sg.updateObjBrowser(1) + +\endcode + */ diff --git a/doc/salome/gui/GEOM/input/working_with_groups.doc b/doc/salome/gui/GEOM/input/working_with_groups.doc index 07838d585..a09865efa 100644 --- a/doc/salome/gui/GEOM/input/working_with_groups.doc +++ b/doc/salome/gui/GEOM/input/working_with_groups.doc @@ -3,13 +3,25 @@ \page work_with_groups_page Working with groups Creation and editing groups of sub-shapes of a geometrical object makes -handling sub-shapes much easier. This functionality is available in OCC -viewer only. +handling sub-shapes much easier. Also some Boolean operations on +groups are available. -

Create a group

+
    +
  • \ref create_groups_anchor "Create a Group"
  • +
  • \ref edit_groups_anchor "Edit a Group"
  • +
  • \ref union_groups_anchor "Union Groups"
  • +
  • \ref intersect_groups_anchor "Intersect Groups"
  • +
  • \ref cut_groups_anchor "Cut Groups"
  • +
+ +
+\anchor create_groups_anchor +

Create a group

\image html image56.png +This functionality is available in OCC viewer only. + To create a group of sub-shapes of a geometrical object in the main menu select New entity > Group > Create \n The following menu will appear: @@ -72,19 +84,29 @@ ShapeType), where MainShape is a shape for which the group is created, ShapeType is a type of shapes in the created group. \n Arguments: 1 Shape + Type of sub-shape. +Our TUI Scripts provide you with useful examples of +\ref tui_create_groups_anchor "Create a Group" operation. + Example: \image html image193.png "Groups on a cylinder" - -

Edit a group

+
+\anchor edit_groups_anchor +

Edit a group

\image html image57.png +This functionality is available in OCC viewer only. + To \b Edit an existing group in the main menu select New entity > Group > Edit. This menu is designed in the same way as the Create a group menu. +\n Dialog Box: + +\image html editgroup.png + \n The \b Result of the operation will be a \b GEOM_Object. \n TUI Command: @@ -101,11 +123,80 @@ the sub-shape to be removed from the group. \n Arguments: 1 Shape + its sub-shapes. -\n Dialog Box: +Our TUI Scripts provide you with useful examples of +\ref tui_edit_groups_anchor "Edit a Group" operation. -\image html editgroup.png +
+\anchor union_groups_anchor +

Union of groups

+ +This operation allows to create a new group in such a way that all +sub-shapes that are present in the initial groups will be added to +the new one. + +To union groups: +
    +
  1. In the New Entity menu select the \b Group - Union Groups item. +The following dialog box will appear: + +\image html groups_union_dlg.png + +In this dialog box you should specify the name of the resulting group +and set of groups which will be united. +
  2. +
  3. Click the \b Apply or Apply and Close button to confirm creation of the group.
  4. +
+ +See Also a sample TUI Script of a +\ref tui_union_groups_anchor "Union of Groups" operation. + +
+\anchor intersect_groups_anchor +

Intersection of groups

+ +This operation allows to create a new group in such a way that only +sub-shapes that are present in all initial groups together are added to the +new one. + +To intersect groups: +
    +
  1. In the New Entity menu select the \b Group - Intersect Groups item. +The following dialog box will appear: + +\image html groups_intersect_dlg.png + +In this dialog box you should specify the name of the resulting group +and set of groups which will be intersected. +
  2. +
  3. Click the \b Apply or Apply and Close button to confirm creation of the group.
  4. +
+ +See Also a sample TUI Script of an +\ref tui_intersect_groups_anchor "Intersection of Groups" operation. + +
+\anchor cut_groups_anchor +

Cut of groups

+ +This operation allows to create a new group in such a way that all +sub-shapes that are present in the main groups but are absent in the +tool groups are added to the new one. + +To cut groups: +
    +
  1. In the New Entity menu select the \b Group - Cut Groups item. +The following dialog box will appear: + +\image html groups_cut_dlg.png + +In this dialog box you should specify the name of the resulting group +and groups which will be cut. +
  2. +
  3. Click the \b Apply or Apply and Close button to confirm creation of the +group.
  4. +
Our TUI Scripts provide you with useful examples of -\ref tui_working_with_groups_page "Working with Groups". +\ref tui_cut_groups_anchor "Cut of Groups" operation. */ diff --git a/idl/GEOM_Gen.idl b/idl/GEOM_Gen.idl index be98cf9eb..e8c5cc4dc 100644 --- a/idl/GEOM_Gen.idl +++ b/idl/GEOM_Gen.idl @@ -3695,6 +3695,65 @@ module GEOM */ void DifferenceIDs (in GEOM_Object theGroup, in ListOfLong theSubShapes); + /*! + * \brief Union of two groups. + * New group is created. It will contain all entities + * which are present in groups theGroup1 and theGroup2. + * \param theGroup1, theGroup2 are the initial GEOM groups + * to create the united group from. + * \return a newly created GEOM group. + */ + GEOM_Object UnionGroups (in GEOM_Object theGroup1, in GEOM_Object theGroup2); + + /*! + * \brief Intersection of two groups. + * New group is created. It will contain only those entities + * which are present in both groups theGroup1 and theGroup2. + * \param theGroup1, theGroup2 are the initial GEOM groups to get common part of. + * \return a newly created GEOM group. + */ + GEOM_Object IntersectGroups (in GEOM_Object theGroup1, in GEOM_Object theGroup2); + + /*! + * \brief Cut of two groups. + * New group is created. It will contain entities which are + * present in group theGroup1 but are not present in group theGroup2. + * \param theGroup1 is a GEOM group to include elements of. + * \param theGroup2 is a GEOM group to exclude elements of. + * \return a newly created GEOM group. + */ + GEOM_Object CutGroups (in GEOM_Object theGroup1, in GEOM_Object theGroup2); + + /*! + * \brief Union of list of groups. + * New group is created. It will contain all entities that are + * present in groups listed in theGList. + * \param theGList is a list of GEOM groups to create the united group from. + * \return a newly created GEOM group. + */ + GEOM_Object UnionListOfGroups (in ListOfGO theGList); + + /*! + * \brief Intersection of list of groups. + * New group is created. It will contain only entities + * which are simultaneously present in the groups listed in theGList. + * \param theGList is a list of GEOM groups to get common part of. + * \return a newly created GEOM group. + */ + GEOM_Object IntersectListOfGroups (in ListOfGO theGList); + + /*! + * \brief Cut of lists of groups. + * New group is created. It will contain only entities + * which are present in groups listed in theGList1 but + * are not present in groups from theGList2. + * \param theGList1 is a list of GEOM groups to include elements of. + * \param theGList2 is a list of GEOM groups to exclude elements of. + * \return a newly created GEOM group. + */ + GEOM_Object CutListOfGroups (in ListOfGO theGList1, + in ListOfGO theGList2); + /*! * \brief Returns a type of sub-objects stored in the group * \param theGroup is a GEOM group which type is returned. diff --git a/src/GEOMGUI/GEOM_images.ts b/src/GEOMGUI/GEOM_images.ts index d9459fdc2..96b164f7b 100644 --- a/src/GEOMGUI/GEOM_images.ts +++ b/src/GEOMGUI/GEOM_images.ts @@ -771,6 +771,10 @@ ICO_COMMON common.png + + ICO_GROUP_INTERSECT + common.png + ICO_COMPOUND build_compound.png @@ -791,6 +795,10 @@ ICO_CUT cut.png + + ICO_GROUP_CUT + cut.png + ICO_CYLINDER cylinder.png @@ -895,6 +903,10 @@ ICO_FUSE fuse.png + + ICO_GROUP_UNION + fuse.png + ICO_GLUE_FACES glue.png diff --git a/src/GEOMGUI/GEOM_msg_en.ts b/src/GEOMGUI/GEOM_msg_en.ts index 26c1f8b80..71fe07144 100644 --- a/src/GEOMGUI/GEOM_msg_en.ts +++ b/src/GEOMGUI/GEOM_msg_en.ts @@ -2574,6 +2574,18 @@ Please, select face, shell or solid and try again MEN_GROUP_EDIT Edit + + MEN_GROUP_UNION + Union Groups + + + MEN_GROUP_INTERSECT + Intersect Groups + + + MEN_GROUP_CUT + Cut Groups + MEN_RELOAD_IMPORTED Reload From Disk @@ -3350,6 +3362,18 @@ Please, select face, shell or solid and try again STB_GROUP_EDIT Edit a group + + STB_GROUP_UNION + Union Groups + + + STB_GROUP_INTERSECT + Intersect Groups + + + STB_GROUP_CUT + Cut Groups + STB_RELOAD_IMPORTED Reload imported shape from its original place on disk @@ -3950,6 +3974,18 @@ Please, select face, shell or solid and try again TOP_GROUP_EDIT Edit a group + + TOP_GROUP_UNION + Union Groups + + + TOP_GROUP_INTERSECT + Intersect Groups + + + TOP_GROUP_CUT + Cut Groups + TOP_HEX_SOLID Hexahedral Solid @@ -5069,6 +5105,45 @@ Number of sketch points too small Please, select a group to edit + + GroupGUI_BooleanDlg + + GEOM_UNION + Union + + + GEOM_UNION_TITLE + Union Groups + + + GEOM_INTERSECT + Intersect + + + GEOM_INTERSECT_TITLE + Intersect Groups + + + GEOM_CUT + Cut + + + GEOM_CUT_TITLE + Cut Groups + + + GEOM_GROUPS + Groups + + + GEOM_MAIN_GROUPS + Main Groups + + + GEOM_TOOL_GROUPS + Tool Groups + + GroupGUI_GroupDlg diff --git a/src/GEOMGUI/GeometryGUI.cxx b/src/GEOMGUI/GeometryGUI.cxx index b59220aad..10eae6910 100644 --- a/src/GEOMGUI/GeometryGUI.cxx +++ b/src/GEOMGUI/GeometryGUI.cxx @@ -557,6 +557,9 @@ void GeometryGUI::OnGUIEvent( int id ) case GEOMOp::OpGroupCreate: // MENU GROUP - CREATE case GEOMOp::OpGroupCreatePopup: // POPUP MENU - CREATE GROUP case GEOMOp::OpGroupEdit: // MENU GROUP - EDIT + case GEOMOp::OpGroupUnion: // MENU GROUP - UNION + case GEOMOp::OpGroupIntersect: // MENU GROUP - INTERSECT + case GEOMOp::OpGroupCut: // MENU GROUP - CUT libName = "GroupGUI"; break; case GEOMOp::OpHexaSolid: // MENU BLOCKS - HEXAHEDRAL SOLID @@ -749,6 +752,9 @@ void GeometryGUI::initialize( CAM_Application* app ) createGeomAction( GEOMOp::OpGroupCreate, "GROUP_CREATE" ); createGeomAction( GEOMOp::OpGroupEdit, "GROUP_EDIT" ); + createGeomAction( GEOMOp::OpGroupUnion, "GROUP_UNION" ); + createGeomAction( GEOMOp::OpGroupIntersect, "GROUP_INTERSECT" ); + createGeomAction( GEOMOp::OpGroupCut, "GROUP_CUT" ); createGeomAction( GEOMOp::OpReimport, "RELOAD_IMPORTED" ); @@ -949,8 +955,11 @@ void GeometryGUI::initialize( CAM_Application* app ) createMenu( separator(), newEntId, -1 ); int groupId = createMenu( tr( "MEN_GROUP" ), newEntId, -1 ); - createMenu( GEOMOp::OpGroupCreate, groupId, -1 ); - createMenu( GEOMOp::OpGroupEdit, groupId, -1 ); + createMenu( GEOMOp::OpGroupCreate, groupId, -1 ); + createMenu( GEOMOp::OpGroupEdit, groupId, -1 ); + createMenu( GEOMOp::OpGroupUnion, groupId, -1 ); + createMenu( GEOMOp::OpGroupIntersect, groupId, -1 ); + createMenu( GEOMOp::OpGroupCut, groupId, -1 ); createMenu( separator(), newEntId, -1 ); @@ -1201,7 +1210,7 @@ void GeometryGUI::initialize( CAM_Application* app ) createTool( GEOMOp::OpCheckCompound, measureTbId ); createTool( GEOMOp::OpGetNonBlocks, measureTbId ); createTool( GEOMOp::OpCheckSelfInters, measureTbId ); - + int picturesTbId = createTool( tr( "TOOL_PICTURES" ) ); createTool( GEOMOp::OpPictureImport, picturesTbId ); #ifdef WITH_OPENCV diff --git a/src/GEOMGUI/GeometryGUI_Operations.h b/src/GEOMGUI/GeometryGUI_Operations.h index 9cb259b5d..89bb954d5 100644 --- a/src/GEOMGUI/GeometryGUI_Operations.h +++ b/src/GEOMGUI/GeometryGUI_Operations.h @@ -176,6 +176,9 @@ namespace GEOMOp { OpGroupCreate = 6000, // MENU GROUP - CREATE OpGroupEdit = 6001, // MENU GROUP - EDIT OpGroupCreatePopup = 6002, // POPUP MENU - CREATE GROUP + OpGroupUnion = 6003, // POPUP MENU - UNION GROUPS + OpGroupIntersect = 6004, // POPUP MENU - INTERSECT GROUPS + OpGroupCut = 6005, // POPUP MENU - CUT GROUPS // BlocksGUI -------------------//-------------------------------- OpHexaSolid = 6100, // MENU BLOCKS - HEXAHEDRAL SOLID OpMultiTransform = 6101, // MENU BLOCKS - MULTI-TRANSFORMATION diff --git a/src/GEOMImpl/GEOMImpl_IGroupOperations.cxx b/src/GEOMImpl/GEOMImpl_IGroupOperations.cxx index db55c72b6..dc47e1f0e 100644 --- a/src/GEOMImpl/GEOMImpl_IGroupOperations.cxx +++ b/src/GEOMImpl/GEOMImpl_IGroupOperations.cxx @@ -18,7 +18,6 @@ // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -// #include @@ -511,10 +510,10 @@ void GEOMImpl_IGroupOperations::DifferenceList (Handle(GEOM_Object) theGroup, if ( aLength - aRemLength > 0 ) { aNewSeq = new TColStd_HArray1OfInteger(1, aLength - aRemLength); for (j = 1; j <= aLength; j++) { - if (!mapIDsToRemove.Contains(aSeq->Value(j))) { - aNewSeq->SetValue(k, aSeq->Value(j)); - k++; - } + if (!mapIDsToRemove.Contains(aSeq->Value(j))) { + aNewSeq->SetValue(k, aSeq->Value(j)); + k++; + } } } else { @@ -716,10 +715,10 @@ void GEOMImpl_IGroupOperations::DifferenceIDs (Handle(GEOM_Object) theGroup, if ( aLength - aRemLength > 0 ) { aNewSeq = new TColStd_HArray1OfInteger(1, aLength - aRemLength); for (j = 1; j <= aLength; j++) { - if (!mapIDsToRemove.Contains(aSeq->Value(j))) { - aNewSeq->SetValue(k, aSeq->Value(j)); - k++; - } + if (!mapIDsToRemove.Contains(aSeq->Value(j))) { + aNewSeq->SetValue(k, aSeq->Value(j)); + k++; + } } } else { @@ -750,6 +749,743 @@ void GEOMImpl_IGroupOperations::DifferenceIDs (Handle(GEOM_Object) theGroup, SetErrorCode(OK); } +//============================================================================= +/*! + * UnionGroups + */ +//============================================================================= +Handle(GEOM_Object) GEOMImpl_IGroupOperations::UnionGroups (Handle(GEOM_Object) theGroup1, + Handle(GEOM_Object) theGroup2) +{ + SetErrorCode(KO); + if (theGroup1.IsNull() || theGroup2.IsNull()) return NULL; + + // Get group type + TopAbs_ShapeEnum aType1 = GetType(theGroup1); + TopAbs_ShapeEnum aType2 = GetType(theGroup2); + TopAbs_ShapeEnum aType = aType1; + if (aType1 != aType2) { + if (aType1 != TopAbs_SHAPE && aType1 != TopAbs_COMPOUND) { + if (aType2 == TopAbs_SHAPE || aType2 == TopAbs_COMPOUND) + aType = aType2; + else { + SetErrorCode("Error: UnionGroups cannot be performed on groups of different type"); + return NULL; + } + } + } + + // Get Main Shape + Handle(GEOM_Function) aFunction1 = theGroup1->GetLastFunction(); + Handle(GEOM_Function) aFunction2 = theGroup2->GetLastFunction(); + if (aFunction1.IsNull() || aFunction2.IsNull()) return NULL; + + GEOM_ISubShape aSSI1 (aFunction1); + GEOM_ISubShape aSSI2 (aFunction2); + + Handle(GEOM_Function) aMainShapeFunc1 = aSSI1.GetMainShape(); + Handle(GEOM_Function) aMainShapeFunc2 = aSSI2.GetMainShape(); + if (aMainShapeFunc1.IsNull() || aMainShapeFunc2.IsNull()) return NULL; + + TDF_Label aLabel1 = aMainShapeFunc1->GetOwnerEntry(); + TDF_Label aLabel2 = aMainShapeFunc2->GetOwnerEntry(); + if (aLabel1.IsRoot() || aLabel2.IsRoot()) { + SetErrorCode("Error: UnionGroups can be performed only on groups"); + return NULL; + } + + if (aLabel1 != aLabel2) { + SetErrorCode("Error: UnionGroups cannot be performed on groups, built on different main shapes"); + return NULL; + } + + Handle(GEOM_Object) aMainObj = GEOM_Object::GetObject(aLabel1); + if (aMainObj.IsNull()) return NULL; + + // New contents of the group + TColStd_ListOfInteger aNewIDs; + TColStd_MapOfInteger mapIDs; + + Handle(TColStd_HArray1OfInteger) aSeq1 = aSSI1.GetIndices(); + Handle(TColStd_HArray1OfInteger) aSeq2 = aSSI2.GetIndices(); + if (aSeq1.IsNull() || aSeq2.IsNull()) return NULL; + + Standard_Integer j, val_j; + Standard_Integer aLength1 = aSeq1->Length(); + Standard_Integer aLength2 = aSeq2->Length(); + + for (j = 1; j <= aLength1; j++) { + val_j = aSeq1->Value(j); + if (val_j > 0 && mapIDs.Add(val_j)) { + aNewIDs.Append(val_j); + } + } + for (j = 1; j <= aLength2; j++) { + val_j = aSeq2->Value(j); + if (val_j > 0 && mapIDs.Add(val_j)) { + aNewIDs.Append(val_j); + } + } + + if (aNewIDs.Extent() < 1) { + SetErrorCode("Error: UnionGroups cannot be performed on two empty groups"); + return NULL; + } + + // Put new indices from the list into an array + Standard_Integer k = 1; + TColStd_ListIteratorOfListOfInteger aNewIDsIter (aNewIDs); + Handle(TColStd_HArray1OfInteger) aNewArr = new TColStd_HArray1OfInteger (1, aNewIDs.Extent()); + for (; aNewIDsIter.More(); aNewIDsIter.Next(), k++) { + aNewArr->SetValue(k, aNewIDsIter.Value()); + } + + // Create the Group + Handle(GEOM_Object) aGroup = GetEngine()->AddSubShape(aMainObj, aNewArr); + aGroup->SetType(GEOM_GROUP); + TDF_Label aFreeLabel = aGroup->GetFreeLabel(); + TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aType); + + // Make a Python command + Handle(GEOM_Function) aFunction = aGroup->GetFunction(1); + GEOM::TPythonDump(aFunction) << aGroup << " = geompy.UnionGroups(" + << theGroup1 << ", " << theGroup2 << ")"; + + SetErrorCode(OK); + return aGroup; +} + +//============================================================================= +/*! + * IntersectGroups + */ +//============================================================================= +Handle(GEOM_Object) GEOMImpl_IGroupOperations::IntersectGroups (Handle(GEOM_Object) theGroup1, + Handle(GEOM_Object) theGroup2) +{ + SetErrorCode(KO); + if (theGroup1.IsNull() || theGroup2.IsNull()) return NULL; + + // Get group type + TopAbs_ShapeEnum aType1 = GetType(theGroup1); + TopAbs_ShapeEnum aType2 = GetType(theGroup2); + TopAbs_ShapeEnum aType = aType1; + if (aType1 != aType2) { + if (aType1 != TopAbs_SHAPE && aType1 != TopAbs_COMPOUND) { + if (aType2 == TopAbs_SHAPE || aType2 == TopAbs_COMPOUND) + aType = aType2; + else { + SetErrorCode("Error: IntersectGroups cannot be performed on groups of different type"); + return NULL; + } + } + } + + // Get Main Shape + Handle(GEOM_Function) aFunction1 = theGroup1->GetLastFunction(); + Handle(GEOM_Function) aFunction2 = theGroup2->GetLastFunction(); + if (aFunction1.IsNull() || aFunction2.IsNull()) return NULL; + + GEOM_ISubShape aSSI1 (aFunction1); + GEOM_ISubShape aSSI2 (aFunction2); + + Handle(GEOM_Function) aMainShapeFunc1 = aSSI1.GetMainShape(); + Handle(GEOM_Function) aMainShapeFunc2 = aSSI2.GetMainShape(); + if (aMainShapeFunc1.IsNull() || aMainShapeFunc2.IsNull()) return NULL; + + TDF_Label aLabel1 = aMainShapeFunc1->GetOwnerEntry(); + TDF_Label aLabel2 = aMainShapeFunc2->GetOwnerEntry(); + if (aLabel1.IsRoot() || aLabel2.IsRoot()) { + SetErrorCode("Error: UnionGroups can be performed only on groups"); + return NULL; + } + + if (aLabel1 != aLabel2) { + SetErrorCode("Error: IntersectGroups cannot be performed on groups, built on different main shapes"); + return NULL; + } + + Handle(GEOM_Object) aMainObj = GEOM_Object::GetObject(aLabel1); + if (aMainObj.IsNull()) return NULL; + + // New contents of the group + TColStd_ListOfInteger aNewIDs; + TColStd_MapOfInteger mapIDs; + + Handle(TColStd_HArray1OfInteger) aSeq1 = aSSI1.GetIndices(); + Handle(TColStd_HArray1OfInteger) aSeq2 = aSSI2.GetIndices(); + if (aSeq1.IsNull() || aSeq2.IsNull()) return NULL; + + Standard_Integer j, val_j; + Standard_Integer aLength1 = aSeq1->Length(); + Standard_Integer aLength2 = aSeq2->Length(); + + for (j = 1; j <= aLength1; j++) { + mapIDs.Add(aSeq1->Value(j)); + } + for (j = 1; j <= aLength2; j++) { + val_j = aSeq2->Value(j); + if (val_j > 0 && !mapIDs.Add(val_j)) { + // add index, if it is in mapIDs (filled from Group_1) + aNewIDs.Append(val_j); + } + } + + Handle(TColStd_HArray1OfInteger) aNewArr; + if (aNewIDs.Extent() < 1) { + aNewArr = new TColStd_HArray1OfInteger (1, 1); + aNewArr->SetValue(1, -1); + } + else { + // Put new indices from the list into an array + Standard_Integer k = 1; + TColStd_ListIteratorOfListOfInteger aNewIDsIter (aNewIDs); + aNewArr = new TColStd_HArray1OfInteger (1, aNewIDs.Extent()); + for (; aNewIDsIter.More(); aNewIDsIter.Next(), k++) { + aNewArr->SetValue(k, aNewIDsIter.Value()); + } + } + + // Create the Group + Handle(GEOM_Object) aGroup = GetEngine()->AddSubShape(aMainObj, aNewArr); + aGroup->SetType(GEOM_GROUP); + TDF_Label aFreeLabel = aGroup->GetFreeLabel(); + TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aType); + + // Make a Python command + Handle(GEOM_Function) aFunction = aGroup->GetFunction(1); + GEOM::TPythonDump(aFunction) << aGroup << " = geompy.IntersectGroups(" + << theGroup1 << ", " << theGroup2 << ")"; + + SetErrorCode(OK); + return aGroup; +} + +//============================================================================= +/*! + * CutGroups + */ +//============================================================================= +Handle(GEOM_Object) GEOMImpl_IGroupOperations::CutGroups (Handle(GEOM_Object) theGroup1, + Handle(GEOM_Object) theGroup2) +{ + SetErrorCode(KO); + if (theGroup1.IsNull() || theGroup2.IsNull()) return NULL; + + // Get group type + TopAbs_ShapeEnum aType1 = GetType(theGroup1); + TopAbs_ShapeEnum aType2 = GetType(theGroup2); + TopAbs_ShapeEnum aType = aType1; + if (aType1 != aType2) { + if (aType1 != TopAbs_SHAPE && aType1 != TopAbs_COMPOUND) { + if (aType2 == TopAbs_SHAPE || aType2 == TopAbs_COMPOUND) + aType = aType2; + else { + SetErrorCode("Error: CutGroups cannot be performed on groups of different type"); + return NULL; + } + } + } + + // Get Main Shape + Handle(GEOM_Function) aFunction1 = theGroup1->GetLastFunction(); + Handle(GEOM_Function) aFunction2 = theGroup2->GetLastFunction(); + if (aFunction1.IsNull() || aFunction2.IsNull()) return NULL; + + GEOM_ISubShape aSSI1 (aFunction1); + GEOM_ISubShape aSSI2 (aFunction2); + + Handle(GEOM_Function) aMainShapeFunc1 = aSSI1.GetMainShape(); + Handle(GEOM_Function) aMainShapeFunc2 = aSSI2.GetMainShape(); + if (aMainShapeFunc1.IsNull() || aMainShapeFunc2.IsNull()) return NULL; + + TDF_Label aLabel1 = aMainShapeFunc1->GetOwnerEntry(); + TDF_Label aLabel2 = aMainShapeFunc2->GetOwnerEntry(); + if (aLabel1.IsRoot() || aLabel2.IsRoot()) { + SetErrorCode("Error: UnionGroups can be performed only on groups"); + return NULL; + } + + if (aLabel1 != aLabel2) { + SetErrorCode("Error: CutGroups cannot be performed on groups, built on different main shapes"); + return NULL; + } + + Handle(GEOM_Object) aMainObj = GEOM_Object::GetObject(aLabel1); + if (aMainObj.IsNull()) return NULL; + + // New contents of the group + TColStd_ListOfInteger aNewIDs; + TColStd_MapOfInteger mapIDs; + + Handle(TColStd_HArray1OfInteger) aSeq1 = aSSI1.GetIndices(); + Handle(TColStd_HArray1OfInteger) aSeq2 = aSSI2.GetIndices(); + if (aSeq1.IsNull() || aSeq2.IsNull()) return NULL; + + Standard_Integer j, val_j; + Standard_Integer aLength1 = aSeq1->Length(); + Standard_Integer aLength2 = aSeq2->Length(); + + for (j = 1; j <= aLength2; j++) { + mapIDs.Add(aSeq2->Value(j)); + } + for (j = 1; j <= aLength1; j++) { + val_j = aSeq1->Value(j); + if (val_j > 0 && mapIDs.Add(val_j)) { + // add index, if it is not in mapIDs (filled from Group_2) + aNewIDs.Append(val_j); + } + } + + Handle(TColStd_HArray1OfInteger) aNewArr; + if (aNewIDs.Extent() < 1) { + aNewArr = new TColStd_HArray1OfInteger (1, 1); + aNewArr->SetValue(1, -1); + } + else { + // Put new indices from the list into an array + Standard_Integer k = 1; + TColStd_ListIteratorOfListOfInteger aNewIDsIter (aNewIDs); + aNewArr = new TColStd_HArray1OfInteger (1, aNewIDs.Extent()); + for (; aNewIDsIter.More(); aNewIDsIter.Next(), k++) { + aNewArr->SetValue(k, aNewIDsIter.Value()); + } + } + + // Create the Group + Handle(GEOM_Object) aGroup = GetEngine()->AddSubShape(aMainObj, aNewArr); + aGroup->SetType(GEOM_GROUP); + TDF_Label aFreeLabel = aGroup->GetFreeLabel(); + TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aType); + + // Make a Python command + Handle(GEOM_Function) aFunction = aGroup->GetFunction(1); + GEOM::TPythonDump(aFunction) << aGroup << " = geompy.CutGroups(" + << theGroup1 << ", " << theGroup2 << ")"; + + SetErrorCode(OK); + return aGroup; +} + +//============================================================================= +/*! + * UnionListOfGroups + */ +//============================================================================= +Handle(GEOM_Object) GEOMImpl_IGroupOperations::UnionListOfGroups + (const Handle(TColStd_HSequenceOfTransient)& theGList) +{ + SetErrorCode(KO); + if (theGList.IsNull()) return NULL; + + Standard_Integer i, aLen = theGList->Length(); + if (aLen < 1) { + SetErrorCode("UnionListOfGroups error: the list of groups is empty"); + return NULL; + } + + TopAbs_ShapeEnum aType, aType_i; + TDF_Label aLabel, aLabel_i; + TColStd_ListOfInteger aNewIDs; + TColStd_MapOfInteger mapIDs; + + // Iterate on the initial groups + for (i = 1; i <= aLen; i++) { + Handle(GEOM_Object) aGr_i = Handle(GEOM_Object)::DownCast(theGList->Value(i)); + + // Get group type + aType_i = GetType(aGr_i); + if (i == 1) + aType = aType_i; + else { + if (aType_i != aType) { + if (aType != TopAbs_SHAPE && aType != TopAbs_COMPOUND) { + if (aType_i == TopAbs_SHAPE || aType_i == TopAbs_COMPOUND) + aType = aType_i; + else { + SetErrorCode("Error: UnionListOfGroups cannot be performed on groups of different type"); + return NULL; + } + } + } + } + + // Get Main Shape + Handle(GEOM_Function) aFunction_i = aGr_i->GetLastFunction(); + if (aFunction_i.IsNull()) return NULL; + GEOM_ISubShape aSSI (aFunction_i); + Handle(GEOM_Function) aMainShapeFunc = aSSI.GetMainShape(); + if (aMainShapeFunc.IsNull()) return NULL; + aLabel_i = aMainShapeFunc->GetOwnerEntry(); + if (aLabel_i.IsRoot()) { + SetErrorCode("Error: UnionGroups can be performed only on groups"); + return NULL; + } + if (i == 1) + aLabel = aLabel_i; + else { + if (aLabel_i != aLabel) { + SetErrorCode("Error: UnionListOfGroups cannot be performed on groups, built on different main shapes"); + return NULL; + } + } + + // New contents of the group + Handle(TColStd_HArray1OfInteger) aSeq = aSSI.GetIndices(); + if (aSeq.IsNull()) return NULL; + + Standard_Integer j, val_j, aLength = aSeq->Length(); + for (j = 1; j <= aLength; j++) { + val_j = aSeq->Value(j); + if (val_j > 0 && mapIDs.Add(val_j)) { + aNewIDs.Append(val_j); + } + } + } + + // Check the resulting list of indices + if (aNewIDs.Extent() < 1) { + SetErrorCode("Error: UnionListOfGroups cannot be performed on all empty groups"); + return NULL; + } + + Handle(GEOM_Object) aMainObj = GEOM_Object::GetObject(aLabel); + if (aMainObj.IsNull()) return NULL; + + // Put new indices from the list into an array + Standard_Integer k = 1; + TColStd_ListIteratorOfListOfInteger aNewIDsIter (aNewIDs); + Handle(TColStd_HArray1OfInteger) aNewArr = new TColStd_HArray1OfInteger (1, aNewIDs.Extent()); + for (; aNewIDsIter.More(); aNewIDsIter.Next(), k++) { + aNewArr->SetValue(k, aNewIDsIter.Value()); + } + + // Create the Group + Handle(GEOM_Object) aGroup = GetEngine()->AddSubShape(aMainObj, aNewArr); + aGroup->SetType(GEOM_GROUP); + TDF_Label aFreeLabel = aGroup->GetFreeLabel(); + TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aType); + + //Make a Python command + Handle(GEOM_Function) aFunction = aGroup->GetFunction(1); + GEOM::TPythonDump pd (aFunction); + pd << aGroup << " = geompy.UnionListOfGroups(["; + for (i = 1; i <= aLen; i++) { + Handle(GEOM_Object) aGr_i = Handle(GEOM_Object)::DownCast(theGList->Value(i)); + pd << aGr_i << ((i < aLen) ? ", " : "])"); + } + + SetErrorCode(OK); + return aGroup; +} + +//============================================================================= +/*! + * IntersectListOfGroups + */ +//============================================================================= +Handle(GEOM_Object) GEOMImpl_IGroupOperations::IntersectListOfGroups + (const Handle(TColStd_HSequenceOfTransient)& theGList) +{ + SetErrorCode(KO); + if (theGList.IsNull()) return NULL; + + Standard_Integer i, aLen = theGList->Length(); + if (aLen < 1) { + SetErrorCode("IntersectListOfGroups error: the list of groups is empty"); + return NULL; + } + + TopAbs_ShapeEnum aType, aType_i; + TDF_Label aLabel, aLabel_i; + TColStd_ListOfInteger aNewIDs; + TColStd_MapOfInteger mapIDs; + + // Iterate on the initial groups + for (i = 1; i <= aLen; i++) { + Handle(GEOM_Object) aGr_i = Handle(GEOM_Object)::DownCast(theGList->Value(i)); + + // Get group type + aType_i = GetType(aGr_i); + if (i == 1) + aType = aType_i; + else { + if (aType_i != aType) { + if (aType != TopAbs_SHAPE && aType != TopAbs_COMPOUND) { + if (aType_i == TopAbs_SHAPE || aType_i == TopAbs_COMPOUND) + aType = aType_i; + else { + SetErrorCode("Error: IntersectListOfGroups cannot be performed on groups of different type"); + return NULL; + } + } + } + } + + // Get Main Shape + Handle(GEOM_Function) aFunction_i = aGr_i->GetLastFunction(); + if (aFunction_i.IsNull()) return NULL; + GEOM_ISubShape aSSI (aFunction_i); + Handle(GEOM_Function) aMainShapeFunc = aSSI.GetMainShape(); + if (aMainShapeFunc.IsNull()) return NULL; + aLabel_i = aMainShapeFunc->GetOwnerEntry(); + if (aLabel_i.IsRoot()) { + SetErrorCode("Error: UnionGroups can be performed only on groups"); + return NULL; + } + if (i == 1) + aLabel = aLabel_i; + else { + if (aLabel_i != aLabel) { + SetErrorCode("Error: IntersectListOfGroups cannot be performed on groups, built on different main shapes"); + return NULL; + } + } + + // New contents of the group + Handle(TColStd_HArray1OfInteger) aSeq = aSSI.GetIndices(); + if (aSeq.IsNull()) return NULL; + + Standard_Integer j, val_j, aLength = aSeq->Length(); + for (j = 1; j <= aLength; j++) { + val_j = aSeq->Value(j); + if (val_j > 0) { + if (i == 1) { + // get all elements of the first group + if (mapIDs.Add(val_j)) + aNewIDs.Append(val_j); + } + else { + // get only elements, present in all previously processed groups + if (!mapIDs.Add(val_j)) + aNewIDs.Append(val_j); + } + } + } + + // refill the map with only validated elements + if (i > 1) { + mapIDs.Clear(); + TColStd_ListIteratorOfListOfInteger aNewIDsIter (aNewIDs); + for (; aNewIDsIter.More(); aNewIDsIter.Next()) { + mapIDs.Add(aNewIDsIter.Value()); + } + } + // clear the resulting list before starting the next sycle + if (i < aLen) { + aNewIDs.Clear(); + } + } + + Handle(GEOM_Object) aMainObj = GEOM_Object::GetObject(aLabel); + if (aMainObj.IsNull()) return NULL; + + Handle(TColStd_HArray1OfInteger) aNewArr; + if (aNewIDs.Extent() < 1) { + aNewArr = new TColStd_HArray1OfInteger (1, 1); + aNewArr->SetValue(1, -1); + } + else { + // Put new indices from the list into an array + Standard_Integer k = 1; + TColStd_ListIteratorOfListOfInteger aNewIDsIter (aNewIDs); + aNewArr = new TColStd_HArray1OfInteger (1, aNewIDs.Extent()); + for (; aNewIDsIter.More(); aNewIDsIter.Next(), k++) { + aNewArr->SetValue(k, aNewIDsIter.Value()); + } + } + + // Create the Group + Handle(GEOM_Object) aGroup = GetEngine()->AddSubShape(aMainObj, aNewArr); + aGroup->SetType(GEOM_GROUP); + TDF_Label aFreeLabel = aGroup->GetFreeLabel(); + TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aType); + + //Make a Python command + Handle(GEOM_Function) aFunction = aGroup->GetFunction(1); + GEOM::TPythonDump pd (aFunction); + pd << aGroup << " = geompy.IntersectListOfGroups(["; + for (i = 1; i <= aLen; i++) { + Handle(GEOM_Object) aGr_i = Handle(GEOM_Object)::DownCast(theGList->Value(i)); + pd << aGr_i << ((i < aLen) ? ", " : "])"); + } + + SetErrorCode(OK); + return aGroup; +} + +//============================================================================= +/*! + * CutListOfGroups + */ +//============================================================================= +Handle(GEOM_Object) GEOMImpl_IGroupOperations::CutListOfGroups + (const Handle(TColStd_HSequenceOfTransient)& theGList1, + const Handle(TColStd_HSequenceOfTransient)& theGList2) +{ + SetErrorCode(KO); + if (theGList1.IsNull() || theGList2.IsNull()) return NULL; + + Standard_Integer i; + Standard_Integer aLen1 = theGList1->Length(); + Standard_Integer aLen2 = theGList2->Length(); + if (aLen1 < 1) { + SetErrorCode("CutListOfGroups error: the first list of groups is empty"); + return NULL; + } + + TopAbs_ShapeEnum aType, aType_i; + TDF_Label aLabel, aLabel_i; + TColStd_ListOfInteger aNewIDs; + TColStd_MapOfInteger mapIDs; + + // 1. Collect indices to be excluded (from theGList2) into the mapIDs + for (i = 1; i <= aLen2; i++) { + Handle(GEOM_Object) aGr_i = Handle(GEOM_Object)::DownCast(theGList2->Value(i)); + + // Get group type + aType_i = GetType(aGr_i); + if (i == 1) + aType = aType_i; + else { + if (aType_i != aType) { + if (aType != TopAbs_SHAPE && aType != TopAbs_COMPOUND) { + if (aType_i == TopAbs_SHAPE || aType_i == TopAbs_COMPOUND) + aType = aType_i; + else { + SetErrorCode("Error: CutListOfGroups cannot be performed on groups of different type"); + return NULL; + } + } + } + } + + // Get Main Shape + Handle(GEOM_Function) aFunction_i = aGr_i->GetLastFunction(); + if (aFunction_i.IsNull()) return NULL; + GEOM_ISubShape aSSI (aFunction_i); + Handle(GEOM_Function) aMainShapeFunc = aSSI.GetMainShape(); + if (aMainShapeFunc.IsNull()) return NULL; + aLabel_i = aMainShapeFunc->GetOwnerEntry(); + if (aLabel_i.IsRoot()) { + SetErrorCode("Error: UnionGroups can be performed only on groups"); + return NULL; + } + if (i == 1) + aLabel = aLabel_i; + else { + if (aLabel_i != aLabel) { + SetErrorCode("Error: CutListOfGroups cannot be performed on groups, built on different main shapes"); + return NULL; + } + } + + // Indiced to exclude + Handle(TColStd_HArray1OfInteger) aSeq = aSSI.GetIndices(); + if (aSeq.IsNull()) return NULL; + + Standard_Integer j, aLength = aSeq->Length(); + for (j = 1; j <= aLength; j++) { + mapIDs.Add(aSeq->Value(j)); + } + } + + // 2. Collect indices from theGList1, avoiding indices from theGList2 (mapIDs) + for (i = 1; i <= aLen1; i++) { + Handle(GEOM_Object) aGr_i = Handle(GEOM_Object)::DownCast(theGList1->Value(i)); + + // Get group type + aType_i = GetType(aGr_i); + if (i == 1 && aLen2 < 1) + aType = aType_i; + else { + if (aType_i != aType) { + if (aType != TopAbs_SHAPE && aType != TopAbs_COMPOUND) { + if (aType_i == TopAbs_SHAPE || aType_i == TopAbs_COMPOUND) + aType = aType_i; + else { + SetErrorCode("Error: CutListOfGroups cannot be performed on groups of different type"); + return NULL; + } + } + } + } + + // Get Main Shape + Handle(GEOM_Function) aFunction_i = aGr_i->GetLastFunction(); + if (aFunction_i.IsNull()) return NULL; + GEOM_ISubShape aSSI (aFunction_i); + Handle(GEOM_Function) aMainShapeFunc = aSSI.GetMainShape(); + if (aMainShapeFunc.IsNull()) return NULL; + aLabel_i = aMainShapeFunc->GetOwnerEntry(); + if (aLabel_i.IsRoot()) { + SetErrorCode("Error: UnionGroups can be performed only on groups"); + return NULL; + } + if (i == 1 && aLen2 < 1) + aLabel = aLabel_i; + else { + if (aLabel_i != aLabel) { + SetErrorCode("Error: CutListOfGroups cannot be performed on groups, built on different main shapes"); + return NULL; + } + } + + // New contents of the group + Handle(TColStd_HArray1OfInteger) aSeq = aSSI.GetIndices(); + if (aSeq.IsNull()) return NULL; + + Standard_Integer j, val_j, aLength = aSeq->Length(); + for (j = 1; j <= aLength; j++) { + val_j = aSeq->Value(j); + if (val_j > 0 && mapIDs.Add(val_j)) { + // get only elements, not present in mapIDs (theGList2) + aNewIDs.Append(val_j); + } + } + } + + Handle(GEOM_Object) aMainObj = GEOM_Object::GetObject(aLabel); + if (aMainObj.IsNull()) return NULL; + + Handle(TColStd_HArray1OfInteger) aNewArr; + if (aNewIDs.Extent() < 1) { + aNewArr = new TColStd_HArray1OfInteger (1, 1); + aNewArr->SetValue(1, -1); + } + else { + // Put new indices from the list into an array + Standard_Integer k = 1; + TColStd_ListIteratorOfListOfInteger aNewIDsIter (aNewIDs); + aNewArr = new TColStd_HArray1OfInteger (1, aNewIDs.Extent()); + for (; aNewIDsIter.More(); aNewIDsIter.Next(), k++) { + aNewArr->SetValue(k, aNewIDsIter.Value()); + } + } + + // Create the Group + Handle(GEOM_Object) aGroup = GetEngine()->AddSubShape(aMainObj, aNewArr); + aGroup->SetType(GEOM_GROUP); + TDF_Label aFreeLabel = aGroup->GetFreeLabel(); + TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aType); + + //Make a Python command + Handle(GEOM_Function) aFunction = aGroup->GetFunction(1); + GEOM::TPythonDump pd (aFunction); + pd << aGroup << " = geompy.CutListOfGroups(["; + for (i = 1; i <= aLen1; i++) { + Handle(GEOM_Object) aGr_i = Handle(GEOM_Object)::DownCast(theGList1->Value(i)); + pd << aGr_i << ((i < aLen1) ? ", " : "], ["); + } + for (i = 1; i <= aLen2; i++) { + Handle(GEOM_Object) aGr_i = Handle(GEOM_Object)::DownCast(theGList2->Value(i)); + pd << aGr_i << ((i < aLen2) ? ", " : "])"); + } + + SetErrorCode(OK); + return aGroup; +} + //============================================================================= /*! * GetType diff --git a/src/GEOMImpl/GEOMImpl_IGroupOperations.hxx b/src/GEOMImpl/GEOMImpl_IGroupOperations.hxx index 0b6a89110..6b8d485ec 100644 --- a/src/GEOMImpl/GEOMImpl_IGroupOperations.hxx +++ b/src/GEOMImpl/GEOMImpl_IGroupOperations.hxx @@ -18,7 +18,6 @@ // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -// #ifndef _GEOMImpl_IGroupOperations_HXX_ #define _GEOMImpl_IGroupOperations_HXX_ @@ -28,7 +27,7 @@ #include "GEOM_Engine.hxx" #include "GEOM_Object.hxx" #include -#include +#include #include #include @@ -55,6 +54,20 @@ class GEOMImpl_IGroupOperations : public GEOM_IOperations { Standard_EXPORT void DifferenceIDs (Handle(GEOM_Object) theGroup, const Handle(TColStd_HSequenceOfInteger)& theSubShapes); + Standard_EXPORT Handle(GEOM_Object) UnionGroups (Handle(GEOM_Object) theGroup1, + Handle(GEOM_Object) theGroup2); + Standard_EXPORT Handle(GEOM_Object) IntersectGroups (Handle(GEOM_Object) theGroup1, + Handle(GEOM_Object) theGroup2); + Standard_EXPORT Handle(GEOM_Object) CutGroups (Handle(GEOM_Object) theGroup1, + Handle(GEOM_Object) theGroup2); + + Standard_EXPORT Handle(GEOM_Object) UnionListOfGroups + (const Handle(TColStd_HSequenceOfTransient)& theGList); + Standard_EXPORT Handle(GEOM_Object) IntersectListOfGroups + (const Handle(TColStd_HSequenceOfTransient)& theGList); + Standard_EXPORT Handle(GEOM_Object) CutListOfGroups (const Handle(TColStd_HSequenceOfTransient)& theGList1, + const Handle(TColStd_HSequenceOfTransient)& theGList2); + Standard_EXPORT TopAbs_ShapeEnum GetType(Handle(GEOM_Object) theGroup); Standard_EXPORT Handle(GEOM_Object) GetMainShape(Handle(GEOM_Object) theGroup); diff --git a/src/GEOM_I/GEOM_IGroupOperations_i.cc b/src/GEOM_I/GEOM_IGroupOperations_i.cc index 3a8cef597..60a26e129 100644 --- a/src/GEOM_I/GEOM_IGroupOperations_i.cc +++ b/src/GEOM_I/GEOM_IGroupOperations_i.cc @@ -18,7 +18,6 @@ // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -// #include @@ -202,7 +201,6 @@ void GEOM_IGroupOperations_i::UnionIDs (GEOM::GEOM_Object_ptr theGroup, //Perform the operation GetOperations()->UnionIDs(aGroupRef, aSubShapes); - return; } //============================================================================= @@ -230,7 +228,176 @@ void GEOM_IGroupOperations_i::DifferenceIDs (GEOM::GEOM_Object_ptr theGroup, //Perform the operation GetOperations()->DifferenceIDs(aGroupRef, aSubShapes); - return; +} + +//============================================================================= +/*! + * UnionGroups + */ +//============================================================================= +GEOM::GEOM_Object_ptr GEOM_IGroupOperations_i::UnionGroups (GEOM::GEOM_Object_ptr theGroup1, + GEOM::GEOM_Object_ptr theGroup2) +{ + GEOM::GEOM_Object_var aGEOMObject; + + //Set a not done flag + GetOperations()->SetNotDone(); + + //Get the reference groups + Handle(GEOM_Object) aGroupRef1 = GetObjectImpl(theGroup1); + Handle(GEOM_Object) aGroupRef2 = GetObjectImpl(theGroup2); + if (aGroupRef1.IsNull() || aGroupRef2.IsNull()) return aGEOMObject._retn(); + + //Perform the operation + Handle(GEOM_Object) anObject = GetOperations()->UnionGroups(aGroupRef1, aGroupRef2); + if (!GetOperations()->IsDone() || anObject.IsNull()) return aGEOMObject._retn(); + + return GetObject(anObject); +} + +//============================================================================= +/*! + * IntersectGroups + */ +//============================================================================= +GEOM::GEOM_Object_ptr GEOM_IGroupOperations_i::IntersectGroups (GEOM::GEOM_Object_ptr theGroup1, + GEOM::GEOM_Object_ptr theGroup2) +{ + GEOM::GEOM_Object_var aGEOMObject; + + //Set a not done flag + GetOperations()->SetNotDone(); + + //Get the reference groups + Handle(GEOM_Object) aGroupRef1 = GetObjectImpl(theGroup1); + Handle(GEOM_Object) aGroupRef2 = GetObjectImpl(theGroup2); + if (aGroupRef1.IsNull() || aGroupRef2.IsNull()) return aGEOMObject._retn(); + + //Perform the operation + Handle(GEOM_Object) anObject = GetOperations()->IntersectGroups(aGroupRef1, aGroupRef2); + if (!GetOperations()->IsDone() || anObject.IsNull()) return aGEOMObject._retn(); + + return GetObject(anObject); +} + +//============================================================================= +/*! + * CutGroups + */ +//============================================================================= +GEOM::GEOM_Object_ptr GEOM_IGroupOperations_i::CutGroups (GEOM::GEOM_Object_ptr theGroup1, + GEOM::GEOM_Object_ptr theGroup2) +{ + GEOM::GEOM_Object_var aGEOMObject; + + //Set a not done flag + GetOperations()->SetNotDone(); + + //Get the reference groups + Handle(GEOM_Object) aGroupRef1 = GetObjectImpl(theGroup1); + Handle(GEOM_Object) aGroupRef2 = GetObjectImpl(theGroup2); + if (aGroupRef1.IsNull() || aGroupRef2.IsNull()) return aGEOMObject._retn(); + + //Perform the operation + Handle(GEOM_Object) anObject = GetOperations()->CutGroups(aGroupRef1, aGroupRef2); + if (!GetOperations()->IsDone() || anObject.IsNull()) return aGEOMObject._retn(); + + return GetObject(anObject); +} + +//============================================================================= +/*! + * UnionListOfGroups + */ +//============================================================================= +GEOM::GEOM_Object_ptr GEOM_IGroupOperations_i::UnionListOfGroups (const GEOM::ListOfGO& theGList) +{ + GEOM::GEOM_Object_var aGEOMObject; + + //Set a not done flag + GetOperations()->SetNotDone(); + + //Get the reference groups + Handle(TColStd_HSequenceOfTransient) aGroups = new TColStd_HSequenceOfTransient; + + int ind, aLen = theGList.length(); + for (ind = 0; ind < aLen; ind++) { + Handle(GEOM_Object) aGr = GetObjectImpl(theGList[ind]); + if (aGr.IsNull()) return aGEOMObject._retn(); + aGroups->Append(aGr); + } + + //Perform the operation + Handle(GEOM_Object) anObject = GetOperations()->UnionListOfGroups(aGroups); + if (!GetOperations()->IsDone() || anObject.IsNull()) return aGEOMObject._retn(); + + return GetObject(anObject); +} + +//============================================================================= +/*! + * IntersectListOfGroups + */ +//============================================================================= +GEOM::GEOM_Object_ptr GEOM_IGroupOperations_i::IntersectListOfGroups (const GEOM::ListOfGO& theGList) +{ + GEOM::GEOM_Object_var aGEOMObject; + + //Set a not done flag + GetOperations()->SetNotDone(); + + //Get the reference groups + Handle(TColStd_HSequenceOfTransient) aGroups = new TColStd_HSequenceOfTransient; + + int ind, aLen = theGList.length(); + for (ind = 0; ind < aLen; ind++) { + Handle(GEOM_Object) aGr = GetObjectImpl(theGList[ind]); + if (aGr.IsNull()) return aGEOMObject._retn(); + aGroups->Append(aGr); + } + + //Perform the operation + Handle(GEOM_Object) anObject = GetOperations()->IntersectListOfGroups(aGroups); + if (!GetOperations()->IsDone() || anObject.IsNull()) return aGEOMObject._retn(); + + return GetObject(anObject); +} + +//============================================================================= +/*! + * CutListOfGroups + */ +//============================================================================= +GEOM::GEOM_Object_ptr GEOM_IGroupOperations_i::CutListOfGroups (const GEOM::ListOfGO& theGList1, + const GEOM::ListOfGO& theGList2) +{ + GEOM::GEOM_Object_var aGEOMObject; + + //Set a not done flag + GetOperations()->SetNotDone(); + + //Get the reference groups + Handle(TColStd_HSequenceOfTransient) aGroups1 = new TColStd_HSequenceOfTransient; + Handle(TColStd_HSequenceOfTransient) aGroups2 = new TColStd_HSequenceOfTransient; + + int ind, aLen = theGList1.length(); + for (ind = 0; ind < aLen; ind++) { + Handle(GEOM_Object) aGr = GetObjectImpl(theGList1[ind]); + if (aGr.IsNull()) return aGEOMObject._retn(); + aGroups1->Append(aGr); + } + aLen = theGList2.length(); + for (ind = 0; ind < aLen; ind++) { + Handle(GEOM_Object) aGr = GetObjectImpl(theGList2[ind]); + if (aGr.IsNull()) return aGEOMObject._retn(); + aGroups2->Append(aGr); + } + + //Perform the operation + Handle(GEOM_Object) anObject = GetOperations()->CutListOfGroups(aGroups1, aGroups2); + if (!GetOperations()->IsDone() || anObject.IsNull()) return aGEOMObject._retn(); + + return GetObject(anObject); } //============================================================================= diff --git a/src/GEOM_I/GEOM_IGroupOperations_i.hh b/src/GEOM_I/GEOM_IGroupOperations_i.hh index b3871e0fe..f213e8be2 100644 --- a/src/GEOM_I/GEOM_IGroupOperations_i.hh +++ b/src/GEOM_I/GEOM_IGroupOperations_i.hh @@ -18,7 +18,6 @@ // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -// #ifndef _GEOM_IGroupOperations_i_HeaderFile #define _GEOM_IGroupOperations_i_HeaderFile @@ -33,17 +32,17 @@ #include "GEOMImpl_IGroupOperations.hxx" -class GEOM_I_EXPORT GEOM_IGroupOperations_i : +class GEOM_I_EXPORT GEOM_IGroupOperations_i : public virtual POA_GEOM::GEOM_IGroupOperations, public virtual GEOM_IOperations_i { public: GEOM_IGroupOperations_i (PortableServer::POA_ptr thePOA, GEOM::GEOM_Gen_ptr theEngine, - ::GEOMImpl_IGroupOperations* theImpl); + ::GEOMImpl_IGroupOperations* theImpl); ~GEOM_IGroupOperations_i(); - GEOM::GEOM_Object_ptr CreateGroup (GEOM::GEOM_Object_ptr theMainShape, CORBA::Long theShapeType); - + GEOM::GEOM_Object_ptr CreateGroup (GEOM::GEOM_Object_ptr theMainShape, CORBA::Long theShapeType); + void AddObject (GEOM::GEOM_Object_ptr theGroup, CORBA::Long theSubShapeId); void RemoveObject (GEOM::GEOM_Object_ptr theGroup, CORBA::Long theSubShapeId); @@ -56,8 +55,16 @@ class GEOM_I_EXPORT GEOM_IGroupOperations_i : void DifferenceIDs (GEOM::GEOM_Object_ptr theGroup, const GEOM::ListOfLong& theSubShapes); + GEOM::GEOM_Object_ptr UnionGroups (GEOM::GEOM_Object_ptr theGroup1, GEOM::GEOM_Object_ptr theGroup2); + GEOM::GEOM_Object_ptr IntersectGroups (GEOM::GEOM_Object_ptr theGroup1, GEOM::GEOM_Object_ptr theGroup2); + GEOM::GEOM_Object_ptr CutGroups (GEOM::GEOM_Object_ptr theGroup1, GEOM::GEOM_Object_ptr theGroup2); + + GEOM::GEOM_Object_ptr UnionListOfGroups (const GEOM::ListOfGO& theGList); + GEOM::GEOM_Object_ptr IntersectListOfGroups (const GEOM::ListOfGO& theGList); + GEOM::GEOM_Object_ptr CutListOfGroups (const GEOM::ListOfGO& theGList1, const GEOM::ListOfGO& theGList2); + CORBA::Long GetType (GEOM::GEOM_Object_ptr theGroup); - + GEOM::GEOM_Object_ptr GetMainShape (GEOM::GEOM_Object_ptr theGroup); GEOM::ListOfLong* GetObjects (GEOM::GEOM_Object_ptr theGroup); diff --git a/src/GEOM_SWIG/GEOM_TestOthers.py b/src/GEOM_SWIG/GEOM_TestOthers.py index 73d91287d..9eee4f171 100644 --- a/src/GEOM_SWIG/GEOM_TestOthers.py +++ b/src/GEOM_SWIG/GEOM_TestOthers.py @@ -144,6 +144,7 @@ def TestOtherOperations (geompy, math): # OrientationChange Box = geompy.MakeBoxDXDYDZ(200, 200, 200) + geompy.addToStudy(Box, "Box") Orientation = geompy.OrientationChange(Box) id_Orientation = geompy.addToStudy(Orientation, "OrientationChange") @@ -316,6 +317,42 @@ def TestOtherOperations (geompy, math): for ObjectID in GetObjectIDs: print " ", ObjectID + # Boolean Operations on Groups (Union, Intersection, Cut) + Group_1 = geompy.CreateGroup(Box, geompy.ShapeType["FACE"]) + geompy.UnionIDs(Group_1, [13, 23]) + Group_2 = geompy.CreateGroup(Box, geompy.ShapeType["FACE"]) + geompy.UnionIDs(Group_2, [3, 27]) + Group_3 = geompy.CreateGroup(Box, geompy.ShapeType["FACE"]) + geompy.UnionIDs(Group_3, [33, 23]) + Group_4 = geompy.CreateGroup(Box, geompy.ShapeType["FACE"]) + geompy.UnionIDs(Group_4, [31, 27]) + + geompy.addToStudyInFather(Box, Group_1, 'Group_1') + geompy.addToStudyInFather(Box, Group_2, 'Group_2') + geompy.addToStudyInFather(Box, Group_3, 'Group_3') + geompy.addToStudyInFather(Box, Group_4, 'Group_4') + + # union groups + Group_U_1_2 = geompy.UnionGroups(Group_1, Group_2) + Group_UL_3_4 = geompy.UnionListOfGroups([Group_3, Group_4]) + + geompy.addToStudyInFather(Box, Group_U_1_2, 'Group_U_1_2') + geompy.addToStudyInFather(Box, Group_UL_3_4, 'Group_UL_3_4') + + # intersect groups + Group_I_1_3 = geompy.IntersectGroups(Group_1, Group_3) + Group_IL_1_3 = geompy.IntersectListOfGroups([Group_1, Group_3]) + + geompy.addToStudyInFather(Box, Group_I_1_3, 'Group_I_1_3') + geompy.addToStudyInFather(Box, Group_IL_1_3, 'Group_IL_1_3') + + # cut groups + Group_C_2_4 = geompy.CutGroups(Group_2, Group_4) + Group_CL_2_4 = geompy.CutListOfGroups([Group_2], [Group_4]) + + geompy.addToStudyInFather(Box, Group_C_2_4, 'Group_C_2_4') + geompy.addToStudyInFather(Box, Group_CL_2_4, 'Group_CL_2_4') + # ----------------------------------------------------------------------------- # enumeration ShapeTypeString as a dictionary # ----------------------------------------------------------------------------- diff --git a/src/GEOM_SWIG/geompyDC.py b/src/GEOM_SWIG/geompyDC.py index 33817a1b8..ed0c12272 100644 --- a/src/GEOM_SWIG/geompyDC.py +++ b/src/GEOM_SWIG/geompyDC.py @@ -8270,6 +8270,156 @@ class geompyDC(GEOM._objref_GEOM_Gen): RaiseIfFailed("DifferenceIDs", self.GroupOp) pass + ## Union of two groups. + # New group is created. It will contain all entities + # which are present in groups theGroup1 and theGroup2. + # @param theGroup1, theGroup2 are the initial GEOM groups + # to create the united group from. + # @return a newly created GEOM group. + # @ref tui_union_groups_anchor "Example" + def UnionGroups (self, theGroup1, theGroup2): + """ + Union of two groups. + New group is created. It will contain all entities + which are present in groups theGroup1 and theGroup2. + + Parameters: + theGroup1, theGroup2 are the initial GEOM groups + to create the united group from. + + Returns: + a newly created GEOM group. + """ + # Example: see GEOM_TestOthers.py + aGroup = self.GroupOp.UnionGroups(theGroup1, theGroup2) + RaiseIfFailed("UnionGroups", self.GroupOp) + return aGroup + + ## Intersection of two groups. + # New group is created. It will contain only those entities + # which are present in both groups theGroup1 and theGroup2. + # @param theGroup1, theGroup2 are the initial GEOM groups to get common part of. + # @return a newly created GEOM group. + # @ref tui_intersect_groups_anchor "Example" + def IntersectGroups (self, theGroup1, theGroup2): + """ + Intersection of two groups. + New group is created. It will contain only those entities + which are present in both groups theGroup1 and theGroup2. + + Parameters: + theGroup1, theGroup2 are the initial GEOM groups to get common part of. + + Returns: + a newly created GEOM group. + """ + # Example: see GEOM_TestOthers.py + aGroup = self.GroupOp.IntersectGroups(theGroup1, theGroup2) + RaiseIfFailed("IntersectGroups", self.GroupOp) + return aGroup + + ## Cut of two groups. + # New group is created. It will contain entities which are + # present in group theGroup1 but are not present in group theGroup2. + # @param theGroup1 is a GEOM group to include elements of. + # @param theGroup2 is a GEOM group to exclude elements of. + # @return a newly created GEOM group. + # @ref tui_cut_groups_anchor "Example" + def CutGroups (self, theGroup1, theGroup2): + """ + Cut of two groups. + New group is created. It will contain entities which are + present in group theGroup1 but are not present in group theGroup2. + + Parameters: + theGroup1 is a GEOM group to include elements of. + theGroup2 is a GEOM group to exclude elements of. + + Returns: + a newly created GEOM group. + """ + # Example: see GEOM_TestOthers.py + aGroup = self.GroupOp.CutGroups(theGroup1, theGroup2) + RaiseIfFailed("CutGroups", self.GroupOp) + return aGroup + + ## Union of list of groups. + # New group is created. It will contain all entities that are + # present in groups listed in theGList. + # @param theGList is a list of GEOM groups to create the united group from. + # @return a newly created GEOM group. + # @ref tui_union_groups_anchor "Example" + def UnionListOfGroups (self, theGList): + """ + Union of list of groups. + New group is created. It will contain all entities that are + present in groups listed in theGList. + + Parameters: + theGList is a list of GEOM groups to create the united group from. + + Returns: + a newly created GEOM group. + """ + # Example: see GEOM_TestOthers.py + aGroup = self.GroupOp.UnionListOfGroups(theGList) + RaiseIfFailed("UnionListOfGroups", self.GroupOp) + return aGroup + + ## Cut of lists of groups. + # New group is created. It will contain only entities + # which are present in groups listed in theGList1 but + # are not present in groups from theGList2. + # @param theGList1 is a list of GEOM groups to include elements of. + # @param theGList2 is a list of GEOM groups to exclude elements of. + # @return a newly created GEOM group. + # @ref tui_intersect_groups_anchor "Example" + def IntersectListOfGroups (self, theGList): + """ + Cut of lists of groups. + New group is created. It will contain only entities + which are present in groups listed in theGList1 but + are not present in groups from theGList2. + + Parameters: + theGList1 is a list of GEOM groups to include elements of. + theGList2 is a list of GEOM groups to exclude elements of. + + Returns: + a newly created GEOM group. + """ + # Example: see GEOM_TestOthers.py + aGroup = self.GroupOp.IntersectListOfGroups(theGList) + RaiseIfFailed("IntersectListOfGroups", self.GroupOp) + return aGroup + + ## Cut of lists of groups. + # New group is created. It will contain only entities + # which are present in groups listed in theGList1 but + # are not present in groups from theGList2. + # @param theGList1 is a list of GEOM groups to include elements of. + # @param theGList2 is a list of GEOM groups to exclude elements of. + # @return a newly created GEOM group. + # @ref tui_cut_groups_anchor "Example" + def CutListOfGroups (self, theGList1, theGList2): + """ + Cut of lists of groups. + New group is created. It will contain only entities + which are present in groups listed in theGList1 but + are not present in groups from theGList2. + + Parameters: + theGList1 is a list of GEOM groups to include elements of. + theGList2 is a list of GEOM groups to exclude elements of. + + Returns: + a newly created GEOM group. + """ + # Example: see GEOM_TestOthers.py + aGroup = self.GroupOp.CutListOfGroups(theGList1, theGList2) + RaiseIfFailed("CutListOfGroups", self.GroupOp) + return aGroup + ## Returns a list of sub-objects ID stored in the group # @param theGroup is a GEOM group for which a list of IDs is requested # diff --git a/src/GroupGUI/GroupGUI.cxx b/src/GroupGUI/GroupGUI.cxx index 990263407..d8f92294f 100644 --- a/src/GroupGUI/GroupGUI.cxx +++ b/src/GroupGUI/GroupGUI.cxx @@ -18,14 +18,14 @@ // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -// // GEOM GEOMGUI : GUI for Geometry component // File : GroupGUI.cxx // Author : Sergey ANIKIN, Open CASCADE S.A.S. (sergey.anikin@opencascade.com) -// + #include "GroupGUI.h" #include "GroupGUI_GroupDlg.h" +#include "GroupGUI_BooleanDlg.h" #include #include "GeometryGUI_Operations.h" @@ -44,8 +44,8 @@ // function : GroupGUI() // purpose : Constructor //======================================================================= -GroupGUI::GroupGUI( GeometryGUI* parent ) - : GEOMGUI( parent ) +GroupGUI::GroupGUI (GeometryGUI* parent) + : GEOMGUI(parent) { } @@ -62,60 +62,67 @@ GroupGUI::~GroupGUI() // function : OnGUIEvent() // purpose : //======================================================================= -bool GroupGUI::OnGUIEvent( int theCommandID, SUIT_Desktop* parent ) +bool GroupGUI::OnGUIEvent (int theCommandID, SUIT_Desktop* parent) { SalomeApp_Application* app = getGeometryGUI()->getApp(); - if ( !app ) return false; + if (!app) return false; getGeometryGUI()->EmitSignalDeactivateDialog(); QDialog* aDlg = 0; - SalomeApp_Study* appStudy = dynamic_cast( app->activeStudy() ); - if ( !appStudy ) return false; + SalomeApp_Study* appStudy = dynamic_cast(app->activeStudy()); + if (!appStudy) return false; _PTR(Study) aStudy = appStudy->studyDS(); - if ( aStudy->GetProperties()->IsLocked() ) { - SUIT_MessageBox::warning( parent, - tr( "WRN_WARNING" ), - tr( "WRN_STUDY_LOCKED" ) ); + if (aStudy->GetProperties()->IsLocked()) { + SUIT_MessageBox::warning(parent, tr("WRN_WARNING"), tr("WRN_STUDY_LOCKED")); return false; } - switch ( theCommandID ) { + switch (theCommandID) { case GEOMOp::OpGroupCreate: case GEOMOp::OpGroupCreatePopup: // CREATE GROUP - aDlg = new GroupGUI_GroupDlg( GroupGUI_GroupDlg::CreateGroup, getGeometryGUI(), parent ); + aDlg = new GroupGUI_GroupDlg (GroupGUI_GroupDlg::CreateGroup, getGeometryGUI(), parent); break; - case GEOMOp::OpGroupEdit: // EDIT GROUP + case GEOMOp::OpGroupEdit: // EDIT GROUP { SALOME_ListIO aList; aList.Clear(); LightApp_SelectionMgr* aSelMgr = app->selectionMgr(); - if ( aSelMgr ) - aSelMgr->selectedObjects( aList ); + if (aSelMgr) + aSelMgr->selectedObjects(aList); - if ( aList.Extent() == 1 ) { + if (aList.Extent() == 1) { GEOM::GEOM_Object_var anObj = - GEOMBase::ConvertIOinGEOMObject( aList.First() ); + GEOMBase::ConvertIOinGEOMObject(aList.First()); - if ( !CORBA::is_nil( anObj ) && anObj->GetType() == GEOM_GROUP ) { - aDlg = new GroupGUI_GroupDlg( GroupGUI_GroupDlg::EditGroup, getGeometryGUI(), parent ); + if (!CORBA::is_nil(anObj) && anObj->GetType() == GEOM_GROUP) { + aDlg = new GroupGUI_GroupDlg (GroupGUI_GroupDlg::EditGroup, getGeometryGUI(), parent); break; } } - SUIT_MessageBox::warning( parent, tr( "WRN_WARNING" ), tr( "NO_GROUP" ) ); - break; + SUIT_MessageBox::warning(parent, tr("WRN_WARNING"), tr("NO_GROUP")); } + break; + case GEOMOp::OpGroupUnion: // UNION GROUPS + aDlg = new GroupGUI_BooleanDlg (GroupGUI_BooleanDlg::UNION, getGeometryGUI(), parent); + break; + case GEOMOp::OpGroupIntersect: // INTERSECT GROUPS + aDlg = new GroupGUI_BooleanDlg (GroupGUI_BooleanDlg::INTERSECT, getGeometryGUI(), parent); + break; + case GEOMOp::OpGroupCut: // CUT GROUPS + aDlg = new GroupGUI_BooleanDlg (GroupGUI_BooleanDlg::CUT, getGeometryGUI(), parent); + break; default: - app->putInfo( tr( "GEOM_PRP_COMMAND" ).arg( theCommandID ) ); + app->putInfo(tr("GEOM_PRP_COMMAND").arg(theCommandID)); break; } - if ( aDlg ) { + if (aDlg) { aDlg->updateGeometry(); - aDlg->resize( aDlg->minimumSizeHint() ); + aDlg->resize(aDlg->minimumSizeHint()); aDlg->show(); } diff --git a/src/GroupGUI/GroupGUI_BooleanDlg.cxx b/src/GroupGUI/GroupGUI_BooleanDlg.cxx new file mode 100644 index 000000000..3c227e0c7 --- /dev/null +++ b/src/GroupGUI/GroupGUI_BooleanDlg.cxx @@ -0,0 +1,320 @@ +// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com + +// GEOM GEOMGUI : GUI for Geometry component +// File : GroupGUI_BooleanDlg.cxx +// Author : Lucien PIGNOLONI, Open CASCADE S.A.S. + +#include "GroupGUI_BooleanDlg.h" + +#include +#include +#include + +#include +#include +#include +#include + +#include + +//================================================================================= +// class : GroupGUI_BooleanDlg() +// purpose : Constructs a GroupGUI_BooleanDlg which is a child of 'parent', with the +// name 'name' and widget flags set to 'f'. +// The dialog will by default be modeless, unless you set 'modal' to +// TRUE to construct a modal dialog. +//================================================================================= +GroupGUI_BooleanDlg::GroupGUI_BooleanDlg (const int theOperation, GeometryGUI* theGeometryGUI, + QWidget* parent, bool modal, Qt::WindowFlags fl) + : GEOMBase_Skeleton(theGeometryGUI, parent, modal, fl), + myOperation(theOperation) +{ + QPixmap image0; + QString aTitle, aCaption; + switch (myOperation) { + case UNION: + image0 = QPixmap(SUIT_Session::session()->resourceMgr()->loadPixmap("GEOM", tr("ICON_DLG_FUSE"))); + aTitle = tr("GEOM_UNION"); + aCaption = tr("GEOM_UNION_TITLE"); + setHelpFileName("work_with_groups_page.html#union_groups_anchor"); + break; + case INTERSECT: + image0 = QPixmap(SUIT_Session::session()->resourceMgr()->loadPixmap("GEOM", tr("ICON_DLG_COMMON"))); + aTitle = tr("GEOM_INTERSECT"); + aCaption = tr("GEOM_INTERSECT_TITLE"); + setHelpFileName("work_with_groups_page.html#intersect_groups_anchor"); + break; + case CUT: + image0 = QPixmap(SUIT_Session::session()->resourceMgr()->loadPixmap("GEOM", tr("ICON_DLG_CUT"))); + aTitle = tr("GEOM_CUT"); + aCaption = tr("GEOM_CUT_TITLE"); + setHelpFileName("work_with_groups_page.html#cut_groups_anchor"); + break; + } + QPixmap image1 (SUIT_Session::session()->resourceMgr()->loadPixmap("GEOM", tr("ICON_SELECT"))); + + setWindowTitle(aCaption); + + /***************************************************************/ + mainFrame()->GroupConstructors->setTitle(aTitle); + mainFrame()->RadioButton1->setIcon(image0); + mainFrame()->RadioButton2->setAttribute(Qt::WA_DeleteOnClose); + mainFrame()->RadioButton2->close(); + mainFrame()->RadioButton3->setAttribute(Qt::WA_DeleteOnClose); + mainFrame()->RadioButton3->close(); + + myGroup = new DlgRef_2Sel (centralWidget()); + + myGroup->GroupBox1->setTitle(tr("GEOM_ARGUMENTS")); + if (myOperation == CUT) { + myGroup->TextLabel1->setText(tr("GEOM_MAIN_GROUPS")); + myGroup->TextLabel2->setText(tr("GEOM_TOOL_GROUPS")); + } + else { + myGroup->TextLabel1->setText(tr("GEOM_GROUPS").arg(1)); + myGroup->TextLabel2->hide(); + myGroup->PushButton2->hide(); + myGroup->LineEdit2->hide(); + } + + myGroup->PushButton1->setIcon(image1); + myGroup->PushButton2->setIcon(image1); + myGroup->LineEdit1->setReadOnly(true); + myGroup->LineEdit2->setReadOnly(true); + + QVBoxLayout* layout = new QVBoxLayout (centralWidget()); + layout->setMargin(0); layout->setSpacing(6); + layout->addWidget(myGroup); + /***************************************************************/ + + // Initialisation + Init(); +} + +//================================================================================= +// function : ~GroupGUI_BooleanDlg() +// purpose : Destroys the object and frees any allocated resources +//================================================================================= +GroupGUI_BooleanDlg::~GroupGUI_BooleanDlg() +{ +} + +//================================================================================= +// function : Init() +// purpose : +//================================================================================= +void GroupGUI_BooleanDlg::Init() +{ + // init variables + myEditCurrentArgument = myGroup->LineEdit1; + + myGroup->LineEdit1->setText(""); + myGroup->LineEdit2->setText(""); + myListShapes.length( 0 ); + myListTools.length( 0 ); + + // signals and slots connections + connect(buttonOk(), SIGNAL(clicked()), this, SLOT(ClickOnOk())); + connect(buttonApply(), SIGNAL(clicked()), this, SLOT(ClickOnApply())); + + connect(myGroup->PushButton1, SIGNAL(clicked()), this, SLOT(SetEditCurrentArgument())); + connect(myGroup->PushButton2, SIGNAL(clicked()), this, SLOT(SetEditCurrentArgument())); + + connect(((SalomeApp_Application*)(SUIT_Session::session()->activeApplication()))->selectionMgr(), + SIGNAL(currentSelectionChanged()), this, SLOT(SelectionIntoArgument())); + + initName(mainFrame()->GroupConstructors->title()); + + setTabOrder(mainFrame()->GroupConstructors, mainFrame()->GroupBoxName); + setTabOrder(mainFrame()->GroupBoxName, mainFrame()->GroupMedium); + setTabOrder(mainFrame()->GroupMedium, mainFrame()->GroupButtons); + + mainFrame()->RadioButton1->setFocus(); + + globalSelection(GEOM_GROUP); + + myGroup->PushButton1->click(); + SelectionIntoArgument(); + resize(100,100); +} + +//================================================================================= +// function : ClickOnOk() +// purpose : +//================================================================================= +void GroupGUI_BooleanDlg::ClickOnOk() +{ + setIsApplyAndClose(true); + if (ClickOnApply()) + ClickOnCancel(); +} + +//================================================================================= +// function : ClickOnApply() +// purpose : +//================================================================================= +bool GroupGUI_BooleanDlg::ClickOnApply() +{ + if (!onAccept()) + return false; + + initName(); + // activate selection and connect selection manager + myGroup->PushButton1->click(); + return true; +} + +//================================================================================= +// function : SelectionIntoArgument() +// purpose : Called when selection is changed or on dialog initialization or activation +//================================================================================= +void GroupGUI_BooleanDlg::SelectionIntoArgument() +{ + myEditCurrentArgument->setText(""); + + LightApp_SelectionMgr* aSelMgr = myGeomGUI->getApp()->selectionMgr(); + SALOME_ListIO aSelList; + aSelMgr->selectedObjects(aSelList); + + QString aString = ""; + GEOMBase::GetNameOfSelectedIObjects(aSelList, aString, true); + + if (myEditCurrentArgument == myGroup->LineEdit1) { + GEOMBase::ConvertListOfIOInListOfGO(aSelList, myListShapes, true); + } + else if ( myEditCurrentArgument == myGroup->LineEdit2 ) { + GEOMBase::ConvertListOfIOInListOfGO(aSelList, myListTools, true); + } + + myEditCurrentArgument->setText(aString); +} + +//================================================================================= +// function : SetEditCurrentArgument() +// purpose : +//================================================================================= +void GroupGUI_BooleanDlg::SetEditCurrentArgument() +{ + QPushButton* send = (QPushButton*)sender(); + + if (send == myGroup->PushButton1) { + myEditCurrentArgument = myGroup->LineEdit1; + + myGroup->PushButton2->setDown(false); + myGroup->LineEdit2->setEnabled(false); + } + else if (send == myGroup->PushButton2) { + myEditCurrentArgument = myGroup->LineEdit2; + + myGroup->PushButton1->setDown(false); + myGroup->LineEdit1->setEnabled(false); + } + + // enable line edit + myEditCurrentArgument->setEnabled(true); + myEditCurrentArgument->setFocus(); + // after setFocus(), because it will be setDown(false) when loses focus + send->setDown(true); +} + +//================================================================================= +// function : ActivateThisDialog() +// purpose : +//================================================================================= +void GroupGUI_BooleanDlg::ActivateThisDialog() +{ + GEOMBase_Skeleton::ActivateThisDialog(); + + connect(myGeomGUI->getApp()->selectionMgr(), SIGNAL(currentSelectionChanged()), + this, SLOT(SelectionIntoArgument())); +} + +//================================================================================= +// function : enterEvent() +// purpose : when mouse enter onto the QWidget +//================================================================================= +void GroupGUI_BooleanDlg::enterEvent (QEvent*) +{ + if (!mainFrame()->GroupConstructors->isEnabled()) + ActivateThisDialog(); +} + +//================================================================================= +// function : createOperation +// purpose : +//================================================================================= +GEOM::GEOM_IOperations_ptr GroupGUI_BooleanDlg::createOperation() +{ + return getGeomEngine()->GetIGroupOperations(getStudyId()); +} + +//================================================================================= +// function : isValid +// purpose : +//================================================================================= +bool GroupGUI_BooleanDlg::isValid (QString&) +{ + return (myListShapes.length() > 0); +} + +//================================================================================= +// function : execute +// purpose : +//================================================================================= +bool GroupGUI_BooleanDlg::execute (ObjectList& objects) +{ + GEOM::GEOM_Object_var anObj; + + GEOM::GEOM_IGroupOperations_var anOper = GEOM::GEOM_IGroupOperations::_narrow(getOperation()); + switch (myOperation) { + case UNION: + anObj = anOper->UnionListOfGroups(myListShapes); + break; + case INTERSECT: + anObj = anOper->IntersectListOfGroups(myListShapes); + break; + case CUT: + anObj = anOper->CutListOfGroups(myListShapes, myListTools); + break; + default: + ; + } + if (!anObj->_is_nil()) + objects.push_back(anObj._retn()); + + return true; +} + +//================================================================ +// Function : getFather +// Purpose : Get father object for object to be added in study +// (called with addInStudy method) +//================================================================ +GEOM::GEOM_Object_ptr GroupGUI_BooleanDlg::getFather(GEOM::GEOM_Object_ptr theObj) +{ + GEOM::GEOM_Object_var aFatherObj; + if (theObj->GetType() == GEOM_GROUP) { + GEOM::GEOM_IGroupOperations_var anOper = GEOM::GEOM_IGroupOperations::_narrow(getOperation()); + aFatherObj = anOper->GetMainShape(theObj); + } + return aFatherObj._retn(); +} diff --git a/src/GroupGUI/GroupGUI_BooleanDlg.h b/src/GroupGUI/GroupGUI_BooleanDlg.h new file mode 100644 index 000000000..467130eec --- /dev/null +++ b/src/GroupGUI/GroupGUI_BooleanDlg.h @@ -0,0 +1,76 @@ +// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com + +// GEOM GEOMGUI : GUI for Geometry component +// File : GroupGUI_BooleanDlg.h +// Author : Lucien PIGNOLONI, Open CASCADE S.A.S. + +#ifndef GROUPGUI_BOOLEANDLG_H +#define GROUPGUI_BOOLEANDLG_H + +#include "GEOMBase_Skeleton.h" +#include "GEOM_GenericObjPtr.h" + +class DlgRef_2Sel; + +//================================================================================= +// class : GroupGUI_BooleanDlg +// purpose : +//================================================================================= +class GroupGUI_BooleanDlg : public GEOMBase_Skeleton +{ + Q_OBJECT + +public: + enum Operation { UNION = 1, INTERSECT = 2, CUT = 3 }; + + GroupGUI_BooleanDlg (const int, GeometryGUI*, QWidget* = 0, + bool = false, Qt::WindowFlags = 0); + ~GroupGUI_BooleanDlg(); + +protected: + // redefined from GEOMBase_Helper + virtual GEOM::GEOM_IOperations_ptr createOperation(); + virtual bool isValid (QString&); + virtual bool execute (ObjectList&); + virtual GEOM::GEOM_Object_ptr getFather (GEOM::GEOM_Object_ptr); + +private: + void Init(); + void enterEvent (QEvent*); + +private slots: + void ClickOnOk(); + bool ClickOnApply(); + void SetEditCurrentArgument(); + void SelectionIntoArgument(); + void ActivateThisDialog(); + +private: + int myOperation; + + GEOM::ListOfGO myListShapes; + GEOM::ListOfGO myListTools; + + DlgRef_2Sel* myGroup; +}; + +#endif // GROUPGUI_BOOLEANDLG_H diff --git a/src/GroupGUI/Makefile.am b/src/GroupGUI/Makefile.am index 068c3587a..78e540589 100755 --- a/src/GroupGUI/Makefile.am +++ b/src/GroupGUI/Makefile.am @@ -15,13 +15,11 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -# -# GEOM GROUPGUI : # File : Makefile.am # Author : Alexander BORODIN, Open CASCADE S.A.S. (alexander.borodin@opencascade.com) # Package : GroupGUI -# + include $(top_srcdir)/adm_local/unix/make_common_starter.am # Libraries targets @@ -30,16 +28,20 @@ lib_LTLIBRARIES = libGroupGUI.la # header files salomeinclude_HEADERS = \ GroupGUI.h \ + GroupGUI_BooleanDlg.h \ GroupGUI_GroupDlg.h dist_libGroupGUI_la_SOURCES = \ GroupGUI.h \ + GroupGUI_BooleanDlg.h \ GroupGUI_GroupDlg.h \ GroupGUI.cxx \ + GroupGUI_BooleanDlg.cxx \ GroupGUI_GroupDlg.cxx -MOC_FILES = \ - GroupGUI_moc.cxx \ +MOC_FILES = \ + GroupGUI_moc.cxx \ + GroupGUI_BooleanDlg_moc.cxx \ GroupGUI_GroupDlg_moc.cxx nodist_libGroupGUI_la_SOURCES = \ -- 2.39.2