From: mpa Date: Mon, 8 Dec 2014 15:14:18 +0000 (+0300) Subject: 0022759: [EDF] Creation of a surface from several edges X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=34cab1d897ec6758e4175c22d45f372df67b87ca;p=modules%2Fgeom.git 0022759: [EDF] Creation of a surface from several edges --- diff --git a/doc/salome/gui/GEOM/input/creating_face.doc b/doc/salome/gui/GEOM/input/creating_face.doc index 9f31c4d04..dc228f671 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,22 @@ 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, user can create a \b Face by specifying a wire and its constraints. +It is necessary to define 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 tree widget. +User must define the constraint face for each edge to get a good result. +\note Please note, that the constraint face must be connected to the 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 constraints, each constraint is a couple (Edge, Face), +where Edge is an Edge within the source Wire and Face is a Face connected to this Edge. + +\image html neo-obj4_3.png "Create face by a wire and its constraints" \n Example: diff --git a/doc/salome/gui/GEOM/input/neo-obj4_3.png b/doc/salome/gui/GEOM/input/neo-obj4_3.png new file mode 100644 index 000000000..c43b08922 Binary files /dev/null and b/doc/salome/gui/GEOM/input/neo-obj4_3.png differ diff --git a/idl/GEOM_Gen.idl b/idl/GEOM_Gen.idl index 83faa46bb..2ace66841 100644 --- a/idl/GEOM_Gen.idl +++ b/idl/GEOM_Gen.idl @@ -1938,6 +1938,15 @@ module GEOM GEOM_Object MakeFaceFromSurface(in GEOM_Object theFace, in GEOM_Object theWire); + /*! + * \brief Create a face on the given constraints. + * \param theConstraints List of constraints. Each constraint is a couple (Edge, Face), + * where Edge is an Edge of closed Wire + * and Face is a Face connected to 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 +2174,21 @@ module GEOM */ string GetShapeTypeString (in GEOM_Object theShape); + /*! + * \brief Check, if the object is sub-object of other GEOM object. + * + * \param theSubObject The checked sub-object or its parent object. + * \param theSubObjectIndex If theSubObjectIndex is defined + * this parameter is the index of checked sub-object within the source theSubObject, + * If theSubObjectIndex is not defined the checked sub-object is theSubObject. + * \param theObject The object or its parent. + * \param theObjectIndex The object index within the source theObject. + * \return TRUE, if the given object contains the checked 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/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/src/BuildGUI/BuildGUI_FaceDlg.cxx b/src/BuildGUI/BuildGUI_FaceDlg.cxx index c1a1ade02..f1b0a4601 100644 --- a/src/BuildGUI/BuildGUI_FaceDlg.cxx +++ b/src/BuildGUI/BuildGUI_FaceDlg.cxx @@ -50,12 +50,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 +65,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 +85,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->setFixedHeight( 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( myGroupWire ); layout->addWidget(myGroupSurf); + layout->addWidget( myGroupWireConstraints ); /***************************************************************/ setHelpFileName("create_face_page.html"); @@ -111,33 +140,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 = NULL; /* 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 +197,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 = NULL; + myEditCurrentArgument = myGroupWireConstraints->LineEdit1; + myGroupWireConstraints->LineEdit1->setText(""); + myGroupWireConstraints->LineEdit1->setEnabled(true); + myGroupWire->hide(); + myGroupSurf->hide(); + myGroupWireConstraints->show(); break; } } @@ -191,6 +244,73 @@ void BuildGUI_FaceDlg::ConstructorsClicked(int constructorId) SelectionIntoArgument(); } +//================================================================================= +// function : updateContraintsTree +// purpose : +//================================================================================= +void BuildGUI_FaceDlg::updateContraintsTree() +{ + 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++ ) { + BuildGUI_TreeWidgetItem* item = new BuildGUI_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; + myCurrentItem->setSelected( false ); + BuildGUI_TreeWidgetItem* itemBelow = dynamic_cast( myTreeConstraints->itemBelow( myCurrentItem ) ); + if( !itemBelow ) + itemBelow = dynamic_cast( myTreeConstraints->topLevelItem(0) ); + myCurrentItem = itemBelow; + if( itemBelow->getFace().isNull() ) { + itemBelow->setSelected( true ); + onItemClicked( itemBelow, 0 ); + } + else + findEmptyTreeItem(); +} + +//================================================================================= +// function : isTreeFull() +// purpose : +//================================================================================= +bool BuildGUI_FaceDlg::isTreeFull() +{ + QTreeWidgetItem* item = myTreeConstraints->topLevelItem(0); + while( !(dynamic_cast(item))->getFace().isNull() ) { + item = myTreeConstraints->itemBelow( item ); + if( !item ) + return true; + } + return false; +} + //================================================================================= // function : ClickOnOk() // purpose : @@ -213,6 +333,9 @@ bool BuildGUI_FaceDlg::ClickOnApply() return false; initName(); + + myEditCurrentArgument->setText(""); + ConstructorsClicked( getConstructorId() ); return true; } @@ -223,8 +346,8 @@ bool BuildGUI_FaceDlg::ClickOnApply() //================================================================================= void BuildGUI_FaceDlg::SelectionIntoArgument() { - if (myEditCurrentArgument == GroupWire->LineEdit1) { - myEditCurrentArgument->setText( "" ); + if( myEditCurrentArgument == myGroupWire->LineEdit1 ) { + myEditCurrentArgument->setText(""); QList types; types << TopAbs_EDGE << TopAbs_WIRE << TopAbs_FACE @@ -235,7 +358,8 @@ 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 || + } + else if (myEditCurrentArgument == myGroupSurf->LineEdit1 || myEditCurrentArgument == myGroupSurf->LineEdit2) { const bool isEditFace = myEditCurrentArgument == myGroupSurf->LineEdit1; const TopAbs_ShapeEnum aType = isEditFace ? TopAbs_FACE : TopAbs_WIRE; @@ -260,8 +384,37 @@ void BuildGUI_FaceDlg::SelectionIntoArgument() } } } - - displayPreview(true); + else if( myEditCurrentArgument == myGroupWireConstraints->LineEdit1 ) { + if( myCurrentItem != NULL ) { + 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(NULL); + } + 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; + updateContraintsTree(); + } + else { + myTreeConstraints->clear(); + erasePreview(true); + } + } + } + //displayPreview(true); } @@ -272,7 +425,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 +435,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 = NULL; + } // enable line edit myEditCurrentArgument->setEnabled(true); myEditCurrentArgument->setFocus(); - send->setDown(true); - displayPreview(true); + SelectionIntoArgument(); } @@ -320,6 +480,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->flags() & Qt::ItemIsSelectable ) ) + return; + + myCurrentItem = dynamic_cast( theItem ); + erasePreview(); + displayPreview( myCurrentItem->getEdge().get(), true, false, true, 5, -1, Quantity_NOC_RED); +} //================================================================================= // function : enterEvent() @@ -355,6 +528,9 @@ bool BuildGUI_FaceDlg::isValid( QString& ) case 1: ok = myFace && myWire; break; + case 2: + ok = myWire; + break; default: break; } @@ -383,13 +559,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++ ) { + BuildGUI_TreeWidgetItem* item = dynamic_cast( myTreeConstraints->topLevelItem(i) ); + constraints[j++] = item->getEdge().get(); + if ( item->getFace() ) + constraints[j++] = item->getFace().get(); + } + constraints->length(j); + anObj = anOper->MakeFaceWithConstraints( constraints.in() ); + res = true; + } break; default: break; @@ -409,3 +602,62 @@ bool BuildGUI_FaceDlg::execute( ObjectList& objects ) 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++ ) { + BuildGUI_TreeWidgetItem* item = dynamic_cast( myTreeConstraints->topLevelItem(i) ); + if( item->getFace().get() ) + GEOMBase::PublishSubObject( item->getFace().get() ); + GEOMBase::PublishSubObject( myWire.get() ); + } + break; + default: + break; + } +} + +BuildGUI_TreeWidgetItem::BuildGUI_TreeWidgetItem( QTreeWidget* view, const GEOM::GeomObjPtr edge, int type ) +:QTreeWidgetItem( view, QStringList()<resizeColumnToContents(1); + myFace = face; +} +GEOM::GeomObjPtr BuildGUI_TreeWidgetItem::getFace() const +{ + return myFace; +} + +GEOM::GeomObjPtr BuildGUI_TreeWidgetItem::getEdge() const +{ + return myEdge; +} diff --git a/src/BuildGUI/BuildGUI_FaceDlg.h b/src/BuildGUI/BuildGUI_FaceDlg.h index 29e152781..dc4eee216 100644 --- a/src/BuildGUI/BuildGUI_FaceDlg.h +++ b/src/BuildGUI/BuildGUI_FaceDlg.h @@ -30,8 +30,29 @@ #include "GEOMBase_Skeleton.h" #include "GEOM_GenericObjPtr.h" +#include + class DlgRef_1Sel1Check; class DlgRef_2Sel; +class DlgRef_1SelExt; + +//================================================================================= +// class : BuildGUI_TreeWidgetItem +// purpose : class for constraint(Edge-Face) creation +//================================================================================= +class BuildGUI_TreeWidgetItem : public QTreeWidgetItem +{ +public: + BuildGUI_TreeWidgetItem( QTreeWidget*, const GEOM::GeomObjPtr, int = Type ); + BuildGUI_TreeWidgetItem( QTreeWidgetItem*, const GEOM::GeomObjPtr, int = Type ); + ~BuildGUI_TreeWidgetItem(); + void setFace( const GEOM::GeomObjPtr ); + GEOM::GeomObjPtr getFace() const; + GEOM::GeomObjPtr getEdge() const; +private: + GEOM::GeomObjPtr myEdge; + GEOM::GeomObjPtr myFace; +}; //================================================================================= // class : BuildGUI_FaceDlg @@ -50,26 +71,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 updateContraintsTree(); + 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; + BuildGUI_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/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 1630caf5a..a94395e5b 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..80a15d0d1 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,211 +99,249 @@ 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(); + + if (mindeg > maxdeg) { + Standard_RangeError::Raise("Minimal degree can not be more than maximal degree"); + } - // 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) { + /* 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 ) + { + 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() ); + } + + // 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 (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"); + } } + B.Add(aComp,Scurrent); } - 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) - - 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; + 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 { - 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 (aMethod == 2) { + if (i == 0) { PL1 = P1; PL2 = P2; } + 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; + } + } } - } - Section.AddCurve(C); - i++; - } + 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); + /* 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); + 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 (!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 (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()); } } - 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); } - 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(); } - // 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); - } + } + else if( aFunction->GetType() == FILLING_ON_CONSTRAINTS ) + { + BRepOffsetAPI_MakeFilling MakeFilling; + + Handle(TColStd_HSequenceOfTransient) aConstraints = IF.GetShapes(); + + TopoDS_Edge E; + TopoDS_Face F; + for( unsigned int ind = 1; ind <= aConstraints->Length(); ind++ ) { + 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"); + return 0; + } + 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() ); + MakeFilling.Add( E, F, GeomAbs_G1 ); + ind++; + } + else + MakeFilling.Add( E, GeomAbs_C0 ); } - 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(); + + MakeFilling.Build(); + if( !MakeFilling.IsDone() ) + { + Standard_RangeError::Raise("filling on constraints failed"); + return 0; + } + + aShape = TopoDS::Face( MakeFilling.Shape() ); } /* We test the validity of resulting shape */ @@ -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..ac8b5652e 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,103 @@ 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 constraint creation"); + return NULL; + } + Handle(GEOM_Function) aRefSh = anObject->GetLastFunction(); + aConstraints->Append(aRefSh); + it++; + if( it != theConstraints.end() ) { + Handle(GEOM_Object) aFace = (*it); + if( aFace.IsNull() ) { + it++; + continue; + } + if( aFace->GetValue().ShapeType() != TopAbs_FACE) + continue; + if( IsSubShapeBelongsTo( anObject, -1, aFace, -1 ) ) { + aRefSh = aFace->GetLastFunction(); + aConstraints->Append(aRefSh); + it++; + } + else { + 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 +2039,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..38f00cad8 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( const GEOM::GEOM_Object_ptr theSubObject, + const CORBA::Long theSubObjectIndex, + const 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..bf79da1a6 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( const GEOM::GEOM_Object_ptr theSubobject, + const CORBA::Long theSubObjectIndex, + const 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/geomBuilder.py b/src/GEOM_SWIG/geomBuilder.py index 83c2e34b0..94c7b5d66 100644 --- a/src/GEOM_SWIG/geomBuilder.py +++ b/src/GEOM_SWIG/geomBuilder.py @@ -4555,6 +4555,30 @@ class geomBuilder(object, GEOM._objref_GEOM_Gen): RaiseIfFailed("MakeFaceFromSurface", self.ShapesOp) self._autoPublish(anObj, theName, "face") return anObj + + @ManageTransactions("ShapesOp") + def MakeFaceWithConstraints(self, theConstraints, theName=None): + """ + Create a face on the given constraints. + + Parameters: + theConstraints List of constraints. + Each constraint is a couple (Edge, Face), + where Edge is an Edge of closed Wire + and Face is a Face connected to 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.