]> SALOME platform Git repositories - modules/geom.git/commitdiff
Salome HOME
Implement bos #35141 Makewire keeping types of edges jfa/35141_MakeWire 22/head
authorjfa <jfa@opencascade.com>
Mon, 17 Jul 2023 20:49:52 +0000 (21:49 +0100)
committerjfa <jfa@opencascade.com>
Mon, 27 May 2024 12:07:29 +0000 (13:07 +0100)
15 files changed:
doc/salome/examples/topological_geom_objs_ex02.py
doc/salome/gui/GEOM/input/creating_wire.doc
idl/GEOM_Gen.idl
src/BuildGUI/BuildGUI_WireDlg.cxx
src/GEOMImpl/GEOMImpl_IShapes.hxx
src/GEOMImpl/GEOMImpl_IShapesOperations.cxx
src/GEOMImpl/GEOMImpl_IShapesOperations.hxx
src/GEOMImpl/GEOMImpl_ShapeDriver.cxx
src/GEOMImpl/GEOMImpl_ShapeDriver.hxx
src/GEOM_I/GEOM_IShapesOperations_i.cc
src/GEOM_I/GEOM_IShapesOperations_i.hh
src/GEOM_I_Superv/GEOM_Superv_i.cc
src/GEOM_SWIG/geomBuilder.py
test/test_wire_modes.py [new file with mode: 0644]
test/tests.set

index 5e1c284973035c4d5f59878dd5381290f4820e66..bdc20c3644cd2a8d35b829a460c3d168c94d1576 100644 (file)
@@ -26,3 +26,32 @@ id_wire = geompy.addToStudy(wire,"Wire")
 
 # display the wire
 gg.createAndDisplayGO(id_wire) 
+
+# Create a wire from edges that are not connected to each other.
+# Given tolerance should cover the gaps to build connected wire.
+# Three different modes to do that are possible.
+gap = 1
+tolerance = gap
+px_gap  = geompy.MakeVertex(100. + gap, 0.  , 0.  )
+py_gap  = geompy.MakeVertex(0.  , 100. + gap, 0.  )
+vxy_gap = geompy.MakeVector(px_gap, py_gap)
+
+# 1. Join edges by fixing tolerance
+wire_ft = geompy.MakeWire([vxy_gap, arc], tolerance, "wire_fixed_tolerance")
+# final wire tolerance will be near the half of the gap (0.5)
+print(geompy.Tolerance(wire_ft)[5])
+assert(abs(geompy.Tolerance(wire_ft)[5] - 0.5) < 1e-04)
+
+# 2. Join edges by changing their underlying curves (but keeping curve types)
+#    This functionality is available in TUI only.
+wire_cc = geompy.MakeWireConstCurveType([vxy_gap, arc], tolerance, "wire_const_curve_type")
+# final wire tolerance will stay small
+print(geompy.Tolerance(wire_cc)[5])
+assert(geompy.Tolerance(wire_cc)[5] < 1e-04)
+
+# 3. Join edges by changing their underlying curves (approximating with b-splines)
+#    This functionality is available in TUI only.
+wire_ap = geompy.MakeWireWithMode([vxy_gap, arc], tolerance, GEOM.WBM_Approximation, "wire_approximated_curves")
+# final wire tolerance will stay small
+print(geompy.Tolerance(wire_ap)[5])
+assert(geompy.Tolerance(wire_ap)[5] < 1e-04)
index 917332160a73166fb2e816a7cc85e756115de998..858fb29f6ae3edacc16c2f41216bcf81cfae73e6 100644 (file)
@@ -29,7 +29,7 @@ connect in the middle of the gap.
 
 \image html wiresn.png "Wire"
 
-Our <b>TUI Scripts</b> provide you with useful examples of creation of 
-\ref tui_creation_wire "Advanced Geometric Objects".
+Our <b>TUI Scripts</b> provide you with useful examples of 
+\ref tui_creation_wire "Creation of a Wire".
 
 */
index 9bf78ddb87e134172cf76b703a3cec09b9f60dda..d1428637a75e00fa1f489ad69c213e6658e749bb 100644 (file)
@@ -220,6 +220,29 @@ module GEOM
     CC_LE  ///< Less then or equal to
   };
 
