diff --git a/doc/salome/examples/topological_geom_objs_ex03.py b/doc/salome/examples/topological_geom_objs_ex03.py index 972d81a6f..6d9d5d43f 100644 --- a/doc/salome/examples/topological_geom_objs_ex03.py +++ b/doc/salome/examples/topological_geom_objs_ex03.py @@ -30,6 +30,10 @@ sketcher2 = geompy.MakeSketcher("Sketcher:F 0 0:TT 70 0:TT 70 70:TT 0 70:WW") sketcher3 = geompy.MakeSketcher("Sketcher:F 20 20:TT 50 20:TT 50 50:TT 20 50:WW") isPlanarFace = 1 +sphere = geompy.MakeSphereR(100) +box = geompy.MakeBoxDXDYDZ(200, 200, 200) +cut = geompy.MakeCutList(sphere, [box], True) + # create a face from the wire face1 = geompy.MakeFace(wire, isPlanarFace) @@ -38,11 +42,17 @@ face2 = geompy.MakeFaceWires([wire, sketcher1],isPlanarFace) face3 = geompy.MakeFaces([sketcher2, sketcher3],isPlanarFace) face4 = geompy.MakeFaceFromSurface(face1, sketcher1) +# create face from edges with constraints +face5 = geompy.MakeFaceWithConstraints([geompy.GetSubShape(cut, [5]), geompy.GetSubShape(cut, [3]), + geompy.GetSubShape(cut, [11]), geompy.GetSubShape(cut, [3]), + geompy.GetSubShape(cut, [13]), geompy.GetSubShape(cut, [3])]) + # add objects in the study id_face1 = geompy.addToStudy(face1,"Face1") id_face2 = geompy.addToStudy(face2,"Face2") id_face3 = geompy.addToStudy(face3,"Face3") id_face4 = geompy.addToStudy(face4,"Face4") +id_face5 = geompy.addToStudy(face5,"Face5") # display the faces gg.createAndDisplayGO(id_face1) @@ -57,3 +67,6 @@ gg.setTransparency(id_face3,0.2) gg.createAndDisplayGO(id_face4) gg.setDisplayMode(id_face4,1) gg.setTransparency(id_face4,0.2) +gg.createAndDisplayGO(id_face5) +gg.setDisplayMode(id_face5,1) +gg.setTransparency(id_face5,0.2) diff --git a/doc/salome/gui/GEOM/images/neo-obj4.png b/doc/salome/gui/GEOM/images/neo-obj4.png index 9b0f84c13..63ce57d1d 100755 Binary files a/doc/salome/gui/GEOM/images/neo-obj4.png and b/doc/salome/gui/GEOM/images/neo-obj4.png differ diff --git a/doc/salome/gui/GEOM/images/neo-obj4_2.png b/doc/salome/gui/GEOM/images/neo-obj4_2.png index 233aa6fb4..07f3a9de4 100644 Binary files a/doc/salome/gui/GEOM/images/neo-obj4_2.png and b/doc/salome/gui/GEOM/images/neo-obj4_2.png differ diff --git a/doc/salome/gui/GEOM/images/neo-obj4_3.png b/doc/salome/gui/GEOM/images/neo-obj4_3.png new file mode 100644 index 000000000..f819ed4ca Binary files /dev/null and b/doc/salome/gui/GEOM/images/neo-obj4_3.png differ diff --git a/doc/salome/gui/GEOM/input/creating_face.doc b/doc/salome/gui/GEOM/input/creating_face.doc index 9f31c4d04..cb626f83d 100644 --- a/doc/salome/gui/GEOM/input/creating_face.doc +++ b/doc/salome/gui/GEOM/input/creating_face.doc @@ -5,7 +5,7 @@ To create a \b Face in the Main Menu select New Entity - > Build - > Face -There are two algorithms to create a \b Face. In both cases the \b Result +There are three algorithms to create a \b Face. In all cases the \b Result of the operation will be a GEOM_Object (FACE). \n Firstly, to create a \b Face you need to select input shape(s). The list of @@ -20,14 +20,18 @@ that can be interpreted as an outer one; other wires can be considered as inner ones. \n Check Try to create a planar face to create a planar face or nothing if it is impossible. -\note Please note, that the resulting face can have a huge tolerance, if the initial wire has a big deviation from the plane. If the final tolerance exceeds 1e-06, a warning will be shown, but the face will be created and published in the study in a normal way. Using such faces can lead to failures or unpredictable results in most operations. +\note Please note, that the resulting face can have a huge tolerance, if +the initial wire has a big deviation from the plane. If the final tolerance +exceeds 1e-06, a warning will be shown, but the face will be created +and published in the study in a normal way. Using such faces can lead to failures +or unpredictable results in most operations. \n The \b Result will be a \b GEOM_Object (FACE). \n TUI Command: geompy.MakeFaceWires([list of Shapes], isPlanarWanted) \n Arguments: Name + 1 wire. -\image html neo-obj4.png +\image html neo-obj4.png "Create face by input shape(s)" \n Secondly, it is possible to create a face based on another face's surface and bounded by a wire. @@ -36,7 +40,24 @@ face or nothing if it is impossible. \n TUI Command: geompy.MakeFaceFromSurface(theFace, theWire) \n Arguments: Name + 1 face + 1 wire. -\image html neo-obj4_2.png +\image html neo-obj4_2.png "Create face by another face's surface" + +Thirdly, it is possible to create a \b Face by specifying a set of edges forming a closed wire +and constraints: +- Specify an input wire by selecting it in the object browser or in the viewer. + The input wire will be exploded on edges which will be shown in the \b Constraints list box. +- Specify constraints by associating faces with the edges. + +\note Please note, that the constraint face must be connected to a reference edge. + +\n The \b Result will be a \b GEOM_Object (FACE). + +\n TUI Command: geompy.MakeFaceWithConstraints([List of constraints]) +\n Arguments: Name + List of input edges and constraint faces. If a constraint +face is missing for some edge, this means that there is no constraint associated to this edge. +\note Set of edges should form a closed wire. + +\image html neo-obj4_3.png "Create face by a wire and its constraints" \n Example: @@ -46,7 +67,7 @@ face or nothing if it is impossible. \image html facesn3.png "Examples of faces" -Our TUI Scripts provide you with useful examples of creation of +Our TUI Scripts provide you with useful examples of creation of \ref tui_creation_face "Advanced Geometric Objects". */ diff --git a/idl/GEOM_Gen.idl b/idl/GEOM_Gen.idl index 83faa46bb..0880b9fd6 100644 --- a/idl/GEOM_Gen.idl +++ b/idl/GEOM_Gen.idl @@ -1938,6 +1938,16 @@ module GEOM GEOM_Object MakeFaceFromSurface(in GEOM_Object theFace, in GEOM_Object theWire); + /*! + * \brief Create a face from a set of edges with the given constraints. + * \param theConstraints List of edges and constraint faces (as a sequence of a Edge + Face couples): + * - edges should form a closed wire; + * - for each edge, constraint face is optional: if a constraint face is missing + * for some edge, this means that there no constraint associated with this edge. + * \return New GEOM_Object, containing the created face. + */ + GEOM_Object MakeFaceWithConstraints(in ListOfGO theConstraints); + /*! * \brief Create a shell from the set of faces and shells. * \param theFacesAndShells List of faces and/or shells. @@ -2165,6 +2175,23 @@ module GEOM */ string GetShapeTypeString (in GEOM_Object theShape); + /*! + * \brief Check if the object is a sub-object of another GEOM object. + * + * \param theSubObject Checked sub-object (or its parent object, in case if + * \a theSubObjectIndex is non-zero). + * \param theSubObjectIndex When non-zero, specifies a sub-shape index that + * identifies a sub-object within its parent specified via \a theSubObject. + * \param theObject An object that is checked for ownership (or its parent object, + * in case if \a theObjectIndex is non-zero). + * \param theObjectIndex When non-zero, specifies a sub-shape index that + * identifies an object within its parent specified via \a theObject. + * \return TRUE, if the given object contains sub-object. + */ + boolean IsSubShapeBelongsTo( in GEOM_Object theSubObject, + in long theSubObjectIndex, + in GEOM_Object theObject, + in long theObjectIndex); /*! * \brief Count number of faces in the given shape. * \param theShape Shape to count faces in. diff --git a/idl/GEOM_Superv.idl b/idl/GEOM_Superv.idl index 4843422c5..de885b9b3 100644 --- a/idl/GEOM_Superv.idl +++ b/idl/GEOM_Superv.idl @@ -391,6 +391,7 @@ module GEOM in boolean isPlanarWanted) ; GEOM_Object MakeFaceWires (in GEOM_List theWires, in boolean isPlanarWanted) ; + GEOM_Object MakeFaceWithConstraints(in GEOM_List theConstraints); GEOM_Object MakeShell (in GEOM_List theFacesAndShells) ; GEOM_Object MakeSolidShell (in GEOM_Object theShell) ; GEOM_Object MakeSolidShells (in GEOM_List theShells) ; diff --git a/resources/CMakeLists.txt b/resources/CMakeLists.txt index 49a7e5362..d887216b3 100755 --- a/resources/CMakeLists.txt +++ b/resources/CMakeLists.txt @@ -55,6 +55,7 @@ SET( _res_files build_edge_curve.png build_face.png build_face_surface.png + build_face_constraints.png build_shell.png build_solid.png build_wire.png diff --git a/resources/GEOMCatalog.xml.in b/resources/GEOMCatalog.xml.in index eeed1d6b1..7ccc9c80c 100644 --- a/resources/GEOMCatalog.xml.in +++ b/resources/GEOMCatalog.xml.in @@ -4283,6 +4283,28 @@ + + MakeFaceWithConstraints + SALOME team + @SALOMEGEOM_VERSION@ + unknown + 0 + + + theConstraints + GEOM/GEOM_List + unknown + + + + + return + GEOM/GEOM_Object + unknown + + + + MakeSolidShell SALOME team diff --git a/resources/build_face_constraints.png b/resources/build_face_constraints.png new file mode 100644 index 000000000..81cab3b87 Binary files /dev/null and b/resources/build_face_constraints.png differ diff --git a/src/BuildGUI/BuildGUI_FaceDlg.cxx b/src/BuildGUI/BuildGUI_FaceDlg.cxx index c1a1ade02..adb886262 100644 --- a/src/BuildGUI/BuildGUI_FaceDlg.cxx +++ b/src/BuildGUI/BuildGUI_FaceDlg.cxx @@ -41,6 +41,62 @@ #include #include +#include + +//================================================================================= +// class : BuildGUI_TreeWidgetItem +// purpose : class for constraint(Edge-Face) creation +//================================================================================= +class BuildGUI_FaceDlg::TreeWidgetItem : public QTreeWidgetItem +{ +public: + TreeWidgetItem( QTreeWidget*, const GEOM::GeomObjPtr, int = Type ); + TreeWidgetItem( QTreeWidgetItem*, const GEOM::GeomObjPtr, int = Type ); + ~TreeWidgetItem(); + void setFace( const GEOM::GeomObjPtr ); + GEOM::GeomObjPtr getFace() const; + GEOM::GeomObjPtr getEdge() const; +private: + GEOM::GeomObjPtr myEdge; + GEOM::GeomObjPtr myFace; +}; + +BuildGUI_FaceDlg::TreeWidgetItem::TreeWidgetItem( QTreeWidget* view, const GEOM::GeomObjPtr edge, int type ) +:QTreeWidgetItem( view, QStringList()<resizeColumnToContents(1); + myFace = face; +} + +GEOM::GeomObjPtr BuildGUI_FaceDlg::TreeWidgetItem::getFace() const +{ + return myFace; +} + +GEOM::GeomObjPtr BuildGUI_FaceDlg::TreeWidgetItem::getEdge() const +{ + return myEdge; +} + //================================================================================= // class : BuildGUI_FaceDlg() // purpose : Constructs a BuildGUI_FaceDlg which is a child of 'parent', with the @@ -50,12 +106,14 @@ //================================================================================= BuildGUI_FaceDlg::BuildGUI_FaceDlg( GeometryGUI* theGeometryGUI, QWidget* parent ) : GEOMBase_Skeleton( theGeometryGUI, parent ), - GroupWire (0), - myGroupSurf (0) + myGroupWire(0), + myGroupSurf(0), + myGroupWireConstraints(0) { QPixmap image0( SUIT_Session::session()->resourceMgr()->loadPixmap( "GEOM", tr( "ICON_SELECT" ) ) ); QPixmap image1( SUIT_Session::session()->resourceMgr()->loadPixmap( "GEOM", tr( "ICON_DLG_BUILD_FACE" ) ) ); QPixmap image2( SUIT_Session::session()->resourceMgr()->loadPixmap( "GEOM", tr( "ICON_DLG_BUILD_FACE_SURFACE" ) ) ); + QPixmap image3( SUIT_Session::session()->resourceMgr()->loadPixmap( "GEOM", tr( "ICON_DLG_BUILD_FACE_CONSTRAINTS" ) ) ); setWindowTitle( tr( "GEOM_FACE_TITLE" ) ); @@ -63,15 +121,18 @@ BuildGUI_FaceDlg::BuildGUI_FaceDlg( GeometryGUI* theGeometryGUI, QWidget* parent mainFrame()->GroupConstructors->setTitle( tr( "GEOM_FACE" ) ); mainFrame()->RadioButton1->setIcon( image1 ); mainFrame()->RadioButton2->setIcon( image2 ); - mainFrame()->RadioButton3->setAttribute( Qt::WA_DeleteOnClose ); - mainFrame()->RadioButton3->close(); + mainFrame()->RadioButton3->setIcon( image3 ); - GroupWire = new DlgRef_1Sel1Check( centralWidget() ); + // Face creation from wires and/or edges - GroupWire->GroupBox1->setTitle( tr( "GEOM_FACE_FFW" ) ); - GroupWire->TextLabel1->setText( tr( "GEOM_OBJECTS" ) ); - GroupWire->CheckButton1->setText( tr( "GEOM_FACE_OPT" ) ); - GroupWire->PushButton1->setIcon( image0 ); + myGroupWire = new DlgRef_1Sel1Check( centralWidget() ); + + myGroupWire->GroupBox1->setTitle( tr( "GEOM_FACE_FFW" ) ); + myGroupWire->TextLabel1->setText( tr( "GEOM_OBJECTS" ) ); + myGroupWire->CheckButton1->setText( tr( "GEOM_FACE_OPT" ) ); + myGroupWire->PushButton1->setIcon( image0 ); + + // Face creation from surface myGroupSurf = new DlgRef_2Sel(centralWidget()); @@ -80,11 +141,35 @@ BuildGUI_FaceDlg::BuildGUI_FaceDlg( GeometryGUI* theGeometryGUI, QWidget* parent myGroupSurf->TextLabel2->setText(tr("GEOM_WIRE")); myGroupSurf->PushButton1->setIcon(image0); myGroupSurf->PushButton2->setIcon(image0); + + // Face creation from wire and constraints + + myGroupWireConstraints = new DlgRef_1SelExt( centralWidget() ); + myGroupWireConstraints->GroupBox1->setTitle( tr( "GEOM_FACE_FFWC" ) ); + myGroupWireConstraints->TextLabel1->setText( tr( "GEOM_WIRE" ) ); + myGroupWireConstraints->PushButton1->setIcon( image0 ); + + QLabel* aLabel = new QLabel( tr( "GEOM_CONSTRAINTS" ) ); + myTreeConstraints = new QTreeWidget( myGroupWireConstraints->Box ); + myTreeConstraints->setColumnCount(2); + QStringList columnNames; + columnNames.append( tr( "GEOM_EDGE" )); + columnNames.append( tr( "GEOM_FACE_CONSTRAINT" ) ); + myTreeConstraints->setHeaderLabels( columnNames ); + myTreeConstraints->header()->setMovable( false ); + myTreeConstraints->header()->setResizeMode( QHeaderView::ResizeToContents ); + myTreeConstraints->setMinimumHeight( 140 ); + + QHBoxLayout* l = new QHBoxLayout( myGroupWireConstraints->Box ); + l->setMargin( 0 ); l->setSpacing( 6 ); + l->addWidget( aLabel); + l->addWidget( myTreeConstraints ); QVBoxLayout* layout = new QVBoxLayout( centralWidget() ); layout->setMargin( 0 ); layout->setSpacing( 6 ); - layout->addWidget( GroupWire ); - layout->addWidget(myGroupSurf); + layout->addWidget( myGroupWire ); + layout->addWidget( myGroupSurf ); + layout->addWidget( myGroupWireConstraints ); /***************************************************************/ setHelpFileName("create_face_page.html"); @@ -111,33 +196,39 @@ BuildGUI_FaceDlg::~BuildGUI_FaceDlg() void BuildGUI_FaceDlg::Init() { /* init variables */ - myEditCurrentArgument = GroupWire->LineEdit1; - GroupWire->LineEdit1->setReadOnly( true ); + myEditCurrentArgument = myGroupWire->LineEdit1; + myGroupWire->LineEdit1->setReadOnly( true ); myGroupSurf->LineEdit1->setReadOnly( true ); myGroupSurf->LineEdit2->setReadOnly( true ); + myGroupWireConstraints->LineEdit1->setReadOnly( true ); - GroupWire->CheckButton1->setChecked( true ); + myGroupWire->CheckButton1->setChecked( true ); myWires.clear(); myFace.nullify(); myWire.nullify(); + myCurrentItem = 0; /* signals and slots connections */ connect(myGeomGUI, SIGNAL(SignalDeactivateActiveDialog()), this, SLOT(DeactivateActiveDialog())); connect(myGeomGUI, SIGNAL(SignalCloseAllDialogs()), this, SLOT(ClickOnCancel())); - connect(this, SIGNAL(constructorsClicked(int)), this, SLOT(ConstructorsClicked(int))); + connect(this, SIGNAL( constructorsClicked( int ) ), this, SLOT( ConstructorsClicked( int ) ) ); connect( buttonOk(), SIGNAL( clicked() ), this, SLOT( ClickOnOk() ) ); connect( buttonApply(), SIGNAL( clicked() ), this, SLOT( ClickOnApply() ) ); - connect( GroupWire->LineEdit1, SIGNAL( returnPressed()), this, SLOT( LineEditReturnPressed() ) ); - connect( GroupWire->PushButton1, SIGNAL( clicked() ), this, SLOT( SetEditCurrentArgument() ) ); + connect( myGroupWire->LineEdit1, SIGNAL( returnPressed()), this, SLOT( LineEditReturnPressed() ) ); + connect( myGroupWire->PushButton1, SIGNAL( clicked() ), this, SLOT( SetEditCurrentArgument() ) ); connect( myGroupSurf->LineEdit1, SIGNAL( returnPressed()), this, SLOT( LineEditReturnPressed() ) ); connect( myGroupSurf->PushButton1, SIGNAL( clicked() ), this, SLOT( SetEditCurrentArgument() ) ); connect( myGroupSurf->LineEdit2, SIGNAL( returnPressed()), this, SLOT( LineEditReturnPressed() ) ); connect( myGroupSurf->PushButton2, SIGNAL( clicked() ), this, SLOT( SetEditCurrentArgument() ) ); + connect( myGroupWireConstraints->LineEdit1, SIGNAL( returnPressed() ), this, SLOT( LineEditReturnPressed() ) ); + connect( myGroupWireConstraints->PushButton1, SIGNAL( clicked() ), this, SLOT( SetEditCurrentArgument() ) ); connect( ( (SalomeApp_Application*)( SUIT_Session::session()->activeApplication() ) )->selectionMgr(), SIGNAL( currentSelectionChanged() ), this, SLOT( SelectionIntoArgument() ) ); + connect( myTreeConstraints, SIGNAL( itemClicked( QTreeWidgetItem*, int) ), this, SLOT( onItemClicked( QTreeWidgetItem*, int ) ) ); + initName( tr( "GEOM_FACE" ) ); ConstructorsClicked(0); @@ -162,22 +253,40 @@ void BuildGUI_FaceDlg::ConstructorsClicked(int constructorId) aMap.Add(GEOM_COMPOUND); globalSelection(aMap); - myEditCurrentArgument = GroupWire->LineEdit1; - GroupWire->LineEdit1->setText(""); - GroupWire->show(); + myEditCurrentArgument = myGroupWire->LineEdit1; + myGroupWire->LineEdit1->setText(""); + myGroupWire->show(); myGroupSurf->hide(); + myGroupWireConstraints->hide(); break; } case 1: { globalSelection(GEOM_FACE); // For the first element. + localSelection( GEOM::GEOM_Object::_nil(), TopAbs_FACE ); myEditCurrentArgument = myGroupSurf->LineEdit1; myGroupSurf->LineEdit1->setText(""); myGroupSurf->PushButton1->setDown(true); myGroupSurf->PushButton2->setDown(false); - GroupWire->hide(); + myGroupWire->hide(); myGroupSurf->show(); + myGroupWireConstraints->hide(); + break; + } + case 2: + { + globalSelection(); + localSelection( GEOM::GEOM_Object::_nil(), TopAbs_WIRE ); + + myTreeConstraints->clear(); + myCurrentItem = 0; + myEditCurrentArgument = myGroupWireConstraints->LineEdit1; + myGroupWireConstraints->LineEdit1->setText(""); + myGroupWireConstraints->LineEdit1->setEnabled(true); + myGroupWire->hide(); + myGroupSurf->hide(); + myGroupWireConstraints->show(); break; } } @@ -191,6 +300,84 @@ void BuildGUI_FaceDlg::ConstructorsClicked(int constructorId) SelectionIntoArgument(); } +//================================================================================= +// function : updateConstraintsTree +// purpose : +//================================================================================= +void BuildGUI_FaceDlg::updateConstraintsTree() +{ + if ( myEditCurrentArgument != myGroupWireConstraints->LineEdit1 || myWire.isNull() ) + return; + + myTreeConstraints->clear(); + + GEOM::GEOM_IShapesOperations_ptr anOper = GEOM::GEOM_IShapesOperations::_narrow(getOperation()); + GEOM::ListOfGO_var aList = anOper->ExtractSubShapes( myWire.get(), TopAbs_EDGE, false ); + if ( !aList->length() ) + return; + + for ( int i = 0, n = aList->length(); i < n; i++ ) { + TreeWidgetItem* item = new TreeWidgetItem( myTreeConstraints, + GEOM::GeomObjPtr( aList[i] ) ); + } + + myEditCurrentArgument->setEnabled(false); + globalSelection(); + localSelection( GEOM::GEOM_Object::_nil(), TopAbs_FACE ); + + myTreeConstraints->resizeColumnToContents(0); + QTreeWidgetItem* firstItem = myTreeConstraints->topLevelItem(0); + firstItem->setSelected( true ); + onItemClicked( firstItem, 0 ); +} + +//================================================================================= +// function : findEmptyTreeItem() +// purpose : +//================================================================================= +void BuildGUI_FaceDlg::findEmptyTreeItem() +{ + if ( isTreeFull() ) + return; + + QTreeWidgetItem* nextItem = 0; + QTreeWidgetItem* item; + for ( item = myTreeConstraints->itemBelow( myCurrentItem ); + item && !nextItem; + item = myTreeConstraints->itemBelow( item ) ) { + if ( (dynamic_cast(item))->getFace().isNull() ) + nextItem = item; + } + for ( item = myTreeConstraints->topLevelItem(0); + item && item != myCurrentItem && !nextItem; + item = myTreeConstraints->itemBelow( item ) ) { + if ( (dynamic_cast(item))->getFace().isNull() ) + nextItem = item; + } + + if ( nextItem && nextItem != myCurrentItem ) { + myCurrentItem->setSelected( false ); + nextItem->setSelected( true ); + onItemClicked( nextItem, 0 ); + } +} + +//================================================================================= +// function : isTreeFull() +// purpose : +//================================================================================= +bool BuildGUI_FaceDlg::isTreeFull() +{ + bool ok = true; + QTreeWidgetItem* item; + for ( item = myTreeConstraints->topLevelItem(0); + item && ok; + item = myTreeConstraints->itemBelow( item ) ) { + ok = !(dynamic_cast(item))->getFace().isNull(); + } + return ok; +} + //================================================================================= // function : ClickOnOk() // purpose : @@ -213,6 +400,9 @@ bool BuildGUI_FaceDlg::ClickOnApply() return false; initName(); + + myEditCurrentArgument->setText(""); + ConstructorsClicked( getConstructorId() ); return true; } @@ -223,7 +413,8 @@ bool BuildGUI_FaceDlg::ClickOnApply() //================================================================================= void BuildGUI_FaceDlg::SelectionIntoArgument() { - if (myEditCurrentArgument == GroupWire->LineEdit1) { + erasePreview(); + if ( myEditCurrentArgument == myGroupWire->LineEdit1 ) { myEditCurrentArgument->setText( "" ); QList types; @@ -235,8 +426,9 @@ void BuildGUI_FaceDlg::SelectionIntoArgument() QString aName = myWires.count() > 1 ? QString( "%1_objects").arg( myWires.count() ) : GEOMBase::GetName( myWires[0].get() ); myEditCurrentArgument->setText( aName ); } - } else if (myEditCurrentArgument == myGroupSurf->LineEdit1 || - myEditCurrentArgument == myGroupSurf->LineEdit2) { + } + else if (myEditCurrentArgument == myGroupSurf->LineEdit1 || + myEditCurrentArgument == myGroupSurf->LineEdit2) { const bool isEditFace = myEditCurrentArgument == myGroupSurf->LineEdit1; const TopAbs_ShapeEnum aType = isEditFace ? TopAbs_FACE : TopAbs_WIRE; GEOM::GeomObjPtr aSelectedObject = getSelected(aType); @@ -260,8 +452,39 @@ void BuildGUI_FaceDlg::SelectionIntoArgument() } } } - - displayPreview(true); + else if ( myEditCurrentArgument == myGroupWireConstraints->LineEdit1 ) { + if ( myCurrentItem ) { + GEOM::GeomObjPtr aSelectedObject = getSelected( TopAbs_FACE ); + TopoDS_Shape aFaceShape; + GEOM::GEOM_IShapesOperations_ptr anOper = GEOM::GEOM_IShapesOperations::_narrow(getOperation()); + if ( aSelectedObject && GEOMBase::GetShape( aSelectedObject.get(), aFaceShape ) && !aFaceShape.IsNull() + && anOper->IsSubShapeBelongsTo( myCurrentItem->getEdge().get(), 0, aSelectedObject.get(), 0 ) ) { + myCurrentItem->setFace( aSelectedObject ); + findEmptyTreeItem(); + } + else { + myCurrentItem->setFace( 0 ); + displayPreview( myCurrentItem->getEdge().get(), true, false, true, 5, -1, Quantity_NOC_RED ); + } + } + else { + myWire.nullify(); + myEditCurrentArgument->setText( "" ); + GEOM::GeomObjPtr aSelectedObject = getSelected( TopAbs_WIRE ); + TopoDS_Shape aWireShape; + if ( aSelectedObject && GEOMBase::GetShape( aSelectedObject.get(), aWireShape ) && !aWireShape.IsNull() ) { + QString aName = GEOMBase::GetName( aSelectedObject.get() ); + myEditCurrentArgument->setText( aName ); + myWire = aSelectedObject; + updateConstraintsTree(); + } + else { + myTreeConstraints->clear(); + erasePreview( true ); + } + } + } + displayPreview( true, false, true, true, -1, -1, -1, true ); } @@ -272,7 +495,7 @@ void BuildGUI_FaceDlg::SelectionIntoArgument() void BuildGUI_FaceDlg::SetEditCurrentArgument() { QPushButton* send = (QPushButton*)sender(); - if (send == GroupWire->PushButton1) { + if ( send == myGroupWire->PushButton1 ) { TColStd_MapOfInteger aMap; aMap.Add(GEOM_EDGE); @@ -282,26 +505,33 @@ void BuildGUI_FaceDlg::SetEditCurrentArgument() aMap.Add(GEOM_SOLID); aMap.Add(GEOM_COMPOUND); globalSelection(aMap); - myEditCurrentArgument = GroupWire->LineEdit1; + myEditCurrentArgument = myGroupWire->LineEdit1; } else if (send == myGroupSurf->PushButton1) { globalSelection(GEOM_FACE); + localSelection( GEOM::GEOM_Object::_nil(), TopAbs_FACE ); myEditCurrentArgument = myGroupSurf->LineEdit1; myGroupSurf->PushButton2->setDown(false); myGroupSurf->LineEdit2->setEnabled(false); } else if (send == myGroupSurf->PushButton2) { globalSelection(GEOM_WIRE); + localSelection( GEOM::GEOM_Object::_nil(), TopAbs_WIRE ); myEditCurrentArgument = myGroupSurf->LineEdit2; myGroupSurf->PushButton1->setDown(false); myGroupSurf->LineEdit1->setEnabled(false); } + else if (send == myGroupWireConstraints->PushButton1) { + globalSelection(); + localSelection( GEOM::GEOM_Object::_nil(), TopAbs_WIRE ); + myEditCurrentArgument = myGroupWireConstraints->LineEdit1; + myCurrentItem = 0; + } // enable line edit myEditCurrentArgument->setEnabled(true); myEditCurrentArgument->setFocus(); - send->setDown(true); - displayPreview(true); + SelectionIntoArgument(); } @@ -320,6 +550,19 @@ void BuildGUI_FaceDlg::ActivateThisDialog() ConstructorsClicked(getConstructorId()); } +//================================================================================= +// function : onItemClicked() +// purpose : called when tree item was clicked +//================================================================================= +void BuildGUI_FaceDlg::onItemClicked( QTreeWidgetItem* theItem, int theColumn ) +{ + if ( !theItem || !( theItem->flags() & Qt::ItemIsSelectable ) ) + return; + + myCurrentItem = dynamic_cast( theItem ); + displayPreview( true ); + displayPreview( myCurrentItem->getEdge().get(), true, false, true, 5, -1, Quantity_NOC_RED ); +} //================================================================================= // function : enterEvent() @@ -355,6 +598,9 @@ bool BuildGUI_FaceDlg::isValid( QString& ) case 1: ok = myFace && myWire; break; + case 2: + ok = myWire; + break; default: break; } @@ -383,13 +629,30 @@ bool BuildGUI_FaceDlg::execute( ObjectList& objects ) objlist[i] = myWires[i].copy(); } - anObj = anOper->MakeFaceWires( objlist.in(), GroupWire->CheckButton1->isChecked() ); - res = true; + anObj = anOper->MakeFaceWires( objlist.in(), myGroupWire->CheckButton1->isChecked() ); + res = true; } break; case 1: anObj = anOper->MakeFaceFromSurface(myFace.get(), myWire.get()); - res = true; + res = true; + break; + case 2: + { + int numberOfItems = myTreeConstraints->topLevelItemCount(); + GEOM::ListOfGO_var constraints = new GEOM::ListOfGO(); + constraints->length( 2 * numberOfItems ); + int j = 0; + for ( int i = 0; i < numberOfItems; i++ ) { + TreeWidgetItem* item = dynamic_cast( myTreeConstraints->topLevelItem(i) ); + constraints[j++] = item->getEdge().copy(); + if ( item->getFace() ) + constraints[j++] = item->getFace().copy(); + } + constraints->length(j); + anObj = anOper->MakeFaceWithConstraints( constraints.in() ); + res = true; + } break; default: break; @@ -398,14 +661,40 @@ bool BuildGUI_FaceDlg::execute( ObjectList& objects ) if (!anObj->_is_nil()) { objects.push_back(anObj._retn()); - if (!anOper->IsDone() && QString(anOper->GetErrorCode()) == "MAKE_FACE_TOLERANCE_TOO_BIG") { - SUIT_OverrideCursor wc; - wc.suspend(); - QString msgw = QObject::tr(anOper->GetErrorCode()); - SUIT_MessageBox::warning(this, tr("WRN_WARNING"), msgw, tr("BUT_OK")); + if ( !anOper->IsDone() && QString(anOper->GetErrorCode()) == "MAKE_FACE_TOLERANCE_TOO_BIG") { + if ( !IsPreview() ) { + SUIT_OverrideCursor wc; + wc.suspend(); + QString msgw = QObject::tr(anOper->GetErrorCode()); + SUIT_MessageBox::warning(this, tr("WRN_WARNING"), msgw, tr("BUT_OK")); + } anOper->SetErrorCode("PAL_NO_ERROR"); } } return res; } + +//================================================================================= +// function : addSubshapeToStudy +// purpose : virtual method to add new SubObjects if local selection +//================================================================================= +void BuildGUI_FaceDlg::addSubshapesToStudy() +{ + switch (getConstructorId()) { + case 0: + break; + case 1: + break; + case 2: + for( int i = 0; i < myTreeConstraints->topLevelItemCount(); i++ ) { + TreeWidgetItem* item = dynamic_cast( myTreeConstraints->topLevelItem(i) ); + if ( item->getFace().get() ) + GEOMBase::PublishSubObject( item->getFace().get() ); + GEOMBase::PublishSubObject( myWire.get() ); + } + break; + default: + break; + } +} diff --git a/src/BuildGUI/BuildGUI_FaceDlg.h b/src/BuildGUI/BuildGUI_FaceDlg.h index 29e152781..929630f58 100644 --- a/src/BuildGUI/BuildGUI_FaceDlg.h +++ b/src/BuildGUI/BuildGUI_FaceDlg.h @@ -32,6 +32,9 @@ class DlgRef_1Sel1Check; class DlgRef_2Sel; +class DlgRef_1SelExt; +class QTreeWidget; +class QTreeWidgetItem; //================================================================================= // class : BuildGUI_FaceDlg @@ -41,6 +44,8 @@ class BuildGUI_FaceDlg : public GEOMBase_Skeleton { Q_OBJECT + class TreeWidgetItem; + public: BuildGUI_FaceDlg( GeometryGUI*, QWidget* = 0 ); ~BuildGUI_FaceDlg(); @@ -50,26 +55,35 @@ protected: virtual GEOM::GEOM_IOperations_ptr createOperation(); virtual bool isValid( QString& ); virtual bool execute( ObjectList& ); + virtual void addSubshapesToStudy(); private: void Init(); void enterEvent( QEvent* ); + void updateConstraintsTree(); + void findEmptyTreeItem(); + bool isTreeFull(); private: QList myWires; GEOM::GeomObjPtr myFace; GEOM::GeomObjPtr myWire; - DlgRef_1Sel1Check* GroupWire; + DlgRef_1Sel1Check* myGroupWire; DlgRef_2Sel* myGroupSurf; + DlgRef_1SelExt* myGroupWireConstraints; + + QTreeWidget* myTreeConstraints; + TreeWidgetItem* myCurrentItem; private slots: - void ConstructorsClicked (int); + void ConstructorsClicked( int ); void ClickOnOk(); bool ClickOnApply(); void ActivateThisDialog(); void SelectionIntoArgument(); void SetEditCurrentArgument(); + void onItemClicked( QTreeWidgetItem*, int ); }; #endif // BUILDGUI_FACEDLG_H diff --git a/src/GEOMBase/GEOMBase_Helper.cxx b/src/GEOMBase/GEOMBase_Helper.cxx index 037fd087a..439bfe7ee 100755 --- a/src/GEOMBase/GEOMBase_Helper.cxx +++ b/src/GEOMBase/GEOMBase_Helper.cxx @@ -259,7 +259,8 @@ void GEOMBase_Helper::displayPreview( const bool display, const bool toRemoveFromEngine, const double lineWidth, const int displayMode, - const int color ) + const int color, + const bool append ) { if(!display) { erasePreview( update ); @@ -275,7 +276,8 @@ void GEOMBase_Helper::displayPreview( const bool display, return; } - erasePreview( false ); + if( !append ) + erasePreview( false ); try { SUIT_OverrideCursor wc; diff --git a/src/GEOMBase/GEOMBase_Helper.h b/src/GEOMBase/GEOMBase_Helper.h index 731b63d06..1878610e2 100755 --- a/src/GEOMBase/GEOMBase_Helper.h +++ b/src/GEOMBase/GEOMBase_Helper.h @@ -79,7 +79,8 @@ protected: const bool toRemoveFromEngine = true, const double lineWidth = -1, const int displayMode = -1, - const int color = -1 ); + const int color = -1, + const bool append = false ); // This is the easiest way to show preview. It is based on execute() method. // It removes temporary GEOM::GEOM_Objects automatically. diff --git a/src/GEOMGUI/GEOM_images.ts b/src/GEOMGUI/GEOM_images.ts index 14cf841bc..8b6d59b49 100644 --- a/src/GEOMGUI/GEOM_images.ts +++ b/src/GEOMGUI/GEOM_images.ts @@ -163,6 +163,10 @@ ICON_DLG_BUILD_FACE_SURFACE build_face_surface.png + + ICON_DLG_BUILD_FACE_CONSTRAINTS + build_face_constraints.png + ICON_DLG_FACE_HW face_hw.png diff --git a/src/GEOMGUI/GEOM_msg_en.ts b/src/GEOMGUI/GEOM_msg_en.ts index e3c19fbe2..b5e65a385 100644 --- a/src/GEOMGUI/GEOM_msg_en.ts +++ b/src/GEOMGUI/GEOM_msg_en.ts @@ -707,6 +707,18 @@ Please, select face, shell or solid and try again GEOM_FACE_OPT Try to create a planar face + + GEOM_FACE_FFWC + Face creation from wire and constraints + + + GEOM_CONSTRAINTS + Constraints + + + GEOM_FACE_CONSTRAINT + Constraint Face + GEOM_SOLID_FROM_FACE_OPT Intersect shapes diff --git a/src/GEOMGUI/GEOM_msg_fr.ts b/src/GEOMGUI/GEOM_msg_fr.ts index 037d015c5..0d42a5b67 100644 --- a/src/GEOMGUI/GEOM_msg_fr.ts +++ b/src/GEOMGUI/GEOM_msg_fr.ts @@ -723,6 +723,18 @@ Choisissez une face, une coque ou un solide et essayez de nouveau GEOM_FACE_OPT Privilégier la création d'une face plane + + GEOM_FACE_FFWC + Face creation from wire and constraints + + + GEOM_CONSTRAINTS + Constraints + + + GEOM_FACE_CONSTRAINT + Constraint Face + GEOM_SOLID_FROM_FACE_OPT Intersect shapes diff --git a/src/GEOMGUI/GEOM_msg_ja.ts b/src/GEOMGUI/GEOM_msg_ja.ts index 65c9fcd45..d7d25aab4 100644 --- a/src/GEOMGUI/GEOM_msg_ja.ts +++ b/src/GEOMGUI/GEOM_msg_ja.ts @@ -703,6 +703,18 @@ GEOM_FACE_OPT 平らなフェースを作成 + + GEOM_FACE_FFWC + Face creation from wire and constraints + + + GEOM_CONSTRAINTS + Constraints + + + GEOM_FACE_CONSTRAINT + Constraint Face + GEOM_SOLID_FROM_FACE_OPT Intersect shapes diff --git a/src/GEOMImpl/GEOMImpl_FillingDriver.cxx b/src/GEOMImpl/GEOMImpl_FillingDriver.cxx index 51d554ea7..2c48ce1d0 100644 --- a/src/GEOMImpl/GEOMImpl_FillingDriver.cxx +++ b/src/GEOMImpl/GEOMImpl_FillingDriver.cxx @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -64,6 +65,7 @@ #include #include #include +#include #include #include @@ -97,217 +99,255 @@ Standard_Integer GEOMImpl_FillingDriver::Execute(TFunction_Logbook& log) const if (Label().IsNull()) return 0; Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label()); if (aFunction.IsNull()) return 0; - if (aFunction->GetType() != BASIC_FILLING) return 0; - + TopoDS_Shape aShape; GEOMImpl_IFilling IF (aFunction); - Standard_Integer mindeg = IF.GetMinDeg(); - Standard_Integer maxdeg = IF.GetMaxDeg(); - Standard_Real tol3d = IF.GetTol3D(); - Standard_Boolean isApprox = IF.GetApprox(); - - if (mindeg > maxdeg) { - Standard_RangeError::Raise("Minimal degree can not be more than maximal degree"); - } - - /* we verify the contents of the shape */ - TopExp_Explorer Ex; - TopoDS_Shape Scurrent; - Standard_Real First, Last; - Handle(Geom_Curve) C; - - TopoDS_Compound aComp; - BRep_Builder B; - B.MakeCompound(aComp); - - // input is either a list or compound of contours - TopTools_SequenceOfShape contours; - Handle(TColStd_HSequenceOfTransient) aShapeFunctions = IF.GetShapes(); - if ( aShapeFunctions.IsNull() || aShapeFunctions->IsEmpty() ) return 0; - for ( int i = 1; i <= aShapeFunctions->Length(); ++i ) + if( aFunction->GetType() == BASIC_FILLING ) { - Handle(GEOM_Function) fun = Handle(GEOM_Function)::DownCast( aShapeFunctions->Value( i )); - if ( fun.IsNull() ) return 0; - TopoDS_Shape s = fun->GetValue(); - if ( s.IsNull() ) return 0; - BRepBuilderAPI_Copy Copy (s); - if ( Copy.IsDone() ) - contours.Append( Copy.Shape() ); - } + GEOMImpl_IFilling IF (aFunction); + Standard_Integer mindeg = IF.GetMinDeg(); + Standard_Integer maxdeg = IF.GetMaxDeg(); + Standard_Real tol3d = IF.GetTol3D(); + Standard_Boolean isApprox = IF.GetApprox(); - // 1. Convert argument wires, if any, into BSpline edges - for ( int i = 1; i <= contours.Length(); ++i ) - { - Scurrent = contours.Value( i ); - if (Scurrent.ShapeType() != TopAbs_EDGE) { - - if (Scurrent.ShapeType() == TopAbs_WIRE) - { - const TopoDS_Wire& CurWire = TopoDS::Wire(Scurrent); - TopoDS_Edge NewEdge = BRepAlgo::ConcatenateWireC0(CurWire); - if (NewEdge.IsNull()) - Standard_ConstructionError::Raise("Failed to join several edges into one"); - Scurrent = NewEdge; - } - else if (Scurrent.ShapeType() == TopAbs_COMPOUND) - { - for ( TopoDS_Iterator It( Scurrent ); It.More(); It.Next() ) - contours.Append( It.Value() ); - continue; - } - else - { - Standard_ConstructionError::Raise("Input must contain only edges or/and wires"); - } + if (mindeg > maxdeg) { + Standard_RangeError::Raise("Minimal degree can not be more than maximal degree"); } - B.Add(aComp,Scurrent); - } - TopoDS_Shape aShape = aComp; - // 2. The surface construction - if (!isApprox) { - // make filling as in old version of SALOME (before 4.1.1) + /* we verify the contents of the shape */ + TopExp_Explorer Ex; + TopoDS_Shape Scurrent; + Standard_Real First, Last; + Handle(Geom_Curve) C; - Standard_Real tol2d = IF.GetTol2D(); - Standard_Integer nbiter = IF.GetNbIter(); - Standard_Integer aMethod = IF.GetMethod(); + TopoDS_Compound aComp; + BRep_Builder B; + B.MakeCompound(aComp); - GeomFill_SectionGenerator Section; - Standard_Integer i = 0; - Handle(Geom_Curve) aLastC; - gp_Pnt PL1,PL2; - for (Ex.Init(aShape, TopAbs_EDGE); Ex.More(); Ex.Next()) { - Scurrent = Ex.Current(); - if (Scurrent.IsNull() || Scurrent.ShapeType() != TopAbs_EDGE) return 0; - if (BRep_Tool::Degenerated(TopoDS::Edge(Scurrent))) continue; - C = BRep_Tool::Curve(TopoDS::Edge(Scurrent), First, Last); - //if (Scurrent.Orientation() == TopAbs_REVERSED) - // // Mantis isuue 0020659: consider the orientation of the edges - // C = new Geom_TrimmedCurve(C, Last, First); - //else - // C = new Geom_TrimmedCurve(C, First, Last); - C = new Geom_TrimmedCurve(C, First, Last); - gp_Pnt P1,P2; - C->D0(First,P1); - C->D0(Last,P2); + // input is either a list or compound of contours + TopTools_SequenceOfShape contours; + Handle(TColStd_HSequenceOfTransient) aShapeFunctions = IF.GetShapes(); + if ( aShapeFunctions.IsNull() || aShapeFunctions->IsEmpty() ) return 0; + for ( int i = 1; i <= aShapeFunctions->Length(); ++i ) + { + Handle(GEOM_Function) fun = Handle(GEOM_Function)::DownCast( aShapeFunctions->Value( i )); + if ( fun.IsNull() ) return 0; + TopoDS_Shape s = fun->GetValue(); + if ( s.IsNull() ) return 0; + BRepBuilderAPI_Copy Copy (s); + if ( Copy.IsDone() ) + contours.Append( Copy.Shape() ); + } - if (aMethod == 1 && Scurrent.Orientation() == TopAbs_REVERSED) { - C->Reverse(); - } - else if (aMethod == 2) { - if (i == 0) { - PL1 = P1; - PL2 = P2; + // 1. Convert argument wires, if any, into BSpline edges + for ( int i = 1; i <= contours.Length(); ++i ) + { + Scurrent = contours.Value( i ); + if (Scurrent.ShapeType() != TopAbs_EDGE) { + + if (Scurrent.ShapeType() == TopAbs_WIRE) + { + const TopoDS_Wire& CurWire = TopoDS::Wire(Scurrent); + TopoDS_Edge NewEdge = BRepAlgo::ConcatenateWireC0(CurWire); + if (NewEdge.IsNull()) + Standard_ConstructionError::Raise("Failed to join several edges into one"); + Scurrent = NewEdge; } - else { - double d1 = PL1.Distance(P1) + PL2.Distance(P2); - double d2 = PL1.Distance(P2) + PL2.Distance(P1); - if (d2 < d1) { - C->Reverse(); - PL1 = P2; - PL2 = P1; - } - else { + else if (Scurrent.ShapeType() == TopAbs_COMPOUND) + { + for ( TopoDS_Iterator It( Scurrent ); It.More(); It.Next() ) + contours.Append( It.Value() ); + continue; + } + else + { + Standard_ConstructionError::Raise("Input must contain only edges or/and wires"); + } + } + B.Add(aComp,Scurrent); + } + aShape = aComp; + + // 2. The surface construction + if (!isApprox) { + // make filling as in old version of SALOME (before 4.1.1) + + Standard_Real tol2d = IF.GetTol2D(); + Standard_Integer nbiter = IF.GetNbIter(); + Standard_Integer aMethod = IF.GetMethod(); + + GeomFill_SectionGenerator Section; + Standard_Integer i = 0; + Handle(Geom_Curve) aLastC; + gp_Pnt PL1,PL2; + for (Ex.Init(aShape, TopAbs_EDGE); Ex.More(); Ex.Next()) { + Scurrent = Ex.Current(); + if (Scurrent.IsNull() || Scurrent.ShapeType() != TopAbs_EDGE) return 0; + if (BRep_Tool::Degenerated(TopoDS::Edge(Scurrent))) continue; + C = BRep_Tool::Curve(TopoDS::Edge(Scurrent), First, Last); + //if (Scurrent.Orientation() == TopAbs_REVERSED) + // // Mantis isuue 0020659: consider the orientation of the edges + // C = new Geom_TrimmedCurve(C, Last, First); + //else + // C = new Geom_TrimmedCurve(C, First, Last); + C = new Geom_TrimmedCurve(C, First, Last); + gp_Pnt P1,P2; + C->D0(First,P1); + C->D0(Last,P2); + + if (aMethod == 1 && Scurrent.Orientation() == TopAbs_REVERSED) { + C->Reverse(); + } + else if (aMethod == 2) { + if (i == 0) { PL1 = P1; PL2 = P2; } - } - } - - Section.AddCurve(C); - i++; - } - - /* a 'tolerance' is used to compare 2 knots : see GeomFill_Generator.cdl */ - Section.Perform(Precision::PConfusion()); - Handle(GeomFill_Line) Line = new GeomFill_Line(i); - - GeomFill_AppSurf App (mindeg, maxdeg, tol3d, tol2d, nbiter); /* user parameters */ - App.Perform(Line, Section); - - if (!App.IsDone()) return 0; - Standard_Integer UDegree, VDegree, NbUPoles, NbVPoles, NbUKnots, NbVKnots; - App.SurfShape(UDegree, VDegree, NbUPoles, NbVPoles, NbUKnots, NbVKnots); - Handle(Geom_BSplineSurface) GBS = new Geom_BSplineSurface - (App.SurfPoles(), App.SurfWeights(), App.SurfUKnots(), App.SurfVKnots(), - App.SurfUMults(), App.SurfVMults(), App.UDegree(), App.VDegree()); - - if (GBS.IsNull()) return 0; - aShape = BRepBuilderAPI_MakeFace(GBS, Precision::Confusion()); - } - else { - // implemented by skl 20.03.2008 for bug 16568 - // make approximation - try to create bspline surface - // using GeomAPI_PointsToBSplineSurface - - TColGeom_SequenceOfCurve aSeq; - int MaxNbPoles = 0; - - // add curves from edges to sequence and find maximal - // number of poles if some of them are bsplines - for (Ex.Init(aShape, TopAbs_EDGE); Ex.More(); Ex.Next()) { - Scurrent = Ex.Current(); - if (Scurrent.IsNull() || Scurrent.ShapeType() != TopAbs_EDGE) return 0; - if (BRep_Tool::Degenerated(TopoDS::Edge(Scurrent))) continue; - C = BRep_Tool::Curve(TopoDS::Edge(Scurrent), First, Last); - Handle(Geom_TrimmedCurve) TC = Handle(Geom_TrimmedCurve)::DownCast(C); - if (TC.IsNull()) { - Handle(Geom_BSplineCurve) BC = Handle(Geom_BSplineCurve)::DownCast(C); - if (!BC.IsNull()) { - MaxNbPoles = Max(MaxNbPoles,BC->NbPoles()); - } - } - else { - Handle(Geom_BSplineCurve) BC = Handle(Geom_BSplineCurve)::DownCast(TC->BasisCurve()); - if (BC.IsNull()) { - Handle(Geom_TrimmedCurve) TC1 = Handle(Geom_TrimmedCurve)::DownCast(TC->BasisCurve()); - if (!TC1.IsNull()) { - BC = Handle(Geom_BSplineCurve)::DownCast(TC1->BasisCurve()); + else { + double d1 = PL1.Distance(P1) + PL2.Distance(P2); + double d2 = PL1.Distance(P2) + PL2.Distance(P1); + if (d2 < d1) { + C->Reverse(); + PL1 = P2; + PL2 = P1; + } + else { + PL1 = P1; + PL2 = P2; + } } } - if (!BC.IsNull()) { - MaxNbPoles = Max(MaxNbPoles,BC->NbPoles()); + + Section.AddCurve(C); + i++; + } + + /* a 'tolerance' is used to compare 2 knots : see GeomFill_Generator.cdl */ + Section.Perform(Precision::PConfusion()); + Handle(GeomFill_Line) Line = new GeomFill_Line(i); + + GeomFill_AppSurf App (mindeg, maxdeg, tol3d, tol2d, nbiter); /* user parameters */ + App.Perform(Line, Section); + + if (!App.IsDone()) return 0; + Standard_Integer UDegree, VDegree, NbUPoles, NbVPoles, NbUKnots, NbVKnots; + App.SurfShape(UDegree, VDegree, NbUPoles, NbVPoles, NbUKnots, NbVKnots); + Handle(Geom_BSplineSurface) GBS = new Geom_BSplineSurface + (App.SurfPoles(), App.SurfWeights(), App.SurfUKnots(), App.SurfVKnots(), + App.SurfUMults(), App.SurfVMults(), App.UDegree(), App.VDegree()); + + if (GBS.IsNull()) return 0; + aShape = BRepBuilderAPI_MakeFace(GBS, Precision::Confusion()); + } + else { + // implemented by skl 20.03.2008 for bug 16568 + // make approximation - try to create bspline surface + // using GeomAPI_PointsToBSplineSurface + + TColGeom_SequenceOfCurve aSeq; + int MaxNbPoles = 0; + + // add curves from edges to sequence and find maximal + // number of poles if some of them are bsplines + for (Ex.Init(aShape, TopAbs_EDGE); Ex.More(); Ex.Next()) { + Scurrent = Ex.Current(); + if (Scurrent.IsNull() || Scurrent.ShapeType() != TopAbs_EDGE) return 0; + if (BRep_Tool::Degenerated(TopoDS::Edge(Scurrent))) continue; + C = BRep_Tool::Curve(TopoDS::Edge(Scurrent), First, Last); + Handle(Geom_TrimmedCurve) TC = Handle(Geom_TrimmedCurve)::DownCast(C); + if (TC.IsNull()) { + Handle(Geom_BSplineCurve) BC = Handle(Geom_BSplineCurve)::DownCast(C); + if (!BC.IsNull()) { + MaxNbPoles = Max(MaxNbPoles,BC->NbPoles()); + } + } + else { + Handle(Geom_BSplineCurve) BC = Handle(Geom_BSplineCurve)::DownCast(TC->BasisCurve()); + if (BC.IsNull()) { + Handle(Geom_TrimmedCurve) TC1 = Handle(Geom_TrimmedCurve)::DownCast(TC->BasisCurve()); + if (!TC1.IsNull()) { + BC = Handle(Geom_BSplineCurve)::DownCast(TC1->BasisCurve()); + } + } + if (!BC.IsNull()) { + MaxNbPoles = Max(MaxNbPoles,BC->NbPoles()); + } + } + aSeq.Append(C); + } + // prepare array of points for creation bspline surface + // size of this array: by U parameter - number of curves, + // by V parameter - determ using MaxNbPoles but it's + // value must be between 21(min) and 101(max) + int nbc = aSeq.Length(); + int nbp = Max(21, 2*MaxNbPoles-1); + + // commented for Mantis issue 0021541 + //if (nbp > 101) nbp = 101; + + TColgp_Array2OfPnt Points (1, nbc, 1, nbp); + int ic = 1; + for (; ic <= nbc; ic++) { + Handle(Geom_Curve) C = aSeq.Value(ic); + double fp = C->FirstParameter(); + double lp = C->LastParameter(); + double dp = (lp-fp)/(nbp-1); + int j = 0; + gp_Pnt P; + for (; j < nbp; j++) { + C->D0(fp+dp*j, P); + Points.SetValue(ic, j+1, P); + } + } + GeomAPI_PointsToBSplineSurface PTB (Points, mindeg, maxdeg, GeomAbs_C2, tol3d); + Handle(Geom_BSplineSurface) BS = PTB.Surface(); + BRepBuilderAPI_MakeFace BB (BS, Precision::Confusion()); + TopoDS_Face NewF = BB.Face(); + Handle(ShapeFix_Face) sff = new ShapeFix_Face (NewF); + sff->Perform(); + sff->FixOrientation(); + aShape = sff->Face(); + } + } + else if( aFunction->GetType() == FILLING_ON_CONSTRAINTS ) + { + BRepOffsetAPI_MakeFilling MakeFilling; + + Handle(TColStd_HSequenceOfTransient) aConstraints = IF.GetShapes(); + + for ( unsigned int ind = 1; ind <= aConstraints->Length(); ind++ ) { + TopoDS_Edge E; + TopoDS_Face F; + Handle(GEOM_Function) aRefShape = Handle(GEOM_Function)::DownCast( aConstraints->Value(ind) ); + if ( !aRefShape->GetValue().IsNull() && aRefShape->GetValue().ShapeType() == TopAbs_EDGE ) + E = TopoDS::Edge(aRefShape->GetValue() ); + else { + Standard_RangeError::Raise("Wrong parameters"); + } + if ( ind < aConstraints->Length() ) { + Handle(GEOM_Function) aRefFaceShape = Handle(GEOM_Function)::DownCast( aConstraints->Value(ind+1) ); + if ( !aRefFaceShape->GetValue().IsNull() && aRefFaceShape->GetValue().ShapeType() == TopAbs_FACE ) { + F = TopoDS::Face( aRefFaceShape->GetValue() ); + ind++; } } - aSeq.Append(C); + if ( !F.IsNull() ) + MakeFilling.Add( E, F, GeomAbs_G1 ); + else + MakeFilling.Add( E, GeomAbs_C0 ); } - // prepare array of points for creation bspline surface - // size of this array: by U parameter - number of curves, - // by V parameter - determ using MaxNbPoles but it's - // value must be between 21(min) and 101(max) - int nbc = aSeq.Length(); - int nbp = Max(21, 2*MaxNbPoles-1); - // commented for Mantis issue 0021541 - //if (nbp > 101) nbp = 101; - - TColgp_Array2OfPnt Points (1, nbc, 1, nbp); - int ic = 1; - for (; ic <= nbc; ic++) { - Handle(Geom_Curve) C = aSeq.Value(ic); - double fp = C->FirstParameter(); - double lp = C->LastParameter(); - double dp = (lp-fp)/(nbp-1); - int j = 0; - gp_Pnt P; - for (; j < nbp; j++) { - C->D0(fp+dp*j, P); - Points.SetValue(ic, j+1, P); - } + MakeFilling.Build(); + if ( !MakeFilling.IsDone() ) + { + Standard_RangeError::Raise("Filling on constraints failed"); } - GeomAPI_PointsToBSplineSurface PTB (Points, mindeg, maxdeg, GeomAbs_C2, tol3d); - Handle(Geom_BSplineSurface) BS = PTB.Surface(); - BRepBuilderAPI_MakeFace BB (BS, Precision::Confusion()); - TopoDS_Face NewF = BB.Face(); - Handle(ShapeFix_Face) sff = new ShapeFix_Face (NewF); - sff->Perform(); - sff->FixOrientation(); - aShape = sff->Face(); + + aShape = TopoDS::Face( MakeFilling.Shape() ); } /* We test the validity of resulting shape */ if (!BRepAlgo::IsValid((aShape))) { Standard_ConstructionError::Raise("Algorithm has produced an invalid shape result"); - return 0; } aFunction->SetValue(aShape); @@ -351,6 +391,12 @@ GetCreationInformation(std::string& theOperationName, AddParam( theParams, "Approximation", aCI.GetApprox() ); break; } + case FILLING_ON_CONSTRAINTS: + { + theOperationName = "FACE"; + AddParam( theParams, "Edges/Faces", aCI.GetShapes() ); + break; + } default: return false; } diff --git a/src/GEOMImpl/GEOMImpl_IShapesOperations.cxx b/src/GEOMImpl/GEOMImpl_IShapesOperations.cxx index da8445efc..1a7c43205 100644 --- a/src/GEOMImpl/GEOMImpl_IShapesOperations.cxx +++ b/src/GEOMImpl/GEOMImpl_IShapesOperations.cxx @@ -34,11 +34,13 @@ #include "GEOMImpl_VectorDriver.hxx" #include "GEOMImpl_ShapeDriver.hxx" #include "GEOMImpl_GlueDriver.hxx" +#include "GEOMImpl_FillingDriver.hxx" #include "GEOMImpl_IVector.hxx" #include "GEOMImpl_IShapes.hxx" #include "GEOMImpl_IShapeExtend.hxx" #include "GEOMImpl_IGlue.hxx" +#include "GEOMImpl_IFilling.hxx" #include "GEOMImpl_Block6Explorer.hxx" #include "GEOMImpl_IHealingOperations.hxx" @@ -677,6 +679,107 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFaceFromSurface return aShape; } +//============================================================================= +/*! + * MakeFaceWithConstraints + */ +//============================================================================= +Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFaceWithConstraints + (std::list theConstraints) +{ + SetErrorCode(KO); + + //Add a new object + Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_FILLING); + + //Add a new function + Handle(GEOM_Function) aFunction = + aShape->AddFunction(GEOMImpl_FillingDriver::GetID(), FILLING_ON_CONSTRAINTS); + if (aFunction.IsNull()) return NULL; + + //Check if the function is set correctly + if (aFunction->GetDriverGUID() != GEOMImpl_FillingDriver::GetID()) return NULL; + + GEOMImpl_IFilling aCI (aFunction); + Handle(TColStd_HSequenceOfTransient) aConstraints = new TColStd_HSequenceOfTransient; + + // Shapes + std::list::iterator it = theConstraints.begin(); + while (it != theConstraints.end()) { + Handle(GEOM_Object) anObject = (*it); + if ( anObject.IsNull() || anObject->GetValue().ShapeType() != TopAbs_EDGE ) { + SetErrorCode("NULL argument edge for the face construction"); + return NULL; + } + Handle(GEOM_Function) aRefSh = anObject->GetLastFunction(); + aConstraints->Append(aRefSh); + it++; + if ( it != theConstraints.end() ) { + Handle(GEOM_Object) aFace = (*it); + if ( aFace.IsNull() ) { + // null constraint face - it is a valid case + it++; + continue; + } + if ( aFace->GetValue().ShapeType() != TopAbs_FACE ) + // constraint face can be omitted - it is a valid case + continue; + if ( IsSubShapeBelongsTo( anObject, 0, aFace, 0 ) ) { + // valid constraint + aRefSh = aFace->GetLastFunction(); + aConstraints->Append(aRefSh); + it++; + } + else { + // bad constraint + SetErrorCode("Face is NULL or not connected to the Edge"); + return NULL; + } + } + } + aCI.SetShapes( aConstraints ); + + //Compute the shape + Standard_Boolean isWarning = Standard_False; + try { + OCC_CATCH_SIGNALS; + if (!GetSolver()->ComputeFunction(aFunction)) { + SetErrorCode("Shape driver failed"); + return NULL; + } + } + catch (Standard_Failure) { + Handle(Standard_Failure) aFail = Standard_Failure::Caught(); + SetErrorCode(aFail->GetMessageString()); + // to provide warning + if (!aFunction->GetValue().IsNull()) { + isWarning = Standard_True; + } else { + return NULL; + } + } + + //Make a Python command + GEOM::TPythonDump pd (aFunction); + pd << aShape << " = geompy.MakeFaceWithConstraints(["; + + // Constraints + it = theConstraints.begin(); + if (it != theConstraints.end() ) { + pd << (*it++); + while (it != theConstraints.end()) { + Handle(GEOM_Object) anObject = (*it++); + if( !anObject.IsNull() ) + pd << ", " << anObject; + } + } + pd << "])"; + + // to provide warning + if (!isWarning) SetErrorCode(OK); + return aShape; +} + //============================================================================= /*! * MakeShell @@ -1940,6 +2043,39 @@ TCollection_AsciiString GEOMImpl_IShapesOperations::GetShapeTypeString (Handle(G return aTypeName; } +//============================================================================= +/*! + * IsSubShapeBelongsTo + */ +//============================================================================= +Standard_Boolean GEOMImpl_IShapesOperations::IsSubShapeBelongsTo( Handle(GEOM_Object) theSubObject, + const Standard_Integer theSubObjectIndex, + Handle(GEOM_Object) theObject, + const Standard_Integer theObjectIndex) +{ + if ( theObject.IsNull() || theSubObject.IsNull() ) + return false; + + TopoDS_Shape shape = theObject->GetValue(); + TopoDS_Shape subShape = theSubObject->GetValue(); + + if ( shape.IsNull() || subShape.IsNull() ) + return false; + + TopTools_IndexedMapOfShape anIndices; + if ( theObjectIndex > 0 ) { + TopExp::MapShapes( shape, anIndices ); + shape = anIndices.FindKey(theObjectIndex); + } + if ( theSubObjectIndex > 0 ) { + TopExp::MapShapes( subShape, anIndices ); + subShape = anIndices.FindKey(theSubObjectIndex); + } + + TopExp::MapShapes( shape, anIndices ); + return anIndices.Contains( subShape ); +} + //============================================================================= /*! * NumberOfSubShapes diff --git a/src/GEOMImpl/GEOMImpl_IShapesOperations.hxx b/src/GEOMImpl/GEOMImpl_IShapesOperations.hxx index dca4233a9..06b35dac4 100644 --- a/src/GEOMImpl/GEOMImpl_IShapesOperations.hxx +++ b/src/GEOMImpl/GEOMImpl_IShapesOperations.hxx @@ -88,6 +88,8 @@ class GEOMImpl_IShapesOperations : public GEOM_IOperations Standard_EXPORT Handle(GEOM_Object) MakeFaceFromSurface (Handle(GEOM_Object) theFace, Handle(GEOM_Object) theWire); + + Standard_EXPORT Handle(GEOM_Object) MakeFaceWithConstraints (std::list theConstraints); Standard_EXPORT Handle(GEOM_Object) MakeShell (std::list theShapes); @@ -160,6 +162,11 @@ class GEOMImpl_IShapesOperations : public GEOM_IOperations Standard_EXPORT TCollection_AsciiString GetShapeTypeString (Handle(GEOM_Object) theShape); + Standard_EXPORT Standard_Boolean IsSubShapeBelongsTo(Handle(GEOM_Object) theSubObject, + const Standard_Integer theSubObjectIndex, + Handle(GEOM_Object) theObject, + const Standard_Integer theObjectIndex); + Standard_EXPORT Standard_Integer NumberOfSubShapes (Handle(GEOM_Object) theShape, const Standard_Integer theShapeType); diff --git a/src/GEOMImpl/GEOMImpl_Types.hxx b/src/GEOMImpl/GEOMImpl_Types.hxx index f7f329ebb..272db63b8 100644 --- a/src/GEOMImpl/GEOMImpl_Types.hxx +++ b/src/GEOMImpl/GEOMImpl_Types.hxx @@ -331,6 +331,7 @@ #define DIVIDE_EDGE_BY_POINT 13 #define BASIC_FILLING 1 +#define FILLING_ON_CONSTRAINTS 2 #define GLUE_FACES 1 #define GLUE_FACES_BY_LIST 2 diff --git a/src/GEOM_I/GEOM_IShapesOperations_i.cc b/src/GEOM_I/GEOM_IShapesOperations_i.cc index dce57e0aa..334846938 100644 --- a/src/GEOM_I/GEOM_IShapesOperations_i.cc +++ b/src/GEOM_I/GEOM_IShapesOperations_i.cc @@ -279,6 +279,37 @@ GEOM::GEOM_Object_ptr GEOM_IShapesOperations_i::MakeFaceFromSurface return GetObject(anObject); } +//============================================================================= +/*! + * MakeFaceWithConstraints + */ +//============================================================================= +GEOM::GEOM_Object_ptr GEOM_IShapesOperations_i::MakeFaceWithConstraints + (const GEOM::ListOfGO& theConstraints) +{ + GEOM::GEOM_Object_var aGEOMObject; + + //Set a not done flag + GetOperations()->SetNotDone(); + + //Get the shapes + std::list aConstraints; + for( int ind = 0; ind < theConstraints.length(); ind++ ) { + Handle(GEOM_Object) anObject = GetObjectImpl( theConstraints[ind] ); + aConstraints.push_back(anObject); + } + + // Make Face + Handle(GEOM_Object) anObject = + GetOperations()->MakeFaceWithConstraints( aConstraints ); + + // enable warning status + if (anObject.IsNull()) + return aGEOMObject._retn(); + + return GetObject(anObject); +} + //============================================================================= /*! * MakeShell @@ -976,6 +1007,25 @@ char* GEOM_IShapesOperations_i::GetShapeTypeString (GEOM::GEOM_Object_ptr theSha return CORBA::string_dup(aDescription.ToCString()); } +//============================================================================= +/*! + * IsSubShapeBelongsTo + */ +//============================================================================= +CORBA::Boolean GEOM_IShapesOperations_i::IsSubShapeBelongsTo( GEOM::GEOM_Object_ptr theSubObject, + const CORBA::Long theSubObjectIndex, + GEOM::GEOM_Object_ptr theObject, + const CORBA::Long theObjectIndex) +{ + Handle(GEOM_Object) aSubObject = GetObjectImpl( theSubObject ); + Handle(GEOM_Object) anObject = GetObjectImpl( theObject ); + if( anObject.IsNull() || aSubObject.IsNull() ) + return false; + + // Get parameters + return GetOperations()->IsSubShapeBelongsTo( aSubObject, theSubObjectIndex, anObject, theObjectIndex ); +} + //============================================================================= /*! * NumberOfFaces diff --git a/src/GEOM_I/GEOM_IShapesOperations_i.hh b/src/GEOM_I/GEOM_IShapesOperations_i.hh index 5ba281994..944096750 100644 --- a/src/GEOM_I/GEOM_IShapesOperations_i.hh +++ b/src/GEOM_I/GEOM_IShapesOperations_i.hh @@ -67,6 +67,8 @@ class GEOM_I_EXPORT GEOM_IShapesOperations_i : GEOM::GEOM_Object_ptr MakeFaceFromSurface(GEOM::GEOM_Object_ptr theFace, GEOM::GEOM_Object_ptr theWire); + GEOM::GEOM_Object_ptr MakeFaceWithConstraints (const GEOM::ListOfGO& theConstraints); + GEOM::GEOM_Object_ptr MakeShell (const GEOM::ListOfGO& theFacesAndShells); GEOM::GEOM_Object_ptr MakeSolidShell (GEOM::GEOM_Object_ptr theShell); @@ -144,6 +146,11 @@ class GEOM_I_EXPORT GEOM_IShapesOperations_i : char* GetShapeTypeString (GEOM::GEOM_Object_ptr theShape); + CORBA::Boolean IsSubShapeBelongsTo( GEOM::GEOM_Object_ptr theSubobject, + const CORBA::Long theSubObjectIndex, + GEOM::GEOM_Object_ptr theObject, + const CORBA::Long theObjectIndex ); + CORBA::Long NumberOfFaces (GEOM::GEOM_Object_ptr theShape); CORBA::Long NumberOfEdges (GEOM::GEOM_Object_ptr theShape); CORBA::Long NumberOfSubShapes (GEOM::GEOM_Object_ptr theShape, diff --git a/src/GEOM_I_Superv/GEOM_Superv_i.cc b/src/GEOM_I_Superv/GEOM_Superv_i.cc index 266252668..7c4409f7e 100644 --- a/src/GEOM_I_Superv/GEOM_Superv_i.cc +++ b/src/GEOM_I_Superv/GEOM_Superv_i.cc @@ -2274,6 +2274,24 @@ GEOM::GEOM_Object_ptr GEOM_Superv_i::MakeFaceWires (GEOM::GEOM_List_ptr theWires return NULL; } +//============================================================================= +// MakeFaceWithConstraints: +//============================================================================= +GEOM::GEOM_Object_ptr GEOM_Superv_i::MakeFaceWithConstraints (GEOM::GEOM_List_ptr theConstraints) +{ + beginService( " GEOM_Superv_i::MakeFaceWithConstraints" ); + MESSAGE("GEOM_Superv_i::MakeFaceWithConstraints"); + if (GEOM_List_i* aConstraints = + dynamic_cast*>(GetServant(theConstraints, myPOA).in())) { + getShapesOp(); + GEOM::GEOM_Object_ptr anObj = myShapesOp->MakeFaceWithConstraints(aConstraints->GetList()); + endService( " GEOM_Superv_i::MakeFaceWithConstraints" ); + return anObj; + } + endService( " GEOM_Superv_i::MakeFaceWithConstraints" ); + return NULL; +} + //============================================================================= // MakeShell: //============================================================================= diff --git a/src/GEOM_I_Superv/GEOM_Superv_i.hh b/src/GEOM_I_Superv/GEOM_Superv_i.hh index a41e6b32f..3d59b32bc 100644 --- a/src/GEOM_I_Superv/GEOM_Superv_i.hh +++ b/src/GEOM_I_Superv/GEOM_Superv_i.hh @@ -503,6 +503,7 @@ public: CORBA::Boolean isPlanarWanted); GEOM::GEOM_Object_ptr MakeFaceWires (GEOM::GEOM_List_ptr theWires, CORBA::Boolean isPlanarWanted); + GEOM::GEOM_Object_ptr MakeFaceWithConstraints (GEOM::GEOM_List_ptr theConstraints); GEOM::GEOM_Object_ptr MakeShell (GEOM::GEOM_List_ptr theFacesAndShells); GEOM::GEOM_Object_ptr MakeSolidShell (GEOM::GEOM_Object_ptr theShell); GEOM::GEOM_Object_ptr MakeSolidShells (GEOM::GEOM_List_ptr theShells); diff --git a/src/GEOM_SWIG/GEOM_TestAll.py b/src/GEOM_SWIG/GEOM_TestAll.py index 6dafa5265..2fef6a4c5 100644 --- a/src/GEOM_SWIG/GEOM_TestAll.py +++ b/src/GEOM_SWIG/GEOM_TestAll.py @@ -179,6 +179,12 @@ def TestAll (geompy, math): Face3 = geompy.MakeFaceHW (100., 200., 1) #(2 Doubles, 1 Int)->GEOM_Object Face4 = geompy.MakeFaceObjHW (vz, 200., 100.) #(1 GEOM_Object, 2 Doubles)->GEOM_Object Face5 = geompy.MakeFaceFromSurface(Face, Sketcher) #(2 GEOM_Objects)->GEOM_Object + + Cut2 = geompy.MakeCutList(Sphere1, [Box1], True) + #(List of GEOM_Object)->GEOM_Object + Face6 = geompy.MakeFaceWithConstraints([geompy.GetSubShape(Cut2, [5]), geompy.GetSubShape(Cut2, [3]), + geompy.GetSubShape(Cut2, [11]), geompy.GetSubShape(Cut2, [3]), + geompy.GetSubShape(Cut2, [13]), geompy.GetSubShape(Cut2, [3])]) Disk = geompy.MakeDiskPntVecR (p0, vz, radius) #(2 GEOM_Object, 1 Double)->GEOM_Object Disk2 = geompy.MakeDiskThreePnt(p0, p200, pz) #(3 GEOM_Object)->GEOM_Object Disk3 = geompy.MakeDiskR(100., 1) #(1 Doubles, 1 Int)->GEOM_Object @@ -396,6 +402,7 @@ def TestAll (geompy, math): id_Common = geompy.addToStudy(Common, "Common") id_Cut = geompy.addToStudy(Cut, "Cut") + id_Cut2 = geompy.addToStudy(Cut2, "Cut2") id_Fuse = geompy.addToStudy(Fuse, "Fuse") id_Section = geompy.addToStudy(Section, "Section") @@ -408,6 +415,7 @@ def TestAll (geompy, math): id_Face3 = geompy.addToStudy(Face3, "Face Height Width") id_Face4 = geompy.addToStudy(Face4, "Face Plane_HW") id_Face5 = geompy.addToStudy(Face5, "Face from surface and wire") + id_Face6 = geompy.addToStudy(Face6, "Face from edges with constraints") id_Disk = geompy.addToStudy(Disk, "Disk PntVecR") id_Disk2 = geompy.addToStudy(Disk2, "Disk Three Points") id_Disk3 = geompy.addToStudy(Disk3, "Disk OXY Radius") diff --git a/src/GEOM_SWIG/geomBuilder.py b/src/GEOM_SWIG/geomBuilder.py index 83c2e34b0..07535cdf9 100644 --- a/src/GEOM_SWIG/geomBuilder.py +++ b/src/GEOM_SWIG/geomBuilder.py @@ -4555,6 +4555,42 @@ class geomBuilder(object, GEOM._objref_GEOM_Gen): RaiseIfFailed("MakeFaceFromSurface", self.ShapesOp) self._autoPublish(anObj, theName, "face") return anObj + + ## Create a face from a set of edges with the given constraints. + # @param theConstraints List of edges and constraint faces (as a sequence of a Edge + Face couples): + # - edges should form a closed wire; + # - for each edge, constraint face is optional: if a constraint face is missing + # for some edge, this means that there no constraint associated with this edge. + # @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 created face. + # + # @ref tui_creation_face "Example" + @ManageTransactions("ShapesOp") + def MakeFaceWithConstraints(self, theConstraints, theName=None): + """ + Create a face from a set of edges with the given constraints. + + Parameters: + theConstraints List of edges and constraint faces (as a sequence of a Edge + Face couples): + - edges should form a closed wire; + - for each edge, constraint face is optional: if a constraint face is missing + for some edge, this means that there no constraint associated with this edge. + 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 created face. + """ + # Example: see GEOM_TestAll.py + anObj = self.ShapesOp.MakeFaceWithConstraints(theConstraints) + if anObj is None: + RaiseIfFailed("MakeFaceWithConstraints", self.ShapesOp) + self._autoPublish(anObj, theName, "face") + return anObj ## Create a shell from the set of faces and shells. # @param theFacesAndShells List of faces and/or shells. @@ -6244,6 +6280,38 @@ class geomBuilder(object, GEOM._objref_GEOM_Gen): self._autoPublish(ListObj, theName, "subshape") return ListObj + ## Check if the object is a sub-object of another GEOM object. + # @param aSubObject Checked sub-object (or its parent object, in case if + # \a theSubObjectIndex is non-zero). + # @param anObject An object that is checked for ownership (or its parent object, + # in case if \a theObjectIndex is non-zero). + # @param aSubObjectIndex When non-zero, specifies a sub-shape index that + # identifies a sub-object within its parent specified via \a theSubObject. + # @param anObjectIndex When non-zero, specifies a sub-shape index that + # identifies an object within its parent specified via \a theObject. + # @return TRUE, if the given object contains sub-object. + @ManageTransactions("ShapesOp") + def IsSubShapeBelongsTo(self, aSubObject, anObject, aSubObjectIndex = 0, anObjectIndex = 0): + """ + Check if the object is a sub-object of another GEOM object. + + Parameters: + aSubObject Checked sub-object (or its parent object, in case if + \a theSubObjectIndex is non-zero). + anObject An object that is checked for ownership (or its parent object, + in case if \a theObjectIndex is non-zero). + aSubObjectIndex When non-zero, specifies a sub-shape index that + identifies a sub-object within its parent specified via \a theSubObject. + anObjectIndex When non-zero, specifies a sub-shape index that + identifies an object within its parent specified via \a theObject. + + Returns + TRUE, if the given object contains sub-object. + """ + IsOk = self.ShapesOp.IsSubShapeBelongsTo(aSubObject, aSubObjectIndex, anObject, anObjectIndex) + RaiseIfFailed("IsSubShapeBelongsTo", self.ShapesOp) + return IsOk + # end of l4_decompose ## @}