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
- Unable to create a shell. Result is a compound of faces.
+ Unable to create single shell. Result is a compound of shells.
+
+
+
+ Unable to create single face. Result is a compound of faces.
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
- 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.
+
+
+
+ Impossible de créer une face. Le résultat est un assemblage de faces.
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 @@
シェルを作成できません。面の結合です。
+
+
+ Impossible de créer une face. Le résultat est un assemblage de faces.
+ 閉じていないオブジェクト %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 ))