+  /*!
+   *  \brief Wire construction mode. Regulates the way gaps are closed.
+   *
+   *  Is used in function GEOM_IShapesOperations.MakeWire()
+   */
+  enum wire_build_mode
+  {
+    /*! Do not change curves, just enlarge wire tolerance to cover the gaps */
+    WBM_FixTolerance,
+
+    /*!
+     *  Replace curves, neighbour to the gap,
+     *  with BSplines, connecting in the middle of the gap
+     */
+    WBM_Approximation,
+
+    /*!
+     *  Replace curves, neighbour to the gap, with new curves of the same
+     *  type and close parameters, connecting in the middle of the gap
+     */
+    WBM_KeepCurveType
+  };
+
   /*!
    * \brief Object creation parameters
    *
@@ -2034,10 +2057,12 @@ module GEOM
      *  \param theEdgesAndWires List of edge and/or wires.
      *  \param theTolerance Maximum distance between vertices, that will be merged.
      *                      Values less than 1e-07 are equivalent to 1e-07 (Precision::Confusion()).
+     *  \param theMode Mode of gaps filling.
      *  \return New GEOM_Object, containing the created wire.
      */
     GEOM_Object MakeWire (in ListOfGO theEdgesAndWires,
-                          in double   theTolerance);
+                          in double   theTolerance,
+                          in wire_build_mode theMode);
 
     /*!
      *  \brief Create a face on the given wire.
index 916f99e67ceb4e9230a2bd02c51c07cf20c85051..609f5fa8aee169665160ed19376326560deadfa3 100644 (file)
@@ -288,7 +288,9 @@ bool BuildGUI_WireDlg::execute (ObjectList& objects)
   for ( int i = 0; i < myEdgesAndWires.count(); i++ )
     objlist[i] = myEdgesAndWires[i].copy();
 
-  GEOM::GEOM_Object_var anObj = anOper->MakeWire(objlist.in(), GroupArgs->SpinBox_DX->value());
+  GEOM::GEOM_Object_var anObj = anOper->MakeWire(objlist.in(),
+                                                 GroupArgs->SpinBox_DX->value(),
+                                                 GEOM::WBM_FixTolerance);
 
   if (!anObj->_is_nil())
     objects.push_back(anObj._retn());
index d58e82dbfaf9d4e2a39181a2057b8203f9d9ac18..60d7e8750575fca69ca05900a123012d9a8d3f36 100644 (file)
@@ -41,6 +41,7 @@ class GEOMImpl_IShapes
     SHAPE_ARG_INDICES   = 5, // for Sub-shape
     SHAPE_ARG_TOLERANCE = 6, // linear tolerance (for Wire, Edge)
     SHAPE_ARG_ANGLE_TOL = 7, // angular tolerance (for Edge)
+    SHAPE_ARG_WIRE_MODE = 8, // gaps closing mode (for Wire)
   };
 
   GEOMImpl_IShapes(Handle(GEOM_Function) theFunction): _func(theFunction) {}
@@ -77,6 +78,11 @@ class GEOMImpl_IShapes
 
   Standard_Real GetTolerance() { return _func->GetReal(SHAPE_ARG_TOLERANCE); }
 
+  void SetWireMode(const Standard_Integer theValue)
+  { _func->SetInteger(SHAPE_ARG_WIRE_MODE, theValue); }
+
+  Standard_Integer GetWireMode() { return _func->GetInteger(SHAPE_ARG_WIRE_MODE); }
+
   void SetAngularTolerance(const Standard_Real theValue)
   { _func->SetReal(SHAPE_ARG_ANGLE_TOL, theValue); }
 
index c253bba984d8d1bacc55d59fe34373a8c927176b..edc8d56fdd4fa415ed6f14534494d9c86317e45a 100644 (file)
@@ -379,7 +379,8 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeEdgeWire
 //=============================================================================
 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeWire
                              (std::list<Handle(GEOM_Object)> theShapes,
-                              const Standard_Real            theTolerance)
+                              const Standard_Real            theTolerance,
+                              const GEOMImpl_WireBuildMode   theMode)
 {
   SetErrorCode(KO);
 
@@ -396,6 +397,7 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeWire
 
   GEOMImpl_IShapes aCI (aFunction);
   aCI.SetTolerance(theTolerance);
+  aCI.SetWireMode(theMode);
 
   Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
 
@@ -426,7 +428,19 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeWire
 
   //Make a Python command
   GEOM::TPythonDump pd (aFunction);
-  pd << aWire << " = geompy.MakeWire([";
+  pd << aWire;
+  switch (theMode) {
+  case GEOMImpl_WBM_FixTolerance:
+    pd << " = geompy.MakeWire([";
+    break;
+  case GEOMImpl_WBM_Approximation:
+    pd << " = geompy.MakeWireWithMode([";
+    break;
+  case GEOMImpl_WBM_KeepCurveType:
+    pd << " = geompy.MakeWireConstCurveType([";
+    break;
+  default: ;
+  }
 
   // Shapes
   it = theShapes.begin();
@@ -436,7 +450,11 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeWire
       pd << ", " << (*it++);
     }
   }
-  pd << "], " << theTolerance << ")";
+  pd << "], " << theTolerance;
+  if (theMode == GEOMImpl_WBM_Approximation) {
+    pd << ", GEOM.WBM_Approximation";
+  }
+  pd << ")";
 
   SetErrorCode(OK);
   return aWire;
index cd20bea5fabe6dd32bbbf81b11f1dae52e2d8b54..dc352ba585e11261f1ec7883874fba9b7204d03e 100644 (file)
@@ -48,6 +48,12 @@ class GEOM_Engine;
 class GEOM_Object;
 class TopoDS_Shape;
 
+enum GEOMImpl_WireBuildMode {
+  GEOMImpl_WBM_FixTolerance  = 1,
+  GEOMImpl_WBM_Approximation = 2,
+  GEOMImpl_WBM_KeepCurveType = 3
+};
+
 class GEOMImpl_IShapesOperations : public GEOM_IOperations
 {
  public:
@@ -94,7 +100,8 @@ class GEOMImpl_IShapesOperations : public GEOM_IOperations
                                                     const Standard_Real theAngularTolerance);
 
   Standard_EXPORT Handle(GEOM_Object) MakeWire (std::list<Handle(GEOM_Object)> theEdgesAndWires,
-                                                const Standard_Real            theTolerance);
+                                                const Standard_Real            theTolerance,
+                                                const GEOMImpl_WireBuildMode   theMode = GEOMImpl_WBM_FixTolerance);
 
   Standard_EXPORT Handle(GEOM_Object) MakeFace (Handle(GEOM_Object) theWire, const bool isPlanarWanted);
 
index 8f1f24850f4c42257354fa14ef3fac2ac9f8445f..0923bd112dc33700c8bf45fee129aeb5e375ff41 100644 (file)
@@ -22,6 +22,8 @@
 
 #include <GEOMImpl_ShapeDriver.hxx>
 
+#include <Basics_OCCTVersion.hxx>
+
 #include <GEOMImpl_IExtract.hxx>
 #include <GEOMImpl_IIsoline.hxx>
 #include <GEOMImpl_IShapes.hxx>
@@ -436,7 +438,9 @@ Standard_Integer GEOMImpl_ShapeDriver::Execute(Handle(TFunction_Logbook)& log) c
     if (aTolerance < Precision::Confusion())
       aTolerance = Precision::Confusion();
 
-    aShape = MakeWireFromEdges(aShapes, aTolerance);
+    Standard_Integer aMode = aCI.GetWireMode();
+
+    aShape = MakeWireFromEdges(aShapes, aTolerance, (GEOMImpl_WireBuildMode)aMode);
   }
   else if (aType == FACE_WIRE) {
     // result may be a face or a compound of faces
@@ -1088,7 +1092,8 @@ Standard_Integer GEOMImpl_ShapeDriver::Execute(Handle(TFunction_Logbook)& log) c
 }
 
 TopoDS_Wire GEOMImpl_ShapeDriver::MakeWireFromEdges(const Handle(TColStd_HSequenceOfTransient)& theEdgesFuncs,
-                                                    const Standard_Real theTolerance)
+                                                    const Standard_Real theTolerance,
+                                                    const GEOMImpl_WireBuildMode theMode)
 {
   BRep_Builder B;
 
@@ -1136,14 +1141,30 @@ TopoDS_Wire GEOMImpl_ShapeDriver::MakeWireFromEdges(const Handle(TColStd_HSequen
   }
   aFW->ClosedWireMode() = isClosed;
   aFW->FixConnected(theTolerance);
+
   if (aFW->StatusConnected(ShapeExtend_FAIL)) {
     Standard_ConstructionError::Raise("Wire construction failed: cannot build connected wire");
   }
   // IMP 0019766
 
-  if (aFW->StatusConnected(ShapeExtend_DONE3)) {
-    // Confused with <prec> but not Analyzer.Precision(), set the same
-    aFW->SetPrecision(theTolerance); // bos #33377, prevent conversion of initial curves to BSplines
+  if (theMode == GEOMImpl_WBM_KeepCurveType) {
+#if OCC_VERSION_LARGE > 0x07050305
+    aFW->FixCurves();
+    if (aFW->StatusCurves(ShapeExtend_FAIL1)) {
+      Standard_ConstructionError::Raise("Wire construction failed: cannot update Bezier or B-Spline curve ends, because they don't correspond to the first and last poles");
+    }
+    if (aFW->StatusCurves(ShapeExtend_FAIL)) {
+      Standard_ConstructionError::Raise("Wire construction failed: cannot rebuild curves through new points");
+    }
+#else
+    Standard_NotImplemented::Raise("Wire construction failed: option KeepCurveType is not supported by current OCCT version: please, use OCCT 7.5.3p6 or newer.");
+#endif // OCC_VERSION_LARGE > 0x07050305
+  }
+  else if (aFW->StatusConnected(ShapeExtend_DONE3)) {
+    if (theMode != GEOMImpl_WBM_Approximation) {
+      // Confused with <prec> but not Analyzer.Precision(), set the same
+      aFW->SetPrecision(theTolerance);
+    }
     aFW->FixGapsByRangesMode() = Standard_True;
     if (aFW->FixGaps3d()) {
       Handle(ShapeExtend_WireData) sbwd = aFW->WireData();
@@ -1906,6 +1927,7 @@ GetCreationInformation(std::string&             theOperationName,
     theOperationName = "WIRE";
     AddParam( theParams, "Wires/edges", aCI.GetShapes() );
     AddParam( theParams, "Tolerance", aCI.GetTolerance() );
+    AddParam( theParams, "Mode", aCI.GetWireMode() );
     break;
   case FACE_WIRE:
     theOperationName = "FACE";
index 1e3328781e7e6187ae3d22f2c56085c8769eb942..4336142fa470a847b6dc775532b3ecd78887e751 100644 (file)
@@ -31,6 +31,8 @@
 #include <TopoDS_Wire.hxx>
 #include <TColStd_HSequenceOfTransient.hxx>
 
+#include "GEOMImpl_IShapesOperations.hxx"
+
 #include <GEOM_BaseDriver.hxx>
 
 class TopoDS_Face;
@@ -56,7 +58,8 @@ public:
 
   Standard_EXPORT static TopoDS_Wire MakeWireFromEdges
                                      (const Handle(TColStd_HSequenceOfTransient)& theEdgesFuncs,
-                                      const Standard_Real theTolerance);
+                                      const Standard_Real theTolerance,
+                                      const GEOMImpl_WireBuildMode theMode = GEOMImpl_WBM_FixTolerance);
   Standard_EXPORT virtual
   bool GetCreationInformation(std::string&             theOperationName,
                               std::vector<GEOM_Param>& params);
index 7526c83ed43a32c5628beaacb7f9f62543810282..1e02554d7788ac4d7f02ce9cadf5753fe07bd92a 100644 (file)
@@ -186,7 +186,8 @@ GEOM::GEOM_Object_ptr GEOM_IShapesOperations_i::MakeEdgeWire
 //=============================================================================
 GEOM::GEOM_Object_ptr GEOM_IShapesOperations_i::MakeWire
                            (const GEOM::ListOfGO& theEdgesAndWires,
-                            const CORBA::Double   theTolerance)
+                            const CORBA::Double   theTolerance,
+                            const GEOM::wire_build_mode theMode)
 {
   GEOM::GEOM_Object_var aGEOMObject;
 
@@ -204,9 +205,22 @@ GEOM::GEOM_Object_ptr GEOM_IShapesOperations_i::MakeWire
     aShapes.push_back(aSh);
   }
 
+  // Mode of gaps closing
+  GEOMImpl_WireBuildMode aMode = GEOMImpl_WBM_FixTolerance;
+  switch (theMode) {
+  case GEOM::WBM_Approximation:
+    aMode = GEOMImpl_WBM_Approximation;
+    break;
+  case GEOM::WBM_KeepCurveType:
+    aMode = GEOMImpl_WBM_KeepCurveType;
+    break;
+  default:
+    break;
+  }
+
   // Make Solid
   Handle(::GEOM_Object) anObject =
-    GetOperations()->MakeWire(aShapes, theTolerance);
+    GetOperations()->MakeWire(aShapes, theTolerance, aMode);
   if (!GetOperations()->IsDone() || anObject.IsNull())
     return aGEOMObject._retn();
 
index 28c5944f409e374a936dc68d1c33ec3dcf243f3d..2d8cdf36eddaacd4f0a8994062c42c373bc7c67b 100644 (file)
@@ -56,7 +56,8 @@ class GEOM_I_EXPORT GEOM_IShapesOperations_i :
                                      const CORBA::Double theAngularTolerance);
 
   GEOM::GEOM_Object_ptr MakeWire (const GEOM::ListOfGO& theEdgesAndWires,
-                                  const CORBA::Double   theTolerance);
+                                  const CORBA::Double   theTolerance,
+                                  const GEOM::wire_build_mode theMode);
 
   GEOM::GEOM_Object_ptr MakeFace (GEOM::GEOM_Object_ptr theWire,
                                   CORBA::Boolean  isPlanarWanted);
index ecca075325c2ee6f78c9723b6f6f93cf66435302..c510ec9a376665ab309dcbb48508140e2a27aa82 100644 (file)
@@ -2153,7 +2153,7 @@ GEOM::GEOM_Object_ptr GEOM_Superv_i::MakeWire (GEOM::GEOM_List_ptr theEdgesAndWi
   if (GEOM_List_i<GEOM::ListOfGO>* aListImplEW =
       dynamic_cast<GEOM_List_i<GEOM::ListOfGO>*>(GetServant(theEdgesAndWires, myPOA).in())) {
     getShapesOp();
-    GEOM::GEOM_Object_ptr anObj = myShapesOp->MakeWire(aListImplEW->GetList(), theTolerance);
+    GEOM::GEOM_Object_ptr anObj = myShapesOp->MakeWire(aListImplEW->GetList(), theTolerance, GEOM::WBM_FixTolerance);
     endService( " GEOM_Superv_i::MakeWire" );
     return anObj;
   }
index d62ca1288c1afb566b0e281a0a0c3bf41f8fc119..7cf3edc64a4c34e8b7e9013927a28297bee6263d 100644 (file)
@@ -4717,6 +4717,8 @@ class geomBuilder(GEOM._objref_GEOM_Gen):
             return anObj
 
         ## Create a wire from the set of edges and wires.
+        #  To close a gap, enlarges wire tolerance.
+        #
         #  @param theEdgesAndWires List of edges and/or wires.
         #  @param theTolerance Maximum distance between vertices, that will be merged.
         #                      Values less than 1e-07 are equivalent to 1e-07 (Precision::Confusion())
@@ -4731,6 +4733,7 @@ class geomBuilder(GEOM._objref_GEOM_Gen):
         def MakeWire(self, theEdgesAndWires, theTolerance = 1e-07, theName=None):
             """
             Create a wire from the set of edges and wires.
+            To close a gap, enlarges wire tolerance.
 
             Parameters:
                 theEdgesAndWires List of edges and/or wires.
@@ -4744,11 +4747,90 @@ class geomBuilder(GEOM._objref_GEOM_Gen):
                 New GEOM.GEOM_Object, containing the created wire.
             """
             # Example: see GEOM_TestAll.py
-            anObj = self.ShapesOp.MakeWire(theEdgesAndWires, theTolerance)
+            anObj = self.ShapesOp.MakeWire(theEdgesAndWires, theTolerance, GEOM.WBM_FixTolerance)
             RaiseIfFailed("MakeWire", self.ShapesOp)
             self._autoPublish(anObj, theName, "wire")
             return anObj
 
+        ## Create a wire from the set of edges and wires.
+        #  To close a gap, replaces curves, neighbour to the gap, with new curves
+        #  of the same type and close parameters, connecting in the middle of the gap.
+        #
+        #  @param theEdgesAndWires List of edges and/or wires.
+        #  @param theTolerance Maximum distance between vertices, that will be merged.
+        #                      Values less than 1e-07 are equivalent to 1e-07 (Precision::Confusion())
+        #  @param theName Object name; when specified, this parameter is used
+        #         for result publication in the study. Otherwise, if automatic
+        #         publication is switched on, default value is used for result name.
+        #
+        #  @return New GEOM.GEOM_Object, containing the created wire.
+        #
+        #  @ref tui_creation_wire "Example"
+        @ManageTransactions("ShapesOp")
+        def MakeWireConstCurveType(self, theEdgesAndWires, theTolerance = 1e-07, theName=None):
+            """
+            Create a wire from the set of edges and wires.
+            To close a gap, replaces curves, neighbour to the gap, with new curves
+            of the same type and close parameters, connecting in the middle of the gap.
+
+            Parameters:
+                theEdgesAndWires List of edges and/or wires.
+                theTolerance Maximum distance between vertices, that will be merged.
+                             Values less than 1e-07 are equivalent to 1e-07 (Precision::Confusion()).
+                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 wire.
+            """
+            anObj = self.ShapesOp.MakeWire(theEdgesAndWires, theTolerance, GEOM.WBM_KeepCurveType)
+            RaiseIfFailed("MakeWireConstCurveType", self.ShapesOp)
+            self._autoPublish(anObj, theName, "wire")
+            return anObj
+
+        ## Create a wire from the set of edges and wires.
+        #  Possible gaps are closed according to theMode.
+        #
+        #  @param theEdgesAndWires List of edges and/or wires.
+        #  @param theTolerance Maximum distance between vertices, that will be merged.
+        #                      Values less than 1e-07 are equivalent to 1e-07 (Precision::Confusion())
+        #  @param theMode GEOM.wire_build_mode Mode of gaps closing.
+        #                 Possible values are GEOM.WBM_FixTolerance, GEOM.WBM_KeepCurveType
+        #                 and GEOM.WBM_Approximation.
+        #  @param theName Object name; when specified, this parameter is used
+        #         for result publication in the study. Otherwise, if automatic
+        #         publication is switched on, default value is used for result name.
+        #
+        #  @return New GEOM.GEOM_Object, containing the created wire.
+        #
+        #  @ref tui_creation_wire "Example"
+        @ManageTransactions("ShapesOp")
+        def MakeWireWithMode(self, theEdgesAndWires, theTolerance = 1e-07,
+                             theMode = GEOM.WBM_Approximation, theName=None):
+            """
+            Create a wire from the set of edges and wires.
+            Possible gaps are closed according to theMode.
+
+            Parameters:
+                theEdgesAndWires List of edges and/or wires.
+                theTolerance Maximum distance between vertices, that will be merged.
+                             Values less than 1e-07 are equivalent to 1e-07 (Precision::Confusion()).
+                theMode GEOM.wire_build_mode Mode of gaps closing.
+                        Possible values are GEOM.WBM_FixTolerance, GEOM.WBM_KeepCurveType
+                        and GEOM.WBM_Approximation.
+                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 wire.
+            """
+            anObj = self.ShapesOp.MakeWire(theEdgesAndWires, theTolerance, theMode)
+            RaiseIfFailed("MakeWireWithMode", self.ShapesOp)
+            self._autoPublish(anObj, theName, "wire")
+            return anObj
+
         ## Create a face on the given wire.
         #  @param theWire closed Wire or Edge to build the face on.
         #  @param isPlanarWanted If TRUE, the algorithm tries to build a planar face.
diff --git a/test/test_wire_modes.py b/test/test_wire_modes.py
new file mode 100644 (file)
index 0000000..31614fa
--- /dev/null
@@ -0,0 +1,310 @@
+#  -*- coding: iso-8859-1 -*-
+# Copyright (C) 2007-2022  CEA/DEN, EDF R&D, OPEN CASCADE
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+#
+# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+#
+
+import salome
+salome.salome_init()
+
+import GEOM
+from salome.geom import geomBuilder
+import math
+geompy = geomBuilder.New()
+
+# gaps and tolerances
+halfGap = math.sqrt(2.0) / 2.0 # dx = 1 and dy = 1
+tol = 3.0 # max. gap to be closed
+prec = 1e-4 # precision of comparison
+
+# prepare edges
+O = geompy.MakeVertex(0, 0, 0)
+OX = geompy.MakeVectorDXDYDZ(1, 0, 0)
+OY = geompy.MakeVectorDXDYDZ(0, 1, 0)
+OZ = geompy.MakeVectorDXDYDZ(0, 0, 1)
+
+Vertex_1 = geompy.MakeVertex(30, 70, 0)
+Vertex_2 = geompy.MakeVertex(100, 0, 0)
+Vertex_3 = geompy.MakeVertex(100, 70, 0)
+Vertex_4 = geompy.MakeVertex(0, 70, 0)
+Vertex_5 = geompy.MakeVertex(60, 60, 0)
+Vertex_6 = geompy.MakeVertex(10, 50, 0)
+Vertex_7 = geompy.MakeVertex(20, 0, 0)
+Vertex_8 = geompy.MakeVertex(15, 80, 0)
+Vertex_9 = geompy.MakeVertex(35, 60, 0)
+Vertex_10 = geompy.MakeVertex(-20, 80, 0)
+Vertex_11 = geompy.MakeVertex(10, -10, 0)
+Vertex_12 = geompy.MakeVertex(10, 20, 0)
+Vertex_13 = geompy.MakeVertex(-10, 30, 0)
+Vertex_14 = geompy.MakeVertex(-20, 0, 0)
+Vertex_15 = geompy.MakeVertex(-10, -10, 0)
+
+# Linear segments
+Curve_1 = geompy.MakePolyline([O, Vertex_2, Vertex_3, Vertex_4], True)
+
+# Circles
+Circle_1 = geompy.MakeCircle(Vertex_3, None, 10)
+Circle_2 = geompy.MakeCircle(Vertex_5, None, 15)
+
+# Ellipses
+geomObj_1 = geompy.MakeEllipse(O, None, 30, 10)
+geomObj_2 = geompy.MakeRotation(geomObj_1, OZ, 45*math.pi/180.0)
+Translation_1 = geompy.MakeTranslation(geomObj_2, 100, 0, 0)
+geomObj_3 = geompy.MakeEllipse(None, None, 20, 10)
+geomObj_4 = geompy.MakeRotation(geomObj_3, OZ, 90*math.pi/180.0)
+Translation_2 = geompy.MakeTranslation(geomObj_4, 50, 10, 0)
+
+# Closed B-Spline curve
+Curve_2 = geompy.MakeInterpol([Vertex_1, Vertex_6, Vertex_10, Vertex_8], True, False)
+
+# Closed Bezier curve
+Curve_4 = geompy.MakeBezier([Vertex_7, Vertex_12, Vertex_13, Vertex_14, Vertex_15, Vertex_11], True)
+
+# Partition
+Partition_1 = geompy.MakePartition([Circle_1, Circle_2, Curve_1, Curve_2, Translation_1, Translation_2, Curve_4], [], [], [], geompy.ShapeType["EDGE"], 0, [], 0)
+
+[Edge_1,Edge_2,Edge_3,Edge_4,Edge_5,Edge_6,Edge_7,Edge_8,Edge_9,Edge_10,Edge_11,Edge_12,Edge_13,Edge_14,Edge_15,Edge_16,Edge_17,Edge_18,Edge_19,Edge_20,Edge_21,Edge_22,Edge_23,Edge_24,Edge_25,Edge_26,Edge_27,Edge_28,Edge_29,Edge_30,Edge_31,Edge_32] = geompy.ExtractShapes(Partition_1, geompy.ShapeType["FLAT"], True)
+
+# FuseCollinearEdges
+Wire_1 = geompy.MakeWire([Edge_16, Edge_20], 1e-07)
+Wire_2 = geompy.MakeWire([Edge_30, Edge_32], 1e-07)
+Wire_3 = geompy.MakeWire([Edge_24, Edge_31], 1e-07)
+Wire_4 = geompy.MakeWire([Edge_11, Edge_15], 1e-07)
+
+FuseEdges_1 = geompy.FuseCollinearEdgesWithinWire(Wire_1, [])
+[Edge_33] = geompy.ExtractShapes(FuseEdges_1, geompy.ShapeType["EDGE"], True)
+FuseEdges_2 = geompy.FuseCollinearEdgesWithinWire(Wire_2, [])
+[Edge_34] = geompy.ExtractShapes(FuseEdges_2, geompy.ShapeType["EDGE"], True)
+FuseEdges_3 = geompy.FuseCollinearEdgesWithinWire(Wire_3, [])
+[Edge_35] = geompy.ExtractShapes(FuseEdges_3, geompy.ShapeType["EDGE"], True)
+FuseEdges_4 = geompy.FuseCollinearEdgesWithinWire(Wire_4, [])
+[Edge_36] = geompy.ExtractShapes(FuseEdges_4, geompy.ShapeType["EDGE"], True)
+
+# Make gaps
+Translation_3 = geompy.MakeTranslation(Edge_2, -1, -1, 0) # closed bezier outer part
+Translation_4 = geompy.MakeTranslation(Edge_5, -1, 1, 0) # closed b-spline outer part
+Translation_5 = geompy.MakeTranslation(Edge_18, 0, 1, 0)
+Translation_6 = geompy.MakeTranslation(Edge_34, 1, 1, 0)
+Translation_7 = geompy.MakeTranslation(Edge_35, 1, -1, 0)
+Translation_8 = geompy.MakeTranslation(Edge_13, 0, -1, 0)
+
+Translation_9 = geompy.MakeTranslation(Edge_7, 1, 1, 0) # closed bezier inner part
+Translation_10 = geompy.MakeTranslation(Edge_9, 1, -1, 0) # closed b-spline inner part
+Translation_11 = geompy.MakeTranslation(Edge_33, 0, -1, 0)
+Translation_12 = geompy.MakeTranslation(Edge_25, -1, -1, 0)
+Translation_13 = geompy.MakeTranslation(Edge_23, -1, 1, 0)
+Translation_14 = geompy.MakeTranslation(Edge_36, 0, 1, 0)
+
+# Not closed B-Spline and Bezier curves
+translated_vertex_3 = geompy.GetSubShape(Translation_3, [3])
+translated_vertex_2 = geompy.GetSubShape(Translation_3, [2])
+Curve_1 = geompy.MakeBezier([translated_vertex_3, Vertex_11, Vertex_15, Vertex_14, translated_vertex_2], False)
+
+translated_vertex_2_1 = geompy.GetSubShape(Translation_9, [2])
+translated_vertex_3_1 = geompy.GetSubShape(Translation_9, [3])
+Curve_2 = geompy.MakeBezier([translated_vertex_2_1, Vertex_12, translated_vertex_3_1], False)
+
+translated_vertex_2_2 = geompy.GetSubShape(Translation_4, [2])
+translated_vertex_3_2 = geompy.GetSubShape(Translation_4, [3])
+Curve_3 = geompy.MakeInterpol([translated_vertex_2_2, Vertex_10, Vertex_8, translated_vertex_3_2], False, False)
+
+translated_vertex_2_3 = geompy.GetSubShape(Translation_10, [2])
+translated_vertex_3_3 = geompy.GetSubShape(Translation_10, [3])
+Curve_4 = geompy.MakeInterpol([translated_vertex_2_3, Vertex_9, Vertex_6, translated_vertex_3_3], False, False)
+
+# Make wires with different methods
+
+###########################################################
+### Use case 1. With pieces of closed Beziers and B_Splines
+###
+### MakeWire() works good
+### MakeWireConstCurveType() raises exception,
+###         as pieces of Beziers and B_Splines are not supported now
+### MakeWireWithMode(GEOM.WBM_Approximation) gives wrong result,
+###         as pieces of closed bezier curve are wrongly treated
+###########################################################
+
+# add to study argument edges
+edges_outer_1 = [Translation_3, Translation_4, Translation_5, Translation_6, Translation_7, Translation_8, Edge_3, Edge_10, Edge_12, Edge_19, Edge_21, Edge_28]
+
+edges_inner_1 = [Translation_9, Translation_10, Translation_11, Translation_12, Translation_13, Translation_14, Edge_3, Edge_10, Edge_12, Edge_19, Edge_21, Edge_28]
+
+edges_outer_1_folder = geompy.NewFolder('edges_outer_1')
+edges_inner_1_folder = geompy.NewFolder('edges_inner_1')
+
+ii = 1
+for ee in edges_outer_1:
+    geompy.addToStudy(ee, "edge_outer_1_%d"%ii)
+    geompy.PutToFolder(ee, edges_outer_1_folder)
+    ii += 1
+    pass
+ii = 1
+for ee in edges_inner_1:
+    geompy.addToStudy(ee, "edge_inner_1_%d"%ii)
+    geompy.PutToFolder(ee, edges_inner_1_folder)
+    ii += 1
+    pass
+
+# a. Old implementation (FixTolerance)
+Wire_FixTolerance_Outer_1 = geompy.MakeWire(edges_outer_1, tol, 'Wire_FixTolerance_Outer_1')
+Wire_FixTolerance_Inner_1 = geompy.MakeWire(edges_inner_1, tol, 'Wire_FixTolerance_Inner_1')
+
+# b. New implementation (ConstCurveType)
+
+# b.1. Not supported case:
+#      Errors because of not supported Bezier and B-Spline
+#      (Ends of edge do not correspond to first and last poles)
+#
+#Wire_ConstCurveType_Outer_1 = geompy.MakeWireConstCurveType(edges_outer_1, tol, 'Wire_ConstCurveType_Outer_1')
+#Wire_ConstCurveType_Inner_1 = geompy.MakeWireConstCurveType(edges_inner_1, tol, 'Wire_ConstCurveType_Inner_1')
+#
+try:
+    Wire_ConstCurveType_BezierOnly = geompy.MakeWireConstCurveType([Edge_1, Edge_6, Translation_4, Translation_5, Translation_6, Translation_7, Translation_8, Edge_3, Edge_10, Edge_12, Edge_19, Edge_21, Edge_28], tol, 'Wire_ConstCurveType_BezierOnly')
+except:
+    print("KNOWN PROBLEM: MakeWireConstCurveType doesn't support pieces of Bezier curves")
+else:
+    assert(False), "MakeWireConstCurveType should fail here"
+    pass
+#
+try:
+    Wire_ConstCurveType_BSplineOnly = geompy.MakeWireConstCurveType([Translation_9, Edge_4, Edge_8, Translation_11, Translation_12, Translation_13, Translation_14, Edge_3, Edge_10, Edge_12, Edge_19, Edge_21, Edge_28], tol, 'Wire_ConstCurveType_BSplineOnly')
+except:
+    print("KNOWN PROBLEM: MakeWireConstCurveType doesn't support pieces of BSpline curves")
+else:
+    assert(False), "MakeWireConstCurveType should fail here"
+    pass
+
+# c. Approximation mode (canonical curves are approximated with b-splines)
+Wire_Approximation_Outer_1 = geompy.MakeWireWithMode(edges_outer_1, tol, GEOM.WBM_Approximation, 'Wire_Approximation_Outer_1')
+Wire_Approximation_Inner_1 = geompy.MakeWireWithMode(edges_inner_1, tol, GEOM.WBM_Approximation, 'Wire_Approximation_Inner_1')
+
+### check tolerances
+#
+tol_FO1 = geompy.Tolerance(Wire_FixTolerance_Outer_1)[5]
+tol_FI1 = geompy.Tolerance(Wire_FixTolerance_Inner_1)[5]
+assert(abs(tol_FO1 - halfGap) < prec)
+assert(abs(tol_FI1 - halfGap) < prec)
+#
+### Not supported case
+#tol_CO1 = geompy.Tolerance(Wire_ConstCurveType_Outer_1)[5]
+#tol_CI1 = geompy.Tolerance(Wire_ConstCurveType_Inner_1)[5]
+#assert(tol_CO1 < prec)
+#assert(tol_CI1 < prec)
+#
+tol_AO1 = geompy.Tolerance(Wire_Approximation_Outer_1)[5]
+tol_AI1 = geompy.Tolerance(Wire_Approximation_Inner_1)[5]
+assert(tol_AO1 < prec)
+assert(tol_AI1 < prec)
+
+### check wire length
+#
+Length_FO1 = geompy.BasicProperties( Wire_FixTolerance_Outer_1 )[0]
+Length_FI1 = geompy.BasicProperties( Wire_FixTolerance_Inner_1 )[0]
+assert(abs(Length_FO1 - 530.13081) < prec)
+assert(abs(Length_FI1 - 415.46762) < prec)
+#
+### Not supported case
+#Length_CO1 = geompy.BasicProperties( Wire_ConstCurveType_Outer_1 )[0]
+#Length_CI1 = geompy.BasicProperties( Wire_ConstCurveType_Inner_1 )[0]
+#assert(abs(Length_CO1 - ) < prec)
+#assert(abs(Length_CI1 - ) < prec)
+#
+# Here we have a problem with Approximation mode: pieces of bezier curve are wrongly treated
+Length_AO1 = geompy.BasicProperties( Wire_Approximation_Outer_1 )[0]
+Length_AI1 = geompy.BasicProperties( Wire_Approximation_Inner_1 )[0]
+#assert(math.abs(Length_AO1 - 514.35263) < prec)
+#assert(math.abs(Length_AI1 - 437.69903) < prec)
+if Length_AO1 < 520.0 or Length_AI1 > 425.0:
+    print("KNOWN PROBLEM: MakeWireWithMode(GEOM.WBM_Approximation) error: pieces of closed bezier curve are wrongly treated")
+    pass
+
+##############################################################
+### Use case 2. With entire Beziers and B_Splines (not closed)
+###
+### All three methods give good results
+##############################################################
+
+# add to study argument edges
+edges_outer_2 = [Curve_1, Curve_3, Translation_5, Translation_6, Translation_7, Translation_8, Edge_3, Edge_10, Edge_12, Edge_19, Edge_21, Edge_28]
+
+edges_inner_2 = [Curve_2, Curve_4, Translation_11, Translation_12, Translation_13, Translation_14, Edge_3, Edge_10, Edge_12, Edge_19, Edge_21, Edge_28]
+
+edges_outer_2_folder = geompy.NewFolder('edges_outer_2')
+edges_inner_2_folder = geompy.NewFolder('edges_inner_2')
+
+ii = 1
+for ee in edges_outer_2:
+    geompy.addToStudy(ee, "edge_outer_2_%d"%ii)
+    geompy.PutToFolder(ee, edges_outer_2_folder)
+    ii += 1
+    pass
+ii = 1
+for ee in edges_inner_2:
+    geompy.addToStudy(ee, "edge_inner_2_%d"%ii)
+    geompy.PutToFolder(ee, edges_inner_2_folder)
+    ii += 1
+    pass
+
+# a. Old implementation (FixTolerance)
+Wire_FixTolerance_Outer_2 = geompy.MakeWire(edges_outer_2, tol, 'Wire_FixTolerance_Outer_2')
+Wire_FixTolerance_Inner_2 = geompy.MakeWire(edges_inner_2, tol, 'Wire_FixTolerance_Inner_2')
+
+# b. New implementation (ConstCurveType)
+Wire_ConstCurveType_Outer_2 = geompy.MakeWireConstCurveType(edges_outer_2, tol, 'Wire_ConstCurveType_Outer_2')
+Wire_ConstCurveType_Inner_2 = geompy.MakeWireConstCurveType(edges_inner_2, tol, 'Wire_ConstCurveType_Inner_2')
+
+# c. Approximation mode (in case of need canonical curves are approximated with b-splines)
+Wire_Approximation_Outer_2 = geompy.MakeWireWithMode(edges_outer_2, tol, GEOM.WBM_Approximation, 'Wire_Approximation_Outer_2')
+Wire_Approximation_Inner_2 = geompy.MakeWireWithMode(edges_inner_2, tol, GEOM.WBM_Approximation, 'Wire_Approximation_Inner_2')
+
+### check tolerances
+#
+tol_FO2 = geompy.Tolerance(Wire_FixTolerance_Outer_2)[5]
+tol_FI2 = geompy.Tolerance(Wire_FixTolerance_Inner_2)[5]
+assert(abs(tol_FO2 - halfGap) < prec)
+assert(abs(tol_FI2 - halfGap) < prec)
+#
+tol_CO2 = geompy.Tolerance(Wire_ConstCurveType_Outer_2)[5]
+tol_CI2 = geompy.Tolerance(Wire_ConstCurveType_Inner_2)[5]
+assert(tol_CO2 < prec)
+assert(tol_CI2 < prec)
+#
+tol_AO2 = geompy.Tolerance(Wire_Approximation_Outer_2)[5]
+tol_AI2 = geompy.Tolerance(Wire_Approximation_Inner_2)[5]
+assert(tol_AO2 < prec)
+assert(tol_AI2 < prec)
+
+### check wire length
+#
+Length_FO2 = geompy.BasicProperties( Wire_FixTolerance_Outer_2 )[0]
+Length_FI2 = geompy.BasicProperties( Wire_FixTolerance_Inner_2 )[0]
+assert(abs(Length_FO2 - 527.57476) < prec)
+assert(abs(Length_FI2 - 421.28096) < prec)
+#
+Length_CO2 = geompy.BasicProperties( Wire_ConstCurveType_Outer_2 )[0]
+Length_CI2 = geompy.BasicProperties( Wire_ConstCurveType_Inner_2 )[0]
+assert(abs(Length_CO2 - 534.02648) < prec)
+assert(abs(Length_CI2 - 418.95420) < prec)
+#
+Length_AO2 = geompy.BasicProperties( Wire_Approximation_Outer_2 )[0]
+Length_AI2 = geompy.BasicProperties( Wire_Approximation_Inner_2 )[0]
+assert(abs(Length_AO2 - 537.15192) < prec)
+assert(abs(Length_AI2 - 422.09815) < prec)
+
+
+if salome.sg.hasDesktop():
+  salome.sg.updateObjBrowser()
index aa00e8dfe59522faa5133528e30126f02944addf..417fe17710e865a9932f91d0cf3a6244f094e643 100644 (file)
@@ -34,3 +34,9 @@ IF(${OpenCASCADE_VERSION}.${OpenCASCADE_SP_VERSION} VERSION_GREATER "7.5.3.3")
       test_WrappedFace.py
     )
 ENDIF()
+
+IF(${OpenCASCADE_VERSION}.${OpenCASCADE_SP_VERSION} VERSION_GREATER "7.5.3.5")
+    LIST(APPEND ALL_TESTS
+      test_wire_modes.py
+    )
+ENDIF()