diff --git a/doc/salome/examples/boolean_operations_ex01.py b/doc/salome/examples/boolean_operations_ex01.py index 01809955e..7c365d7eb 100644 --- a/doc/salome/examples/boolean_operations_ex01.py +++ b/doc/salome/examples/boolean_operations_ex01.py @@ -20,22 +20,32 @@ cylinder = geompy.MakeCylinder(p1, v, radius1, height) # create a sphere sphere = geompy.MakeSphereR(40) +# create a box +box = geompy.MakeBoxDXDYDZ(80, 80, 80) + # fuse fuse1 = geompy.MakeFuse(cylinder, sphere) fuse2 = geompy.MakeBoolean(cylinder, sphere, 3) +fuse3 = geompy.MakeFuseList([cylinder, sphere, box]) # add objects in the study id_cylinder = geompy.addToStudy(cylinder, "Cylinder") id_sphere = geompy.addToStudy(sphere, "Sphere") +id_box = geompy.addToStudy(box, "Box") id_fuse1 = geompy.addToStudy(fuse1, "Fuse_1") id_fuse2 = geompy.addToStudy(fuse2, "Fuse_2") +id_fuse3 = geompy.addToStudy(fuse3, "Fuse_3") # display results gg.createAndDisplayGO(id_cylinder) gg.setDisplayMode(id_cylinder,1) gg.createAndDisplayGO(id_sphere) gg.setDisplayMode(id_sphere,1) +gg.createAndDisplayGO(id_box) +gg.setDisplayMode(id_box,1) gg.createAndDisplayGO(id_fuse1) gg.setDisplayMode(id_fuse1,1) gg.createAndDisplayGO(id_fuse2) gg.setDisplayMode(id_fuse2,1) +gg.createAndDisplayGO(id_fuse3) +gg.setDisplayMode(id_fuse3,1) diff --git a/doc/salome/examples/boolean_operations_ex02.py b/doc/salome/examples/boolean_operations_ex02.py index 90317ba93..212e313d4 100644 --- a/doc/salome/examples/boolean_operations_ex02.py +++ b/doc/salome/examples/boolean_operations_ex02.py @@ -20,12 +20,28 @@ cylinder = geompy.MakeCylinder(p1, v, radius1, height) # create a sphere sphere = geompy.MakeSphereR(40) +# create a box +box = geompy.MakeBoxDXDYDZ(80, 80, 80) + # make common -common = geompy.MakeCommon(cylinder, sphere) +common1 = geompy.MakeCommon(cylinder, sphere) +common2 = geompy.MakeCommonList([cylinder, sphere, box]) # add objects in the study -id_common = geompy.addToStudy(common, "Common") +id_cylinder = geompy.addToStudy(cylinder, "Cylinder") +id_sphere = geompy.addToStudy(sphere, "Sphere") +id_box = geompy.addToStudy(box, "Box") +id_common1 = geompy.addToStudy(common1, "Common_1") +id_common2 = geompy.addToStudy(common2, "Common_2") # display the results -gg.createAndDisplayGO(id_common) -gg.setDisplayMode(id_common,1) +gg.createAndDisplayGO(id_cylinder) +gg.setDisplayMode(id_cylinder,1) +gg.createAndDisplayGO(id_sphere) +gg.setDisplayMode(id_sphere,1) +gg.createAndDisplayGO(id_box) +gg.setDisplayMode(id_box,1) +gg.createAndDisplayGO(id_common1) +gg.setDisplayMode(id_common1,1) +gg.createAndDisplayGO(id_common2) +gg.setDisplayMode(id_common2,1) diff --git a/doc/salome/examples/boolean_operations_ex03.py b/doc/salome/examples/boolean_operations_ex03.py index 7c97b09f0..fdb7545f1 100644 --- a/doc/salome/examples/boolean_operations_ex03.py +++ b/doc/salome/examples/boolean_operations_ex03.py @@ -20,12 +20,28 @@ cylinder = geompy.MakeCylinder(p1, v, radius1, height) # create a sphere sphere = geompy.MakeSphereR(40) +# create a box +box = geompy.MakeBoxDXDYDZ(80, 80, 80) + #cut -cut = geompy.MakeCut(cylinder, sphere) +cut1 = geompy.MakeCut(cylinder, sphere) +cut2 = geompy.MakeCutList(cylinder, [sphere, box]) # add objects in the study -id_cut = geompy.addToStudy(cut, "Cut") +id_cylinder = geompy.addToStudy(cylinder, "Cylinder") +id_sphere = geompy.addToStudy(sphere, "Sphere") +id_box = geompy.addToStudy(box, "Box") +id_cut1 = geompy.addToStudy(cut1, "Cut_1") +id_cut2 = geompy.addToStudy(cut2, "Cut_2") # display the results -gg.createAndDisplayGO(id_cut) -gg.setDisplayMode(id_cut,1) +gg.createAndDisplayGO(id_cylinder) +gg.setDisplayMode(id_cylinder,1) +gg.createAndDisplayGO(id_sphere) +gg.setDisplayMode(id_sphere,1) +gg.createAndDisplayGO(id_box) +gg.setDisplayMode(id_box,1) +gg.createAndDisplayGO(id_cut1) +gg.setDisplayMode(id_cut1,1) +gg.createAndDisplayGO(id_cut2) +gg.setDisplayMode(id_cut2,1) diff --git a/doc/salome/gui/GEOM/input/common_operation.doc b/doc/salome/gui/GEOM/input/common_operation.doc index f6903e24c..e24645f31 100644 --- a/doc/salome/gui/GEOM/input/common_operation.doc +++ b/doc/salome/gui/GEOM/input/common_operation.doc @@ -2,23 +2,23 @@ \page common_operation_page Common -For detail description of the Boolean operations please refer to -this document. -It provides a general review of the Partition and Boolean -operations algorithms, describes the usage methodology and highlighs -major limitations of these operations. - To produce a \b Common operation in the Main Menu select Operations - > Boolean - > Common -This operation cuts the common part of two shapes and transforms it into an independent geometrical object. +This operation cuts the common part of a list of shapes and transforms it into an independent geometrical object. -The \b Result will be any \b GEOM_Object. -TUI Command: geompy.MakeCommon(s1, s2) -Arguments: Name + 2 shapes. +The \b Result will be a \b GEOM_Object. + +TUI Command: geompy.MakeCommonList(theShapesList)\n +Arguments: Name + a list of shapes.\n Advanced option: \ref restore_presentation_parameters_page "Set presentation parameters and sub-shapes from arguments". -\image html bool2.png +\image html bool2.png "Common dialog" + +For a particular case with two shapes for the Common operation there is the following TUI command: + +TUI Command: geompy.MakeCommon(s1, s2)\n +Arguments: Name + 2 shapes. Example: @@ -29,4 +29,12 @@ The \b Result will be any \b GEOM_Object. Our TUI Scripts provide you with useful examples of the use of \ref tui_common "Boolean Operations". + More details + +For a detailed description of the Boolean operations please refer to +this document. +It provides a general review of the Partition and Boolean +operations algorithms, describes the usage methodology and highlights +major limitations of these operations. + */ diff --git a/doc/salome/gui/GEOM/input/cut_operation.doc b/doc/salome/gui/GEOM/input/cut_operation.doc index 5ea6c5dfc..d00c587eb 100644 --- a/doc/salome/gui/GEOM/input/cut_operation.doc +++ b/doc/salome/gui/GEOM/input/cut_operation.doc @@ -2,23 +2,23 @@ \page cut_operation_page Cut -For detail description of the Boolean operations please refer to -this document. -It provides a general review of the Partition and Boolean -operations algorithms, describes the usage methodology and highlighs -major limitations of these operations. - To produce a \b Cut operation in the Main Menu select Operations - > Boolean - > Cut -This operation cuts a shape with another one. -The \b Result will be any \b GEOM_Object. -Arguments: Name + 2 shapes. +This operation cuts a shape with a list of other shapes. + +The \b Result will be a \b GEOM_Object. + +TUI Command: geompy.MakeCutList(theMainShape, theShapesList)\n +Arguments: Name + a main shape + a list of other shapes.\n Advanced option: \ref restore_presentation_parameters_page "Set presentation parameters and sub-shapes from arguments". -Dialog Box: +\image html bool3.png "Cut dialog" -\image html bool3.png +For a particular case with two shapes (object and tool) for the Cut operation there is the following TUI command: + +TUI Command: geompy.MakeCut(s1, s2)\n +Arguments: Name + the object + the tool. Example: @@ -29,4 +29,12 @@ The \b Result will be any \b GEOM_Object. Our TUI Scripts provide you with useful examples of the use of \ref tui_cut "Boolean Operations". + More details + +For a detailed description of the Boolean operations please refer to +this document. +It provides a general review of the Partition and Boolean +operations algorithms, describes the usage methodology and highlights +major limitations of these operations. + */ diff --git a/doc/salome/gui/GEOM/input/fuse_operation.doc b/doc/salome/gui/GEOM/input/fuse_operation.doc index df13c732e..b45e580a8 100644 --- a/doc/salome/gui/GEOM/input/fuse_operation.doc +++ b/doc/salome/gui/GEOM/input/fuse_operation.doc @@ -5,8 +5,21 @@ To produce a \b Fuse operation in the Main Menu select Operations - > Boolean - > Fuse. -This operation creates one shape from two shapes. -The \b Result will be any \b GEOM_Object. +This operation creates one shape from a list of shapes. + +The \b Result will be a \b GEOM_Object. + +TUI Command: geompy.MakeFuseList(theShapesList)\n +Arguments: Name + a list of shapes.\n +Advanced option: +\ref restore_presentation_parameters_page "Set presentation parameters and sub-shapes from arguments". + +\image html bool1.png "Fuse dialog" + +For a particular case with two shapes to be fused there is the following TUI command: + +TUI Command: geompy.MakeFuse(s1, s2)\n +Arguments: Name + 2 shapes. Example: @@ -14,13 +27,6 @@ The \b Result will be any \b GEOM_Object. \image html fusesn2.png "The resulting fuse" -TUI Command: geompy.MakeFuse(s1, s2)\n -Arguments: Name + 2 shapes.\n -Advanced option: -\ref restore_presentation_parameters_page "Set presentation parameters and sub-shapes from arguments". - -\image html bool1.png - Our TUI Scripts provide you with useful examples of the use of \ref tui_fuse "Boolean Operations". diff --git a/doc/salome/gui/GEOM/input/section_operation.doc b/doc/salome/gui/GEOM/input/section_operation.doc index 383f1c5de..5d60cf433 100644 --- a/doc/salome/gui/GEOM/input/section_operation.doc +++ b/doc/salome/gui/GEOM/input/section_operation.doc @@ -2,24 +2,19 @@ \page section_opeartion_page Section -For detail description of the Boolean operations please refer to -this document. -It provides a general review of the Partition and Boolean -operations algorithms, describes the usage methodology and highlighs -major limitations of these operations. - To produce a \b Section operation in the Main Menu select Operations - > Boolean - > Section This operation creates the section between 2 shapes. The \b Result will be any \b GEOM_Object (EDGE or WIRE). -TUI Command: geompy.MakeSection(s1, s2) -Arguments: Name + 2 shapes. + +TUI Command: geompy.MakeSection(s1, s2)\n +Arguments: Name + 2 shapes.\n Advanced option: \ref restore_presentation_parameters_page "Set presentation parameters and sub-shapes from arguments". -\image html neo-section.png +\image html neo-section.png "Section dialog" Example: @@ -30,4 +25,12 @@ The \b Result will be any \b GEOM_Object (EDGE or WIRE). Our TUI Scripts provide you with useful examples of the use of \ref tui_section "Boolean Operations". + More details + +For a detailed description of the Boolean operations please refer to +this document. +It provides a general review of the Partition and Boolean +operations algorithms, describes the usage methodology and highlights +major limitations of these operations. + */ diff --git a/doc/salome/gui/GEOM/input/using_boolean_operations.doc b/doc/salome/gui/GEOM/input/using_boolean_operations.doc index d0bca5b6a..84301523e 100644 --- a/doc/salome/gui/GEOM/input/using_boolean_operations.doc +++ b/doc/salome/gui/GEOM/input/using_boolean_operations.doc @@ -12,16 +12,35 @@ You can use the following boolean operations for construction of more complex geometrical objects (2D & 3D elements): -There is a general TUI command covering all these operations, which -can be used alongside with separate commands for each operation. +You can use advanced TUI commands performing these operations +independently from each other: +\par +geompy.MakeFuseList(theShapesList), where \em theShapesList is +the list of shapes for Fuse operation; +\par +geompy.MakeCommonList(theShapesList), where \em theShapesList is +the list of shapes for Common operation; +\par +geompy.MakeCutList(theMainShape, theShapesList), where \em +theMainShape is the object of the operation and \em theShapesList is +the list of tools for Cut operation; +\par +geompy.MakeSection(Shape1, Shape2), where \em Shape1 is the first +argument and \em Shape2 is the second argument of Section operation; + + +There are several TUI commands that can be used to perform boolean operations +with only two arguments. There is a general TUI command covering these +operations, which can be used alongside with separate commands for each +operation. \par geompy.MakeBoolean(Shape1, Shape2, Operation), where \em Shape1 is the first argument and \em Shape2 is the second argument of @@ -32,17 +51,14 @@ Boolean operation, \em Operation is a type of the Boolean operation (1 Besides, you can use advanced TUI commands performing these operations independently from each other: \par -geompy.MakeFuse(Shape1, Shape2), where \em Shape1 and \em -Shape2 is the second argument of Fuse operation; +geompy.MakeFuse(Shape1, Shape2), where \em Shape1 is the first +argument and \em Shape2 is the second argument of Fuse operation; \par -geompy.MakeCommon(Shape1, Shape2), where \em Shape1 and \em -Shape2 is the second argument of Common operation; +geompy.MakeCommon(Shape1, Shape2), where \em Shape1 is the first +argument and \em Shape2 is the second argument of Common operation; \par -geompy.MakeCut(Shape1, Shape2), where \em Shape1 and \em -Shape2 is the second argument of Cut operation; -\par -geompy.MakeSection(Shape1, Shape2), where \em Shape1 and \em -Shape2 is the second argument of Section operation; +geompy.MakeCut(Shape1, Shape2), where \em Shape1 is the first +argument and \em Shape2 is the second argument of Cut operation; Our TUI Scripts provide you with useful examples of the use of \ref tui_boolean_operations_page "Boolean Operations". diff --git a/idl/GEOM_Gen.idl b/idl/GEOM_Gen.idl index b3b95cedb..1395c5859 100644 --- a/idl/GEOM_Gen.idl +++ b/idl/GEOM_Gen.idl @@ -2675,6 +2675,29 @@ module GEOM in GEOM_Object theShape2, in long theOperation); + /*! + * \brief Perform fusion boolean operation on list of objects. + * \param theShapes Shapes to be fused. + * \return New GEOM_Object, containing the result shape. + */ + GEOM_Object MakeFuseList (in ListOfGO theShapes); + + /*! + * \brief Perform common boolean operation on list of objects. + * \param theShapes Shapes for common operation. + * \return New GEOM_Object, containing the result shape. + */ + GEOM_Object MakeCommonList (in ListOfGO theShapes); + + /*! + * \brief Perform cutting of list of objects from theMainShape. + * \param theMainShape the object for cut operation. + * \param theShapes Shapes to be cut from theMainShape (tools). + * \return New GEOM_Object, containing the result shape. + */ + GEOM_Object MakeCutList (in GEOM_Object theMainShape, + in ListOfGO theShapes); + /*! * \brief Perform partition operation. * diff --git a/src/BooleanGUI/BooleanGUI_Dialog.cxx b/src/BooleanGUI/BooleanGUI_Dialog.cxx index 1ee191665..b312686e3 100644 --- a/src/BooleanGUI/BooleanGUI_Dialog.cxx +++ b/src/BooleanGUI/BooleanGUI_Dialog.cxx @@ -35,6 +35,7 @@ #include #include #include +#include // VSR 22/08/2012: issue 0021787: remove "Preview" button from BOP and Partition operations // Comment next line to enable preview in BOP dialog box @@ -95,19 +96,27 @@ BooleanGUI_Dialog::BooleanGUI_Dialog (const int theOperation, GeometryGUI* theGe myGroup = new DlgRef_2Sel(centralWidget()); myGroup->GroupBox1->setTitle(tr("GEOM_ARGUMENTS")); - if (myOperation != BooleanGUI::CUT) { + if (myOperation == BooleanGUI::CUT) { + myGroup->TextLabel1->setText(tr("GEOM_MAIN_OBJECT")); + myGroup->TextLabel2->setText(tr("GEOM_TOOL_OBJECTS")); + } + else if (myOperation == BooleanGUI::SECTION) { myGroup->TextLabel1->setText(tr("GEOM_OBJECT_I").arg(1)); myGroup->TextLabel2->setText(tr("GEOM_OBJECT_I").arg(2)); - } - else { - myGroup->TextLabel1->setText(tr("GEOM_MAIN_OBJECT")); - myGroup->TextLabel2->setText(tr("GEOM_TOOL_OBJECT")); + } else { // Fuse or Common + myGroup->TextLabel1->setText(tr( "GEOM_SELECTED_OBJECTS" )); + 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); + + if (myOperation != BooleanGUI::FUSE && myOperation != BooleanGUI::COMMON) { + myGroup->PushButton2->setIcon(image1); + myGroup->LineEdit2->setReadOnly(true); + } QVBoxLayout* layout = new QVBoxLayout(centralWidget()); layout->setMargin(0); layout->setSpacing(6); @@ -144,14 +153,17 @@ void BooleanGUI_Dialog::Init() myGroup->LineEdit1->setText(""); myGroup->LineEdit2->setText(""); myObject1.nullify(); - myObject2.nullify(); + reset(); // 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())); + + if (!myGroup->PushButton2->isHidden()) { + connect(myGroup->PushButton2, SIGNAL(clicked()), this, SLOT(SetEditCurrentArgument())); + } connect(((SalomeApp_Application*)(SUIT_Session::session()->activeApplication()))->selectionMgr(), SIGNAL(currentSelectionChanged()), this, SLOT(SelectionIntoArgument())); @@ -198,10 +210,20 @@ bool BooleanGUI_Dialog::ClickOnApply() } //================================================================================= -// function : SelectionIntoArgument() -// purpose : Called when selection is changed or on dialog initialization or activation +// function : reset() +// purpose : //================================================================================= -void BooleanGUI_Dialog::SelectionIntoArgument() +void BooleanGUI_Dialog::reset() +{ + myObjects = new GEOM::ListOfGO; + myObjects->length( 0 ); +} + +//================================================================================= +// function : singleSelection +// purpose : Performs single selection. Called from SelectionIntoArgument() +//================================================================================= +void BooleanGUI_Dialog::singleSelection() { myEditCurrentArgument->setText(""); @@ -219,19 +241,67 @@ void BooleanGUI_Dialog::SelectionIntoArgument() if (myEditCurrentArgument == myGroup->LineEdit1) { myObject1 = aSelectedObject; - if (!myObject2) + if (!myGroup->PushButton2->isHidden() && !myObjects->length()) myGroup->PushButton2->click(); } else if (myEditCurrentArgument == myGroup->LineEdit2) { - myObject2 = aSelectedObject; + myObjects->length(1); + myObjects[0] = aSelectedObject.get(); if (!myObject1) myGroup->PushButton1->click(); } } else { if (myEditCurrentArgument == myGroup->LineEdit1) myObject1.nullify(); - else if (myEditCurrentArgument == myGroup->LineEdit2) myObject2.nullify(); + else if (myEditCurrentArgument == myGroup->LineEdit2) reset(); } +} + +//================================================================================= +// function : multipleSelection +// purpose : Performs multiple selection. Called from SelectionIntoArgument() +//================================================================================= +void BooleanGUI_Dialog::multipleSelection() +{ + myEditCurrentArgument->setText( "" ); + reset(); + + LightApp_SelectionMgr* aSelMgr = myGeomGUI->getApp()->selectionMgr(); + SALOME_ListIO aSelList; + aSelMgr->selectedObjects(aSelList); + myObjects->length(aSelList.Extent()); + + int i = 0; + for (SALOME_ListIteratorOfListIO anIt (aSelList); anIt.More(); anIt.Next()) { + GEOM::GEOM_Object_var aSelectedObject = GEOMBase::ConvertIOinGEOMObject( anIt.Value() ); + + if ( !CORBA::is_nil( aSelectedObject ) ) { + myObjects[i++] = aSelectedObject; + } + } + + myObjects->length( i ); + if ( i == 1 ) { + myEditCurrentArgument->setText( GEOMBase::GetName( myObjects[0] ) ); + } else if ( i > 0 ) { + myEditCurrentArgument->setText( QString::number( i ) + "_" + tr( "GEOM_OBJECTS" ) ); + } +} + +//================================================================================= +// function : SelectionIntoArgument() +// purpose : Called when selection is changed or on dialog initialization or activation +//================================================================================= +void BooleanGUI_Dialog::SelectionIntoArgument() +{ + if ( myOperation == BooleanGUI::SECTION || + (myOperation == BooleanGUI::CUT && + myEditCurrentArgument == myGroup->LineEdit1)) { + singleSelection(); + } else { + multipleSelection(); + } + processPreview(); } @@ -246,8 +316,10 @@ void BooleanGUI_Dialog::SetEditCurrentArgument() if (send == myGroup->PushButton1) { myEditCurrentArgument = myGroup->LineEdit1; - myGroup->PushButton2->setDown(false); - myGroup->LineEdit2->setEnabled(false); + if (!myGroup->PushButton2->isHidden()) { + myGroup->PushButton2->setDown(false); + myGroup->LineEdit2->setEnabled(false); + } } else if (send == myGroup->PushButton2) { myEditCurrentArgument = myGroup->LineEdit2; @@ -301,7 +373,24 @@ GEOM::GEOM_IOperations_ptr BooleanGUI_Dialog::createOperation() //================================================================================= bool BooleanGUI_Dialog::isValid (QString&) { - return myObject1 && myObject2; + bool isOK = false; + + switch (myOperation) { + case BooleanGUI::FUSE: + case BooleanGUI::COMMON: + isOK = myObjects->length() > 1; + break; + case BooleanGUI::CUT: + isOK = myObject1 && myObjects->length(); + break; + case BooleanGUI::SECTION: + isOK = myObject1 && (myObjects->length() == 1); + break; + default: + break; + } + + return isOK; } //================================================================================= @@ -313,7 +402,24 @@ bool BooleanGUI_Dialog::execute (ObjectList& objects) GEOM::GEOM_Object_var anObj; GEOM::GEOM_IBooleanOperations_var anOper = GEOM::GEOM_IBooleanOperations::_narrow(getOperation()); - anObj = anOper->MakeBoolean(myObject1.get(), myObject2.get(), myOperation); + + switch (myOperation) { + case BooleanGUI::FUSE: + anObj = anOper->MakeFuseList(myObjects); + break; + case BooleanGUI::COMMON: + anObj = anOper->MakeCommonList(myObjects); + break; + case BooleanGUI::CUT: + anObj = anOper->MakeCutList(myObject1.get(), myObjects); + break; + case BooleanGUI::SECTION: + anObj = anOper->MakeBoolean(myObject1.get(), myObjects[0], myOperation); + break; + default: + break; + } + if (!anObj->_is_nil()) objects.push_back(anObj._retn()); diff --git a/src/BooleanGUI/BooleanGUI_Dialog.h b/src/BooleanGUI/BooleanGUI_Dialog.h index 4601cc97d..14d84ffd9 100644 --- a/src/BooleanGUI/BooleanGUI_Dialog.h +++ b/src/BooleanGUI/BooleanGUI_Dialog.h @@ -55,12 +55,15 @@ protected: private: void Init(); void enterEvent( QEvent* ); + void reset(); + void singleSelection(); + void multipleSelection(); private: int myOperation; GEOM::GeomObjPtr myObject1; - GEOM::GeomObjPtr myObject2; + GEOM::ListOfGO_var myObjects; DlgRef_2Sel* myGroup; diff --git a/src/GEOMGUI/GEOM_msg_en.ts b/src/GEOMGUI/GEOM_msg_en.ts index a853aa998..2d94e74b7 100644 --- a/src/GEOMGUI/GEOM_msg_en.ts +++ b/src/GEOMGUI/GEOM_msg_en.ts @@ -439,7 +439,7 @@ Please, select face, shell or solid and try again GEOM_COMMON_TITLE - Common Of Two Objects + Common Of Objects GEOM_COMPOUND @@ -507,7 +507,7 @@ Please, select face, shell or solid and try again GEOM_CUT_TITLE - Cut Of Two Objects + Cut Of Objects GEOM_CYLINDER @@ -836,7 +836,7 @@ Please, select face, shell or solid and try again GEOM_FUSE_TITLE - Fuse Two Objects + Fuse Objects GEOM_FixFaceSize @@ -2142,10 +2142,6 @@ Please, select face, shell or solid and try again GEOM_TOLERANCE_VERTEX Vertex : - - GEOM_TOOL_OBJECT - Tool Object - GEOM_TOOL_OBJECTS Tool Objects diff --git a/src/GEOMGUI/GEOM_msg_fr.ts b/src/GEOMGUI/GEOM_msg_fr.ts index f8dd0ec20..3676d3905 100644 --- a/src/GEOMGUI/GEOM_msg_fr.ts +++ b/src/GEOMGUI/GEOM_msg_fr.ts @@ -439,7 +439,7 @@ Choisissez une face, une coque ou un solide et essayez de nouveau GEOM_COMMON_TITLE - Intersection de deux objets + Intersection des objets GEOM_COMPOUND @@ -507,7 +507,7 @@ Choisissez une face, une coque ou un solide et essayez de nouveau GEOM_CUT_TITLE - Découpe de deux objets + Découpe des objets GEOM_CYLINDER @@ -836,7 +836,7 @@ Choisissez une face, une coque ou un solide et essayez de nouveau GEOM_FUSE_TITLE - Réunir deux objets + Réunir des objets GEOM_FixFaceSize @@ -2142,10 +2142,6 @@ Choisissez une face, une coque ou un solide et essayez de nouveau GEOM_TOLERANCE_VERTEX Point: - - GEOM_TOOL_OBJECT - Objet outil - GEOM_TOOL_OBJECTS Objets outils diff --git a/src/GEOMImpl/GEOMImpl_BooleanDriver.cxx b/src/GEOMImpl/GEOMImpl_BooleanDriver.cxx index a0af1efd6..8cc9f8bfd 100644 --- a/src/GEOMImpl/GEOMImpl_BooleanDriver.cxx +++ b/src/GEOMImpl/GEOMImpl_BooleanDriver.cxx @@ -41,7 +41,6 @@ #include #include -#include #include #include #include @@ -87,124 +86,166 @@ Standard_Integer GEOMImpl_BooleanDriver::Execute (TFunction_Logbook& log) const TopoDS_Shape aShape; - Handle(GEOM_Function) aRefShape1 = aCI.GetShape1(); - Handle(GEOM_Function) aRefShape2 = aCI.GetShape2(); - TopoDS_Shape aShape1 = aRefShape1->GetValue(); - TopoDS_Shape aShape2 = aRefShape2->GetValue(); + switch (aType) { + case BOOLEAN_COMMON: + case BOOLEAN_CUT: + case BOOLEAN_FUSE: + case BOOLEAN_SECTION: + { + Handle(GEOM_Function) aRefShape1 = aCI.GetShape1(); + Handle(GEOM_Function) aRefShape2 = aCI.GetShape2(); + TopoDS_Shape aShape1 = aRefShape1->GetValue(); + TopoDS_Shape aShape2 = aRefShape2->GetValue(); - if (!aShape1.IsNull() && !aShape2.IsNull()) { - // check arguments for Mantis issue 0021019 - BRepCheck_Analyzer ana (aShape1, Standard_True); - if (!ana.IsValid()) - StdFail_NotDone::Raise("Boolean operation will not be performed, because argument shape is not valid"); - ana.Init(aShape2); - if (!ana.IsValid()) - StdFail_NotDone::Raise("Boolean operation will not be performed, because argument shape is not valid"); + if (!aShape1.IsNull() && !aShape2.IsNull()) { + // check arguments for Mantis issue 0021019 + BRepCheck_Analyzer ana (aShape1, Standard_True); + if (!ana.IsValid()) + StdFail_NotDone::Raise("Boolean operation will not be performed, because argument shape is not valid"); + ana.Init(aShape2); + if (!ana.IsValid()) + StdFail_NotDone::Raise("Boolean operation will not be performed, because argument shape is not valid"); - // perform COMMON operation - if (aType == BOOLEAN_COMMON) { - BRep_Builder B; - TopoDS_Compound C; - B.MakeCompound(C); + aShape = performOperation (aShape1, aShape2, aType); - TopTools_ListOfShape listShape1, listShape2; - GEOMUtils::AddSimpleShapes(aShape1, listShape1); - GEOMUtils::AddSimpleShapes(aShape2, listShape2); - - Standard_Boolean isCompound = - (listShape1.Extent() > 1 || listShape2.Extent() > 1); - - TopTools_ListIteratorOfListOfShape itSub1 (listShape1); - for (; itSub1.More(); itSub1.Next()) { - TopoDS_Shape aValue1 = itSub1.Value(); - TopTools_ListIteratorOfListOfShape itSub2 (listShape2); - for (; itSub2.More(); itSub2.Next()) { - TopoDS_Shape aValue2 = itSub2.Value(); - BRepAlgoAPI_Common BO (aValue1, aValue2); - if (!BO.IsDone()) { - StdFail_NotDone::Raise("Common operation can not be performed on the given shapes"); - } - if (isCompound) { - TopoDS_Shape aStepResult = BO.Shape(); - - // check result of this step: if it is a compound (boolean operations - // allways return a compound), we add all sub-shapes of it. - // This allows to avoid adding empty compounds, - // resulting from COMMON on two non-intersecting shapes. - if (aStepResult.ShapeType() == TopAbs_COMPOUND) { - TopoDS_Iterator aCompIter (aStepResult); - for (; aCompIter.More(); aCompIter.Next()) { - // add shape in a result - B.Add(C, aCompIter.Value()); - } - } - else { - // add shape in a result - B.Add(C, aStepResult); - } - } - else - aShape = BO.Shape(); - } - } - - if (isCompound) { - /* - TopTools_ListOfShape listShapeC; - GEOMUtils::AddSimpleShapes(C, listShapeC); - TopTools_ListIteratorOfListOfShape itSubC (listShapeC); - bool isOnlySolids = true; - for (; itSubC.More(); itSubC.Next()) { - TopoDS_Shape aValueC = itSubC.Value(); - if (aValueC.ShapeType() != TopAbs_SOLID) isOnlySolids = false; - } - if (isOnlySolids) - aShape = GEOMImpl_GlueDriver::GlueFaces(C, Precision::Confusion()); - else - aShape = C; - */ - - // As GlueFaces has been improved to keep all kind of shapes - TopExp_Explorer anExp (C, TopAbs_VERTEX); - if (anExp.More()) - aShape = GEOMImpl_GlueDriver::GlueFaces(C, Precision::Confusion(), Standard_True); - else - aShape = C; + if (aShape.IsNull()) + return 0; } } + break; + case BOOLEAN_COMMON_LIST: + case BOOLEAN_FUSE_LIST: + { + Handle(TColStd_HSequenceOfTransient) aShapes = aCI.GetShapes(); + const Standard_Integer nbShapes = aShapes->Length(); + Standard_Integer i; + Handle(GEOM_Function) aRefShape; + TopoDS_Shape aShape2; + Standard_Integer aSimpleType = + (aType == BOOLEAN_FUSE_LIST ? BOOLEAN_FUSE : BOOLEAN_COMMON); - // perform CUT operation - else if (aType == BOOLEAN_CUT) { - BRep_Builder B; - TopoDS_Compound C; - B.MakeCompound(C); + if (nbShapes > 0) { + aRefShape = Handle(GEOM_Function)::DownCast(aShapes->Value(1)); + aShape = aRefShape->GetValue(); - TopTools_ListOfShape listShapes, listTools; - GEOMUtils::AddSimpleShapes(aShape1, listShapes); - GEOMUtils::AddSimpleShapes(aShape2, listTools); + if (!aShape.IsNull()) { + BRepCheck_Analyzer anAna (aShape, Standard_True); - Standard_Boolean isCompound = (listShapes.Extent() > 1); - - TopTools_ListIteratorOfListOfShape itSub1 (listShapes); - for (; itSub1.More(); itSub1.Next()) { - TopoDS_Shape aCut = itSub1.Value(); - // tools - TopTools_ListIteratorOfListOfShape itSub2 (listTools); - for (; itSub2.More(); itSub2.Next()) { - TopoDS_Shape aTool = itSub2.Value(); - BRepAlgoAPI_Cut BO (aCut, aTool); - if (!BO.IsDone()) { - StdFail_NotDone::Raise("Cut operation can not be performed on the given shapes"); + if (!anAna.IsValid()) { + StdFail_NotDone::Raise("Boolean operation will not be performed, because argument shape is not valid"); } - aCut = BO.Shape(); + + for (i = 2; i <= nbShapes; i++) { + aRefShape = Handle(GEOM_Function)::DownCast(aShapes->Value(i)); + aShape2 = aRefShape->GetValue(); + anAna.Init(aShape2); + + if (!anAna.IsValid()) { + StdFail_NotDone::Raise("Boolean operation will not be performed, because argument shape is not valid"); + } + + aShape = performOperation (aShape, aShape2, aSimpleType); + + if (aShape.IsNull()) { + return 0; + } + } + } + } + } + break; + case BOOLEAN_CUT_LIST: + { + Handle(GEOM_Function) aRefObject = aCI.GetShape1(); + + aShape = aRefObject->GetValue(); + + if (!aShape.IsNull()) { + // check arguments for Mantis issue 0021019 + BRepCheck_Analyzer anAna (aShape, Standard_True); + + if (!anAna.IsValid()) { + StdFail_NotDone::Raise("Boolean operation will not be performed, because argument shape is not valid"); + } + + Handle(TColStd_HSequenceOfTransient) aTools = aCI.GetShapes(); + const Standard_Integer nbShapes = aTools->Length(); + Standard_Integer i; + Handle(GEOM_Function) aRefTool; + TopoDS_Shape aTool; + + for (i = 1; i <= nbShapes; i++) { + aRefTool = Handle(GEOM_Function)::DownCast(aTools->Value(i)); + aTool = aRefTool->GetValue(); + anAna.Init(aTool); + + if (!anAna.IsValid()) { + StdFail_NotDone::Raise("Boolean operation will not be performed, because argument shape is not valid"); + } + + aShape = performOperation (aShape, aTool, BOOLEAN_CUT); + + if (aShape.IsNull()) { + return 0; + } + } + } + } + break; + default: + break; + } + + aFunction->SetValue(aShape); + + log.SetTouched(Label()); + + return 1; +} + +//======================================================================= +//function : performOperation +//purpose : +//======================================================================= +TopoDS_Shape GEOMImpl_BooleanDriver::performOperation + (const TopoDS_Shape theShape1, + const TopoDS_Shape theShape2, + const Standard_Integer theType)const +{ + TopoDS_Shape aShape; + + // perform COMMON operation + if (theType == BOOLEAN_COMMON) { + BRep_Builder B; + TopoDS_Compound C; + B.MakeCompound(C); + + TopTools_ListOfShape listShape1, listShape2; + GEOMUtils::AddSimpleShapes(theShape1, listShape1); + GEOMUtils::AddSimpleShapes(theShape2, listShape2); + + Standard_Boolean isCompound = + (listShape1.Extent() > 1 || listShape2.Extent() > 1); + + TopTools_ListIteratorOfListOfShape itSub1 (listShape1); + for (; itSub1.More(); itSub1.Next()) { + TopoDS_Shape aValue1 = itSub1.Value(); + TopTools_ListIteratorOfListOfShape itSub2 (listShape2); + for (; itSub2.More(); itSub2.Next()) { + TopoDS_Shape aValue2 = itSub2.Value(); + BRepAlgoAPI_Common BO (aValue1, aValue2); + if (!BO.IsDone()) { + StdFail_NotDone::Raise("Common operation can not be performed on the given shapes"); } if (isCompound) { + TopoDS_Shape aStepResult = BO.Shape(); + // check result of this step: if it is a compound (boolean operations // allways return a compound), we add all sub-shapes of it. // This allows to avoid adding empty compounds, - // resulting from CUT of parts - if (aCut.ShapeType() == TopAbs_COMPOUND) { - TopoDS_Iterator aCompIter (aCut); + // resulting from COMMON on two non-intersecting shapes. + if (aStepResult.ShapeType() == TopAbs_COMPOUND) { + TopoDS_Iterator aCompIter (aStepResult); for (; aCompIter.More(); aCompIter.Next()) { // add shape in a result B.Add(C, aCompIter.Value()); @@ -212,200 +253,163 @@ Standard_Integer GEOMImpl_BooleanDriver::Execute (TFunction_Logbook& log) const } else { // add shape in a result - B.Add(C, aCut); + B.Add(C, aStepResult); } } else - aShape = aCut; - } - - if (isCompound) { - /* - TopTools_ListOfShape listShapeC; - GEOMUtils::AddSimpleShapes(C, listShapeC); - TopTools_ListIteratorOfListOfShape itSubC (listShapeC); - bool isOnlySolids = true; - for (; itSubC.More(); itSubC.Next()) { - TopoDS_Shape aValueC = itSubC.Value(); - if (aValueC.ShapeType() != TopAbs_SOLID) isOnlySolids = false; - } - if (isOnlySolids) - aShape = GEOMImpl_GlueDriver::GlueFaces(C, Precision::Confusion()); - else - aShape = C; - */ - - // As GlueFaces has been improved to keep all kind of shapes - TopExp_Explorer anExp (C, TopAbs_VERTEX); - if (anExp.More()) - aShape = GEOMImpl_GlueDriver::GlueFaces(C, Precision::Confusion(), Standard_True); - else - aShape = C; + aShape = BO.Shape(); } } - // perform FUSE operation - else if (aType == BOOLEAN_FUSE) { - /* Fix for NPAL15379: refused - // Check arguments - TopTools_ListOfShape listShape1, listShape2; - GEOMUtils::AddSimpleShapes(aShape1, listShape1); - GEOMUtils::AddSimpleShapes(aShape2, listShape2); - - Standard_Boolean isIntersect = Standard_False; - - if (listShape1.Extent() > 1 && !isIntersect) { - // check intersections inside the first compound - TopTools_ListIteratorOfListOfShape it1 (listShape1); - for (; it1.More() && !isIntersect; it1.Next()) { - TopoDS_Shape aValue1 = it1.Value(); - TopTools_ListIteratorOfListOfShape it2 (listShape1); - for (; it2.More() && !isIntersect; it2.Next()) { - TopoDS_Shape aValue2 = it2.Value(); - if (aValue2 != aValue1) { - BRepAlgoAPI_Section BO (aValue1, aValue2); - if (BO.IsDone()) { - TopoDS_Shape aSect = BO.Shape(); - TopExp_Explorer anExp (aSect, TopAbs_EDGE); - if (anExp.More()) { - isIntersect = Standard_True; - } - } - } - } - } - } - - if (listShape2.Extent() > 1 && !isIntersect) { - // check intersections inside the second compound - TopTools_ListIteratorOfListOfShape it1 (listShape2); - for (; it1.More() && !isIntersect; it1.Next()) { - TopoDS_Shape aValue1 = it1.Value(); - TopTools_ListIteratorOfListOfShape it2 (listShape2); - for (; it2.More() && !isIntersect; it2.Next()) { - TopoDS_Shape aValue2 = it2.Value(); - if (aValue2 != aValue1) { - BRepAlgoAPI_Section BO (aValue1, aValue2); - if (BO.IsDone()) { - TopoDS_Shape aSect = BO.Shape(); - TopExp_Explorer anExp (aSect, TopAbs_EDGE); - if (anExp.More()) { - isIntersect = Standard_True; - } - } - } - } - } - } - - if (isIntersect) { - // have intersections inside compounds - // check intersections between compounds - TopTools_ListIteratorOfListOfShape it1 (listShape1); - for (; it1.More(); it1.Next()) { - TopoDS_Shape aValue1 = it1.Value(); - TopTools_ListIteratorOfListOfShape it2 (listShape2); - for (; it2.More(); it2.Next()) { - TopoDS_Shape aValue2 = it2.Value(); - if (aValue2 != aValue1) { - BRepAlgoAPI_Section BO (aValue1, aValue2); - if (BO.IsDone()) { - TopoDS_Shape aSect = BO.Shape(); - TopExp_Explorer anExp (aSect, TopAbs_EDGE); - if (anExp.More()) { - StdFail_NotDone::Raise("Bad argument for Fuse: compound with intersecting sub-shapes"); - } - } - } - } - } - } - */ - - // Perform - BRepAlgoAPI_Fuse BO (aShape1, aShape2); - if (!BO.IsDone()) { - StdFail_NotDone::Raise("Fuse operation can not be performed on the given shapes"); - } - aShape = BO.Shape(); - } - - // perform SECTION operation - else if (aType == BOOLEAN_SECTION) { - BRep_Builder B; - TopoDS_Compound C; - B.MakeCompound(C); - - TopTools_ListOfShape listShape1, listShape2; - GEOMUtils::AddSimpleShapes(aShape1, listShape1); - GEOMUtils::AddSimpleShapes(aShape2, listShape2); - - Standard_Boolean isCompound = - (listShape1.Extent() > 1 || listShape2.Extent() > 1); - - TopTools_ListIteratorOfListOfShape itSub1 (listShape1); - for (; itSub1.More(); itSub1.Next()) { - TopoDS_Shape aValue1 = itSub1.Value(); - TopTools_ListIteratorOfListOfShape itSub2 (listShape2); - for (; itSub2.More(); itSub2.Next()) { - TopoDS_Shape aValue2 = itSub2.Value(); - BRepAlgoAPI_Section BO (aValue1, aValue2, Standard_False); - // Set approximation to have an attached 3D BSpline geometry to each edge, - // where analytic curve is not possible. Without this flag in some cases - // we obtain BSpline curve of degree 1 (C0), which is slowly - // processed by some algorithms (Partition for example). - BO.Approximation(Standard_True); - //modified by NIZNHY-PKV Tue Oct 18 14:34:16 2011f - BO.ComputePCurveOn1(Standard_True); - BO.ComputePCurveOn2(Standard_True); - //modified by NIZNHY-PKV Tue Oct 18 14:34:18 2011t - - BO.Build(); - if (!BO.IsDone()) { - StdFail_NotDone::Raise("Section operation can not be performed on the given shapes"); - } - if (isCompound) { - TopoDS_Shape aStepResult = BO.Shape(); - - // check result of this step: if it is a compound (boolean operations - // allways return a compound), we add all sub-shapes of it. - // This allows to avoid adding empty compounds, - // resulting from SECTION on two non-intersecting shapes. - if (aStepResult.ShapeType() == TopAbs_COMPOUND) { - TopoDS_Iterator aCompIter (aStepResult); - for (; aCompIter.More(); aCompIter.Next()) { - // add shape in a result - B.Add(C, aCompIter.Value()); - } - } - else { - // add shape in a result - B.Add(C, aStepResult); - } - } - else - aShape = BO.Shape(); - } - } - - if (isCompound) { - //aShape = C; - - // As GlueFaces has been improved to keep all kind of shapes - TopExp_Explorer anExp (C, TopAbs_VERTEX); - if (anExp.More()) - aShape = GEOMImpl_GlueDriver::GlueFaces(C, Precision::Confusion(), Standard_True); - else - aShape = C; - } - } - - // UNKNOWN operation - else { + if (isCompound) { + // As GlueFaces has been improved to keep all kind of shapes + TopExp_Explorer anExp (C, TopAbs_VERTEX); + if (anExp.More()) + aShape = GEOMImpl_GlueDriver::GlueFaces(C, Precision::Confusion(), Standard_True); + else + aShape = C; } } - if (aShape.IsNull()) return 0; + // perform CUT operation + else if (theType == BOOLEAN_CUT) { + BRep_Builder B; + TopoDS_Compound C; + B.MakeCompound(C); + + TopTools_ListOfShape listShapes, listTools; + GEOMUtils::AddSimpleShapes(theShape1, listShapes); + GEOMUtils::AddSimpleShapes(theShape2, listTools); + + Standard_Boolean isCompound = (listShapes.Extent() > 1); + + TopTools_ListIteratorOfListOfShape itSub1 (listShapes); + for (; itSub1.More(); itSub1.Next()) { + TopoDS_Shape aCut = itSub1.Value(); + // tools + TopTools_ListIteratorOfListOfShape itSub2 (listTools); + for (; itSub2.More(); itSub2.Next()) { + TopoDS_Shape aTool = itSub2.Value(); + BRepAlgoAPI_Cut BO (aCut, aTool); + if (!BO.IsDone()) { + StdFail_NotDone::Raise("Cut operation can not be performed on the given shapes"); + } + aCut = BO.Shape(); + } + if (isCompound) { + // check result of this step: if it is a compound (boolean operations + // allways return a compound), we add all sub-shapes of it. + // This allows to avoid adding empty compounds, + // resulting from CUT of parts + if (aCut.ShapeType() == TopAbs_COMPOUND) { + TopoDS_Iterator aCompIter (aCut); + for (; aCompIter.More(); aCompIter.Next()) { + // add shape in a result + B.Add(C, aCompIter.Value()); + } + } + else { + // add shape in a result + B.Add(C, aCut); + } + } + else + aShape = aCut; + } + + if (isCompound) { + // As GlueFaces has been improved to keep all kind of shapes + TopExp_Explorer anExp (C, TopAbs_VERTEX); + if (anExp.More()) + aShape = GEOMImpl_GlueDriver::GlueFaces(C, Precision::Confusion(), Standard_True); + else + aShape = C; + } + } + + // perform FUSE operation + else if (theType == BOOLEAN_FUSE) { + // Perform + BRepAlgoAPI_Fuse BO (theShape1, theShape2); + if (!BO.IsDone()) { + StdFail_NotDone::Raise("Fuse operation can not be performed on the given shapes"); + } + aShape = BO.Shape(); + } + + // perform SECTION operation + else if (theType == BOOLEAN_SECTION) { + BRep_Builder B; + TopoDS_Compound C; + B.MakeCompound(C); + + TopTools_ListOfShape listShape1, listShape2; + GEOMUtils::AddSimpleShapes(theShape1, listShape1); + GEOMUtils::AddSimpleShapes(theShape2, listShape2); + + Standard_Boolean isCompound = + (listShape1.Extent() > 1 || listShape2.Extent() > 1); + + TopTools_ListIteratorOfListOfShape itSub1 (listShape1); + for (; itSub1.More(); itSub1.Next()) { + TopoDS_Shape aValue1 = itSub1.Value(); + TopTools_ListIteratorOfListOfShape itSub2 (listShape2); + for (; itSub2.More(); itSub2.Next()) { + TopoDS_Shape aValue2 = itSub2.Value(); + BRepAlgoAPI_Section BO (aValue1, aValue2, Standard_False); + // Set approximation to have an attached 3D BSpline geometry to each edge, + // where analytic curve is not possible. Without this flag in some cases + // we obtain BSpline curve of degree 1 (C0), which is slowly + // processed by some algorithms (Partition for example). + BO.Approximation(Standard_True); + //modified by NIZNHY-PKV Tue Oct 18 14:34:16 2011f + BO.ComputePCurveOn1(Standard_True); + BO.ComputePCurveOn2(Standard_True); + //modified by NIZNHY-PKV Tue Oct 18 14:34:18 2011t + + BO.Build(); + if (!BO.IsDone()) { + StdFail_NotDone::Raise("Section operation can not be performed on the given shapes"); + } + if (isCompound) { + TopoDS_Shape aStepResult = BO.Shape(); + + // check result of this step: if it is a compound (boolean operations + // allways return a compound), we add all sub-shapes of it. + // This allows to avoid adding empty compounds, + // resulting from SECTION on two non-intersecting shapes. + if (aStepResult.ShapeType() == TopAbs_COMPOUND) { + TopoDS_Iterator aCompIter (aStepResult); + for (; aCompIter.More(); aCompIter.Next()) { + // add shape in a result + B.Add(C, aCompIter.Value()); + } + } + else { + // add shape in a result + B.Add(C, aStepResult); + } + } + else + aShape = BO.Shape(); + } + } + + if (isCompound) { + // As GlueFaces has been improved to keep all kind of shapes + TopExp_Explorer anExp (C, TopAbs_VERTEX); + if (anExp.More()) + aShape = GEOMImpl_GlueDriver::GlueFaces(C, Precision::Confusion(), Standard_True); + else + aShape = C; + } + } + + // UNKNOWN operation + else { + } + + if (aShape.IsNull()) return aShape; // as boolean operations always produce compound, lets simplify it // for the case, if it contains only one sub-shape @@ -413,7 +417,7 @@ Standard_Integer GEOMImpl_BooleanDriver::Execute (TFunction_Logbook& log) const GEOMUtils::AddSimpleShapes(aShape, listShapeRes); if (listShapeRes.Extent() == 1) { aShape = listShapeRes.First(); - if (aShape.IsNull()) return 0; + if (aShape.IsNull()) return aShape; } // 08.07.2008 skl for bug 19761 from Mantis @@ -430,9 +434,6 @@ Standard_Integer GEOMImpl_BooleanDriver::Execute (TFunction_Logbook& log) const if (!ana.IsValid()) Standard_ConstructionError::Raise("Boolean operation aborted : non valid shape result"); } - //if (!BRepAlgo::IsValid(aShape)) { - // Standard_ConstructionError::Raise("Boolean operation aborted : non valid shape result"); - //} // BEGIN: Mantis issue 0021060: always limit tolerance of BOP result // 1. Get shape parameters for comparison @@ -506,24 +507,9 @@ Standard_Integer GEOMImpl_BooleanDriver::Execute (TFunction_Logbook& log) const } // END: Mantis issue 0021060 - //Alternative case to check shape result Mantis 0020604: EDF 1172 -/* TopoDS_Iterator It (aShape, Standard_True, Standard_True); - int nbSubshapes=0; - for (; It.More(); It.Next()) - nbSubshapes++; - if (!nbSubshapes) - Standard_ConstructionError::Raise("Boolean operation aborted : result object is empty compound");*/ - //end of 0020604: EDF 1172 - //! the changes temporary commented because of customer needs (see the same mantis bug) - - aFunction->SetValue(aShape); - - log.SetTouched(Label()); - - return 1; + return aShape; } - //======================================================================= //function : GEOMImpl_BooleanDriver_Type_ //purpose : diff --git a/src/GEOMImpl/GEOMImpl_BooleanDriver.hxx b/src/GEOMImpl/GEOMImpl_BooleanDriver.hxx index 80e57116c..6bc1af7f2 100644 --- a/src/GEOMImpl/GEOMImpl_BooleanDriver.hxx +++ b/src/GEOMImpl/GEOMImpl_BooleanDriver.hxx @@ -51,6 +51,11 @@ #include #endif +#ifndef _TopoDS_Shape_HeaderFile +#include +#endif + + class Standard_Transient; class Handle_Standard_Type; class Handle(TFunction_Driver); @@ -156,6 +161,12 @@ Standard_EXPORT const Handle(Standard_Type)& DynamicType() const { return STAND Standard_EXPORT Standard_Boolean IsKind(const Handle(Standard_Type)& AType) const { return (STANDARD_TYPE(GEOMImpl_BooleanDriver) == AType || TFunction_Driver::IsKind(AType)); } +private: + + TopoDS_Shape performOperation(const TopoDS_Shape theShape1, + const TopoDS_Shape theShape2, + const Standard_Integer theType) const; + }; #endif diff --git a/src/GEOMImpl/GEOMImpl_IBoolean.hxx b/src/GEOMImpl/GEOMImpl_IBoolean.hxx index 54c246740..46d5c8e48 100644 --- a/src/GEOMImpl/GEOMImpl_IBoolean.hxx +++ b/src/GEOMImpl/GEOMImpl_IBoolean.hxx @@ -23,9 +23,11 @@ //NOTE: This is an intreface to a function for the Common, Cut and Fuse creation. // #include "GEOM_Function.hxx" +#include "TColStd_HSequenceOfTransient.hxx" #define BOOL_ARG_SHAPE1 1 #define BOOL_ARG_SHAPE2 2 +#define BOOL_ARG_SHAPES 3 class GEOMImpl_IBoolean { @@ -35,9 +37,13 @@ class GEOMImpl_IBoolean void SetShape1(Handle(GEOM_Function) theRef) { _func->SetReference(BOOL_ARG_SHAPE1, theRef); } void SetShape2(Handle(GEOM_Function) theRef) { _func->SetReference(BOOL_ARG_SHAPE2, theRef); } + void SetShapes(const Handle(TColStd_HSequenceOfTransient)& theShapes) + { _func->SetReferenceList(BOOL_ARG_SHAPES, theShapes); } Handle(GEOM_Function) GetShape1() { return _func->GetReference(BOOL_ARG_SHAPE1); } Handle(GEOM_Function) GetShape2() { return _func->GetReference(BOOL_ARG_SHAPE2); } + Handle(TColStd_HSequenceOfTransient) GetShapes() + { return _func->GetReferenceList(BOOL_ARG_SHAPES); } private: diff --git a/src/GEOMImpl/GEOMImpl_IBooleanOperations.cxx b/src/GEOMImpl/GEOMImpl_IBooleanOperations.cxx index 3db2537ec..a96b1810b 100644 --- a/src/GEOMImpl/GEOMImpl_IBooleanOperations.cxx +++ b/src/GEOMImpl/GEOMImpl_IBooleanOperations.cxx @@ -139,6 +139,185 @@ Handle(GEOM_Object) GEOMImpl_IBooleanOperations::MakeBoolean (Handle(GEOM_Object return aBool; } +//============================================================================= +/*! + * MakeFuseList + */ +//============================================================================= +Handle(GEOM_Object) GEOMImpl_IBooleanOperations::MakeFuseList + (const Handle(TColStd_HSequenceOfTransient)& theShapes) +{ + SetErrorCode(KO); + + if (theShapes.IsNull()) return NULL; + + //Add a new Boolean object + Handle(GEOM_Object) aBool = GetEngine()->AddObject(GetDocID(), GEOM_BOOLEAN); + + //Add a new Boolean function + Handle(GEOM_Function) aFunction = + aBool->AddFunction(GEOMImpl_BooleanDriver::GetID(), BOOLEAN_FUSE_LIST); + + if (aFunction.IsNull()) return NULL; + + //Check if the function is set correctly + if (aFunction->GetDriverGUID() != GEOMImpl_BooleanDriver::GetID()) return NULL; + + GEOMImpl_IBoolean aCI (aFunction); + + TCollection_AsciiString aDescription; + Handle(TColStd_HSequenceOfTransient) aShapesSeq = + getShapeFunctions(theShapes, aDescription); + + if (aShapesSeq.IsNull()) return NULL; + + aCI.SetShapes(aShapesSeq); + + //Compute the Boolean value + try { +#if OCC_VERSION_LARGE > 0x06010000 + OCC_CATCH_SIGNALS; +#endif + if (!GetSolver()->ComputeFunction(aFunction)) { + SetErrorCode("Boolean driver failed"); + return NULL; + } + } + catch (Standard_Failure) { + Handle(Standard_Failure) aFail = Standard_Failure::Caught(); + SetErrorCode(aFail->GetMessageString()); + return NULL; + } + + //Make a Python command + GEOM::TPythonDump(aFunction) << aBool << + " = geompy.MakeFuseList([" << aDescription.ToCString() << "])"; + + SetErrorCode(OK); + return aBool; +} + +//============================================================================= +/*! + * MakeCommonList + */ +//============================================================================= +Handle(GEOM_Object) GEOMImpl_IBooleanOperations::MakeCommonList + (const Handle(TColStd_HSequenceOfTransient)& theShapes) +{ + SetErrorCode(KO); + + if (theShapes.IsNull()) return NULL; + + //Add a new Boolean object + Handle(GEOM_Object) aBool = GetEngine()->AddObject(GetDocID(), GEOM_BOOLEAN); + + //Add a new Boolean function + Handle(GEOM_Function) aFunction = + aBool->AddFunction(GEOMImpl_BooleanDriver::GetID(), BOOLEAN_COMMON_LIST); + + if (aFunction.IsNull()) return NULL; + + //Check if the function is set correctly + if (aFunction->GetDriverGUID() != GEOMImpl_BooleanDriver::GetID()) return NULL; + + GEOMImpl_IBoolean aCI (aFunction); + + TCollection_AsciiString aDescription; + Handle(TColStd_HSequenceOfTransient) aShapesSeq = + getShapeFunctions(theShapes, aDescription); + + if (aShapesSeq.IsNull()) return NULL; + + aCI.SetShapes(aShapesSeq); + + //Compute the Boolean value + try { +#if OCC_VERSION_LARGE > 0x06010000 + OCC_CATCH_SIGNALS; +#endif + if (!GetSolver()->ComputeFunction(aFunction)) { + SetErrorCode("Boolean driver failed"); + return NULL; + } + } + catch (Standard_Failure) { + Handle(Standard_Failure) aFail = Standard_Failure::Caught(); + SetErrorCode(aFail->GetMessageString()); + return NULL; + } + + //Make a Python command + GEOM::TPythonDump(aFunction) << aBool << + " = geompy.MakeCommonList([" << aDescription.ToCString() << "])"; + + SetErrorCode(OK); + return aBool; +} + +//============================================================================= +/*! + * MakeCutList + */ +//============================================================================= +Handle(GEOM_Object) GEOMImpl_IBooleanOperations::MakeCutList + (Handle(GEOM_Object) theMainShape, + const Handle(TColStd_HSequenceOfTransient)& theShapes) +{ + SetErrorCode(KO); + + if (theShapes.IsNull()) return NULL; + + //Add a new Boolean object + Handle(GEOM_Object) aBool = GetEngine()->AddObject(GetDocID(), GEOM_BOOLEAN); + + //Add a new Boolean function + Handle(GEOM_Function) aFunction = + aBool->AddFunction(GEOMImpl_BooleanDriver::GetID(), BOOLEAN_CUT_LIST); + + if (aFunction.IsNull()) return NULL; + + //Check if the function is set correctly + if (aFunction->GetDriverGUID() != GEOMImpl_BooleanDriver::GetID()) return NULL; + + GEOMImpl_IBoolean aCI (aFunction); + Handle(GEOM_Function) aMainRef = theMainShape->GetLastFunction(); + + if (aMainRef.IsNull()) return NULL; + + TCollection_AsciiString aDescription; + Handle(TColStd_HSequenceOfTransient) aShapesSeq = + getShapeFunctions(theShapes, aDescription); + + if (aShapesSeq.IsNull()) return NULL; + + aCI.SetShape1(aMainRef); + aCI.SetShapes(aShapesSeq); + + //Compute the Boolean value + try { +#if OCC_VERSION_LARGE > 0x06010000 + OCC_CATCH_SIGNALS; +#endif + if (!GetSolver()->ComputeFunction(aFunction)) { + SetErrorCode("Boolean driver failed"); + return NULL; + } + } + catch (Standard_Failure) { + Handle(Standard_Failure) aFail = Standard_Failure::Caught(); + SetErrorCode(aFail->GetMessageString()); + return NULL; + } + + //Make a Python command + GEOM::TPythonDump(aFunction) << aBool << " = geompy.MakeCutList(" + << theMainShape << ", [" << aDescription.ToCString() << "])"; + + SetErrorCode(OK); + return aBool; +} + //============================================================================= /*! * MakePartition @@ -173,85 +352,47 @@ Handle(GEOM_Object) GEOMImpl_IBooleanOperations::MakePartition GEOMImpl_IPartition aCI (aFunction); - Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient; - Handle(TColStd_HSequenceOfTransient) aToolsSeq = new TColStd_HSequenceOfTransient; - Handle(TColStd_HSequenceOfTransient) aKeepInsSeq = new TColStd_HSequenceOfTransient; - Handle(TColStd_HSequenceOfTransient) aRemInsSeq = new TColStd_HSequenceOfTransient; - - Standard_Integer ind, aLen; - TCollection_AsciiString anEntry; + Handle(TColStd_HSequenceOfTransient) aShapesSeq; + Handle(TColStd_HSequenceOfTransient) aToolsSeq; + Handle(TColStd_HSequenceOfTransient) aKeepInsSeq; + Handle(TColStd_HSequenceOfTransient) aRemInsSeq; TCollection_AsciiString aShapesDescr, aToolsDescr, aKeepInsDescr, aRemoveInsDescr; // Shapes - aLen = theShapes->Length(); - for (ind = 1; ind <= aLen; ind++) { - Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(theShapes->Value(ind)); - Handle(GEOM_Function) aRefSh = anObj->GetLastFunction(); - if (aRefSh.IsNull()) { - SetErrorCode("NULL shape for Partition"); - return NULL; - } - aShapesSeq->Append(aRefSh); + aShapesSeq = getShapeFunctions(theShapes, aShapesDescr); - // For Python command - TDF_Tool::Entry(anObj->GetEntry(), anEntry); - if (ind > 1) aShapesDescr += ", "; - aShapesDescr += anEntry; + if (aShapesSeq.IsNull()) { + SetErrorCode("NULL shape for Partition"); + return NULL; } - aCI.SetShapes(aShapesSeq); // Tools - aLen = theTools->Length(); - for (ind = 1; ind <= aLen; ind++) { - Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(theTools->Value(ind)); - Handle(GEOM_Function) aRefSh = anObj->GetLastFunction(); - if (aRefSh.IsNull()) { - SetErrorCode("NULL tool shape for Partition"); - return NULL; - } - aToolsSeq->Append(aRefSh); + aToolsSeq = getShapeFunctions(theTools, aToolsDescr); - // For Python command - TDF_Tool::Entry(anObj->GetEntry(), anEntry); - if (ind > 1) aToolsDescr += ", "; - aToolsDescr += anEntry; + if (aToolsSeq.IsNull()) { + SetErrorCode("NULL tool shape for Partition"); + return NULL; } - aCI.SetTools(aToolsSeq); // Keep Inside - aLen = theKeepIns->Length(); - for (ind = 1; ind <= aLen; ind++) { - Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(theKeepIns->Value(ind)); - Handle(GEOM_Function) aRefSh = anObj->GetLastFunction(); - if (aRefSh.IsNull()) { - SetErrorCode("NULL shape for Partition"); - return NULL; - } - aKeepInsSeq->Append(aRefSh); + aKeepInsSeq = getShapeFunctions(theKeepIns, aKeepInsDescr); - // For Python command - TDF_Tool::Entry(anObj->GetEntry(), anEntry); - if (ind > 1) aKeepInsDescr += ", "; - aKeepInsDescr += anEntry; + if (aKeepInsSeq.IsNull()) { + SetErrorCode("NULL shape for Partition"); + return NULL; } - aCI.SetKeepIns(aKeepInsSeq); // Remove Inside - aLen = theRemoveIns->Length(); - for (ind = 1; ind <= aLen; ind++) { - Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(theRemoveIns->Value(ind)); - Handle(GEOM_Function) aRefSh = anObj->GetLastFunction(); - if (aRefSh.IsNull()) { - SetErrorCode("NULL shape for Partition"); - return NULL; - } - aRemInsSeq->Append(aRefSh); + aRemInsSeq = getShapeFunctions(theRemoveIns, aRemoveInsDescr); - // For Python command - TDF_Tool::Entry(anObj->GetEntry(), anEntry); - if (ind > 1) aRemoveInsDescr += ", "; - aRemoveInsDescr += anEntry; + if (aRemInsSeq.IsNull()) { + SetErrorCode("NULL shape for Partition"); + return NULL; } + + aCI.SetShapes(aShapesSeq); + aCI.SetTools(aToolsSeq); + aCI.SetKeepIns(aKeepInsSeq); aCI.SetRemoveIns(aRemInsSeq); // Limit @@ -370,3 +511,46 @@ Handle(GEOM_Object) GEOMImpl_IBooleanOperations::MakeHalfPartition SetErrorCode(OK); return aPart; } + +//============================================================================= +/*! + * getShapeFunctions + */ +//============================================================================= +Handle(TColStd_HSequenceOfTransient) + GEOMImpl_IBooleanOperations::getShapeFunctions + (const Handle(TColStd_HSequenceOfTransient)& theObjects, + TCollection_AsciiString &theDescription) +{ + Handle(TColStd_HSequenceOfTransient) aResult = + new TColStd_HSequenceOfTransient; + Standard_Integer aNbObjects = theObjects->Length(); + Standard_Integer i; + TCollection_AsciiString anEntry; + Handle(GEOM_Object) anObj; + Handle(GEOM_Function) aRefObj; + + // Shapes + for (i = 1; i <= aNbObjects; i++) { + anObj = Handle(GEOM_Object)::DownCast(theObjects->Value(i)); + aRefObj = anObj->GetLastFunction(); + + if (aRefObj.IsNull()) { + aResult.Nullify(); + break; + } + + aResult->Append(aRefObj); + + // For Python command + TDF_Tool::Entry(anObj->GetEntry(), anEntry); + + if (i > 1) { + theDescription += ", "; + } + + theDescription += anEntry; + } + + return aResult; +} diff --git a/src/GEOMImpl/GEOMImpl_IBooleanOperations.hxx b/src/GEOMImpl/GEOMImpl_IBooleanOperations.hxx index ff93dcc89..c1c492c47 100644 --- a/src/GEOMImpl/GEOMImpl_IBooleanOperations.hxx +++ b/src/GEOMImpl/GEOMImpl_IBooleanOperations.hxx @@ -40,6 +40,16 @@ class GEOMImpl_IBooleanOperations : public GEOM_IOperations { Handle(GEOM_Object) theShape2, Standard_Integer theOp); + Standard_EXPORT Handle(GEOM_Object) MakeFuseList + (const Handle(TColStd_HSequenceOfTransient)& theShapes); + + Standard_EXPORT Handle(GEOM_Object) MakeCommonList + (const Handle(TColStd_HSequenceOfTransient)& theShapes); + + Standard_EXPORT Handle(GEOM_Object) MakeCutList + (Handle(GEOM_Object) theMainShape, + const Handle(TColStd_HSequenceOfTransient)& theShapes); + Standard_EXPORT Handle(GEOM_Object) MakePartition (const Handle(TColStd_HSequenceOfTransient)& theShapes, const Handle(TColStd_HSequenceOfTransient)& theTools, @@ -53,6 +63,13 @@ class GEOMImpl_IBooleanOperations : public GEOM_IOperations { Standard_EXPORT Handle(GEOM_Object) MakeHalfPartition (Handle(GEOM_Object) theShape, Handle(GEOM_Object) thePlane); + +private: + + Handle(TColStd_HSequenceOfTransient) getShapeFunctions + (const Handle(TColStd_HSequenceOfTransient)& theObjects, + TCollection_AsciiString &theDescription); + }; #endif diff --git a/src/GEOMImpl/GEOMImpl_Types.hxx b/src/GEOMImpl/GEOMImpl_Types.hxx index 8f85c2ac4..b00671937 100755 --- a/src/GEOMImpl/GEOMImpl_Types.hxx +++ b/src/GEOMImpl/GEOMImpl_Types.hxx @@ -229,10 +229,13 @@ #define THRUSECTIONS_RULED 1 #define THRUSECTIONS_SMOOTHED 2 -#define BOOLEAN_COMMON 1 -#define BOOLEAN_CUT 2 -#define BOOLEAN_FUSE 3 -#define BOOLEAN_SECTION 4 +#define BOOLEAN_COMMON 1 +#define BOOLEAN_CUT 2 +#define BOOLEAN_FUSE 3 +#define BOOLEAN_SECTION 4 +#define BOOLEAN_COMMON_LIST 5 +#define BOOLEAN_CUT_LIST 6 +#define BOOLEAN_FUSE_LIST 7 #define PARTITION_PARTITION 1 #define PARTITION_HALF 2 diff --git a/src/GEOM_I/GEOM_IBooleanOperations_i.cc b/src/GEOM_I/GEOM_IBooleanOperations_i.cc index 6afade797..2cad84b5d 100644 --- a/src/GEOM_I/GEOM_IBooleanOperations_i.cc +++ b/src/GEOM_I/GEOM_IBooleanOperations_i.cc @@ -85,6 +85,100 @@ GEOM::GEOM_Object_ptr GEOM_IBooleanOperations_i::MakeBoolean return GetObject(anObject); } +//============================================================================= +/*! + * MakeFuseList + */ +//============================================================================= +GEOM::GEOM_Object_ptr GEOM_IBooleanOperations_i::MakeFuseList + (const GEOM::ListOfGO& theShapes) +{ + GEOM::GEOM_Object_var aGEOMObject; + + //Set a not done flag + GetOperations()->SetNotDone(); + + Handle(TColStd_HSequenceOfTransient) aShapes = + GetListOfObjectsImpl(theShapes); + + if (aShapes.IsNull()) { + return aGEOMObject._retn(); + } + + // Make fusion + Handle(GEOM_Object) anObject = GetOperations()->MakeFuseList(aShapes); + + if (!GetOperations()->IsDone() || anObject.IsNull()) + return aGEOMObject._retn(); + + return GetObject(anObject); +} + +//============================================================================= +/*! + * MakeCommonList + */ +//============================================================================= +GEOM::GEOM_Object_ptr GEOM_IBooleanOperations_i::MakeCommonList + (const GEOM::ListOfGO& theShapes) +{ + GEOM::GEOM_Object_var aGEOMObject; + + //Set a not done flag + GetOperations()->SetNotDone(); + + Handle(TColStd_HSequenceOfTransient) aShapes = + GetListOfObjectsImpl(theShapes); + + if (aShapes.IsNull()) { + return aGEOMObject._retn(); + } + + // Make fusion + Handle(GEOM_Object) anObject = GetOperations()->MakeCommonList(aShapes); + + if (!GetOperations()->IsDone() || anObject.IsNull()) + return aGEOMObject._retn(); + + return GetObject(anObject); +} + +//============================================================================= +/*! + * MakeCutList + */ +//============================================================================= +GEOM::GEOM_Object_ptr GEOM_IBooleanOperations_i::MakeCutList + (GEOM::GEOM_Object_ptr theMainShape, + const GEOM::ListOfGO& theShapes) +{ + GEOM::GEOM_Object_var aGEOMObject; + + //Set a not done flag + GetOperations()->SetNotDone(); + + Handle(GEOM_Object) aMainShape = GetObjectImpl(theMainShape); + + if (aMainShape.IsNull()) { + return aGEOMObject._retn(); + } + + Handle(TColStd_HSequenceOfTransient) aShapes = + GetListOfObjectsImpl(theShapes); + + if (aShapes.IsNull()) { + return aGEOMObject._retn(); + } + + // Make fusion + Handle(GEOM_Object) anObject = GetOperations()->MakeCutList(aMainShape, aShapes); + + if (!GetOperations()->IsDone() || anObject.IsNull()) + return aGEOMObject._retn(); + + return GetObject(anObject); +} + //============================================================================= /*! * MakePartition @@ -105,47 +199,20 @@ GEOM::GEOM_Object_ptr GEOM_IBooleanOperations_i::MakePartition //Set a not done flag GetOperations()->SetNotDone(); - int ind, aLen; - Handle(TColStd_HSequenceOfTransient) aShapes = new TColStd_HSequenceOfTransient; - Handle(TColStd_HSequenceOfTransient) aTools = new TColStd_HSequenceOfTransient; - Handle(TColStd_HSequenceOfTransient) aKeepIns = new TColStd_HSequenceOfTransient; - Handle(TColStd_HSequenceOfTransient) aRemIns = new TColStd_HSequenceOfTransient; + Handle(TColStd_HSequenceOfTransient) aShapes = GetListOfObjectsImpl(theShapes); + Handle(TColStd_HSequenceOfTransient) aTools = GetListOfObjectsImpl(theTools); + Handle(TColStd_HSequenceOfTransient) aKeepIns = GetListOfObjectsImpl(theKeepIns); + Handle(TColStd_HSequenceOfTransient) aRemIns = GetListOfObjectsImpl(theRemoveIns); Handle(TColStd_HArray1OfInteger) aMaterials; - //Get the shapes - aLen = theShapes.length(); - for (ind = 0; ind < aLen; ind++) { - Handle(GEOM_Object) aSh = GetObjectImpl(theShapes[ind]); - if (aSh.IsNull()) return aGEOMObject._retn(); - aShapes->Append(aSh); - } - - //Get the tools - aLen = theTools.length(); - for (ind = 0; ind < aLen; ind++) { - Handle(GEOM_Object) aSh = GetObjectImpl(theTools[ind]); - if (aSh.IsNull()) return aGEOMObject._retn(); - aTools->Append(aSh); - } - - //Get the keep inside shapes - aLen = theKeepIns.length(); - for (ind = 0; ind < aLen; ind++) { - Handle(GEOM_Object) aSh = GetObjectImpl(theKeepIns[ind]); - if (aSh.IsNull()) return aGEOMObject._retn(); - aKeepIns->Append(aSh); - } - - //Get the remove inside shapes - aLen = theRemoveIns.length(); - for (ind = 0; ind < aLen; ind++) { - Handle(GEOM_Object) aSh = GetObjectImpl(theRemoveIns[ind]); - if (aSh.IsNull()) return aGEOMObject._retn(); - aRemIns->Append(aSh); + if (aShapes.IsNull() || aTools.IsNull() || + aKeepIns.IsNull() || aRemIns.IsNull()) { + return aGEOMObject._retn(); } //Get the materials - aLen = theMaterials.length(); + int ind; + int aLen = theMaterials.length(); if ( aLen ) { aMaterials = new TColStd_HArray1OfInteger (1, aLen); for (ind = 0; ind < aLen; ind++) { @@ -185,47 +252,20 @@ GEOM::GEOM_Object_ptr GEOM_IBooleanOperations_i::MakePartitionNonSelfIntersected //Set a not done flag GetOperations()->SetNotDone(); - int ind, aLen; - Handle(TColStd_HSequenceOfTransient) aShapes = new TColStd_HSequenceOfTransient; - Handle(TColStd_HSequenceOfTransient) aTools = new TColStd_HSequenceOfTransient; - Handle(TColStd_HSequenceOfTransient) aKeepIns = new TColStd_HSequenceOfTransient; - Handle(TColStd_HSequenceOfTransient) aRemIns = new TColStd_HSequenceOfTransient; + Handle(TColStd_HSequenceOfTransient) aShapes = GetListOfObjectsImpl(theShapes); + Handle(TColStd_HSequenceOfTransient) aTools = GetListOfObjectsImpl(theTools); + Handle(TColStd_HSequenceOfTransient) aKeepIns = GetListOfObjectsImpl(theKeepIns); + Handle(TColStd_HSequenceOfTransient) aRemIns = GetListOfObjectsImpl(theRemoveIns); Handle(TColStd_HArray1OfInteger) aMaterials; - //Get the shapes - aLen = theShapes.length(); - for (ind = 0; ind < aLen; ind++) { - Handle(GEOM_Object) aSh = GetObjectImpl(theShapes[ind]); - if (aSh.IsNull()) return aGEOMObject._retn(); - aShapes->Append(aSh); - } - - //Get the tools - aLen = theTools.length(); - for (ind = 0; ind < aLen; ind++) { - Handle(GEOM_Object) aSh = GetObjectImpl(theTools[ind]); - if (aSh.IsNull()) return aGEOMObject._retn(); - aTools->Append(aSh); - } - - //Get the keep inside shapes - aLen = theKeepIns.length(); - for (ind = 0; ind < aLen; ind++) { - Handle(GEOM_Object) aSh = GetObjectImpl(theKeepIns[ind]); - if (aSh.IsNull()) return aGEOMObject._retn(); - aKeepIns->Append(aSh); - } - - //Get the remove inside shapes - aLen = theRemoveIns.length(); - for (ind = 0; ind < aLen; ind++) { - Handle(GEOM_Object) aSh = GetObjectImpl(theRemoveIns[ind]); - if (aSh.IsNull()) return aGEOMObject._retn(); - aRemIns->Append(aSh); + if (aShapes.IsNull() || aTools.IsNull() || + aKeepIns.IsNull() || aRemIns.IsNull()) { + return aGEOMObject._retn(); } //Get the materials - aLen = theMaterials.length(); + int ind; + int aLen = theMaterials.length(); if ( aLen ) { aMaterials = new TColStd_HArray1OfInteger (1, aLen); for (ind = 0; ind < aLen; ind++) { diff --git a/src/GEOM_I/GEOM_IBooleanOperations_i.hh b/src/GEOM_I/GEOM_IBooleanOperations_i.hh index 81885d879..3150fcd56 100644 --- a/src/GEOM_I/GEOM_IBooleanOperations_i.hh +++ b/src/GEOM_I/GEOM_IBooleanOperations_i.hh @@ -46,6 +46,13 @@ class GEOM_I_EXPORT GEOM_IBooleanOperations_i : GEOM::GEOM_Object_ptr theShape2, CORBA::Long theOp); + GEOM::GEOM_Object_ptr MakeFuseList (const GEOM::ListOfGO& theShapes); + + GEOM::GEOM_Object_ptr MakeCommonList (const GEOM::ListOfGO& theShapes); + + GEOM::GEOM_Object_ptr MakeCutList (GEOM::GEOM_Object_ptr theMainShape, + const GEOM::ListOfGO& theShapes); + GEOM::GEOM_Object_ptr MakePartition (const GEOM::ListOfGO& theShapes, const GEOM::ListOfGO& theTools, const GEOM::ListOfGO& theKeepInside, diff --git a/src/GEOM_I/GEOM_IOperations_i.cc b/src/GEOM_I/GEOM_IOperations_i.cc index 090bf8e82..059e751ae 100644 --- a/src/GEOM_I/GEOM_IOperations_i.cc +++ b/src/GEOM_I/GEOM_IOperations_i.cc @@ -160,6 +160,34 @@ Handle(GEOM_Object) GEOM_IOperations_i::GetObjectImpl(GEOM::GEOM_Object_ptr theO return anImpl; } +//============================================================================= +/*! + * GetListOfObjectsImpl + */ +//============================================================================= +Handle(TColStd_HSequenceOfTransient) GEOM_IOperations_i::GetListOfObjectsImpl + (const GEOM::ListOfGO& theObjects) +{ + Handle(TColStd_HSequenceOfTransient) aResult = + new TColStd_HSequenceOfTransient; + + int i; + int aNbObj = theObjects.length(); + + for (i = 0; i < aNbObj; i++) { + Handle(GEOM_Object) anObj = GetObjectImpl(theObjects[i]); + + if (anObj.IsNull()) { + aResult.Nullify(); + break; + } + + aResult->Append(anObj); + } + + return aResult; +} + //============================================================================= /*! * UpdateGUIForObject diff --git a/src/GEOM_I/GEOM_IOperations_i.hh b/src/GEOM_I/GEOM_IOperations_i.hh index 8fa579842..4d8757cd8 100644 --- a/src/GEOM_I/GEOM_IOperations_i.hh +++ b/src/GEOM_I/GEOM_IOperations_i.hh @@ -50,6 +50,9 @@ class GEOM_I_EXPORT GEOM_IOperations_i : public virtual POA_GEOM::GEOM_IOperatio virtual GEOM::GEOM_Object_ptr GetObject(Handle(GEOM_Object) theObject); virtual Handle(GEOM_Object) GetObjectImpl(GEOM::GEOM_Object_ptr theObject); + virtual Handle(TColStd_HSequenceOfTransient) + GetListOfObjectsImpl(const GEOM::ListOfGO& theObjects); + virtual void StartOperation(); virtual void FinishOperation(); diff --git a/src/GEOM_SWIG/GEOM_TestOthers.py b/src/GEOM_SWIG/GEOM_TestOthers.py index 8fa5964b5..0a8ab0413 100644 --- a/src/GEOM_SWIG/GEOM_TestOthers.py +++ b/src/GEOM_SWIG/GEOM_TestOthers.py @@ -163,17 +163,29 @@ def TestOtherOperations (geompy, math): id_Orientation = geompy.addToStudy(Orientation, "OrientationChange") # MakeCommon, MakeCut, MakeFuse, MakeSection + p1 = geompy.MakeVertex(60, 120, 0) + p2 = geompy.MakeVertex( 0, 0, 0) + v = geompy.MakeVector(p1, p2) + height = 90 + radius1 = 50 + cylinder = geompy.MakeCylinder(p1, v, radius1, height) Sphere = geompy.MakeSphereR(100) - Common = geompy.MakeCommon (Box, Sphere) - Cut = geompy.MakeCut (Box, Sphere) - Fuse = geompy.MakeFuse (Box, Sphere) - Section = geompy.MakeSection(Box, Sphere) + Common1 = geompy.MakeCommon (Box, Sphere) + Cut1 = geompy.MakeCut (Box, Sphere) + Fuse1 = geompy.MakeFuse (Box, Sphere) + Section = geompy.MakeSection (Box, Sphere) + Common2 = geompy.MakeCommonList([Box, Sphere, cylinder]) + Cut2 = geompy.MakeCutList (Box, [Sphere, cylinder]) + Fuse2 = geompy.MakeFuseList ([Box, Sphere, cylinder]) - id_Common = geompy.addToStudy(Common, "Common") - id_Cut = geompy.addToStudy(Cut, "Cut") - id_Fuse = geompy.addToStudy(Fuse, "Fuse") + id_Common1 = geompy.addToStudy(Common1, "Common_1") + id_Cut1 = geompy.addToStudy(Cut1, "Cut_1") + id_Fuse1 = geompy.addToStudy(Fuse1, "Fuse_1") id_Section = geompy.addToStudy(Section, "Section") + id_Common2 = geompy.addToStudy(Common2, "Common_2") + id_Cut2 = geompy.addToStudy(Cut2, "Cut_2") + id_Fuse2 = geompy.addToStudy(Fuse2, "Fuse_2") # Partition p100 = geompy.MakeVertex(100, 100, 100) @@ -713,10 +725,9 @@ def TestOtherOperations (geompy, math): sph2 = geompy.MakeSphere(50, 50, -50, 40) pcyl = geompy.MakeVertex(50, 50, -50) cyli = geompy.MakeCylinder(pcyl, vz, 40, 100) - fuse = geompy.MakeFuse(sph1, cyli) - sh_1 = geompy.MakeFuse(fuse, sph2) + sh_1 = geompy.MakeFuseList([sph1, cyli, sph2]) # As after Fuse we have a compound, we need to obtain a solid from it - #shsh = geompy.SubShapeAll(fuse, geompy.ShapeType["SOLID"]) + #shsh = geompy.SubShapeAll(sh_1, geompy.ShapeType["SOLID"]) #sh_1 = shsh[0] geompy.addToStudy(sh_1, "sh_1") diff --git a/src/GEOM_SWIG/geomBuilder.py b/src/GEOM_SWIG/geomBuilder.py index 6b9058dbd..28dab6b5e 100644 --- a/src/GEOM_SWIG/geomBuilder.py +++ b/src/GEOM_SWIG/geomBuilder.py @@ -6637,6 +6637,98 @@ class geomBuilder(object, GEOM._objref_GEOM_Gen): # note: auto-publishing is done in self.MakeBoolean() return self.MakeBoolean(theShape1, theShape2, 4, theName) + ## Perform Fuse boolean operation on the list of shapes. + # @param theShapesList Shapes to be fused. + # @param theName Object name; when specified, this parameter is used + # for result publication in the study. Otherwise, if automatic + # publication is switched on, default value is used for result name. + # + # @return New GEOM.GEOM_Object, containing the result shape. + # + # @ref tui_fuse "Example 1" + # \n @ref swig_MakeCommon "Example 2" + def MakeFuseList(self, theShapesList, theName=None): + """ + Perform Fuse boolean operation on the list of shapes. + + Parameters: + theShapesList Shapes to be fused. + theName Object name; when specified, this parameter is used + for result publication in the study. Otherwise, if automatic + publication is switched on, default value is used for result name. + + Returns: + New GEOM.GEOM_Object, containing the result shape. + + """ + # Example: see GEOM_TestOthers.py + anObj = self.BoolOp.MakeFuseList(theShapesList) + RaiseIfFailed("MakeFuseList", self.BoolOp) + self._autoPublish(anObj, theName, "fuse") + return anObj + + ## Perform Common boolean operation on the list of shapes. + # @param theShapesList Shapes for Common operation. + # @param theName Object name; when specified, this parameter is used + # for result publication in the study. Otherwise, if automatic + # publication is switched on, default value is used for result name. + # + # @return New GEOM.GEOM_Object, containing the result shape. + # + # @ref tui_common "Example 1" + # \n @ref swig_MakeCommon "Example 2" + def MakeCommonList(self, theShapesList, theName=None): + """ + Perform Common boolean operation on the list of shapes. + + Parameters: + theShapesList Shapes for Common operation. + theName Object name; when specified, this parameter is used + for result publication in the study. Otherwise, if automatic + publication is switched on, default value is used for result name. + + Returns: + New GEOM.GEOM_Object, containing the result shape. + + """ + # Example: see GEOM_TestOthers.py + anObj = self.BoolOp.MakeCommonList(theShapesList) + RaiseIfFailed("MakeCommonList", self.BoolOp) + self._autoPublish(anObj, theName, "common") + return anObj + + ## Perform Cut boolean operation on one object and the list of tools. + # @param theMainShape The object of the operation. + # @param theShapesList The list of tools of the operation. + # @param theName Object name; when specified, this parameter is used + # for result publication in the study. Otherwise, if automatic + # publication is switched on, default value is used for result name. + # + # @return New GEOM.GEOM_Object, containing the result shape. + # + # @ref tui_cut "Example 1" + # \n @ref swig_MakeCommon "Example 2" + def MakeCutList(self, theMainShape, theShapesList, theName=None): + """ + Perform Cut boolean operation on one object and the list of tools. + + Parameters: + theMainShape The object of the operation. + theShapesList The list of tools of the operation. + theName Object name; when specified, this parameter is used + for result publication in the study. Otherwise, if automatic + publication is switched on, default value is used for result name. + + Returns: + New GEOM.GEOM_Object, containing the result shape. + + """ + # Example: see GEOM_TestOthers.py + anObj = self.BoolOp.MakeCutList(theMainShape, theShapesList) + RaiseIfFailed("MakeCutList", self.BoolOp) + self._autoPublish(anObj, theName, "cut") + return anObj + # end of l3_boolean ## @}