From e27516a96fbd6b149b05e7a7d86a6eebea8947ac Mon Sep 17 00:00:00 2001 From: vsr Date: Wed, 2 Sep 2015 17:16:57 +0300 Subject: [PATCH] 0023152: EDF GEOM: Use a self-intersected wire with MakeFace --- doc/salome/gui/GEOM/input/creating_face.doc | 8 +- .../gui/GEOM/input/creating_isoline.doc | 4 +- src/BuildGUI/BuildGUI_FaceDlg.cxx | 10 +- src/BuildGUI/BuildGUI_ShellDlg.cxx | 5 +- src/GEOMGUI/GEOM_msg_en.ts | 6 +- src/GEOMGUI/GEOM_msg_fr.ts | 6 +- src/GEOMGUI/GEOM_msg_ja.ts | 4 + src/GEOMImpl/GEOMImpl_ShapeDriver.cxx | 141 ++++++++++++++---- src/GEOM_SWIG/geomBuilder.py | 12 +- 9 files changed, 149 insertions(+), 47 deletions(-) diff --git a/doc/salome/gui/GEOM/input/creating_face.doc b/doc/salome/gui/GEOM/input/creating_face.doc index cb626f83d..e75288de7 100644 --- a/doc/salome/gui/GEOM/input/creating_face.doc +++ b/doc/salome/gui/GEOM/input/creating_face.doc @@ -11,7 +11,7 @@ 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 input shapes can include shapes of any type except vertices; if the shapes are neither wires nor edges, the algorithm extracts all edges from -the input shapes and works on the obtaineed edges. +the input shapes and works on the obtained edges. \n The edges and wires do not necessarily have to be closed, the algorithm automatically builds a wire of maximum length from all given edges and wires. If several closed wires are detected the algorithm tries @@ -26,7 +26,7 @@ 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 The \b Result will be a \b GEOM_Object. It can be either a single face or, in specific cases, a compound of faces. \n TUI Command: geompy.MakeFaceWires([list of Shapes], isPlanarWanted) \n Arguments: Name + 1 wire. @@ -35,7 +35,7 @@ or unpredictable results in most operations. \n Secondly, it is possible to create a face based on another face's surface and bounded by a wire. -\n The \b Result will be a \b GEOM_Object (FACE). +\n The \b Result will be a \b GEOM_Object (face). \n TUI Command: geompy.MakeFaceFromSurface(theFace, theWire) \n Arguments: Name + 1 face + 1 wire. @@ -50,7 +50,7 @@ and constraints: \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 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 diff --git a/doc/salome/gui/GEOM/input/creating_isoline.doc b/doc/salome/gui/GEOM/input/creating_isoline.doc index c69418547..9736a2982 100644 --- a/doc/salome/gui/GEOM/input/creating_isoline.doc +++ b/doc/salome/gui/GEOM/input/creating_isoline.doc @@ -3,7 +3,9 @@ \page create_isoline_page Isoline \b Isoline is a 3D curve built on a bounded face limited by [Umin, Umax] and [Vmin, Vmax] -values of U and V parameters. For all points of the isoline U or V parameter value is constant. +values of U and V parameters. For all points of the isoline U or V parameter value is constant. + +Result of this operation is either a single edge or a compound of edges. To create an \b Isoline of a face in the Main Menu select New Entity - > Basic - > Isoline. diff --git a/src/BuildGUI/BuildGUI_FaceDlg.cxx b/src/BuildGUI/BuildGUI_FaceDlg.cxx index 1f42c752a..14ac07bb5 100644 --- a/src/BuildGUI/BuildGUI_FaceDlg.cxx +++ b/src/BuildGUI/BuildGUI_FaceDlg.cxx @@ -659,8 +659,6 @@ 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") { if ( !IsPreview() ) { SUIT_OverrideCursor wc; @@ -670,6 +668,14 @@ bool BuildGUI_FaceDlg::execute( ObjectList& objects ) } anOper->SetErrorCode("PAL_NO_ERROR"); } + else if ( anObj->GetShapeType() == GEOM::COMPOUND ) { + if ( !IsPreview() ) { + SUIT_MessageBox::warning(this, + QObject::tr("GEOM_WRN_WARNING"), + QObject::tr("GEOM_WRN_FACES_NOT_FACE")); + } + } + objects.push_back(anObj._retn()); } return res; diff --git a/src/BuildGUI/BuildGUI_ShellDlg.cxx b/src/BuildGUI/BuildGUI_ShellDlg.cxx index 36ed6ad7e..6674e9eac 100644 --- a/src/BuildGUI/BuildGUI_ShellDlg.cxx +++ b/src/BuildGUI/BuildGUI_ShellDlg.cxx @@ -262,10 +262,7 @@ bool BuildGUI_ShellDlg::execute( ObjectList& objects ) GEOM::GEOM_Object_var anObj = anOper->MakeShell( objlist.in() ); if ( !anObj->_is_nil() ) { - TopoDS_Shape aShell; - GEOMBase::GetShape(anObj, aShell, TopAbs_SHELL); - - if (aShell.IsNull()) { + if (anObj->GetShapeType() == GEOM::COMPOUND) { SUIT_MessageBox::warning(this, QObject::tr("GEOM_WRN_WARNING"), QObject::tr("GEOM_WRN_FACES_NOT_SHELL")); diff --git a/src/GEOMGUI/GEOM_msg_en.ts b/src/GEOMGUI/GEOM_msg_en.ts index 5bec27d7c..491d964f8 100644 --- a/src/GEOMGUI/GEOM_msg_en.ts +++ b/src/GEOMGUI/GEOM_msg_en.ts @@ -2426,7 +2426,11 @@ Please, select face, shell or solid and try again GEOM_WRN_FACES_NOT_SHELL - Unable to create a shell. Result is a compound of faces. + Unable to create single shell. Result is a compound of shells. + + + GEOM_WRN_FACES_NOT_FACE + Unable to create single face. Result is a compound of faces. WRN_SHAPE_UNCLOSED diff --git a/src/GEOMGUI/GEOM_msg_fr.ts b/src/GEOMGUI/GEOM_msg_fr.ts index 8ff9bde85..ef98f61ec 100644 --- a/src/GEOMGUI/GEOM_msg_fr.ts +++ b/src/GEOMGUI/GEOM_msg_fr.ts @@ -2418,7 +2418,11 @@ Choisissez une face, une coque ou un solide et essayez de nouveau GEOM_WRN_FACES_NOT_SHELL - Impossible de créer une coque. Le résultat est un assemblage de faces. + Impossible de créer une coque. Le résultat est un assemblage de coques. + + + GEOM_WRN_FACES_NOT_FACE + Impossible de créer une face. Le résultat est un assemblage de faces. WRN_SHAPE_UNCLOSED diff --git a/src/GEOMGUI/GEOM_msg_ja.ts b/src/GEOMGUI/GEOM_msg_ja.ts index 4a7d00101..2ed220891 100644 --- a/src/GEOMGUI/GEOM_msg_ja.ts +++ b/src/GEOMGUI/GEOM_msg_ja.ts @@ -2431,6 +2431,10 @@ GEOM_WRN_FACES_NOT_SHELL シェルを作成できません。面の結合です。 + + GEOM_WRN_FACES_NOT_FACE + Impossible de créer une face. Le résultat est un assemblage de faces. + WRN_SHAPE_UNCLOSED 閉じていないオブジェクト %1 からソリッドを作成できません diff --git a/src/GEOMImpl/GEOMImpl_ShapeDriver.cxx b/src/GEOMImpl/GEOMImpl_ShapeDriver.cxx index 35224af79..46b7d1d7b 100644 --- a/src/GEOMImpl/GEOMImpl_ShapeDriver.cxx +++ b/src/GEOMImpl/GEOMImpl_ShapeDriver.cxx @@ -107,6 +107,61 @@ #include +namespace +{ + // check that compound includes only shapes of expected type + bool checkCompound( TopoDS_Shape& c, TopAbs_ShapeEnum t ) + { + TopoDS_Iterator it( c, Standard_True, Standard_True ); + + // check that compound is not empty + bool result = it.More(); + + // => if expected type is TopAbs_SHAPE, we allow compound consisting of any shapes, this above check is enough + // => otherwise we have to check compound's content + // => compound sometimes can contain enclosed compound(s), we process them recursively and rebuild initial compound + + if ( t != TopAbs_SHAPE ) { + std::list compounds, shapes; + compounds.push_back( c ); + while ( !compounds.empty() && result ) { + // check that compound contains only shapes of expected type + TopoDS_Shape cc = compounds.front(); + compounds.pop_front(); + it.Initialize( cc, Standard_True, Standard_True ); + for ( ; it.More() && result; it.Next() ) { + TopAbs_ShapeEnum tt = it.Value().ShapeType(); + if ( tt == TopAbs_COMPOUND || tt == TopAbs_COMPSOLID ) { + compounds.push_back( it.Value() ); + continue; + } + shapes.push_back( it.Value() ); + result = tt == t; + } + } + if ( result ) { + if ( shapes.empty() ) { + result = false; + } + else if ( shapes.size() == 1 ) { + c = shapes.front(); + } + else { + BRep_Builder b; + TopoDS_Compound newc; + b.MakeCompound( newc ); + std::list ::const_iterator sit; + for ( sit = shapes.begin(); sit != shapes.end(); ++sit ) + b.Add( newc, *sit ); + c = newc; + } + } + } + + return result; + } +} + //modified by NIZNHY-PKV Wed Dec 28 13:48:20 2011f //static // void KeepEdgesOrder(const Handle(TopTools_HSequenceOfShape)& aEdges, @@ -146,12 +201,17 @@ Standard_Integer GEOMImpl_ShapeDriver::Execute(TFunction_Logbook& log) const TopoDS_Shape aShape; TCollection_AsciiString aWarning; - std::list anExpectedType; + + // this is an exact type of expected shape, or shape in a compound if compound is allowed as a result (see below) + TopAbs_ShapeEnum anExpectedType = TopAbs_SHAPE; + // this should be true if result can be a compound of shapes of strict type (see above) + bool allowCompound = false; BRep_Builder B; if (aType == WIRE_EDGES) { - anExpectedType.push_back(TopAbs_WIRE); + // result may be only a single wire + anExpectedType = TopAbs_WIRE; Handle(TColStd_HSequenceOfTransient) aShapes = aCI.GetShapes(); @@ -162,7 +222,9 @@ Standard_Integer GEOMImpl_ShapeDriver::Execute(TFunction_Logbook& log) const aShape = MakeWireFromEdges(aShapes, aTolerance); } else if (aType == FACE_WIRE) { - anExpectedType.push_back(TopAbs_FACE); + // result may be a face or a compound of faces + anExpectedType = TopAbs_FACE; + allowCompound = true; Handle(GEOM_Function) aRefBase = aCI.GetBase(); TopoDS_Shape aShapeBase = aRefBase->GetValue(); @@ -197,7 +259,9 @@ Standard_Integer GEOMImpl_ShapeDriver::Execute(TFunction_Logbook& log) const } } else if (aType == FACE_WIRES) { - anExpectedType.push_back(TopAbs_FACE); + // result may be a face or a compound of faces + anExpectedType = TopAbs_FACE; + allowCompound = true; // Try to build a face from a set of wires and edges int ind; @@ -325,7 +389,8 @@ Standard_Integer GEOMImpl_ShapeDriver::Execute(TFunction_Logbook& log) const } } else if (aType == FACE_FROM_SURFACE) { - anExpectedType.push_back(TopAbs_FACE); + // result may be only a face + anExpectedType = TopAbs_FACE; Handle(TColStd_HSequenceOfTransient) aShapes = aCI.GetShapes(); @@ -361,7 +426,9 @@ Standard_Integer GEOMImpl_ShapeDriver::Execute(TFunction_Logbook& log) const } } else if (aType == SHELL_FACES) { - anExpectedType.push_back(TopAbs_SHELL); + // result may be only a shell or a compound of shells + anExpectedType = TopAbs_SHELL; + allowCompound = true; Handle(TColStd_HSequenceOfTransient) aShapes = aCI.GetShapes(); unsigned int ind, nbshapes = aShapes->Length(); @@ -420,7 +487,9 @@ Standard_Integer GEOMImpl_ShapeDriver::Execute(TFunction_Logbook& log) const } else if (aType == SOLID_SHELLS) { - anExpectedType.push_back(TopAbs_SOLID); + // result may be only a solid or a compound of solids + anExpectedType = TopAbs_SOLID; + allowCompound = true; Handle(TColStd_HSequenceOfTransient) aShapes = aCI.GetShapes(); unsigned int ind, nbshapes = aShapes->Length(); @@ -463,7 +532,8 @@ Standard_Integer GEOMImpl_ShapeDriver::Execute(TFunction_Logbook& log) const aShape = Sol; } else if (aType == COMPOUND_SHAPES) { - anExpectedType.push_back(TopAbs_COMPOUND); + // result may be only a compound of any shapes + allowCompound = true; Handle(TColStd_HSequenceOfTransient) aShapes = aCI.GetShapes(); unsigned int ind, nbshapes = aShapes->Length(); @@ -484,7 +554,8 @@ Standard_Integer GEOMImpl_ShapeDriver::Execute(TFunction_Logbook& log) const } else if (aType == EDGE_WIRE) { - anExpectedType.push_back(TopAbs_EDGE); + // result may be only an edge + anExpectedType = TopAbs_EDGE; Handle(GEOM_Function) aRefBase = aCI.GetBase(); TopoDS_Shape aWire = aRefBase->GetValue(); @@ -495,9 +566,9 @@ Standard_Integer GEOMImpl_ShapeDriver::Execute(TFunction_Logbook& log) const aShape = MakeEdgeFromWire(aWire, LinTol, AngTol); } else if (aType == SOLID_FACES) { - anExpectedType.push_back(TopAbs_SOLID); - anExpectedType.push_back(TopAbs_COMPOUND); - anExpectedType.push_back(TopAbs_COMPSOLID); + // result may be only a solid or a compound of solids + anExpectedType = TopAbs_SOLID; + allowCompound = true; Handle(TColStd_HSequenceOfTransient) aShapes = aCI.GetShapes(); unsigned int ind, nbshapes = aShapes->Length(); @@ -534,7 +605,8 @@ Standard_Integer GEOMImpl_ShapeDriver::Execute(TFunction_Logbook& log) const aShape = aMV.Shape(); } else if (aType == EDGE_CURVE_LENGTH) { - anExpectedType.push_back(TopAbs_EDGE); + // result may be only an edge + anExpectedType = TopAbs_EDGE; GEOMImpl_IVector aVI (aFunction); @@ -609,7 +681,12 @@ Standard_Integer GEOMImpl_ShapeDriver::Execute(TFunction_Logbook& log) const BRepBuilderAPI_MakeEdge aME (ReOrientedCurve, UFirst, aParam); if (aME.IsDone()) aShape = aME.Shape(); - } else if (aType == SHAPE_ISOLINE) { + } + else if (aType == SHAPE_ISOLINE) { + // result may be only an edge or compound of edges + anExpectedType = TopAbs_EDGE; + allowCompound = true; + GEOMImpl_IIsoline aII (aFunction); Handle(GEOM_Function) aRefFace = aII.GetFace(); TopoDS_Shape aShapeFace = aRefFace->GetValue(); @@ -635,8 +712,11 @@ Standard_Integer GEOMImpl_ShapeDriver::Execute(TFunction_Logbook& log) const Standard_NullObject::Raise ("Shape for isoline construction is not a face"); } - } else if (aType == EDGE_UV) { - anExpectedType.push_back(TopAbs_EDGE); + } + else if (aType == EDGE_UV) { + // result may be only an edge + anExpectedType = TopAbs_EDGE; + GEOMImpl_IShapeExtend aSE (aFunction); Handle(GEOM_Function) aRefEdge = aSE.GetShape(); TopoDS_Shape aShapeEdge = aRefEdge->GetValue(); @@ -646,8 +726,10 @@ Standard_Integer GEOMImpl_ShapeDriver::Execute(TFunction_Logbook& log) const aShape = ExtendEdge(anEdge, aSE.GetUMin(), aSE.GetUMax()); } - } else if (aType == FACE_UV) { - anExpectedType.push_back(TopAbs_FACE); + } + else if (aType == FACE_UV) { + // result may be only a face + anExpectedType = TopAbs_FACE; GEOMImpl_IShapeExtend aSE (aFunction); Handle(GEOM_Function) aRefFace = aSE.GetShape(); @@ -660,8 +742,10 @@ Standard_Integer GEOMImpl_ShapeDriver::Execute(TFunction_Logbook& log) const aShape = ExtendFace(aFace, aSE.GetUMin(), aSE.GetUMax(), aSE.GetVMin(), aSE.GetVMax()); } - } else if (aType == SURFACE_FROM_FACE) { - anExpectedType.push_back(TopAbs_FACE); + } + else if (aType == SURFACE_FROM_FACE) { + // result may be only a face + anExpectedType = TopAbs_FACE; GEOMImpl_IShapeExtend aSE (aFunction); Handle(GEOM_Function) aRefFace = aSE.GetShape(); @@ -715,17 +799,18 @@ Standard_Integer GEOMImpl_ShapeDriver::Execute(TFunction_Logbook& log) const aShape = aSfs->Shape(); } - // Check if the result shape type is compatible with the expected. + // Check if the result shape is of expected type. const TopAbs_ShapeEnum aShType = aShape.ShapeType(); - if (!anExpectedType.empty()) { - bool ok = false; - std::list::const_iterator it; - for (it = anExpectedType.begin(); it != anExpectedType.end() && !ok; ++it) - ok = (*it == TopAbs_SHAPE || *it == aShType); - if (!ok) - Standard_ConstructionError::Raise("Result type check failed"); + bool ok = false; + if ( aShType == TopAbs_COMPOUND || aShType == TopAbs_COMPSOLID ) { + ok = allowCompound && checkCompound( aShape, anExpectedType ); + } + else { + ok = ( anExpectedType == TopAbs_SHAPE ) || ( aShType == anExpectedType ); } + if (!ok) + Standard_ConstructionError::Raise("Result type check failed"); aFunction->SetValue(aShape); diff --git a/src/GEOM_SWIG/geomBuilder.py b/src/GEOM_SWIG/geomBuilder.py index be3cffc07..46573011e 100644 --- a/src/GEOM_SWIG/geomBuilder.py +++ b/src/GEOM_SWIG/geomBuilder.py @@ -4679,7 +4679,7 @@ class geomBuilder(object, GEOM._objref_GEOM_Gen): # 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. + # @return New GEOM.GEOM_Object, containing the created face (compound of faces). # # @ref tui_creation_face "Example" @ManageTransactions("ShapesOp") @@ -4699,7 +4699,7 @@ class geomBuilder(object, GEOM._objref_GEOM_Gen): publication is switched on, default value is used for result name. Returns: - New GEOM.GEOM_Object, containing the created face. + New GEOM.GEOM_Object, containing the created face (compound of faces). """ # Example: see GEOM_TestAll.py anObj = self.ShapesOp.MakeFace(theWire, isPlanarWanted) @@ -4721,7 +4721,7 @@ class geomBuilder(object, GEOM._objref_GEOM_Gen): # 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. + # @return New GEOM.GEOM_Object, containing the created face (compound of faces). # # @ref tui_creation_face "Example" @ManageTransactions("ShapesOp") @@ -4741,7 +4741,7 @@ class geomBuilder(object, GEOM._objref_GEOM_Gen): publication is switched on, default value is used for result name. Returns: - New GEOM.GEOM_Object, containing the created face. + New GEOM.GEOM_Object, containing the created face (compound of faces). """ # Example: see GEOM_TestAll.py anObj = self.ShapesOp.MakeFaceWires(ToList(theWires), isPlanarWanted) @@ -4840,7 +4840,7 @@ class geomBuilder(object, GEOM._objref_GEOM_Gen): # 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 shell. + # @return New GEOM.GEOM_Object, containing the created shell (compound of shells). # # @ref tui_creation_shell "Example" @ManageTransactions("ShapesOp") @@ -4855,7 +4855,7 @@ class geomBuilder(object, GEOM._objref_GEOM_Gen): publication is switched on, default value is used for result name. Returns: - New GEOM.GEOM_Object, containing the created shell. + New GEOM.GEOM_Object, containing the created shell (compound of shells). """ # Example: see GEOM_TestAll.py anObj = self.ShapesOp.MakeShell( ToList( theFacesAndShells )) -- 2.30.2