Salome HOME
0023152: EDF GEOM: Use a self-intersected wire with MakeFace
authorvsr <vsr@opencascade.com>
Wed, 2 Sep 2015 14:16:57 +0000 (17:16 +0300)
committervsr <vsr@opencascade.com>
Thu, 17 Sep 2015 09:55:28 +0000 (12:55 +0300)
doc/salome/gui/GEOM/input/creating_face.doc
doc/salome/gui/GEOM/input/creating_isoline.doc
src/BuildGUI/BuildGUI_FaceDlg.cxx
src/BuildGUI/BuildGUI_ShellDlg.cxx
src/GEOMGUI/GEOM_msg_en.ts
src/GEOMGUI/GEOM_msg_fr.ts
src/GEOMGUI/GEOM_msg_ja.ts
src/GEOMImpl/GEOMImpl_ShapeDriver.cxx
src/GEOM_SWIG/geomBuilder.py

index cb626f83d0e1665576a83171547ee0cd467a0823..e75288de730c49f3617e952d802733a75e57ff14 100644 (file)
@@ -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 <b>TUI Command:</b> <em>geompy.MakeFaceWires([list of Shapes], isPlanarWanted)</em>
 \n <b>Arguments:</b> 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 <b>TUI Command:</b> <em>geompy.MakeFaceFromSurface(theFace, theWire)</em>
 \n <b>Arguments:</b> 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 <b>TUI Command:</b> <em>geompy.MakeFaceWithConstraints([List of constraints])</em>
 \n <b>Arguments:</b> Name + List of input edges and constraint faces. If a constraint
index c69418547ebbf10e564707fb3b4e96be27799a64..9736a29822525523b734f43acd523d697e4b2d00 100644 (file)
@@ -3,7 +3,9 @@
 \page create_isoline_page Isoline
 
 \b Isoline is a 3D curve built on a bounded face limited by <em> [Umin, Umax] </em> and <em> [Vmin, Vmax] </em>
-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 <b>Main Menu</b> select <b>New Entity - > Basic - > Isoline</b>.
 
index 1f42c752a8448b095e2e1cf7d6c07070e4e13d93..14ac07bb5de70603f4e3694874792d3675600f80 100644 (file)
@@ -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;
index 36ed6ad7ea04a24e2c04fadc63d35047c3046be9..6674e9eace88c02a269576aa12d6a894ec13e1bb 100644 (file)
@@ -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"));
index 5bec27d7cada8d342e466531ff37e127994677db..491d964f84abd7a51aa2548739a4e357776ddf8d 100644 (file)
@@ -2426,7 +2426,11 @@ Please, select face, shell or solid and try again</translation>
     </message>
     <message>
         <source>GEOM_WRN_FACES_NOT_SHELL</source>
-        <translation>Unable to create a shell. Result is a compound of faces.</translation>
+        <translation>Unable to create single shell. Result is a compound of shells.</translation>
+    </message>
+    <message>
+        <source>GEOM_WRN_FACES_NOT_FACE</source>
+        <translation>Unable to create single face. Result is a compound of faces.</translation>
     </message>
     <message>
         <source>WRN_SHAPE_UNCLOSED</source>
index 8ff9bde85a52f79d056296948934260b62c5a9fd..ef98f61ec3075121b31dfb51eb854ab846f7883b 100644 (file)
@@ -2418,7 +2418,11 @@ Choisissez une face, une coque ou un solide et essayez de nouveau</translation>
     </message>
     <message>
         <source>GEOM_WRN_FACES_NOT_SHELL</source>
-        <translation>Impossible de créer une coque. Le résultat est un assemblage de faces.</translation>
+        <translation>Impossible de créer une coque. Le résultat est un assemblage de coques.</translation>
+    </message>
+    <message>
+        <source>GEOM_WRN_FACES_NOT_FACE</source>
+        <translation>Impossible de créer une face. Le résultat est un assemblage de faces.</translation>
     </message>
     <message>
         <source>WRN_SHAPE_UNCLOSED</source>
index 4a7d00101ccb5f36742796d83cba974535affb39..2ed220891589fd2e9f467dd7a763769999f3f2d4 100644 (file)
       <source>GEOM_WRN_FACES_NOT_SHELL</source>
       <translation>シェルを作成できません。面の結合です。</translation>
     </message>
+    <message>
+      <source>GEOM_WRN_FACES_NOT_FACE</source>
+      <translation type="unfinished">Impossible de créer une face. Le résultat est un assemblage de faces.</translation>
+    </message>
     <message>
       <source>WRN_SHAPE_UNCLOSED</source>
       <translation>閉じていないオブジェクト %1 からソリッドを作成できません</translation>
index 35224af79f4d042e5f04f99a70c68eb8316b854a..46b7d1d7bd3c45999edf4e430cb7db9a89ebdb85 100644 (file)
 
 #include <list>
 
+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<TopoDS_Shape> 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<TopoDS_Shape> ::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<TopAbs_ShapeEnum> 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<TopAbs_ShapeEnum>::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);
 
index be3cffc073b82c27bb3c1cb8d724fc415a76d632..46573011e832db7b49ca4cd35c3471b2bb99ad62 100644 (file)
@@ -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 ))