]> SALOME platform Git repositories - modules/geom.git/commitdiff
Salome HOME
IMPs 0021476 (fuse edges) and 0021477 (suppress a vertex from a wire for fillet1d).
authorjfa <jfa@opencascade.com>
Fri, 27 Jul 2012 11:32:14 +0000 (11:32 +0000)
committerjfa <jfa@opencascade.com>
Fri, 27 Jul 2012 11:32:14 +0000 (11:32 +0000)
43 files changed:
doc/salome/gui/GEOM/images/fillet1d_2.png
doc/salome/gui/GEOM/images/fuse_collinear_edges.png [new file with mode: 0644]
doc/salome/gui/GEOM/input/fillet1d_operation.doc
doc/salome/gui/GEOM/input/fuse_edges_operation.doc [new file with mode: 0644]
doc/salome/gui/GEOM/input/repairing_operations.doc
doc/salome/gui/GEOM/input/tui_repairing_operations.doc
idl/GEOM_Gen.idl
resources/Makefile.am
resources/fuse_collinear_edges.png [new file with mode: 0644]
src/GEOMGUI/GEOM_images.ts
src/GEOMGUI/GEOM_msg_en.ts
src/GEOMGUI/GeometryGUI.cxx
src/GEOMGUI/GeometryGUI_Operations.h
src/GEOMImpl/GEOMImpl_Fillet1d.cxx
src/GEOMImpl/GEOMImpl_Fillet1d.hxx
src/GEOMImpl/GEOMImpl_Fillet1dDriver.cxx
src/GEOMImpl/GEOMImpl_Fillet1dDriver.hxx
src/GEOMImpl/GEOMImpl_HealingDriver.cxx
src/GEOMImpl/GEOMImpl_HealingDriver.hxx
src/GEOMImpl/GEOMImpl_IFillet1d.hxx
src/GEOMImpl/GEOMImpl_IHealing.hxx
src/GEOMImpl/GEOMImpl_IHealingOperations.cxx
src/GEOMImpl/GEOMImpl_IHealingOperations.hxx
src/GEOMImpl/GEOMImpl_ILocalOperations.cxx
src/GEOMImpl/GEOMImpl_ILocalOperations.hxx
src/GEOMImpl/GEOMImpl_IShapesOperations.cxx
src/GEOMImpl/GEOMImpl_ShapeDriver.cxx
src/GEOMImpl/GEOMImpl_ShapeDriver.hxx
src/GEOMImpl/GEOMImpl_Types.hxx
src/GEOM_I/GEOM_IHealingOperations_i.cc
src/GEOM_I/GEOM_IHealingOperations_i.hh
src/GEOM_I/GEOM_ILocalOperations_i.cc
src/GEOM_I/GEOM_ILocalOperations_i.hh
src/GEOM_I_Superv/GEOM_Superv_i.cc
src/GEOM_I_Superv/GEOM_Superv_i.hh
src/GEOM_SWIG/GEOM_TestHealing.py
src/GEOM_SWIG/geompyDC.py
src/OperationGUI/OperationGUI_Fillet1d2dDlg.cxx
src/OperationGUI/OperationGUI_Fillet1d2dDlg.h
src/RepairGUI/Makefile.am
src/RepairGUI/RepairGUI.cxx
src/RepairGUI/RepairGUI_FuseEdgesDlg.cxx [new file with mode: 0644]
src/RepairGUI/RepairGUI_FuseEdgesDlg.h [new file with mode: 0644]

index e9da08fa397faba23f410edcecd43b6bb09a59eb..053053370e833f1f0253721bee624a84e1f5340a 100644 (file)
Binary files a/doc/salome/gui/GEOM/images/fillet1d_2.png and b/doc/salome/gui/GEOM/images/fillet1d_2.png differ
diff --git a/doc/salome/gui/GEOM/images/fuse_collinear_edges.png b/doc/salome/gui/GEOM/images/fuse_collinear_edges.png
new file mode 100644 (file)
index 0000000..85531b2
Binary files /dev/null and b/doc/salome/gui/GEOM/images/fuse_collinear_edges.png differ
index 861a6ae937edc1c05b4270186f357eeeffee083b..322b7c965cd5dab037613e360ee59b40fb633156 100644 (file)
@@ -17,9 +17,13 @@ vertexes on this wire in the OCC Viewer and define the \b Radius of the Fillet.
 
 \b Note: This Operation Works for the Wires with <b>Planar Edges</b> only.
 
+\b Note: Use option <b>Fuse collinear edges to allow bigger radius</b>
+         to allow ignoring of possible secant points, i.e. the
+         joints of collinear edges, thus processing such edges as one.
+
 <b>TUI Command:</b> <em>geompy.MakeFillet1D(Shape, R, ListVertexes)</em>
 \n <b>Arguments:</b> Name + 1 shape + empty list or several vertexes + 1 value (Fillet radius).
-\n <b>Advanced options</b> \ref preview_anchor "Preview"
+\n <b>Advanced options:</b> \ref preview_anchor "Preview"
 
 <b>Examples:</b>
 
diff --git a/doc/salome/gui/GEOM/input/fuse_edges_operation.doc b/doc/salome/gui/GEOM/input/fuse_edges_operation.doc
new file mode 100644 (file)
index 0000000..7924f73
--- /dev/null
@@ -0,0 +1,23 @@
+/*!
+
+\page fuse_edges_operation_page Fuse Collinear Edges within a Wire
+
+\n To <b>Fuse Collinear Edges within a Wire</b> in the <b>Main Menu</b>
+select <b>Repair - > Fuse Collinear Edges within a Wire</b>.
+\n This operation removes selected vertices from a given wire in case
+if adjacent edges are C1 continuous. The function takes a list of
+vertices to suppress as a parameter. If the list is empty, all
+vertices in a wire are assumed.
+
+\n <b>Arguments:</b> Name + a wire + a list of vertices (can be empty).
+
+\image html fuse_collinear_edges.png
+
+\n <b>TUI Command:</b> <em>geompy.FuseCollinearEdgesWithinWire(wire, vertices)</em>,
+where <em>wire</em> is a wire and <em>vertices</em> is a list of
+vertices to be suppressed.
+
+Our <b>TUI Scripts</b> provide you with useful examples of the
+\ref tui_fuse_collinear_edges "Fuse Collinear Edges" functionality usage.
+
+*/
index 96ff03ae077c99079d6cf97e2e13c2fdc7fcb4fd..8fd31bab135a633dff6b95a8da085f70d252ce0c 100644 (file)
@@ -27,6 +27,9 @@ splits an edge in two.</li>
 reverses the normals of the selected faces.</li>
 <li>\subpage remove_extra_edges_operation_page "Remove extra edges" -
 removes seam and degenerated edges from the given shape.</li>
+<li>\subpage fuse_edges_operation_page "Fuse Collinear Edges within a Wire" -
+removes selected vertices from a given wire in case if adjacent edges
+are C1 continuous.</li>
 </ul>
 
 */
index 4b1f067cc9973e99acf73ed397cd930c8e0c8e99..0ce8b63dbd0d7b8df3eeb442b02b1cced53ab855 100644 (file)
@@ -391,5 +391,57 @@ for point in edge_points:
 salome.sg.updateObjBrowser(1) 
 \endcode
 
+\anchor tui_fuse_collinear_edges
+<br><h2>Fuse Collinear Edges within a Wire</h2>
+
+\code
+import geompy
+import salome
+
+# create vertices
+p1 = geompy.MakeVertex(0, 0, 0)
+p2 = geompy.MakeVertex(70, 0, 0)
+p3 = geompy.MakeVertex(70, 50, 0)
+p4 = geompy.MakeVertex(70, 80, 0)
+p5 = geompy.MakeVertex(50, 80, 0)
+p6 = geompy.MakeVertex(20, 80, 0)
+p7 = geompy.MakeVertex(0, 80, 0)
+p8 = geompy.MakeVertex(0, 30, 0)
+
+points = [p1, p2, p3, p4, p5, p6, p7, p8]
+
+# make a wire
+wire_1 = geompy.MakePolyline(points, True)
+
+# suppress some vertices in the wire
+wire_2 = geompy.FuseCollinearEdgesWithinWire(wire_1, [p3])
+wire_3 = geompy.FuseCollinearEdgesWithinWire(wire_1, [p5, p6])
+
+# suppress all suitable vertices in the wire
+wire_4 = geompy.FuseCollinearEdgesWithinWire(wire_1, [])
+
+wires = [wire_1, wire_2, wire_3, wire_4]
+
+# add objects in the study
+ii = 1
+for point in points:
+    geompy.addToStudy(point, "p%d"%ii)
+    ii = ii + 1
+    pass
+
+ii = 1
+for wire in wires:
+    geompy.addToStudy(wire, "wire_%d"%ii)
+    wire_points = geompy.SubShapeAllSortedCentres(wire, geompy.ShapeType["VERTEX"])
+    jj = 1
+    for point in wire_points:
+        geompy.addToStudyInFather(wire, point, "point_%d"%jj)
+        jj = jj + 1
+        pass
+    ii = ii + 1
+    pass
+
+salome.sg.updateObjBrowser(1) 
+\endcode
 
 */
index a3819178c458b5500f906a42c301e91b6402b103..f3a41ad16011e42f7dd4069fd7b07be6e0a65f88 100644 (file)
@@ -2905,11 +2905,18 @@ module GEOM
      *          <VAR>GEOM_IShapesOperations.GetSubShapeIndex()</VAR>.
      *    \note The list of vertices coudl be empty, in this case fillet fill be done
      *          at all vertices in given wire
+     *  \param doIgnoreSecantVertices If FALSE, fillet radius is always limited
+     *         by the length of the edges, nearest to the fillet vertex.
+     *         But sometimes the next edge is C1 continuous with the one, nearest to
+     *         the fillet point, and such two (or more) edges can be united to allow
+     *         bigger radius. Set this flag to TRUE to allow collinear edges union,
+     *         thus ignoring the secant vertex (vertices).
      *  \return New GEOM_Object, containing the result shape.
      */
     GEOM_Object MakeFillet1D (in GEOM_Object theShape,
                               in double      theR,
-                              in ListOfLong  theVertexes);
+                              in ListOfLong  theVertexes,
+                              in boolean     doIgnoreSecantVertices);
 
     /*!
      *  \brief Perform a symmetric chamfer on all edges of the given shape.
@@ -3120,6 +3127,16 @@ module GEOM
     GEOM_Object DivideEdge (in GEOM_Object theObject, in short theEdgeIndex,
                             in double theValue, in boolean isByParameter);
 
+    /*!
+     *  \brief Suppress the vertices in the wire in case if adjacent edges are C1 continuous.
+     *  \param theWire Wire to minimize the number of C1 continuous edges in.
+     *  \param theVertices A list of vertices to suppress. If the list
+     *                     is empty, all vertices in a wire will be assumed.
+     *  \return New GEOM_Object with modified wire.
+     */
+    GEOM_Object FuseCollinearEdgesWithinWire (in GEOM_Object theWire,
+                                              in ListOfGO theVertices);
+
     /*!
      *  \brief Get a list of wires (wrapped in GEOM_Object-s),
      *  that constitute a free boundary of the given shape.
index 6ec86cabe60c40500520550b990138d70df52d07..d5aab779ca87db29719d67a97fd2e1ef8da64ccf 100644 (file)
@@ -98,6 +98,7 @@ filletwire.png                        \
 filletface.png                 \
 filling.png                    \
 fuse.png                       \
+fuse_collinear_edges.png       \
 geometry.png                   \
 import_picture.png             \
 limit_tolerance.png            \
diff --git a/resources/fuse_collinear_edges.png b/resources/fuse_collinear_edges.png
new file mode 100644 (file)
index 0000000..52d8ff8
Binary files /dev/null and b/resources/fuse_collinear_edges.png differ
index a1580cdd473a456a7ba698057e48f3223df10b57..d15ade1d2a0f2f27da6c6e53b85f481c6f963f8d 100644 (file)
             <source>ICON_DLG_REMOVE_EXTRA_EDGES</source>
             <translation>remove_extra_edges.png</translation>
         </message>
+        <message>
+            <source>ICON_DLG_FUSE_EDGES</source>
+            <translation>fuse_collinear_edges.png</translation>
+        </message>
         <message>
             <source>ICON_DLG_CHECKSHAPE</source>
             <translation>check.png</translation>
             <source>ICO_REMOVE_EXTRA_EDGES</source>
             <translation>remove_extra_edges.png</translation>
         </message>
+        <message>
+            <source>ICO_FUSE_EDGES</source>
+            <translation>fuse_collinear_edges.png</translation>
+        </message>
         <message>
             <source>ICO_NORMALE</source>
             <translation>normale.png</translation>
index 1da62ff229d3131809ce35029967c62f10fdf4ad..cf4c13db2a3231ba6550aabf8e9230c43fea9928 100644 (file)
@@ -710,6 +710,10 @@ Please, select face, shell or solid and try again</translation>
         <source>GEOM_FILLET_1D</source>
         <translation>Fillet 1D</translation>
     </message>
+    <message>
+        <source>GEOM_FILLET_1D_IGNORE_SECANT</source>
+        <translation>Fuse collinear edges to allow bigger radius</translation>
+    </message>
     <message>
         <source>GEOM_FILLET_ABORT</source>
         <translation>Fillet can&apos;t be computed with radius %1</translation>
@@ -4306,6 +4310,30 @@ Please, select face, shell or solid and try again</translation>
         <source>STB_REMOVE_EXTRA_EDGES</source>
         <translation>Remove extra edges</translation>
     </message>
+    <message>
+        <source>GEOM_FUSE_EDGES_TITLE</source>
+        <translation>Fuse Collinear Edges within a Wire</translation>
+    </message>
+    <message>
+        <source>GEOM_FUSE_EDGES</source>
+        <translation>Fuse edges</translation>
+    </message>
+    <message>
+        <source>FUSE_EDGES_NEW_OBJ_NAME</source>
+        <translation>FuseEdges</translation>
+    </message>
+    <message>
+        <source>TOP_FUSE_EDGES</source>
+        <translation>Fuse collinear edges within a wire</translation>
+    </message>
+    <message>
+        <source>MEN_FUSE_EDGES</source>
+        <translation>Fuse Collinear Edges within a Wire</translation>
+    </message>
+    <message>
+        <source>STB_FUSE_EDGES</source>
+        <translation>Fuse collinear edges within a wire</translation>
+    </message>
     <message>
         <source>TOP_NORMALE</source>
         <translation>Normal to a face</translation>
index 1ae3b2977f37753f4451276b4d1cc28920ac6c1a..23694246d53be3d77688dcfaaf77fb1f6f29c10f 100644 (file)
@@ -535,6 +535,7 @@ void GeometryGUI::OnGUIEvent( int id )
   case GEOMOp::OpGlueEdges:          // MENU REPAIR - GLUE EDGES
   case GEOMOp::OpLimitTolerance:     // MENU REPAIR - LIMIT TOLERANCE
   case GEOMOp::OpRemoveExtraEdges:   // MENU REPAIR - REMOVE EXTRA EDGES
+  case GEOMOp::OpFuseEdges:          // MENU REPAIR - FUSE COLLINEAR EDGES
     libName = "RepairGUI";
     break;
   case GEOMOp::OpProperties:         // MENU MEASURE - PROPERTIES
@@ -813,6 +814,7 @@ void GeometryGUI::initialize( CAM_Application* app )
   createGeomAction( GEOMOp::OpFreeFaces,        "CHECK_FREE_FACES" );
   createGeomAction( GEOMOp::OpOrientation,      "CHANGE_ORIENTATION" );
   createGeomAction( GEOMOp::OpRemoveExtraEdges, "REMOVE_EXTRA_EDGES" );
+  createGeomAction( GEOMOp::OpFuseEdges,        "FUSE_EDGES" );
 
   createGeomAction( GEOMOp::OpPointCoordinates, "POINT_COORDS" );
   createGeomAction( GEOMOp::OpProperties,       "BASIC_PROPS" );
@@ -1032,6 +1034,7 @@ void GeometryGUI::initialize( CAM_Application* app )
   //createMenu( GEOMOp::OpFreeFaces,       repairId, -1 );
   createMenu( GEOMOp::OpOrientation,      repairId, -1 );
   createMenu( GEOMOp::OpRemoveExtraEdges, repairId, -1 );
+  createMenu( GEOMOp::OpFuseEdges,        repairId, -1 );
 
   int measurId = createMenu( tr( "MEN_MEASURES" ), -1, -1, 10 );
   createMenu( GEOMOp::OpPointCoordinates, measurId, -1 );
index 77e51f1c354b0e5e39224110bf73fb0104f2ba81..3d8a41d4e9efd8941c2f60807e759ce0e9fd8dda 100644 (file)
@@ -157,6 +157,7 @@ namespace GEOMOp {
     OpRemoveExtraEdges    = 4011,   // MENU REPAIR - REMOVE EXTRA EDGES
     OpLimitTolerance      = 4012,   // MENU REPAIR - LIMIT TOLERANCE
     OpGlueEdges           = 4013,   // MENU REPAIR - GLUE EDGES
+    OpFuseEdges           = 4014,   // MENU REPAIR - FUSE COLLINEAR EDGES
     // MeasureGUI ----------------//--------------------------------
     OpProperties          = 5000,   // MENU MEASURES - PROPERTIES
     OpCenterMass          = 5001,   // MENU MEASURES - CENTRE OF MASS
index c4780bd335e6432ef3117775cf52a5268d134ae7..0a648ad2ce7bf10f161108189d16fd575d30681d 100644 (file)
@@ -15,7 +15,6 @@
 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 //
 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
-//
 
 //  File   : GEOMImpl_Fillet1d.cxx
 //  Module : GEOMImpl
@@ -401,7 +400,7 @@ void GEOMImpl_Fillet1d::performNewton(GEOMImpl_Fillet1dPoint* theLeft,
     else
     {
       if (fabs(aB) > fabs(aDet * 1000000.))
-      {  // possible floating point operations accurancy errors
+      {  // possible floating point operations accuracy errors
         processPoint(theLeft, theRight, theLeft->GetParam() + aDX / 2.0); // linear division otherwise
       }
       else
index 1fb32c489a5dc937925423ad2017336dc843a64e..679e3fc70a0075eb4b48eb646f13f59a0326eb34 100644 (file)
 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 //
 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
-//
-\r
-//  File   : GEOMImpl_Fillet1d.hxx\r
-//  Module : GEOMImpl\r
-//\r
-#ifndef _GEOMImpl_Fillet1d_HeaderFile\r
-#define _GEOMImpl_Fillet1d_HeaderFile\r
-\r
-#include <gp_Pnt.hxx>\r
-#include <Geom_Plane.hxx>\r
-#include <Geom2d_Curve.hxx>\r
-\r
-#include <TopoDS_Edge.hxx>\r
-#include <TColStd_ListOfReal.hxx>\r
-#include <TColStd_SequenceOfReal.hxx>\r
-#include <TColStd_SequenceOfInteger.hxx>\r
-\r
-class GEOMImpl_Fillet1dPoint;\r
-\r
-/**\r
-* GEOMImpl_Fillet1d is 1D fillet algorithm on two planar edges with given radius\r
-*/\r
-\r
-class GEOMImpl_Fillet1d \r
-{\r
-public:\r
-  //! Constructor\r
-  //! The fillet 1D algorithm initialise by two edges and plane\r
-  Standard_EXPORT GEOMImpl_Fillet1d(const TopoDS_Edge& theEdge1,\r
-                                    const TopoDS_Edge& theEdge2,\r
-                                    const gp_Pln&      thePlane);\r
-  //! Makes fillet with given radius\r
-  //! @returns Standard_True, if at least one result computed\r
-  Standard_EXPORT Standard_Boolean Perform(const Standard_Real theRadius);\r
-  //! Returns result fillet edge and modified edges as out parameters\r
-  Standard_EXPORT TopoDS_Edge Result(const gp_Pnt& thePoint, TopoDS_Edge& theEdge1, TopoDS_Edge& theEdge2);\r
-\r
-private:\r
-  //! private methods\r
-  void fillPoint(GEOMImpl_Fillet1dPoint*);\r
-  void fillDiff(GEOMImpl_Fillet1dPoint*, Standard_Real, Standard_Boolean);\r
-  void performNewton(GEOMImpl_Fillet1dPoint*, GEOMImpl_Fillet1dPoint*);\r
-  Standard_Boolean processPoint(GEOMImpl_Fillet1dPoint*, GEOMImpl_Fillet1dPoint*, Standard_Real);\r
-\r
-\r
-private:\r
-  //! private fields\r
-  TopoDS_Edge myEdge1, myEdge2;\r
-  Handle(Geom_Plane) myPlane;\r
-  Handle(Geom2d_Curve) myCurve1, myCurve2;\r
-  Standard_Real myStart1, myEnd1, myStart2, myEnd2, myRadius;\r
-  TColStd_ListOfReal myResultParams;\r
-  TColStd_SequenceOfInteger myResultOrientation;\r
-  Standard_Boolean myStartSide, myEdgesExchnged;\r
-  Standard_Integer myDegreeOfRecursion;\r
-};\r
-\r
-\r
-/**\r
-* GEOMImpl_Fillet1dPoint is an internal class for 1D fillet algorithm\r
-*   to store and compare computed solutions on edges\r
-*/\r
-\r
-class GEOMImpl_Fillet1dPoint\r
-{\r
-public:\r
-  //! Puiblic methods\r
-\r
-  //! Constructor\r
-  Standard_EXPORT GEOMImpl_Fillet1dPoint(Standard_Real theParam)\r
-  {myParam = theParam;}\r
-  \r
-  //! Make copy of point\r
-  //!WARNING: Copies only field values: myParam, myV, myD, myValid\r
-  Standard_EXPORT GEOMImpl_Fillet1dPoint* Copy(); // warning: this is not the full copy! \r
-\r
-  //! Set/Get parameter\r
-  Standard_EXPORT inline void SetParam(Standard_Real theParam)\r
-    {myParam = theParam;}\r
-  Standard_EXPORT inline Standard_Real GetParam() const\r
-    {return myParam;}\r
-  Standard_EXPORT inline void SetParam2(const Standard_Real theParam2)\r
-    {myParam2 = theParam2;}\r
-  Standard_EXPORT inline Standard_Real GetParam2()\r
-    { return myParam2 ; }\r
-\r
-  //! Returns validity  \r
-  Standard_EXPORT inline Standard_Boolean IsValid(int theIndex)\r
-    {return (Standard_Boolean)myValid.Value(theIndex);}\r
-\r
-  //! Get values\r
-  Standard_EXPORT inline Standard_Integer GetNBValues() {return myV.Length();}\r
-  Standard_EXPORT inline Standard_Real GetValue(Standard_Integer theIndex)\r
-    {return myV.Value(theIndex);}\r
-  Standard_EXPORT inline Standard_Real GetDiff(Standard_Integer theIndex)\r
-    {return myD.Value(theIndex);}\r
-  Standard_EXPORT inline Standard_Integer GetNear(Standard_Integer theIndex)\r
-    {return myNear.Value(theIndex);}\r
-\r
-  //! Set/Get center point\r
-  Standard_EXPORT inline void SetCenter(const gp_Pnt2d thePoint)\r
-    {myCenter = thePoint;}\r
-  Standard_EXPORT inline const gp_Pnt2d GetCenter()\r
-    {return myCenter;}\r
-\r
-  Standard_EXPORT void AddValue(Standard_Real theValue, Standard_Boolean theIsValid);\r
-\r
-  //! compute difference between this and given point\r
-  Standard_EXPORT Standard_Boolean ComputeDifference(GEOMImpl_Fillet1dPoint*);\r
-  Standard_EXPORT void FilterPoints(GEOMImpl_Fillet1dPoint*);\r
-  \r
-  //! Check is point contains solution and  returns the index of them if any\r
-  Standard_EXPORT Standard_Integer HasSolution(Standard_Real theRadius); \r
-  //! Remove solution by index\r
-  void RemoveSolution(Standard_Integer theIndex);\r
-\r
-private:\r
-  //! Private fields\r
-  gp_Pnt2d myCenter;\r
-  Standard_Real myParam, myParam2;\r
-  TColStd_SequenceOfReal myV, myD;\r
-  TColStd_SequenceOfInteger myValid, myNear;\r
-};\r
-\r
-#endif\r
+
+//  File   : GEOMImpl_Fillet1d.hxx
+//  Module : GEOMImpl
+
+#ifndef _GEOMImpl_Fillet1d_HeaderFile
+#define _GEOMImpl_Fillet1d_HeaderFile
+
+#include <TopoDS_Edge.hxx>
+
+#include <Geom_Plane.hxx>
+#include <Geom2d_Curve.hxx>
+
+#include <gp_Pnt.hxx>
+
+#include <TColStd_ListOfReal.hxx>
+#include <TColStd_SequenceOfReal.hxx>
+#include <TColStd_SequenceOfInteger.hxx>
+
+class GEOMImpl_Fillet1dPoint;
+
+/**
+* GEOMImpl_Fillet1d is 1D fillet algorithm on two planar edges with given radius
+*/
+
+class GEOMImpl_Fillet1d
+{
+public:
+  //! Constructor
+  //! The fillet 1D algorithm is initialised by two edges and plane
+  Standard_EXPORT GEOMImpl_Fillet1d(const TopoDS_Edge& theEdge1,
+                                    const TopoDS_Edge& theEdge2,
+                                    const gp_Pln&      thePlane);
+  //! Makes fillet with given radius
+  //! @returns Standard_True, if at least one result computed
+  Standard_EXPORT Standard_Boolean Perform(const Standard_Real theRadius);
+
+  //! Returns result fillet edge and modified edges as out parameters
+  Standard_EXPORT TopoDS_Edge Result(const gp_Pnt& thePoint, TopoDS_Edge& theEdge1, TopoDS_Edge& theEdge2);
+
+private:
+  //! private methods
+  void fillPoint(GEOMImpl_Fillet1dPoint*);
+  void fillDiff(GEOMImpl_Fillet1dPoint*, Standard_Real, Standard_Boolean);
+  void performNewton(GEOMImpl_Fillet1dPoint*, GEOMImpl_Fillet1dPoint*);
+  Standard_Boolean processPoint(GEOMImpl_Fillet1dPoint*, GEOMImpl_Fillet1dPoint*, Standard_Real);
+
+private:
+  //! private fields
+  TopoDS_Edge myEdge1, myEdge2;
+  Handle(Geom_Plane) myPlane;
+  Handle(Geom2d_Curve) myCurve1, myCurve2;
+  Standard_Real myStart1, myEnd1, myStart2, myEnd2, myRadius;
+  TColStd_ListOfReal myResultParams;
+  TColStd_SequenceOfInteger myResultOrientation;
+  Standard_Boolean myStartSide, myEdgesExchnged;
+  Standard_Integer myDegreeOfRecursion;
+};
+
+
+/**
+* GEOMImpl_Fillet1dPoint is an internal class for 1D fillet algorithm
+*   to store and compare computed solutions on edges
+*/
+
+class GEOMImpl_Fillet1dPoint
+{
+public:
+  //! Puiblic methods
+
+  //! Constructor
+  Standard_EXPORT GEOMImpl_Fillet1dPoint(Standard_Real theParam)
+  {myParam = theParam;}
+
+  //! Make copy of point
+  //!WARNING: Copies only field values: myParam, myV, myD, myValid
+  Standard_EXPORT GEOMImpl_Fillet1dPoint* Copy(); // warning: this is not the full copy!
+
+  //! Set/Get parameter
+  Standard_EXPORT inline void SetParam(Standard_Real theParam)
+    {myParam = theParam;}
+  Standard_EXPORT inline Standard_Real GetParam() const
+    {return myParam;}
+  Standard_EXPORT inline void SetParam2(const Standard_Real theParam2)
+    {myParam2 = theParam2;}
+  Standard_EXPORT inline Standard_Real GetParam2()
+    { return myParam2 ; }
+
+  //! Returns validity
+  Standard_EXPORT inline Standard_Boolean IsValid(int theIndex)
+    {return (Standard_Boolean)myValid.Value(theIndex);}
+
+  //! Get values
+  Standard_EXPORT inline Standard_Integer GetNBValues() {return myV.Length();}
+  Standard_EXPORT inline Standard_Real GetValue(Standard_Integer theIndex)
+    {return myV.Value(theIndex);}
+  Standard_EXPORT inline Standard_Real GetDiff(Standard_Integer theIndex)
+    {return myD.Value(theIndex);}
+  Standard_EXPORT inline Standard_Integer GetNear(Standard_Integer theIndex)
+    {return myNear.Value(theIndex);}
+
+  //! Set/Get center point
+  Standard_EXPORT inline void SetCenter(const gp_Pnt2d thePoint)
+    {myCenter = thePoint;}
+  Standard_EXPORT inline const gp_Pnt2d GetCenter()
+    {return myCenter;}
+
+  Standard_EXPORT void AddValue(Standard_Real theValue, Standard_Boolean theIsValid);
+
+  //! compute difference between this and given point
+  Standard_EXPORT Standard_Boolean ComputeDifference(GEOMImpl_Fillet1dPoint*);
+  Standard_EXPORT void FilterPoints(GEOMImpl_Fillet1dPoint*);
+
+  //! Checks if point contains solution and returns the index of it if any
+  Standard_EXPORT Standard_Integer HasSolution(Standard_Real theRadius);
+  //! Remove solution by index
+  void RemoveSolution(Standard_Integer theIndex);
+
+private:
+  //! Private fields
+  gp_Pnt2d myCenter;
+  Standard_Real myParam, myParam2;
+  TColStd_SequenceOfReal myV, myD;
+  TColStd_SequenceOfInteger myValid, myNear;
+};
+
+#endif
index bd99d94d7edc8de76e1b8ccb2fc48f90e75752fb..f781f228eb4e41ad6e79a6a64fd69fe6cfb85bd0 100644 (file)
@@ -15,7 +15,6 @@
 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 //
 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
-//
 
 #include <Standard_Stream.hxx>
 
 #include <GEOMImpl_Fillet1d.hxx>
 #include <GEOMImpl_IFillet1d.hxx>
 #include <GEOMImpl_Types.hxx>
-#include <GEOMImpl_ILocalOperations.hxx>
 #include <GEOMImpl_IShapesOperations.hxx>
+#include <GEOMImpl_HealingDriver.hxx>
 #include <GEOM_Function.hxx>
 
-#include <gp_Pln.hxx>
-#include <gp_Dir.hxx>
-#include <gp_XYZ.hxx>
-
-#include <BRep_Tool.hxx>
-#include <BRepTools.hxx>
-#include <BRepBuilderAPI_MakeWire.hxx>
-#include <BRepCheck_Analyzer.hxx>
-
-#include <Precision.hxx>
-
 #include <ShapeFix_Wire.hxx>
 #include <StdFail_NotDone.hxx>
 #include <Standard_ConstructionError.hxx>
 #include <TopTools_ListOfShape.hxx>
 #include <TopTools_ListIteratorOfListOfShape.hxx>
 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
+#include <TopTools_IndexedMapOfShape.hxx>
+
+#include <BRep_Tool.hxx>
+#include <BRepTools.hxx>
+#include <BRepBuilderAPI_MakeWire.hxx>
+#include <BRepCheck_Analyzer.hxx>
+
+#include <gp_Pln.hxx>
+#include <gp_Dir.hxx>
+#include <gp_XYZ.hxx>
+
+#include <Precision.hxx>
 
 //=======================================================================
 //function : GetID
@@ -161,32 +161,112 @@ Standard_Integer GEOMImpl_Fillet1dDriver::Execute(TFunction_Logbook& log) const
 
   TopoDS_Wire aWire = TopoDS::Wire(aShape);
 
-  double rad = aCI.GetR();
+  bool doIgnoreSecantPoints = aCI.GetFlag();
 
-  if ( rad < Precision::Confusion())
+  double rad = aCI.GetR();
+  if (rad < Precision::Confusion())
     return 0;
 
   // collect vertices for make fillet
   TopTools_ListOfShape aVertexList;
-  TopTools_MapOfShape mapShape;
+  TopTools_IndexedMapOfShape anIndices;
+  TopExp::MapShapes(aWire, anIndices);
   int aLen = aCI.GetLength();
-  if ( aLen > 0 ) {
-    for (int ind = 1; ind <= aLen; ind++) {
-      TopoDS_Shape aShapeVertex;
-      if (GEOMImpl_ILocalOperations::GetSubShape
-          (aWire, aCI.GetVertex(ind), aShapeVertex))
-        if (mapShape.Add(aShapeVertex))
-          aVertexList.Append( aShapeVertex );
+  if (aLen > 0) {
+    for (int ii = 1; ii <= aLen; ii++) {
+      int ind = aCI.GetVertex(ii);
+      if (1 <= ind && ind <= anIndices.Extent()) {
+        TopoDS_Shape aShapeVertex = anIndices.FindKey(ind);
+        if (aShapeVertex.ShapeType() == TopAbs_VERTEX)
+          aVertexList.Append(aShapeVertex);
+      }
     }
-  } else { // get all vertices from wire
-    TopExp_Explorer anExp( aWire, TopAbs_VERTEX );
-    for ( ; anExp.More(); anExp.Next() ) {
+  }
+  else { // get all vertices from wire
+    TopTools_MapOfShape mapShape;
+    TopExp_Explorer anExp (aWire, TopAbs_VERTEX);
+    for (; anExp.More(); anExp.Next()) {
       if (mapShape.Add(anExp.Current()))
-        aVertexList.Append( anExp.Current() );
+        aVertexList.Append(anExp.Current());
     }
   }
   if (aVertexList.IsEmpty())
-    Standard_ConstructionError::Raise("Invalid input no vertices to make fillet");
+    Standard_ConstructionError::Raise("Invalid input: no vertices to make fillet");
+
+  // at first we try to make fillet on the initial wire (without edges fusing)
+  bool isFinalPass = !doIgnoreSecantPoints;
+  TopoDS_Wire aResult;
+  bool isAllStepsOk = MakeFillet(aWire, aVertexList, rad, isFinalPass, aResult);
+
+  // try to fuse collinear edges to allow bigger radius
+  if (!isFinalPass && !isAllStepsOk) {
+    // 1. Fuse
+    TopoDS_Shape aShapeNew;
+    Handle(TColStd_HSequenceOfTransient) aVerts;
+    GEOMImpl_HealingDriver::FuseCollinearEdges(aWire, aVerts, aShapeNew);
+    TopoDS_Wire aWireNew = TopoDS::Wire(aShapeNew);
+
+    // 2. Rebuild the list of vertices (by coincidence)
+    Standard_Real tol, tolMax = Precision::Confusion();
+    for (TopExp_Explorer ExV (aWireNew, TopAbs_VERTEX); ExV.More(); ExV.Next()) {
+      TopoDS_Vertex Vertex = TopoDS::Vertex(ExV.Current());
+      tol = BRep_Tool::Tolerance(Vertex);
+      if (tol > tolMax)
+        tolMax = tol;
+    }
+
+    TopTools_ListOfShape aVertexListNew;
+    TopTools_IndexedMapOfShape anIndicesNew;
+    TopExp::MapShapes(aWireNew, anIndicesNew);
+    TopTools_ListIteratorOfListOfShape anIt (aVertexList);
+    for (; anIt.More(); anIt.Next()) {
+      TopoDS_Vertex aV = TopoDS::Vertex(anIt.Value());
+      if (anIndicesNew.Contains(aV))
+        aVertexListNew.Append(aV);
+      else {
+        // try to find by coords in the new wire
+        gp_Pnt aP = BRep_Tool::Pnt(aV);
+
+        bool isFound = false;
+        TopTools_MapOfShape mapShape;
+        TopExp_Explorer exp (aWireNew, TopAbs_VERTEX);
+        for (; exp.More() && !isFound; exp.Next()) {
+          if (mapShape.Add(exp.Current())) {
+            TopoDS_Vertex aVi = TopoDS::Vertex(exp.Current());
+            gp_Pnt aPi = BRep_Tool::Pnt(aVi);
+            if (aPi.Distance(aP) < tolMax) {
+              aVertexListNew.Append(aVi);
+              isFound = true;
+            }
+          }
+        }
+      }
+    }
+
+    // 3. Repeat the fillet algorithm
+    isFinalPass = true;
+    MakeFillet(aWireNew, aVertexListNew, rad, isFinalPass, aResult);
+  }
+
+  aFunction->SetValue(aResult);
+  log.SetTouched(Label());
+
+  return 1;
+}
+
+//=======================================================================
+//function : MakeFillet
+//purpose  :
+//=======================================================================
+bool GEOMImpl_Fillet1dDriver::MakeFillet(const TopoDS_Wire& aWire,
+                                         const TopTools_ListOfShape& aVertexList,
+                                         const Standard_Real rad,
+                                         bool isFinalPass,
+                                         TopoDS_Wire& aResult) const
+{
+  // this variable is needed to break execution
+  // in case of fillet failure and try to fuse edges
+  bool isAllStepsOk = true;
 
   //INFO: this algorithm implemented in assumption that user can select both
   //  vertices of some edges to make fillet. In this case we should remember
@@ -220,54 +300,69 @@ Standard_Integer GEOMImpl_Fillet1dDriver::Execute(TFunction_Logbook& log) const
     if ( !takePlane(anEdge1, anEdge2, aV, aPlane) )
       continue; // seems edges does not belong to same plane or parallel (fillet can not be build)
 
-    GEOMImpl_Fillet1d aFilletAlgo(anEdge1, anEdge2, aPlane);
-    if ( !aFilletAlgo.Perform(rad) )
-      continue; // can not create fillet with given radius
+    GEOMImpl_Fillet1d aFilletAlgo (anEdge1, anEdge2, aPlane);
+    if (!aFilletAlgo.Perform(rad)) {
+      if (isFinalPass)
+        continue; // can not create fillet with given radius
+      else {
+        isAllStepsOk = false;
+        break; // can not create fillet with given radius
+      }
+    }
 
     // take fillet result in given vertex
     TopoDS_Edge aModifE1, aModifE2;
     TopoDS_Edge aNewE = aFilletAlgo.Result(BRep_Tool::Pnt(aV), aModifE1, aModifE2);
-    if (aNewE.IsNull())
-      continue; // no result found
+    if (aNewE.IsNull()) {
+      if (isFinalPass)
+        continue; // no result found
+      else {
+        isAllStepsOk = false;
+        break; // no result found
+      }
+    }
 
     // add  new created edges and take modified edges
-    aListOfNewEdge.Append( aNewE );
+    aListOfNewEdge.Append(aNewE);
 
-    // check if face edges modified,
-    // if yes, than map to original edges (from vertex-edges list), because edges can be modified before
+    // check if wire edges modified,
+    // if yes, then map to original edges (from vertex-edges list), because edges can be modified before
     if (aModifE1.IsNull() || !anEdge1.IsSame( aModifE1 ))
       addEdgeRelation( anEdgeToEdgeMap, TopoDS::Edge(aVertexEdges.First()), aModifE1 );
     if (aModifE2.IsNull() || !anEdge2.IsSame( aModifE2 ))
       addEdgeRelation( anEdgeToEdgeMap, TopoDS::Edge(aVertexEdges.Last()), aModifE2 );
   }
 
-  if ( anEdgeToEdgeMap.IsEmpty() && aListOfNewEdge.IsEmpty() ) {
-    StdFail_NotDone::Raise("1D Fillet can't be computed on the given shape with the given radius");
-    return 0;
+  if (anEdgeToEdgeMap.IsEmpty() && aListOfNewEdge.IsEmpty()) {
+    if (isFinalPass)
+      StdFail_NotDone::Raise("1D Fillet can't be computed on the given shape with the given radius");
+    else
+      isAllStepsOk = false;
   }
 
+  if (!isAllStepsOk)
+    return false;
+
   // create new wire instead of original
-  for ( TopExp_Explorer anExp( aWire, TopAbs_EDGE ); anExp.More(); anExp.Next() ) {
+  for (TopExp_Explorer anExp (aWire, TopAbs_EDGE); anExp.More(); anExp.Next()) {
     TopoDS_Shape anEdge = anExp.Current();
-    if ( !anEdgeToEdgeMap.IsBound( anEdge ) )
-      aListOfNewEdge.Append( anEdge );
-    else if (!anEdgeToEdgeMap.Find( anEdge ).IsNull())
-      aListOfNewEdge.Append( anEdgeToEdgeMap.Find( anEdge ) );
+    if (!anEdgeToEdgeMap.IsBound(anEdge))
+      aListOfNewEdge.Append(anEdge);
+    else if (!anEdgeToEdgeMap.Find(anEdge).IsNull())
+      aListOfNewEdge.Append(anEdgeToEdgeMap.Find(anEdge));
   }
 
-  GEOMImpl_IShapesOperations::SortShapes( aListOfNewEdge );
+  GEOMImpl_IShapesOperations::SortShapes(aListOfNewEdge);
 
   BRepBuilderAPI_MakeWire aWireTool;
-  aWireTool.Add( aListOfNewEdge );
+  aWireTool.Add(aListOfNewEdge);
   aWireTool.Build();
   if (!aWireTool.IsDone())
     return 0;
 
-  aWire = aWireTool.Wire();
-  aFunction->SetValue(aWire);
-  log.SetTouched(Label());
+  aResult = aWireTool.Wire();
 
-  return 1;
+  return isAllStepsOk;
 }
 
 
index 87b9ce89756df03b097bde326ebac5ad8257e7fe..dc8b9da89959c191b7227f50f0125fcff5c6ce15 100644 (file)
 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 //
 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
-//
 
 //  File   : GEOMImpl_Fillet1dDriver.ixx
 //  Module : GEOMImpl
-//
+
 #ifndef _GEOMImpl_Fillet1dDriver_HeaderFile
 #define _GEOMImpl_Fillet1dDriver_HeaderFile
 
@@ -48,6 +47,9 @@
 #include <Handle_TFunction_Driver.hxx>
 #endif
 
+#include <TopoDS_Wire.hxx>
+#include <TopTools_ListOfShape.hxx>
+
 class Standard_Transient;
 class Handle_Standard_Type;
 class Handle(TFunction_Driver);
@@ -123,37 +125,42 @@ class GEOMImpl_Fillet1dDriver : public TFunction_Driver {
 
 public:
 
-    inline void* operator new(size_t,void* anAddress) 
-      {
-        return anAddress;
-      }
-    inline void* operator new(size_t size) 
-      { 
-        return Standard::Allocate(size); 
-      }
-    inline void  operator delete(void *anAddress) 
-      { 
-        if (anAddress) Standard::Free((Standard_Address&)anAddress); 
-      }
-
- // Methods PUBLIC
- // 
-Standard_EXPORT GEOMImpl_Fillet1dDriver();
-Standard_EXPORT virtual  Standard_Integer Execute(TFunction_Logbook& log) const; 
-Standard_EXPORT virtual void Validate(TFunction_Logbook&) const {}
-Standard_EXPORT Standard_Boolean MustExecute(const TFunction_Logbook&) const { return Standard_True; }
-Standard_EXPORT static const Standard_GUID& GetID();
-Standard_EXPORT ~GEOMImpl_Fillet1dDriver() {};
-
-
- // Type management
- //
-Standard_EXPORT friend Handle_Standard_Type& GEOMImpl_Fillet1dDriver_Type_();
-Standard_EXPORT const Handle(Standard_Type)& DynamicType() const 
- { return STANDARD_TYPE(GEOMImpl_Fillet1dDriver) ; }
-Standard_EXPORT Standard_Boolean IsKind(const Handle(Standard_Type)& AType) const
- { return (STANDARD_TYPE(GEOMImpl_Fillet1dDriver) == AType || TFunction_Driver::IsKind(AType)); } 
-
+  inline void* operator new(size_t,void* anAddress) 
+  {
+    return anAddress;
+  }
+  inline void* operator new(size_t size) 
+  { 
+    return Standard::Allocate(size); 
+  }
+  inline void  operator delete(void *anAddress) 
+  { 
+    if (anAddress) Standard::Free((Standard_Address&)anAddress); 
+  }
+
+  // Methods PUBLIC
+  // 
+  Standard_EXPORT GEOMImpl_Fillet1dDriver();
+  Standard_EXPORT ~GEOMImpl_Fillet1dDriver() {};
+
+  Standard_EXPORT static const Standard_GUID& GetID();
+
+  Standard_EXPORT virtual  Standard_Integer Execute(TFunction_Logbook& log) const; 
+  Standard_EXPORT virtual void Validate(TFunction_Logbook&) const {}
+  Standard_EXPORT Standard_Boolean MustExecute(const TFunction_Logbook&) const { return Standard_True; }
+
+  // Type management
+  //
+  Standard_EXPORT friend Handle_Standard_Type& GEOMImpl_Fillet1dDriver_Type_();
+  Standard_EXPORT const Handle(Standard_Type)& DynamicType() const 
+  { return STANDARD_TYPE(GEOMImpl_Fillet1dDriver) ; }
+  Standard_EXPORT Standard_Boolean IsKind(const Handle(Standard_Type)& AType) const
+  { return (STANDARD_TYPE(GEOMImpl_Fillet1dDriver) == AType || TFunction_Driver::IsKind(AType)); } 
+
+private:
+
+  Standard_EXPORT bool MakeFillet(const TopoDS_Wire&, const TopTools_ListOfShape&,
+                                  const Standard_Real, bool, TopoDS_Wire&) const; 
 
 };
 
index f21bc14f95baa321aaef9ed4c95f3ee3ca5ca99a..7771033fbdbd65e82042a28c6ab3c5fed4d613e9 100644 (file)
@@ -18,7 +18,6 @@
 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 //
 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
-//
 
 #include <Standard_Stream.hxx>
 
@@ -28,6 +27,7 @@
 #include <GEOM_Function.hxx>
 
 #include <GEOMImpl_GlueDriver.hxx>
+#include <GEOMImpl_ShapeDriver.hxx>
 
 #include <ShHealOper_ShapeProcess.hxx>
 #include <ShHealOper_RemoveFace.hxx>
 #include <ShHealOper_EdgeDivide.hxx>
 #include <ShHealOper_ChangeOrientation.hxx>
 
+#include <TNaming_CopyShape.hxx>
+
+#include <ShapeFix_ShapeTolerance.hxx>
+#include <ShapeFix_Shape.hxx>
+
 #include <BRep_Builder.hxx>
+#include <BRepAdaptor_Curve.hxx>
+#include <BRepCheck_Analyzer.hxx>
+#include <BRepTools_WireExplorer.hxx>
 
 #include <TopExp.hxx>
+#include <TopExp_Explorer.hxx>
 #include <TopoDS.hxx>
 #include <TopoDS_Iterator.hxx>
 #include <TopTools_IndexedMapOfShape.hxx>
+#include <TopTools_ListOfShape.hxx>
+#include <TopTools_ListIteratorOfListOfShape.hxx>
 
 #include <TColStd_IndexedDataMapOfTransientTransient.hxx>
-#include <TNaming_CopyShape.hxx>
-#include <ShapeFix_ShapeTolerance.hxx>
-#include <ShapeFix_Shape.hxx>
-#include <BRepCheck_Analyzer.hxx>
 
 #include <Precision.hxx>
 
 #include <StdFail_NotDone.hxx>
+#include <Standard_NullObject.hxx>
 
 //=======================================================================
 //function :  raiseNotDoneExeption
@@ -135,6 +143,12 @@ Standard_Integer GEOMImpl_HealingDriver::Execute(TFunction_Logbook& log) const
   case LIMIT_TOLERANCE:
     LimitTolerance(&HI, anOriginalShape, aShape);
     break;
+  case FUSE_COLLINEAR_EDGES:
+    {
+      Handle(TColStd_HSequenceOfTransient) aVerts = HI.GetShapes();
+      FuseCollinearEdges(anOriginalShape, aVerts, aShape);
+    }
+    break;
   default:
     return 0;
   }
@@ -505,6 +519,258 @@ void GEOMImpl_HealingDriver::LimitTolerance (GEOMImpl_IHealing* theHI,
     StdFail_NotDone::Raise("Non valid shape result");
 }
 
+//=======================================================================
+//function : FuseCollinearEdges
+//purpose  :
+//=======================================================================
+void GEOMImpl_HealingDriver::FuseCollinearEdges (const TopoDS_Shape& theOriginalShape,
+                                                 const Handle(TColStd_HSequenceOfTransient)& aVerts,
+                                                 TopoDS_Shape& theOutShape)
+{
+  if (theOriginalShape.ShapeType() != TopAbs_WIRE)
+    Standard_TypeMismatch::Raise("Not a wire is given");
+
+  // Tolerances
+  Standard_Real AngTol = Precision::Angular();
+  Standard_Real LinTol = Precision::Confusion();
+  Standard_Real tol;
+  for (TopExp_Explorer ExV (theOriginalShape, TopAbs_VERTEX); ExV.More(); ExV.Next()) {
+    TopoDS_Vertex Vertex = TopoDS::Vertex(ExV.Current());
+    tol = BRep_Tool::Tolerance(Vertex);
+    if (tol > LinTol)
+      LinTol = tol;
+  }
+
+  // 1. Make a copy to prevent the original shape changes.
+  TopoDS_Shape aWire;
+  TColStd_IndexedDataMapOfTransientTransient aMapTShapes;
+  TNaming_CopyShape::CopyTool(theOriginalShape, aMapTShapes, aWire);
+  TopoDS_Wire theWire = TopoDS::Wire(aWire);
+
+  // 2. Sub-shapes of the wire
+  TopTools_MapOfShape aMapToRemove;
+
+  TopTools_IndexedMapOfShape anOldIndices;
+  TopExp::MapShapes(theOriginalShape, anOldIndices);
+
+  TopTools_IndexedMapOfShape aNewIndices;
+  TopExp::MapShapes(theWire, aNewIndices);
+
+  // 3. Collect vertices of the wire, same or equal to the given vertices
+  bool removeAll = false;
+  if (aVerts.IsNull() || aVerts->Length() < 1)
+    removeAll = true;
+
+  if (!removeAll) {
+    for (unsigned int ind = 1; ind <= aVerts->Length(); ind++) {
+      Handle(GEOM_Function) aRefShape = Handle(GEOM_Function)::DownCast(aVerts->Value(ind));
+      TopoDS_Shape aShape_i = aRefShape->GetValue();
+      if (aShape_i.IsNull())
+        Standard_NullObject::Raise("Null vertex given");
+      if (aShape_i.ShapeType() != TopAbs_VERTEX)
+        Standard_TypeMismatch::Raise("Shape to suppress is not a vertex");
+
+      // find vertices shared with the initial wire
+      if (anOldIndices.Contains(aShape_i)) {
+        aMapToRemove.Add(aNewIndices.FindKey(anOldIndices.FindIndex(aShape_i)));
+      } else {
+        // try to find by coords in the new wire
+        TopoDS_Vertex aVert = TopoDS::Vertex(aShape_i);
+        gp_Pnt aP = BRep_Tool::Pnt(aVert);
+
+        bool isFound = false;
+        TopTools_MapOfShape mapShape;
+        TopExp_Explorer exp (theWire, TopAbs_VERTEX);
+        for (; exp.More() && !isFound; exp.Next()) {
+          if (mapShape.Add(exp.Current())) {
+            TopoDS_Vertex aVi = TopoDS::Vertex(exp.Current());
+            gp_Pnt aPi = BRep_Tool::Pnt(aVi);
+            if (aPi.Distance(aP) < LinTol) {
+              aMapToRemove.Add(aVi);
+              isFound = true;
+            }
+          }
+        }
+      }
+    }
+  }
+
+  /*
+  BRepLib::BuildCurves3d(theWire);
+  Handle(ShapeFix_Shape) Fixer = new ShapeFix_Shape(theWire);
+  Fixer->SetPrecision(LinTol);
+  Fixer->SetMaxTolerance(LinTol);
+  Fixer->Perform();
+  theWire = TopoDS::Wire(Fixer->Shape());
+  */
+
+  TopoDS_Edge prevEdge;
+  TopTools_ListOfShape finalList, currChain;
+
+  BRepTools_WireExplorer wexp (theWire);
+  if (wexp.More()) {
+    prevEdge = wexp.Current();
+    currChain.Append(prevEdge);
+    wexp.Next();
+  }
+  else {
+    Standard_NullObject::Raise("Empty wire given");
+  }
+
+  for (; wexp.More(); wexp.Next()) {
+    TopoDS_Edge anEdge = wexp.Current();
+    TopoDS_Vertex CurVertex = wexp.CurrentVertex();
+
+    bool continueChain = false;
+    if (aMapToRemove.Contains(CurVertex) || removeAll) {
+      // if C1 -> continue chain
+      if (AreEdgesC1(prevEdge, anEdge)) {
+        continueChain = true;
+      }
+    }
+
+    if (!continueChain) {
+      if (currChain.Extent() == 1) {
+        // add one edge to the final list
+        finalList.Append(currChain.First());
+      }
+      else {
+        // make wire from the list of edges
+        BRep_Builder B;
+        TopoDS_Wire aCurrWire;
+        B.MakeWire(aCurrWire);
+        TopTools_ListIteratorOfListOfShape itEdges (currChain);
+        for (; itEdges.More(); itEdges.Next()) {
+          TopoDS_Shape aValue = itEdges.Value();
+          B.Add(aCurrWire, TopoDS::Edge(aValue));
+        }
+
+        // make edge from the wire
+        TopoDS_Edge anEdge = GEOMImpl_ShapeDriver::MakeEdgeFromWire(aCurrWire, LinTol, AngTol);
+
+        // add this new edge to the final list
+        finalList.Append(anEdge);
+      }
+      currChain.Clear();
+    }
+
+    // add one edge to the chain
+    currChain.Append(anEdge);
+    prevEdge = anEdge;
+  }
+
+  if (currChain.Extent() == 1) {
+    // add one edge to the final list
+    finalList.Append(currChain.First());
+  }
+  else {
+    // make wire from the list of edges
+    BRep_Builder B;
+    TopoDS_Wire aCurrWire;
+    B.MakeWire(aCurrWire);
+    TopTools_ListIteratorOfListOfShape itEdges (currChain);
+    for (; itEdges.More(); itEdges.Next()) {
+      TopoDS_Shape aValue = itEdges.Value();
+      B.Add(aCurrWire, TopoDS::Edge(aValue));
+    }
+
+    // make edge from the wire
+    TopoDS_Edge anEdge = GEOMImpl_ShapeDriver::MakeEdgeFromWire(aCurrWire, LinTol, AngTol);
+
+    // add this new edge to the final list
+    finalList.Append(anEdge);
+  }
+
+  BRep_Builder B;
+  TopoDS_Wire aFinalWire;
+  B.MakeWire(aFinalWire);
+  TopTools_ListIteratorOfListOfShape itEdges (finalList);
+  for (; itEdges.More(); itEdges.Next()) {
+    TopoDS_Shape aValue = itEdges.Value();
+    B.Add(aFinalWire, TopoDS::Edge(aValue));
+  }
+  theOutShape = aFinalWire;
+
+  BRepCheck_Analyzer ana (theOutShape, Standard_True);
+  if (!ana.IsValid())
+    StdFail_NotDone::Raise("Non valid shape result");
+}
+
+//=======================================================================
+//function : AreEdgesC1
+//purpose  :
+//=======================================================================
+Standard_Boolean GEOMImpl_HealingDriver::AreEdgesC1 (const TopoDS_Edge& E1, const TopoDS_Edge& E2)
+{
+  BRepAdaptor_Curve aCurve1 (E1);
+  BRepAdaptor_Curve aCurve2 (E2);
+
+  if (aCurve1.Continuity() == GeomAbs_C0 || aCurve2.Continuity() == GeomAbs_C0)
+    return Standard_False;
+
+  Standard_Real tol, tolMax = Precision::Confusion();
+  for (TopExp_Explorer ExV1 (E1, TopAbs_VERTEX); ExV1.More(); ExV1.Next()) {
+    TopoDS_Vertex Vertex = TopoDS::Vertex(ExV1.Current());
+    tol = BRep_Tool::Tolerance(Vertex);
+      if (tol > tolMax)
+        tolMax = tol;
+  }
+  for (TopExp_Explorer ExV2 (E2, TopAbs_VERTEX); ExV2.More(); ExV2.Next()) {
+    TopoDS_Vertex Vertex = TopoDS::Vertex(ExV2.Current());
+    tol = BRep_Tool::Tolerance(Vertex);
+      if (tol > tolMax)
+        tolMax = tol;
+  }
+
+  Standard_Real f1, l1, f2, l2;
+  f1 = aCurve1.FirstParameter();
+  l1 = aCurve1.LastParameter();
+  f2 = aCurve2.FirstParameter();
+  l2 = aCurve2.LastParameter();
+
+  if (f1 > l1) {
+    Standard_Real tmp = f1;
+    f1 = l1;
+    l1 = tmp;
+  }
+
+  if (f2 > l2) {
+    Standard_Real tmp = f2;
+    f2 = l2;
+    l2 = tmp;
+  }
+
+  gp_Pnt pf1, pl1, pf2, pl2;
+  gp_Vec vf1, vl1, vf2, vl2;
+  aCurve1.D1(f1, pf1, vf1);
+  aCurve1.D1(l1, pl1, vl1);
+  aCurve2.D1(f2, pf2, vf2);
+  aCurve2.D1(l2, pl2, vl2);
+
+  // pf1--->---pl1.pf2--->---pl2
+  if (pl1.SquareDistance(pf2) < tolMax*tolMax) {
+    if (vl1.Angle(vf2) < Precision::Angular())
+      return Standard_True;
+  }
+  // pl1---<---pf1.pf2--->---pl2
+  else if (pf1.SquareDistance(pf2) < tolMax*tolMax) {
+    if (vf1.Angle(-vf2) < Precision::Angular())
+      return Standard_True;
+  }
+  // pf1--->---pl1.pl2---<---pf2
+  else if (pl1.SquareDistance(pl2) < tolMax*tolMax) {
+    if (vl1.Angle(-vl2) < Precision::Angular())
+      return Standard_True;
+  }
+  // pl1---<---pf1.pl2---<---pf2
+  else {
+    if (vf1.Angle(vl2) < Precision::Angular())
+      return Standard_True;
+  }
+
+  return Standard_False;
+}
+
 //=======================================================================
 //function :  GEOMImpl_HealingDriver_Type_
 //purpose  :
index 9493912d93f3f53ad8b9ff9f3d0faf419f3bf489..f1d740d6fcca4c65335828811577a7b87b08509d 100644 (file)
@@ -57,6 +57,8 @@ class GEOMImpl_HealingDriver;
 
 class GEOMImpl_IHealing;
 #include <TopoDS_Shape.hxx>
+#include <TopoDS_Edge.hxx>
+#include <TColStd_HSequenceOfTransient.hxx>
 
 Standard_EXPORT Handle_Standard_Type& STANDARD_TYPE(GEOMImpl_HealingDriver);
 
@@ -128,45 +130,51 @@ class GEOMImpl_HealingDriver : public TFunction_Driver {
 
 public:
 
-    inline void* operator new(size_t,void* anAddress)
-      {
-        return anAddress;
-      }
-    inline void* operator new(size_t size)
-      {
-        return Standard::Allocate(size);
-      }
-    inline void  operator delete(void *anAddress)
-      {
-        if (anAddress) Standard::Free((Standard_Address&)anAddress);
-      }
-
- // Methods PUBLIC
- //
-Standard_EXPORT GEOMImpl_HealingDriver();
-Standard_EXPORT virtual  Standard_Integer Execute(TFunction_Logbook& log) const;
-Standard_EXPORT virtual void Validate(TFunction_Logbook&) const {}
-Standard_EXPORT Standard_Boolean MustExecute(const TFunction_Logbook&) const { return Standard_True; }
-Standard_EXPORT static const Standard_GUID& GetID();
-Standard_EXPORT ~GEOMImpl_HealingDriver() {};
-
-
- // Type management
- //
-Standard_EXPORT friend Handle_Standard_Type& GEOMImpl_HealingDriver_Type_();
-Standard_EXPORT const Handle(Standard_Type)& DynamicType() const  { return STANDARD_TYPE(GEOMImpl_HealingDriver) ; }
-Standard_EXPORT Standard_Boolean IsKind(const Handle(Standard_Type)& AType) const { return (STANDARD_TYPE(GEOMImpl_HealingDriver) == AType || TFunction_Driver::IsKind(AType)); }
+  inline void* operator new(size_t,void* anAddress)
+  {
+    return anAddress;
+  }
+  inline void* operator new(size_t size)
+  {
+    return Standard::Allocate(size);
+  }
+  inline void  operator delete(void *anAddress)
+  {
+    if (anAddress) Standard::Free((Standard_Address&)anAddress);
+  }
+
+  // Methods PUBLIC
+  //
+  Standard_EXPORT GEOMImpl_HealingDriver();
+  Standard_EXPORT ~GEOMImpl_HealingDriver() {};
+
+  Standard_EXPORT static const Standard_GUID& GetID();
+
+  Standard_EXPORT virtual Standard_Integer Execute(TFunction_Logbook& log) const;
+  Standard_EXPORT virtual void Validate(TFunction_Logbook&) const {}
+  Standard_EXPORT Standard_Boolean MustExecute(const TFunction_Logbook&) const { return Standard_True; }
+
+  Standard_EXPORT static Standard_Boolean AreEdgesC1 (const TopoDS_Edge& E1, const TopoDS_Edge& E2);
+  Standard_EXPORT static void FuseCollinearEdges (const TopoDS_Shape&,
+                                                  const Handle(TColStd_HSequenceOfTransient)&,
+                                                  TopoDS_Shape&);
+
+  // Type management
+  //
+  Standard_EXPORT friend Handle_Standard_Type& GEOMImpl_HealingDriver_Type_();
+  Standard_EXPORT const Handle(Standard_Type)& DynamicType() const  { return STANDARD_TYPE(GEOMImpl_HealingDriver) ; }
+  Standard_EXPORT Standard_Boolean IsKind(const Handle(Standard_Type)& AType) const { return (STANDARD_TYPE(GEOMImpl_HealingDriver) == AType || TFunction_Driver::IsKind(AType)); }
 
 private:
-Standard_Boolean ShapeProcess  ( GEOMImpl_IHealing*, const TopoDS_Shape&, TopoDS_Shape& ) const;
-Standard_Boolean SuppressFaces ( GEOMImpl_IHealing*, const TopoDS_Shape&, TopoDS_Shape& ) const;
-Standard_Boolean CloseContour  ( GEOMImpl_IHealing*, const TopoDS_Shape&, TopoDS_Shape& ) const;
-Standard_Boolean RemoveIntWires( GEOMImpl_IHealing*, const TopoDS_Shape&, TopoDS_Shape& ) const;
-Standard_Boolean RemoveHoles   ( GEOMImpl_IHealing*, const TopoDS_Shape&, TopoDS_Shape& ) const;
-Standard_Boolean Sew           ( GEOMImpl_IHealing*, const TopoDS_Shape&, TopoDS_Shape& ) const;
-Standard_Boolean AddPointOnEdge( GEOMImpl_IHealing*, const TopoDS_Shape&, TopoDS_Shape& ) const;
-Standard_Boolean ChangeOrientation( GEOMImpl_IHealing*, const TopoDS_Shape&, TopoDS_Shape& ) const;
-void             LimitTolerance( GEOMImpl_IHealing*, const TopoDS_Shape&, TopoDS_Shape& ) const;
+  Standard_Boolean ShapeProcess  ( GEOMImpl_IHealing*, const TopoDS_Shape&, TopoDS_Shape& ) const;
+  Standard_Boolean SuppressFaces ( GEOMImpl_IHealing*, const TopoDS_Shape&, TopoDS_Shape& ) const;
+  Standard_Boolean CloseContour  ( GEOMImpl_IHealing*, const TopoDS_Shape&, TopoDS_Shape& ) const;
+  Standard_Boolean RemoveIntWires( GEOMImpl_IHealing*, const TopoDS_Shape&, TopoDS_Shape& ) const;
+  Standard_Boolean RemoveHoles   ( GEOMImpl_IHealing*, const TopoDS_Shape&, TopoDS_Shape& ) const;
+  Standard_Boolean Sew           ( GEOMImpl_IHealing*, const TopoDS_Shape&, TopoDS_Shape& ) const;
+  Standard_Boolean AddPointOnEdge( GEOMImpl_IHealing*, const TopoDS_Shape&, TopoDS_Shape& ) const;
+  Standard_Boolean ChangeOrientation( GEOMImpl_IHealing*, const TopoDS_Shape&, TopoDS_Shape& ) const;
+  void             LimitTolerance( GEOMImpl_IHealing*, const TopoDS_Shape&, TopoDS_Shape& ) const;
 
 };
 
index 484d92b65d668bceff44d976486f1766aee011ab..eb3ef0ee6dbd939d8dd0869999201aa2a621e70c 100644 (file)
 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 //
 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
-//
 
 //NOTE: This is an interface to a function for the Fillet1d and creation.
-//
+
 #include "GEOM_Function.hxx"
 
 #define FILLET1D_ARG_SH   1
 #define FILLET1D_ARG_R    2
-#define FILLET1D_ARG_LENG 3
-#define FILLET1D_ARG_LAST 4
+#define FILLET1D_ARG_BOOL 3
+#define FILLET1D_ARG_LENG 4
+#define FILLET1D_ARG_LAST 5
 
 class GEOMImpl_IFillet1d
 {
@@ -36,11 +36,13 @@ class GEOMImpl_IFillet1d
   Handle(GEOM_Function) GetShape() { return _func->GetReference(FILLET1D_ARG_SH); }
 
   void SetR(double theR) { _func->SetReal(FILLET1D_ARG_R, theR); }
+  void SetFlag(const Standard_Boolean theFlag) { _func->SetInteger(FILLET1D_ARG_BOOL, theFlag ? 1 : 0); }
   void SetLength(int theLen) { _func->SetInteger(FILLET1D_ARG_LENG, theLen); }
   void SetVertex(int theInd, int theVertex)
               { _func->SetInteger(FILLET1D_ARG_LAST + theInd, theVertex); }
 
   double GetR() { return _func->GetReal(FILLET1D_ARG_R); }
+  Standard_Boolean GetFlag() { return (_func->GetInteger(FILLET1D_ARG_BOOL) == 1); }
   int GetLength() { return _func->GetInteger(FILLET1D_ARG_LENG); }
   int GetVertex(int theInd) { return _func->GetInteger(FILLET1D_ARG_LAST + theInd); }
 
index 91f8c34f0b0b37993abb114aa001b3352697fa4b..2ee3879087426ab9e32797cbe2597d0029cba69c 100755 (executable)
 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 //
 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
-//
 
 #include "GEOM_Function.hxx"
 
 #include <TColStd_HArray1OfInteger.hxx>
 #include <TColStd_HArray1OfExtendedString.hxx>
-
-#define ARG_SHAPE_PROCESS_OPERATORS   1
-#define ARG_SHAPE_PROCESS_PARAMS      2
-#define ARG_SHAPE_PROCESS_VALUES      3
-#define ARG_ORIGINAL                  4
-#define ARG_LIST_ARGUMENTS            5
-#define ARG_IS_COMMON_VERTEX          6
-#define ARG_TOLERANCE                 7
-#define ARG_DEV_EDGE_VALUE            8
-#define ARG_IS_BY_PARAMETER           9
-#define ARG_SUBSHAPE_INDEX           10
-
+#include "TColStd_HSequenceOfTransient.hxx"
 
 class GEOMImpl_IHealing
 {
 public:
+
+  enum {
+    ARG_SHAPE_PROCESS_OPERATORS =  1,
+    ARG_SHAPE_PROCESS_PARAMS    =  2,
+    ARG_SHAPE_PROCESS_VALUES    =  3,
+    ARG_ORIGINAL                =  4,
+    ARG_LIST_ARGUMENTS          =  5,
+    ARG_IS_COMMON_VERTEX        =  6,
+    ARG_TOLERANCE               =  7,
+    ARG_DEV_EDGE_VALUE          =  8,
+    ARG_IS_BY_PARAMETER         =  9,
+    ARG_SUBSHAPE_INDEX          = 10,
+    ARG_LIST_SHAPES             = 11
+  };
+
   GEOMImpl_IHealing(Handle(GEOM_Function) theFunction): _func(theFunction) {}
 
   void SetOperators( const Handle(TColStd_HArray1OfExtendedString)& arr ) {  if ( !arr.IsNull() ) _func->SetStringArray(ARG_SHAPE_PROCESS_OPERATORS, arr); }
@@ -75,6 +78,11 @@ public:
   void SetIndex( Standard_Integer val ) { _func->SetInteger(ARG_SUBSHAPE_INDEX, val); }
   Standard_Integer GetIndex() { return _func->GetInteger(ARG_SUBSHAPE_INDEX); }
 
+  void SetShapes(const Handle(TColStd_HSequenceOfTransient)& theShapes)
+  { _func->SetReferenceList(ARG_LIST_SHAPES, theShapes); }
+  Handle(TColStd_HSequenceOfTransient) GetShapes()
+  { return _func->GetReferenceList(ARG_LIST_SHAPES); }
+
 private:
   Handle(GEOM_Function) _func;
 };
index 9043f811abdec1fdb3ec4573e351b75ab5f61fa8..3db0e6a93c37f88a5afe9ddfbff68c44c1e1ce5d 100644 (file)
@@ -691,15 +691,13 @@ Handle(GEOM_Object) GEOMImpl_IHealingOperations::DivideEdge (Handle(GEOM_Object)
 #if OCC_VERSION_LARGE > 0x06010000
     OCC_CATCH_SIGNALS;
 #endif
-    if (!GetSolver()->ComputeFunction(aFunction))
-    {
+    if (!GetSolver()->ComputeFunction(aFunction)) {
       SetErrorCode("Healing driver failed");
       return NULL;
     }
   }
-  catch (Standard_Failure)
-  {
-        Handle(Standard_Failure) aFail = Standard_Failure::Caught();
+  catch (Standard_Failure) {
+    Handle(Standard_Failure) aFail = Standard_Failure::Caught();
     SetErrorCode(aFail->GetMessageString());
     return NULL;
   }
@@ -712,6 +710,81 @@ Handle(GEOM_Object) GEOMImpl_IHealingOperations::DivideEdge (Handle(GEOM_Object)
   return aNewObject;
 }
 
+//=============================================================================
+/*!
+ *  FuseCollinearEdgesWithinWire
+ */
+//=============================================================================
+Handle(GEOM_Object) GEOMImpl_IHealingOperations::FuseCollinearEdgesWithinWire
+                                   (Handle(GEOM_Object) theWire,
+                                    std::list<Handle(GEOM_Object)> theVertices)
+{
+  SetErrorCode(KO);
+
+  if (theWire.IsNull()) return NULL;
+
+  // Add a new object
+  Handle(GEOM_Object) aRes = GetEngine()->AddObject(GetDocID(), theWire->GetType());
+
+  // Add a new function
+  Handle(GEOM_Function) aFunction;
+  aFunction = aRes->AddFunction(GEOMImpl_HealingDriver::GetID(), FUSE_COLLINEAR_EDGES);
+  if (aFunction.IsNull()) return NULL;
+
+  // Check if the function is set correctly
+  if (aFunction->GetDriverGUID() != GEOMImpl_HealingDriver::GetID()) return NULL;
+
+  GEOMImpl_IHealing aCI (aFunction);
+
+  Handle(GEOM_Function) aRefShape = theWire->GetLastFunction();
+  if (aRefShape.IsNull()) return NULL;
+  aCI.SetOriginal(aRefShape);
+
+  Handle(TColStd_HSequenceOfTransient) aVertices = new TColStd_HSequenceOfTransient;
+  std::list<Handle(GEOM_Object)>::iterator it = theVertices.begin();
+  for (; it != theVertices.end(); it++) {
+    Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction();
+    if (aRefSh.IsNull()) {
+      SetErrorCode("NULL argument shape for the shape construction");
+      return NULL;
+    }
+    aVertices->Append(aRefSh);
+  }
+  aCI.SetShapes(aVertices);
+
+  // Compute the new wire
+  try {
+#if OCC_VERSION_LARGE > 0x06010000
+    OCC_CATCH_SIGNALS;
+#endif
+    if (!GetSolver()->ComputeFunction(aFunction)) {
+      SetErrorCode("Healing driver failed");
+      return NULL;
+    }
+  }
+  catch (Standard_Failure) {
+    Handle(Standard_Failure) aFail = Standard_Failure::Caught();
+    SetErrorCode(aFail->GetMessageString());
+    return NULL;
+  }
+
+  // Make a Python command
+  GEOM::TPythonDump pd (aFunction);
+  pd << aRes << " = geompy.FuseCollinearEdgesWithinWire(" << theWire << ", [";
+  // Vertices
+  it = theVertices.begin();
+  if (it != theVertices.end()) {
+    pd << (*it++);
+    while (it != theVertices.end()) {
+      pd << ", " << (*it++);
+    }
+  }
+  pd << "])";
+
+  SetErrorCode(OK);
+  return aRes;
+}
+
 //=============================================================================
 /*!
  *  GetFreeBoundary
index e659761901bf7bb6212843b8a605df6644eb212f..7434d937c5284911005382d51ad04917e5f1bd74 100644 (file)
@@ -18,7 +18,6 @@
 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 //
 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
-//
 
 #ifndef _GEOMImpl_IHealingOperations_HXX_
 #define _GEOMImpl_IHealingOperations_HXX_
@@ -78,6 +77,10 @@ class GEOMImpl_IHealingOperations : public GEOM_IOperations {
                                                   double theValue,
                                                   bool isByParameter );
 
+  Standard_EXPORT Handle(GEOM_Object) FuseCollinearEdgesWithinWire
+                                     (Handle(GEOM_Object) theWire,
+                                      std::list<Handle(GEOM_Object)> theVertices);
+
   // this function does not use Function-Driver mechanism, it just computes the free
   // boundary edges and returns them in the sequence.  It is called just for information reasons
   // and it's not intended for history/undo/redo/etc..
index 92b3c91a48fbd49f774c2e160f5e7ca45fe2269b..76b8f0563eaaa4abf4d639d2442238cd815153ef 100644 (file)
@@ -18,7 +18,6 @@
 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 //
 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
-//
 
 #include <Standard_Stream.hxx>
 
@@ -492,7 +491,8 @@ Handle(GEOM_Object) GEOMImpl_ILocalOperations::MakeFillet2D
  */
 //=============================================================================
 Handle(GEOM_Object) GEOMImpl_ILocalOperations::MakeFillet1D
-       (Handle(GEOM_Object) theShape, double theR, std::list<int> theVertexes)
+                      (Handle(GEOM_Object) theShape, double theR,
+                       std::list<int> theVertexes, bool doIgnoreSecantVertices)
 {
   SetErrorCode(KO);
 
@@ -514,6 +514,7 @@ Handle(GEOM_Object) GEOMImpl_ILocalOperations::MakeFillet1D
 
   aCI.SetShape(aRefShape);
   aCI.SetR(theR);
+  aCI.SetFlag(doIgnoreSecantVertices);
   int aLen = theVertexes.size();
   aCI.SetLength(aLen);
 
index e1588da417f3af3c26727c038cf72c40ffc2511e..e3877b63b97b51d6024012c16e3fbab7e8223442 100644 (file)
@@ -18,7 +18,6 @@
 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 //
 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
-//
 
 #ifndef _GEOMImpl_ILocalOperations_HXX_
 #define _GEOMImpl_ILocalOperations_HXX_
@@ -50,7 +49,7 @@ class GEOMImpl_ILocalOperations : public GEOM_IOperations {
   Standard_EXPORT Handle(GEOM_Object) MakeFillet2D (Handle(GEOM_Object) theShape, double theR,
                                                     std::list<int> theVertexes);
   Standard_EXPORT Handle(GEOM_Object) MakeFillet1D (Handle(GEOM_Object) theShape, double theR,
-                                                    std::list<int> theVertexes);
+                                                    std::list<int> theVertexes, bool doIgnoreSecantVertices);
 
   Standard_EXPORT Handle(GEOM_Object) MakeChamferAll   (Handle(GEOM_Object) theShape, double theD);
   Standard_EXPORT Handle(GEOM_Object) MakeChamferEdge  (Handle(GEOM_Object) theShape,
index b81b261ce0e0a7c62376ca50427225407460d986..68231130216ea6a1bcf1ebba3bb98498ad6e3b24 100644 (file)
@@ -18,7 +18,6 @@
 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 //
 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
-//
 
 //  File      : GEOMImpl_IShapesOperations.cxx
 //  Created   :
@@ -1010,10 +1009,10 @@ Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetGlueShapes
   TopTools_DataMapIteratorOfDataMapOfShapeListOfShape aItDMSLS (aImages);
   for (int index = 1; aItDMSLS.More(); aItDMSLS.Next(), ++index) {
     // some key shape
-    //const TopoDS_Shape& aSkey = aItDMSLS.Key();  
+    //const TopoDS_Shape& aSkey = aItDMSLS.Key();
 
     // list of shapes of the argument that can be glued
-    const TopTools_ListOfShape& aLSD = aItDMSLS.Value(); 
+    const TopTools_ListOfShape& aLSD = aItDMSLS.Value();
 
     //listShape.Append(aLSD.First());
     TopoDS_Shape aValue = aLSD.First();
@@ -3920,8 +3919,8 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlace (Handle(GEOM_Object)
     return NULL;
   }
 
-  // the list of shapes aLSA contains the shapes 
-  // of the Shape For Search that corresponds 
+  // the list of shapes aLSA contains the shapes
+  // of the Shape For Search that corresponds
   // to the Argument aWhat
   const TopTools_ListOfShape& aLSA = aDMSLS.Find(aWhat);
   if (aLSA.Extent() == 0) {
@@ -4920,7 +4919,8 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetSame(const Handle(GEOM_Object
 //function : GetSameIDs
 //purpose  :
 //=======================================================================
-Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetSameIDs(const Handle(GEOM_Object)& theShapeWhere,
+Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetSameIDs
+                                                       (const Handle(GEOM_Object)& theShapeWhere,
                                                         const Handle(GEOM_Object)& theShapeWhat)
 {
   SetErrorCode(KO);
@@ -4931,8 +4931,6 @@ Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetSameIDs(const
 
   if (aWhere.IsNull() || aWhat.IsNull()) return NULL;
 
-  int anIndex = -1;
-  bool isFound = false;
   TopTools_ListOfShape listShape;
   TopTools_MapOfShape aMap;
 
@@ -5017,6 +5015,6 @@ Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetSameIDs(const
     return aSeq;
   } else {
     SetErrorCode(NOT_FOUND_ANY);
-    return NULL; 
+    return NULL;
   }
 }
index c05db9fc196d75e0a32f66dab6800bf754165ee5..e1ef2802214944538c3c5d6409f788b89f764736 100644 (file)
@@ -144,14 +144,14 @@ Standard_Integer GEOMImpl_ShapeDriver::Execute(TFunction_Logbook& log) const
       if (aShape_i.IsNull()) {
         Standard_NullObject::Raise("Shape for wire construction is null");
       }
-     if (aShape_i.ShapeType() == TopAbs_EDGE || aShape_i.ShapeType() == TopAbs_WIRE) {
-       TopExp_Explorer exp (aShape_i, TopAbs_EDGE);
-       for (; exp.More(); exp.Next())
-         B.Add(aWire, TopoDS::Edge(exp.Current()));
-     } else {
-       Standard_TypeMismatch::Raise
-         ("Shape for wire construction is neither an edge nor a wire");
-     }
+      if (aShape_i.ShapeType() == TopAbs_EDGE || aShape_i.ShapeType() == TopAbs_WIRE) {
+        TopExp_Explorer exp (aShape_i, TopAbs_EDGE);
+        for (; exp.More(); exp.Next())
+          B.Add(aWire, TopoDS::Edge(exp.Current()));
+      } else {
+        Standard_TypeMismatch::Raise
+          ("Shape for wire construction is neither an edge nor a wire");
+      }
     }
 
     // fix edges order
@@ -491,6 +491,108 @@ Standard_Integer GEOMImpl_ShapeDriver::Execute(TFunction_Logbook& log) const
     Standard_Real AngTol = aCI.GetAngularTolerance();
     if (aWire.IsNull()) Standard_NullObject::Raise("Argument Wire is null");
 
+    aShape = MakeEdgeFromWire(aWire, LinTol, AngTol);
+  }
+  else if (aType == EDGE_CURVE_LENGTH) {
+    GEOMImpl_IVector aVI (aFunction);
+
+    // RefCurve
+    Handle(GEOM_Function) aRefCurve = aVI.GetPoint1();
+    if (aRefCurve.IsNull()) Standard_NullObject::Raise("Argument Curve is null");
+    TopoDS_Shape aRefShape1 = aRefCurve->GetValue();
+    if (aRefShape1.ShapeType() != TopAbs_EDGE) {
+      Standard_TypeMismatch::Raise
+        ("Edge On Curve creation aborted : curve shape is not an edge");
+    }
+    TopoDS_Edge aRefEdge = TopoDS::Edge(aRefShape1);
+    TopoDS_Vertex V1, V2;
+    TopExp::Vertices(aRefEdge, V1, V2, Standard_True);
+
+    // RefPoint
+    TopoDS_Vertex aRefVertex;
+    Handle(GEOM_Function) aRefPoint = aVI.GetPoint2();
+    if (aRefPoint.IsNull()) {
+      aRefVertex = V1;
+    }
+    else {
+      TopoDS_Shape aRefShape2 = aRefPoint->GetValue();
+      if (aRefShape2.ShapeType() != TopAbs_VERTEX) {
+        Standard_TypeMismatch::Raise
+          ("Edge On Curve creation aborted : start point shape is not a vertex");
+      }
+      aRefVertex = TopoDS::Vertex(aRefShape2);
+    }
+    gp_Pnt aRefPnt = BRep_Tool::Pnt(aRefVertex);
+
+    // Length
+    Standard_Real aLength = aVI.GetParameter();
+    //Standard_Real aCurveLength = IntTools::Length(aRefEdge);
+    //if (aLength > aCurveLength) {
+    //  Standard_ConstructionError::Raise
+    //    ("Edge On Curve creation aborted : given length is greater than edges length");
+    //}
+    if (fabs(aLength) < Precision::Confusion()) {
+      Standard_ConstructionError::Raise
+        ("Edge On Curve creation aborted : given length is smaller than Precision::Confusion()");
+    }
+
+    // Check orientation
+    Standard_Real UFirst, ULast;
+    Handle(Geom_Curve) EdgeCurve = BRep_Tool::Curve(aRefEdge, UFirst, ULast);
+    Handle(Geom_Curve) ReOrientedCurve = EdgeCurve;
+
+    Standard_Real dU = ULast - UFirst;
+    Standard_Real par1 = UFirst + 0.1 * dU;
+    Standard_Real par2 = ULast  - 0.1 * dU;
+
+    gp_Pnt P1 = EdgeCurve->Value(par1);
+    gp_Pnt P2 = EdgeCurve->Value(par2);
+
+    if (aRefPnt.SquareDistance(P2) < aRefPnt.SquareDistance(P1)) {
+      ReOrientedCurve = EdgeCurve->Reversed();
+      UFirst = EdgeCurve->ReversedParameter(ULast);
+    }
+
+    // Get the point by length
+    GeomAdaptor_Curve AdapCurve = GeomAdaptor_Curve(ReOrientedCurve);
+    GCPnts_AbscissaPoint anAbsPnt (AdapCurve, aLength, UFirst);
+    Standard_Real aParam = anAbsPnt.Parameter();
+
+    if (AdapCurve.IsClosed() && aLength < 0.0) {
+      Standard_Real aTmp = aParam;
+      aParam = UFirst;
+      UFirst = aTmp;
+    }
+
+    BRepBuilderAPI_MakeEdge aME (ReOrientedCurve, UFirst, aParam);
+    if (aME.IsDone())
+      aShape = aME.Shape();
+  }
+  else {
+  }
+
+  if (aShape.IsNull()) return 0;
+
+  // Check shape validity
+  BRepCheck_Analyzer ana (aShape, false);
+  if (!ana.IsValid()) {
+    //Standard_ConstructionError::Raise("Algorithm have produced an invalid shape result");
+  }
+
+  aFunction->SetValue(aShape);
+
+  log.SetTouched(Label());
+
+  if (!aWarning.IsEmpty())
+    Standard_Failure::Raise(aWarning.ToCString());
+
+  return 1;
+}
+
+TopoDS_Edge GEOMImpl_ShapeDriver::MakeEdgeFromWire(const TopoDS_Shape& aWire,
+                                                   const Standard_Real LinTol,
+                                                   const Standard_Real AngTol)
+{
     TopoDS_Edge ResEdge;
 
     BRepLib::BuildCurves3d(aWire);
@@ -834,105 +936,9 @@ Standard_Integer GEOMImpl_ShapeDriver::Execute(TFunction_Logbook& log) const
     if (FinalReverse)
       ResEdge.Reverse();
 
-    aShape = ResEdge;
-  }
-  else if (aType == EDGE_CURVE_LENGTH) {
-    GEOMImpl_IVector aVI (aFunction);
-
-    // RefCurve
-    Handle(GEOM_Function) aRefCurve = aVI.GetPoint1();
-    if (aRefCurve.IsNull()) Standard_NullObject::Raise("Argument Curve is null");
-    TopoDS_Shape aRefShape1 = aRefCurve->GetValue();
-    if (aRefShape1.ShapeType() != TopAbs_EDGE) {
-      Standard_TypeMismatch::Raise
-        ("Edge On Curve creation aborted : curve shape is not an edge");
-    }
-    TopoDS_Edge aRefEdge = TopoDS::Edge(aRefShape1);
-    TopoDS_Vertex V1, V2;
-    TopExp::Vertices(aRefEdge, V1, V2, Standard_True);
-
-    // RefPoint
-    TopoDS_Vertex aRefVertex;
-    Handle(GEOM_Function) aRefPoint = aVI.GetPoint2();
-    if (aRefPoint.IsNull()) {
-      aRefVertex = V1;
-    }
-    else {
-      TopoDS_Shape aRefShape2 = aRefPoint->GetValue();
-      if (aRefShape2.ShapeType() != TopAbs_VERTEX) {
-        Standard_TypeMismatch::Raise
-          ("Edge On Curve creation aborted : start point shape is not a vertex");
-      }
-      aRefVertex = TopoDS::Vertex(aRefShape2);
-    }
-    gp_Pnt aRefPnt = BRep_Tool::Pnt(aRefVertex);
-
-    // Length
-    Standard_Real aLength = aVI.GetParameter();
-    //Standard_Real aCurveLength = IntTools::Length(aRefEdge);
-    //if (aLength > aCurveLength) {
-    //  Standard_ConstructionError::Raise
-    //    ("Edge On Curve creation aborted : given length is greater than edges length");
-    //}
-    if (fabs(aLength) < Precision::Confusion()) {
-      Standard_ConstructionError::Raise
-        ("Edge On Curve creation aborted : given length is smaller than Precision::Confusion()");
-    }
-
-    // Check orientation
-    Standard_Real UFirst, ULast;
-    Handle(Geom_Curve) EdgeCurve = BRep_Tool::Curve(aRefEdge, UFirst, ULast);
-    Handle(Geom_Curve) ReOrientedCurve = EdgeCurve;
-
-    Standard_Real dU = ULast - UFirst;
-    Standard_Real par1 = UFirst + 0.1 * dU;
-    Standard_Real par2 = ULast  - 0.1 * dU;
-
-    gp_Pnt P1 = EdgeCurve->Value(par1);
-    gp_Pnt P2 = EdgeCurve->Value(par2);
-
-    if (aRefPnt.SquareDistance(P2) < aRefPnt.SquareDistance(P1)) {
-      ReOrientedCurve = EdgeCurve->Reversed();
-      UFirst = EdgeCurve->ReversedParameter(ULast);
-    }
-
-    // Get the point by length
-    GeomAdaptor_Curve AdapCurve = GeomAdaptor_Curve(ReOrientedCurve);
-    GCPnts_AbscissaPoint anAbsPnt (AdapCurve, aLength, UFirst);
-    Standard_Real aParam = anAbsPnt.Parameter();
-
-    if (AdapCurve.IsClosed() && aLength < 0.0) {
-      Standard_Real aTmp = aParam;
-      aParam = UFirst;
-      UFirst = aTmp;
-    }
-
-    BRepBuilderAPI_MakeEdge aME (ReOrientedCurve, UFirst, aParam);
-    if (aME.IsDone())
-      aShape = aME.Shape();
-  }
-  else {
-  }
-
-  if (aShape.IsNull()) return 0;
-
-  // Check shape validity
-  BRepCheck_Analyzer ana (aShape, false);
-  if (!ana.IsValid()) {
-    //Standard_ConstructionError::Raise("Algorithm have produced an invalid shape result");
-  }
-
-  aFunction->SetValue(aShape);
-
-  log.SetTouched(Label());
-
-  if (!aWarning.IsEmpty())
-    Standard_Failure::Raise(aWarning.ToCString());
-
-  return 1;
+    return ResEdge;
 }
 
-
 //=======================================================================
 //function :  GEOMImpl_ShapeDriver_Type_
 //purpose  :
index 41c0fd6ae64884fd46f9fd7e38bdd390c5c2c528..653ad7e13a821b984787c18d441a6c162b66843b 100644 (file)
 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 //
 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
-//
 
 //  File   : GEOMImpl_ShapeDriver.ixx
 //  Module : GEOMImpl
-//
+
 #ifndef _GEOMImpl_ShapeDriver_HeaderFile
 #define _GEOMImpl_ShapeDriver_HeaderFile
 
@@ -119,6 +118,9 @@ class Handle(GEOMImpl_ShapeDriver) : public Handle(TFunction_Driver) {
 #include <Standard_CString.hxx>
 #endif
 
+#include <TopoDS_Shape.hxx>
+#include <TopoDS_Edge.hxx>
+
 class TColStd_SequenceOfExtendedString;
 
 
@@ -126,35 +128,38 @@ class GEOMImpl_ShapeDriver : public TFunction_Driver {
 
 public:
 
-    inline void* operator new(size_t,void* anAddress) 
-      {
-        return anAddress;
-      }
-    inline void* operator new(size_t size) 
-      { 
-        return Standard::Allocate(size); 
-      }
-    inline void  operator delete(void *anAddress) 
-      { 
-        if (anAddress) Standard::Free((Standard_Address&)anAddress); 
-      }
-
- // Methods PUBLIC
- // 
-Standard_EXPORT GEOMImpl_ShapeDriver();
-Standard_EXPORT virtual  Standard_Integer Execute(TFunction_Logbook& log) const; 
-Standard_EXPORT virtual void Validate(TFunction_Logbook&) const {}
-Standard_EXPORT Standard_Boolean MustExecute(const TFunction_Logbook&) const { return Standard_True; }
-Standard_EXPORT static const Standard_GUID& GetID();
-Standard_EXPORT ~GEOMImpl_ShapeDriver() {};
-
-
- // Type management
- //
-Standard_EXPORT friend Handle_Standard_Type& GEOMImpl_ShapeDriver_Type_();
-Standard_EXPORT const Handle(Standard_Type)& DynamicType() const  { return STANDARD_TYPE(GEOMImpl_ShapeDriver) ; }
-Standard_EXPORT Standard_Boolean IsKind(const Handle(Standard_Type)& AType) const { return (STANDARD_TYPE(GEOMImpl_ShapeDriver) == AType || TFunction_Driver::IsKind(AType)); } 
-
+  inline void* operator new(size_t,void* anAddress) 
+  {
+    return anAddress;
+  }
+  inline void* operator new(size_t size) 
+  { 
+    return Standard::Allocate(size); 
+  }
+  inline void  operator delete(void *anAddress) 
+  { 
+    if (anAddress) Standard::Free((Standard_Address&)anAddress); 
+  }
+
+  // Methods PUBLIC
+  // 
+  Standard_EXPORT GEOMImpl_ShapeDriver();
+  Standard_EXPORT ~GEOMImpl_ShapeDriver() {};
+
+  Standard_EXPORT virtual  Standard_Integer Execute(TFunction_Logbook& log) const; 
+  Standard_EXPORT virtual void Validate(TFunction_Logbook&) const {}
+  Standard_EXPORT Standard_Boolean MustExecute(const TFunction_Logbook&) const { return Standard_True; }
+  Standard_EXPORT static const Standard_GUID& GetID();
+
+  Standard_EXPORT static TopoDS_Edge MakeEdgeFromWire(const TopoDS_Shape& aWire,
+                                                      const Standard_Real LinTol,
+                                                      const Standard_Real AngTol);
+
+  // Type management
+  //
+  Standard_EXPORT friend Handle_Standard_Type& GEOMImpl_ShapeDriver_Type_();
+  Standard_EXPORT const Handle(Standard_Type)& DynamicType() const  { return STANDARD_TYPE(GEOMImpl_ShapeDriver) ; }
+  Standard_EXPORT Standard_Boolean IsKind(const Handle(Standard_Type)& AType) const { return (STANDARD_TYPE(GEOMImpl_ShapeDriver) == AType || TFunction_Driver::IsKind(AType)); } 
 
 };
 
index b8a332987a8073b0415494edd47ff9c6c014f3bf..2e5f871b82c8d30c2b3f2225b8d6ce2e4b9e8fc9 100755 (executable)
 #define DIVIDE_EDGE        7
 #define CHANGE_ORIENTATION 8
 #define LIMIT_TOLERANCE    9
+#define FUSE_COLLINEAR_EDGES 10
 
 #define BASIC_FILLING 1
 
index 84f1e2324a586117888227978290fc307d5960e3..9a064b3d042bbc2a3dd5d9cf27d67ba096cd4696 100644 (file)
@@ -18,7 +18,6 @@
 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 //
 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
-//
 
 #include <Standard_Stream.hxx>
 
@@ -396,6 +395,43 @@ GEOM::GEOM_Object_ptr GEOM_IHealingOperations_i::DivideEdge (GEOM::GEOM_Object_p
   return GetObject(aNewObject);
 }
 
+//=============================================================================
+/*!
+ *  FuseCollinearEdgesWithinWire
+ */
+//=============================================================================
+GEOM::GEOM_Object_ptr GEOM_IHealingOperations_i::FuseCollinearEdgesWithinWire
+                                          (GEOM::GEOM_Object_ptr theWire,
+                                           const GEOM::ListOfGO& theVertices)
+{
+  GEOM::GEOM_Object_var aGEOMObject;
+
+  //Set a not done flag
+  GetOperations()->SetNotDone();
+
+  //Get the reference objects
+  Handle(GEOM_Object) aWire = GetObjectImpl(theWire);
+  if (aWire.IsNull()) return aGEOMObject._retn();
+
+  int ind, aLen;
+  std::list<Handle(GEOM_Object)> aVerts;
+  //Get the shapes
+  aLen = theVertices.length();
+  for (ind = 0; ind < aLen; ind++) {
+    Handle(GEOM_Object) aSh = GetObjectImpl(theVertices[ind]);
+    if (aSh.IsNull()) return aGEOMObject._retn();
+    aVerts.push_back(aSh);
+  }
+
+  //Perform operation
+  Handle(GEOM_Object) anObject =
+    GetOperations()->FuseCollinearEdgesWithinWire(aWire, aVerts);
+  if (!GetOperations()->IsDone() || anObject.IsNull())
+    return aGEOMObject._retn();
+
+  return GetObject(anObject);
+}
+
 //=============================================================================
 /*!
  *  GetFreeBoundary
index b7344e9cc431de68b364be7fea185af68fcbd839..bdbaf868973f221f3dd91d56644e1401d55054ad 100644 (file)
@@ -18,8 +18,6 @@
 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 //
 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
-//
-
 
 #ifndef _GEOM_IHealingOperations_i_HeaderFile
 #define _GEOM_IHealingOperations_i_HeaderFile
@@ -81,6 +79,9 @@ class GEOM_I_EXPORT GEOM_IHealingOperations_i :
                                      CORBA::Double theValue,
                                      CORBA::Boolean isByParameter);
 
+   GEOM::GEOM_Object_ptr FuseCollinearEdgesWithinWire (GEOM::GEOM_Object_ptr theWire,
+                                                       const GEOM::ListOfGO& theVertices);
+
    CORBA::Boolean GetFreeBoundary(GEOM::GEOM_Object_ptr theObject,
                                   GEOM::ListOfGO_out theClosedWires,
                                   GEOM::ListOfGO_out theOpenWires );
index ec764c2bee36dac210d88771cb74cf52b3c9fc14..9547786145059833948b33958811338af61bc857 100644 (file)
@@ -18,7 +18,6 @@
 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 //
 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
-//
 
 #include <Standard_Stream.hxx>
 
@@ -245,7 +244,8 @@ GEOM::GEOM_Object_ptr GEOM_ILocalOperations_i::MakeFillet2D
 //=============================================================================
 GEOM::GEOM_Object_ptr GEOM_ILocalOperations_i::MakeFillet1D
                       (GEOM::GEOM_Object_ptr theShape, CORBA::Double theR,
-                       const GEOM::ListOfLong& theVertexes)
+                       const GEOM::ListOfLong& theVertexes,
+                       CORBA::Boolean doIgnoreSecantVertices)
 {
   GEOM::GEOM_Object_var aGEOMObject;
 
@@ -263,7 +263,7 @@ GEOM::GEOM_Object_ptr GEOM_ILocalOperations_i::MakeFillet1D
 
   //Create the Fillet
   Handle(GEOM_Object) anObject =
-    GetOperations()->MakeFillet1D(aShapeRef, theR, aVertexes);
+    GetOperations()->MakeFillet1D(aShapeRef, theR, aVertexes, doIgnoreSecantVertices);
   if (!GetOperations()->IsDone() || anObject.IsNull())
     return aGEOMObject._retn();
 
index 432f56ffc0c96683d03670e78ef7748977d89559..764f8e5cb5640b0c2c753cacfc0832854fcc838b 100644 (file)
@@ -18,7 +18,6 @@
 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 //
 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
-//
 
 #ifndef _GEOM_ILocalOperations_i_HeaderFile
 #define _GEOM_ILocalOperations_i_HeaderFile
@@ -65,7 +64,8 @@ class GEOM_I_EXPORT GEOM_ILocalOperations_i :
                                      const GEOM::ListOfLong& theVertexes);
 
   GEOM::GEOM_Object_ptr MakeFillet1D (GEOM::GEOM_Object_ptr theShape, CORBA::Double theR,
-                                     const GEOM::ListOfLong& theVertexes);
+                                     const GEOM::ListOfLong& theVertexes,
+                                      CORBA::Boolean doIgnoreSecantVertices);
 
   GEOM::GEOM_Object_ptr MakeChamferAll   (GEOM::GEOM_Object_ptr theShape, CORBA::Double theD);
 
index 684558c07b48cf99cedfaa4111f647543f86b3dc..b3c2cf03884ed0b9c6a3383b3709056a26a3275d 100644 (file)
@@ -18,7 +18,6 @@
 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 //
 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
-//
 
 #include "GEOM_Superv_i.hh"
 #include "SALOME_LifeCycleCORBA.hxx"
@@ -3034,14 +3033,16 @@ GEOM::GEOM_Object_ptr GEOM_Superv_i::MakeFillet2D (GEOM::GEOM_Object_ptr theShap
 //=============================================================================
 GEOM::GEOM_Object_ptr GEOM_Superv_i::MakeFillet1D (GEOM::GEOM_Object_ptr theShape,
                                                    CORBA::Double theR,
-                                                   GEOM::GEOM_List_ptr theVertexes)
+                                                   GEOM::GEOM_List_ptr theVertexes,
+                                                   CORBA::Boolean doIgnoreSecantVertices)
 {
   beginService( " GEOM_Superv_i::MakeFillet1D" );
   MESSAGE("GEOM_Superv_i::MakeFillet1D");
   if (GEOM_List_i<GEOM::ListOfLong>* aListImplV =
       dynamic_cast<GEOM_List_i<GEOM::ListOfLong>*>(GetServant(theVertexes, myPOA).in())) {
     getLocalOp();
-    GEOM::GEOM_Object_ptr anObj = myLocalOp->MakeFillet1D(theShape, theR, aListImplV->GetList());
+    GEOM::GEOM_Object_ptr anObj = myLocalOp->MakeFillet1D
+      (theShape, theR, aListImplV->GetList(), doIgnoreSecantVertices);
     endService( " GEOM_Superv_i::MakeFillet1D" );
     return anObj;
   }
index 3dd0192fe593bd1ce381ce0656bc6edc3993c685..7a9014af86b70cc1d3298dc7e8d2244d714b7502 100644 (file)
@@ -642,7 +642,7 @@ public:
   GEOM::GEOM_Object_ptr MakeFillet2D (GEOM::GEOM_Object_ptr theShape, CORBA::Double theR,
                                       GEOM::GEOM_List_ptr theVertexes);
   GEOM::GEOM_Object_ptr MakeFillet1D (GEOM::GEOM_Object_ptr theShape, CORBA::Double theR,
-                                      GEOM::GEOM_List_ptr theVertexes);
+                                      GEOM::GEOM_List_ptr theVertexes, CORBA::Boolean doIgnoreSecantVertices);
   GEOM::GEOM_Object_ptr MakeChamferAll (GEOM::GEOM_Object_ptr theShape, CORBA::Double theD);
   GEOM::GEOM_Object_ptr MakeChamferEdge (GEOM::GEOM_Object_ptr theShape,
                                          CORBA::Double theD1, CORBA::Double theD2,
index 6fe6df6c0afe2504432fa2c9c0ec390e7549c5e1..abe4a9810495f4343caee8535d33ee6dad880c6d 100644 (file)
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 #
 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
-#
 
-#  GEOM GEOM_SWIG : binding of C++ implementaion with Python
+#  GEOM_SWIG : binding of C++ implementaion with Python
 #  File   : GEOM_TestHealing.py
 #  Author : Julia DOROVSKIKH
 #  Module : GEOM
-#  $Header$
-#
+
 def TestProcessShape (geompy):
 
   ##Load shape from BREP file
@@ -324,6 +322,51 @@ def TestDivideEdge (geompy):
   Id_Box    = geompy.addToStudy(Box, "Box")
   Id_Divide = geompy.addToStudy(Divide, "Box with Divided Edge")
 
+def TestFuseEdges (geompy):
+
+  # create vertices
+  p1 = geompy.MakeVertex(0, 0, 0)
+  p2 = geompy.MakeVertex(70, 0, 0)
+  p3 = geompy.MakeVertex(70, 50, 0)
+  p4 = geompy.MakeVertex(70, 80, 0)
+  p5 = geompy.MakeVertex(50, 80, 0)
+  p6 = geompy.MakeVertex(20, 80, 0)
+  p7 = geompy.MakeVertex(0, 80, 0)
+  p8 = geompy.MakeVertex(0, 30, 0)
+
+  points = [p1, p2, p3, p4, p5, p6, p7, p8]
+
+  # make a wire
+  wire_1 = geompy.MakePolyline(points, True)
+
+  # suppress some vertices in the wire
+  wire_2 = geompy.FuseCollinearEdgesWithinWire(wire_1, [p3])
+  wire_3 = geompy.FuseCollinearEdgesWithinWire(wire_1, [p5, p6])
+
+  # suppress all suitable vertices in the wire
+  wire_4 = geompy.FuseCollinearEdgesWithinWire(wire_1, [])
+
+  wires = [wire_1, wire_2, wire_3, wire_4]
+
+  # add objects in the study
+  ii = 1
+  for point in points:
+    geompy.addToStudy(point, "p%d"%ii)
+    ii = ii + 1
+    pass
+
+  ii = 1
+  for wire in wires:
+    geompy.addToStudy(wire, "wire_%d"%ii)
+    wire_points = geompy.SubShapeAllSortedCentres(wire, geompy.ShapeType["VERTEX"])
+    jj = 1
+    for point in wire_points:
+      geompy.addToStudyInFather(wire, point, "point_%d"%jj)
+      jj = jj + 1
+      pass
+    ii = ii + 1
+    pass
+
 def TestHealingOperations (geompy, math):
 
   TestMakeSewing(geompy, math)
@@ -333,3 +376,4 @@ def TestHealingOperations (geompy, math):
   TestCloseContour(geompy)
   TestSuppressFaces(geompy)
   TestProcessShape(geompy)
+  TestFuseEdges(geompy)
index f07490efb793309251a13265c727708b50604845..46a7d224d2e60ba4f8dd028a9186fa0e71fa9c04 100644 (file)
@@ -4642,6 +4642,29 @@ class geompyDC(GEOM._objref_GEOM_Gen):
             anObj.SetParameters(Parameters)
             return anObj
 
+        ## Suppress the vertices in the wire in case if adjacent edges are C1 continuous.
+        #  @param theWire Wire to minimize the number of C1 continuous edges in.
+        #  @param theVertices A list of vertices to suppress. If the list
+        #                     is empty, all vertices in a wire will be assumed.
+        #  @return New GEOM.GEOM_Object with modified wire.
+        #
+        #  @ref tui_fuse_collinear_edges "Example"
+        def FuseCollinearEdgesWithinWire(self, theWire, theVertices = []):
+            """
+            Suppress the vertices in the wire in case if adjacent edges are C1 continuous.
+
+            Parameters: 
+                theWire Wire to minimize the number of C1 continuous edges in.
+                theVertices A list of vertices to suppress. If the list
+                            is empty, all vertices in a wire will be assumed.
+
+            Returns:  
+                New GEOM.GEOM_Object with modified wire.
+            """
+            anObj = self.HealOp.FuseCollinearEdgesWithinWire(theWire, theVertices)
+            RaiseIfFailed("FuseCollinearEdgesWithinWire", self.HealOp)
+            return anObj
+
         ## Change orientation of the given object. Updates given shape.
         #  @param theObject Shape to be processed.
         #  @return Updated <var>theObject</var>
@@ -6001,10 +6024,16 @@ class geompyDC(GEOM._objref_GEOM_Gen):
         #    \note Global index of sub-shape can be obtained, using method GetSubShapeID()
         #    \note The list of vertices could be empty,
         #          in this case fillet will done done at all vertices in wire
+        #  @param doIgnoreSecantVertices If FALSE, fillet radius is always limited
+        #         by the length of the edges, nearest to the fillet vertex.
+        #         But sometimes the next edge is C1 continuous with the one, nearest to
+        #         the fillet point, and such two (or more) edges can be united to allow
+        #         bigger radius. Set this flag to TRUE to allow collinear edges union,
+        #         thus ignoring the secant vertex (vertices).
         #  @return New GEOM.GEOM_Object, containing the result shape.
         #
         #  @ref tui_fillet2d "Example"
-        def MakeFillet1D(self,theShape, theR, theListOfVertexes):
+        def MakeFillet1D(self,theShape, theR, theListOfVertexes, doIgnoreSecantVertices = True):
             """
             Perform a fillet on the specified edges of the given shape
 
@@ -6012,6 +6041,12 @@ class geompyDC(GEOM._objref_GEOM_Gen):
                 theShape  Wire Shape to perform fillet on.
                 theR  Fillet radius.
                 theListOfVertexes Global indices of vertexes to perform fillet on.
+                doIgnoreSecantVertices If FALSE, fillet radius is always limited
+                    by the length of the edges, nearest to the fillet vertex.
+                    But sometimes the next edge is C1 continuous with the one, nearest to
+                    the fillet point, and such two (or more) edges can be united to allow
+                    bigger radius. Set this flag to TRUE to allow collinear edges union,
+                    thus ignoring the secant vertex (vertices).
             Note:
                 Global index of sub-shape can be obtained, using method geompy.GetSubShapeID
 
@@ -6027,8 +6062,8 @@ class geompyDC(GEOM._objref_GEOM_Gen):
                 Fillet_1D_1 = geompy.MakeFillet1D(Wire_1, 55, [3, 4, 6, 8, 10])
             """
             # Example: see GEOM_TestAll.py
-            theR,Parameters = ParseParameters(theR)
-            anObj = self.LocalOp.MakeFillet1D(theShape, theR, theListOfVertexes)
+            theR,doIgnoreSecantVertices,Parameters = ParseParameters(theR,doIgnoreSecantVertices)
+            anObj = self.LocalOp.MakeFillet1D(theShape, theR, theListOfVertexes, doIgnoreSecantVertices)
             RaiseIfFailed("MakeFillet1D", self.LocalOp)
             anObj.SetParameters(Parameters)
             return anObj
index 16cc60845500da1b2e9a64b1b967b5fd032a4638..ee5b866331301e82d24aa06581ca54012148e599 100644 (file)
@@ -15,7 +15,6 @@
 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 //
 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
-//
 
 // GEOM GEOMGUI : GUI for Geometry component
 // File   : OperationGUI_Fillet1d2dDlg.cxx
@@ -68,7 +67,7 @@ OperationGUI_Fillet1d2dDlg::OperationGUI_Fillet1d2dDlg (GeometryGUI* theGeometry
   mainFrame()->RadioButton2->close();
   mainFrame()->RadioButton3->close();
 
-  GroupVertexes = new DlgRef_2Sel1Spin(centralWidget());
+  GroupVertexes = new DlgRef_2Sel1Spin2Check (centralWidget());
   GroupVertexes->GroupBox1->setTitle(myIs1D ? tr("GEOM_FILLET_1D") : tr("GEOM_FILLET_2D"));
   GroupVertexes->TextLabel1->setText(myIs1D ? tr("GEOM_PLANAR_EDGE_WIRE") : tr("GEOM_PLANAR_FACE"));
   GroupVertexes->TextLabel2->setText(tr("GEOM_VERTEXES"));
@@ -77,6 +76,13 @@ OperationGUI_Fillet1d2dDlg::OperationGUI_Fillet1d2dDlg (GeometryGUI* theGeometry
   GroupVertexes->PushButton2->setIcon(iconSelect);
   GroupVertexes->LineEdit1->setReadOnly(true);
   GroupVertexes->LineEdit2->setReadOnly(true);
+  if (myIs1D) {
+    GroupVertexes->CheckButton1->setText(tr("GEOM_FILLET_1D_IGNORE_SECANT"));
+    GroupVertexes->CheckButton1->setChecked(true);
+  }
+  else
+    GroupVertexes->CheckButton1->close();
+  GroupVertexes->CheckButton2->close();
 
   QVBoxLayout* layout = new QVBoxLayout(centralWidget());
   layout->setMargin(0); layout->setSpacing(6);
@@ -127,8 +133,6 @@ void OperationGUI_Fillet1d2dDlg::Init()
   connect(buttonOk(),    SIGNAL(clicked()), this, SLOT(ClickOnOk()   ));
   connect(buttonApply(), SIGNAL(clicked()), this, SLOT(ClickOnApply()));
 
-  //  connect(this,          SIGNAL(constructorsClicked(int)), this, SLOT(ConstructorsClicked(int)));
-
   connect(GroupVertexes->PushButton1, SIGNAL(clicked()), this, SLOT(SetEditCurrentArgument()));
   connect(GroupVertexes->PushButton2, SIGNAL(clicked()), this, SLOT(SetEditCurrentArgument()));
 
@@ -137,6 +141,8 @@ void OperationGUI_Fillet1d2dDlg::Init()
 
   connect(GroupVertexes->SpinBox_DX, SIGNAL(valueChanged(double)), this, SLOT(ValueChangedInSpinBox(double)));
 
+  connect(GroupVertexes->CheckButton1, SIGNAL(toggled(bool)), this, SLOT(processPreview()));
+
   initName(myIs1D ? tr("GEOM_FILLET_1D") : tr("GEOM_FILLET_2D"));
   GroupVertexes->PushButton1->click();
 
@@ -401,7 +407,7 @@ bool OperationGUI_Fillet1d2dDlg::execute (ObjectList& objects)
 
   GEOM::GEOM_ILocalOperations_var anOper = GEOM::GEOM_ILocalOperations::_narrow(getOperation());
   GEOM::GEOM_Object_var anObj = myIs1D ?
-    anOper->MakeFillet1D(myShape, getRadius(), aListOfIndexes) : 
+    anOper->MakeFillet1D(myShape, getRadius(), aListOfIndexes, GroupVertexes->CheckButton1->isChecked()) : 
     anOper->MakeFillet2D(myShape, getRadius(), aListOfIndexes);
 
   if (!anObj->_is_nil())
@@ -416,5 +422,5 @@ bool OperationGUI_Fillet1d2dDlg::execute (ObjectList& objects)
 //=================================================================================
 double OperationGUI_Fillet1d2dDlg::getRadius() const
 {
-  return GroupVertexes ->SpinBox_DX->value();
+  return GroupVertexes->SpinBox_DX->value();
 }
index 85fdf27f7eba1f699ad45b769de1e5cc6afa66ba..04b4a7fce2d76ce4b4b7a00139ea60f6b9448d79 100644 (file)
 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 //
 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
-//
 
 // GEOM GEOMGUI : GUI for Geometry component
 // File   : OperationGUI_Fillet1d2dDlg.h
 // Author : DMV, OCN
-//
+
 #ifndef OPERATIONGUI_Fillet1d2dDLG_H
 #define OPERATIONGUI_Fillet1d2dDLG_H
 
@@ -28,7 +27,7 @@
 
 #include <TColStd_IndexedMapOfInteger.hxx>
 
-class DlgRef_2Sel1Spin;
+class DlgRef_2Sel1Spin2Check;
 
 //=================================================================================
 // class    : OperationGUI_Fillet1d2dDlg
@@ -68,7 +67,7 @@ private:
   GEOM::GEOM_Object_var               myShape;
   TColStd_IndexedMapOfInteger         myVertexes;
 
-  DlgRef_2Sel1Spin*                   GroupVertexes;
+  DlgRef_2Sel1Spin2Check*             GroupVertexes;
 };
 
 #endif // OPERATIONGUI_Fillet1d2dDLG_H
index a4453ae5c09d7f473c999b25074f687edafbdedd..4c1bf3d8ea64f5fd86f018f19ce671097c0ce0af 100644 (file)
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 #
 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
-#
 
-# GEOM REPAIRGUI : 
 # File    : Makefile.am
 # Author  : Alexander BORODIN, Open CASCADE S.A.S. (alexander.borodin@opencascade.com)
 # Package : RepairGUI
-#
+
 include $(top_srcdir)/adm_local/unix/make_common_starter.am
 
 # header files 
@@ -39,7 +37,8 @@ salomeinclude_HEADERS =                               \
        RepairGUI_ChangeOrientationDlg.h        \
        RepairGUI_GlueDlg.h                     \
        RepairGUI_LimitToleranceDlg.h           \
-       RepairGUI_RemoveExtraEdgesDlg.h
+       RepairGUI_RemoveExtraEdgesDlg.h         \
+       RepairGUI_FuseEdgesDlg.h
 
 # Libraries targets
 lib_LTLIBRARIES = libRepairGUI.la
@@ -59,6 +58,7 @@ dist_libRepairGUI_la_SOURCES =                        \
        RepairGUI_GlueDlg.h                     \
        RepairGUI_LimitToleranceDlg.h           \
        RepairGUI_RemoveExtraEdgesDlg.h         \
+       RepairGUI_FuseEdgesDlg.h                \
                                                \
        RepairGUI.cxx                           \
        RepairGUI_SewingDlg.cxx                 \
@@ -73,7 +73,8 @@ dist_libRepairGUI_la_SOURCES =                        \
        RepairGUI_ChangeOrientationDlg.cxx      \
        RepairGUI_GlueDlg.cxx                   \
        RepairGUI_LimitToleranceDlg.cxx         \
-       RepairGUI_RemoveExtraEdgesDlg.cxx
+       RepairGUI_RemoveExtraEdgesDlg.cxx       \
+       RepairGUI_FuseEdgesDlg.cxx
 
 MOC_FILES =                                    \
        RepairGUI_SewingDlg_moc.cxx             \
@@ -88,7 +89,8 @@ MOC_FILES =                                   \
        RepairGUI_ChangeOrientationDlg_moc.cxx  \
        RepairGUI_GlueDlg_moc.cxx               \
        RepairGUI_LimitToleranceDlg_moc.cxx     \
-       RepairGUI_RemoveExtraEdgesDlg_moc.cxx
+       RepairGUI_RemoveExtraEdgesDlg_moc.cxx   \
+       RepairGUI_FuseEdgesDlg_moc.cxx
 
 nodist_libRepairGUI_la_SOURCES =               \
        $(MOC_FILES)
index 3c72cbac3b7ca1a436e214e53e49c06d35fd94ec..5144986fa7d9625e81ab26a92144a39d73f503a1 100644 (file)
@@ -44,6 +44,7 @@
 #include "RepairGUI_LimitToleranceDlg.h"    // Method LIMIT TOLERANCE
 #include "RepairGUI_ChangeOrientationDlg.h" // Method CHANGE ORIENTATION
 #include "RepairGUI_RemoveExtraEdgesDlg.h"  // Method REMOVE EXTRA EDGES
+#include "RepairGUI_FuseEdgesDlg.h"         // Method FUSE COLLINEAR EDGES
 
 //=======================================================================
 // function : RepairGUI()
@@ -90,9 +91,10 @@ bool RepairGUI::OnGUIEvent( int theCommandID, SUIT_Desktop* parent )
   case GEOMOp::OpFreeFaces:        aDlg = new RepairGUI_FreeFacesDlg         (getGeometryGUI(), parent); break;
   case GEOMOp::OpOrientation:      aDlg = new RepairGUI_ChangeOrientationDlg (getGeometryGUI(), parent); break;
   case GEOMOp::OpRemoveExtraEdges: aDlg = new RepairGUI_RemoveExtraEdgesDlg  (getGeometryGUI(), parent); break;
-    default:
-      app->putInfo(tr("GEOM_PRP_COMMAND").arg(theCommandID));
-      break;
+  case GEOMOp::OpFuseEdges:        aDlg = new RepairGUI_FuseEdgesDlg         (getGeometryGUI(), parent); break;
+  default:
+    app->putInfo(tr("GEOM_PRP_COMMAND").arg(theCommandID));
+    break;
   }
 
   if (aDlg)
diff --git a/src/RepairGUI/RepairGUI_FuseEdgesDlg.cxx b/src/RepairGUI/RepairGUI_FuseEdgesDlg.cxx
new file mode 100644 (file)
index 0000000..4356b18
--- /dev/null
@@ -0,0 +1,347 @@
+// Copyright (C) 2007-2012  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.
+//
+// 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
+
+#include "RepairGUI_FuseEdgesDlg.h"
+
+#include <DlgRef.h>
+#include <GeometryGUI.h>
+#include <GEOMBase.h>
+
+#include <SUIT_Desktop.h>
+#include <SUIT_Session.h>
+#include <SUIT_ResourceMgr.h>
+#include <SUIT_ViewWindow.h>
+#include <SUIT_ViewManager.h>
+#include <SalomeApp_Application.h>
+#include <LightApp_SelectionMgr.h>
+#include <OCCViewer_ViewModel.h>
+
+// OCCT Includes
+#include <TColStd_MapOfInteger.hxx>
+#include <TColStd_IndexedMapOfInteger.hxx>
+
+#include <GEOMImpl_Types.hxx>
+
+//=================================================================================
+// class    : RepairGUI_FuseEdgesDlg()
+// purpose  : Constructs a RepairGUI_FuseEdgesDlg which is a child of 'parent', with the
+//            name 'name' and widget flags set to 'f'.
+//            The dialog will by default be modeless, unless you set 'modal' to
+//            TRUE to construct a modal dialog.
+//=================================================================================
+RepairGUI_FuseEdgesDlg::RepairGUI_FuseEdgesDlg (GeometryGUI* theGeometryGUI,
+                                                QWidget* parent)
+  : GEOMBase_Skeleton(theGeometryGUI, parent, false)
+{
+  SUIT_ResourceMgr* aResMgr = myGeomGUI->getApp()->resourceMgr();
+  QPixmap image0 (aResMgr->loadPixmap("GEOM", tr("ICON_DLG_FUSE_EDGES")));
+  QPixmap iconSelect (aResMgr->loadPixmap("GEOM", tr("ICON_SELECT")));
+
+  setWindowTitle(tr("GEOM_FUSE_EDGES_TITLE"));
+
+  mainFrame()->GroupConstructors->setTitle(tr("GEOM_FUSE_EDGES"));
+  mainFrame()->RadioButton1->setIcon(image0);
+  mainFrame()->RadioButton2->close();
+  mainFrame()->RadioButton3->close();
+
+  GroupVertexes = new DlgRef_2Sel1Spin (centralWidget());
+  GroupVertexes->GroupBox1->setTitle(tr("GEOM_FUSE_EDGES"));
+  GroupVertexes->TextLabel1->setText(tr("GEOM_WIRE"));
+  GroupVertexes->TextLabel2->setText(tr("GEOM_VERTEXES"));
+  GroupVertexes->PushButton1->setIcon(iconSelect);
+  GroupVertexes->PushButton2->setIcon(iconSelect);
+  GroupVertexes->LineEdit1->setReadOnly(true);
+  GroupVertexes->LineEdit2->setReadOnly(true);
+
+  GroupVertexes->TextLabel3->setShown(false);
+  GroupVertexes->SpinBox_DX->setShown(false);
+
+  QVBoxLayout* layout = new QVBoxLayout (centralWidget());
+  layout->setMargin(0);
+  layout->setSpacing(6);
+  layout->addWidget(GroupVertexes);
+
+  setHelpFileName("fuse_edges_operation_page.html");
+
+  // Initialisation
+  Init();
+  resize(100,100);
+}
+
+//=================================================================================
+// function : ~RepairGUI_FuseEdgesDlg()
+// purpose  : Destroys the object and frees any allocated resources
+//=================================================================================
+RepairGUI_FuseEdgesDlg::~RepairGUI_FuseEdgesDlg()
+{
+}
+
+//=================================================================================
+// function : Init()
+// purpose  :
+//=================================================================================
+void RepairGUI_FuseEdgesDlg::Init()
+{
+  // Clear line edits
+  GroupVertexes->LineEdit1->setText("");
+  GroupVertexes->LineEdit2->setText("");
+
+  myShape = GEOM::GEOM_Object::_nil();
+
+  myPoints.clear();
+
+  // signals and slots connections
+  connect(buttonOk(),    SIGNAL(clicked()), this, SLOT(ClickOnOk()));
+  connect(buttonApply(), SIGNAL(clicked()), this, SLOT(ClickOnApply()));
+
+  connect(GroupVertexes->PushButton1, SIGNAL(clicked()), this, SLOT(SetEditCurrentArgument()));
+  connect(GroupVertexes->PushButton2, SIGNAL(clicked()), this, SLOT(SetEditCurrentArgument()));
+
+  connect(GroupVertexes->LineEdit1, SIGNAL(returnPressed()), this, SLOT(LineEditReturnPressed()));
+  connect(GroupVertexes->LineEdit2, SIGNAL(returnPressed()), this, SLOT(LineEditReturnPressed()));
+
+  initName(tr("FUSE_EDGES_NEW_OBJ_NAME"));
+  GroupVertexes->PushButton1->click();
+
+  SelectionIntoArgument();
+}
+
+//=================================================================================
+// function : ClickOnOk()
+// purpose  :
+//=================================================================================
+void RepairGUI_FuseEdgesDlg::ClickOnOk()
+{
+  setIsApplyAndClose(true);
+  if (ClickOnApply())
+    ClickOnCancel();
+}
+
+//=================================================================================
+// function : ClickOnApply()
+// purpose  :
+//=================================================================================
+bool RepairGUI_FuseEdgesDlg::ClickOnApply()
+{
+  if (!onAccept())
+    return false;
+
+  initName();
+  // Reset dialog state
+  GroupVertexes->LineEdit1->setText("");
+  GroupVertexes->LineEdit2->setText("");
+  myShape = GEOM::GEOM_Object::_nil();
+  myPoints.clear();
+  GroupVertexes->PushButton1->click();
+
+  return true;
+}
+
+//=================================================================================
+// function : SelectionIntoArgument()
+// purpose  : Called when selection is changed or on dialog initialization or activation
+//=================================================================================
+void RepairGUI_FuseEdgesDlg::SelectionIntoArgument()
+{
+  myEditCurrentArgument->setText("");
+
+  LightApp_SelectionMgr* aSelMgr = myGeomGUI->getApp()->selectionMgr();
+  SALOME_ListIO aSelList;
+  aSelMgr->selectedObjects(aSelList);
+
+  // If selection of main object is activated
+  if (myEditCurrentArgument == GroupVertexes->LineEdit1) {
+    myShape = GEOM::GEOM_Object::_nil();
+    if (aSelList.Extent() == 1) {
+      GEOM::GEOM_Object_var anObj =
+        GEOMBase::ConvertIOinGEOMObject(aSelList.First());
+
+      if (!anObj->_is_nil()) {
+        QString aName = GEOMBase::GetName(anObj);
+        TopoDS_Shape aShape;
+        if (GEOMBase::GetShape(anObj, aShape, TopAbs_SHAPE) && !aShape.IsNull()) {
+          TColStd_IndexedMapOfInteger aMap;
+          aSelMgr->GetIndexes(aSelList.First(), aMap);
+          if (aMap.Extent() == 1) { // Local Selection
+            int anIndex = aMap(1);
+            aName += QString(":wire_%1").arg(anIndex);
+
+            //Find SubShape Object in Father
+            GEOM::GEOM_Object_var aFindedObject = GEOMBase_Helper::findObjectInFather(anObj, aName);
+
+            if (aFindedObject->_is_nil()) { // Object not found in study
+              GEOM::GEOM_IShapesOperations_var aShapesOp = getGeomEngine()->GetIShapesOperations(getStudyId());
+              anObj = aShapesOp->GetSubShape(anObj, anIndex);
+            }
+            else
+              anObj = aFindedObject; // get Object from study
+          }
+          else { // Global Selection
+            if (aShape.ShapeType() != TopAbs_WIRE) {
+              anObj = GEOM::GEOM_Object::_nil();
+              aName = "";
+            }
+          }
+        }
+        myShape = anObj;
+        myEditCurrentArgument->setText(aName);
+      }
+    }
+
+    if (!myShape->_is_nil() && myPoints.isEmpty())
+      GroupVertexes->PushButton2->click();
+  }
+  else if (myEditCurrentArgument == GroupVertexes->LineEdit2) {
+    myPoints = getSelected(TopAbs_VERTEX, -1);
+    if (!myPoints.isEmpty())
+      myEditCurrentArgument->setText(QString::number(myPoints.count()) + "_" + tr("GEOM_POINT") + tr("_S_"));
+    else
+      myEditCurrentArgument->setText("");
+  }
+}
+
+//=================================================================================
+// function : SetEditCurrentArgument()
+// purpose  :
+//=================================================================================
+void RepairGUI_FuseEdgesDlg::SetEditCurrentArgument()
+{
+  QPushButton* send = (QPushButton*)sender();
+
+  if (send == GroupVertexes->PushButton1) {
+    myEditCurrentArgument = GroupVertexes->LineEdit1;
+    GroupVertexes->PushButton2->setDown(false);
+    GroupVertexes->LineEdit2->setEnabled(false);
+  }
+  else if (send == GroupVertexes->PushButton2) {
+    myEditCurrentArgument = GroupVertexes->LineEdit2;
+    GroupVertexes->PushButton1->setDown(false);
+    GroupVertexes->LineEdit1->setEnabled(false);
+  }
+
+  // enable line edit
+  myEditCurrentArgument->setEnabled(true);
+  myEditCurrentArgument->setFocus();
+  // after setFocus(), because it will be setDown(false) when loses focus
+  send->setDown(true);
+
+  activateSelection();
+}
+
+//=================================================================================
+// function : LineEditReturnPressed()
+// purpose  :
+//=================================================================================
+void RepairGUI_FuseEdgesDlg::LineEditReturnPressed()
+{
+  QLineEdit* send = (QLineEdit*)sender();
+
+  if (send == GroupVertexes->LineEdit1)
+    myEditCurrentArgument = GroupVertexes->LineEdit1;
+  else if (send == GroupVertexes->LineEdit2)
+    myEditCurrentArgument = GroupVertexes->LineEdit2;
+  else
+    return;
+
+  GEOMBase_Skeleton::LineEditReturnPressed();
+}
+
+//=================================================================================
+// function : ActivateThisDialog()
+// purpose  :
+//=================================================================================
+void RepairGUI_FuseEdgesDlg::ActivateThisDialog()
+{
+  GEOMBase_Skeleton::ActivateThisDialog();
+}
+
+//=================================================================================
+// function : enterEvent()
+// purpose  :
+//=================================================================================
+void RepairGUI_FuseEdgesDlg::enterEvent (QEvent*)
+{
+  if (!mainFrame()->GroupConstructors->isEnabled())
+    this->ActivateThisDialog();
+}
+
+//=================================================================================
+// function : activateSelection
+// purpose  : Activate selection in accordance with myEditCurrentArgument
+//=================================================================================
+void RepairGUI_FuseEdgesDlg::activateSelection()
+{
+  disconnect(myGeomGUI->getApp()->selectionMgr(), 0, this, 0);
+  globalSelection();
+  if (myEditCurrentArgument == GroupVertexes->LineEdit1)
+    globalSelection(GEOM_WIRE);
+  else if (!myShape->_is_nil() && myEditCurrentArgument == GroupVertexes->LineEdit2)
+    localSelection(myShape, TopAbs_VERTEX);
+
+  connect(myGeomGUI->getApp()->selectionMgr(), SIGNAL(currentSelectionChanged()),
+          this, SLOT(SelectionIntoArgument()));
+}
+
+//=================================================================================
+// function : createOperation
+// purpose  :
+//=================================================================================
+GEOM::GEOM_IOperations_ptr RepairGUI_FuseEdgesDlg::createOperation()
+{
+  return getGeomEngine()->GetIHealingOperations(getStudyId());
+}
+
+//=================================================================================
+// function : isValid()
+// purpose  : Verify validity of input data
+//=================================================================================
+bool RepairGUI_FuseEdgesDlg::isValid (QString& msg)
+{
+  return (!myShape->_is_nil());
+}
+
+//=================================================================================
+// function : execute
+// purpose  :
+//=================================================================================
+bool RepairGUI_FuseEdgesDlg::execute (ObjectList& objects)
+{
+  GEOM::GEOM_IHealingOperations_var anOper = GEOM::GEOM_IHealingOperations::_narrow(getOperation());
+
+  GEOM::ListOfGO_var points = new GEOM::ListOfGO();
+  points->length(myPoints.count());
+  for (int i = 0; i < myPoints.count(); i++)
+    points[i] = myPoints[i].copy();
+
+  GEOM::GEOM_Object_var anObj = anOper->FuseCollinearEdgesWithinWire(myShape, points.in());
+
+  if (!anObj->_is_nil())
+    objects.push_back(anObj._retn());
+
+  return true;
+}
+
+//=================================================================================
+// function : addSubshapeToStudy
+// purpose  : virtual method to add new SubObjects if local selection
+//=================================================================================
+void RepairGUI_FuseEdgesDlg::addSubshapesToStudy()
+{
+  for (int i = 0; i < myPoints.count(); i++)
+    GEOMBase::PublishSubObject(myPoints[i].get());
+}
diff --git a/src/RepairGUI/RepairGUI_FuseEdgesDlg.h b/src/RepairGUI/RepairGUI_FuseEdgesDlg.h
new file mode 100644 (file)
index 0000000..38d019a
--- /dev/null
@@ -0,0 +1,67 @@
+// Copyright (C) 2007-2012  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.
+//
+// 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
+
+#ifndef REPAIRGUI_FuseEdgesDLG_H
+#define REPAIRGUI_FuseEdgesDLG_H
+
+#include <GEOMBase_Skeleton.h>
+
+#include <TColStd_IndexedMapOfInteger.hxx>
+
+class DlgRef_2Sel1Spin;
+
+//=================================================================================
+// class    : RepairGUI_FuseEdgesDlg
+// purpose  :
+//=================================================================================
+class RepairGUI_FuseEdgesDlg : public GEOMBase_Skeleton
+{
+  Q_OBJECT
+
+public:
+  RepairGUI_FuseEdgesDlg (GeometryGUI*, QWidget*);
+  ~RepairGUI_FuseEdgesDlg();
+
+protected:
+  // redefined from GEOMBase_Helper
+  virtual GEOM::GEOM_IOperations_ptr createOperation();
+  virtual bool                       isValid (QString&);
+  virtual bool                       execute (ObjectList&);
+  virtual void                       addSubshapesToStudy();
+
+private slots:
+  void                               ClickOnOk();
+  bool                               ClickOnApply();
+  void                               ActivateThisDialog();
+  void                               LineEditReturnPressed();
+  void                               SelectionIntoArgument();
+  void                               SetEditCurrentArgument();
+
+private:
+  void                               Init();
+  void                               enterEvent (QEvent*);
+  void                               activateSelection();
+
+private:
+  GEOM::GEOM_Object_var              myShape;
+  QList<GEOM::GeomObjPtr>            myPoints;
+
+  DlgRef_2Sel1Spin*                  GroupVertexes;
+};
+
+#endif // REPAIRGUI_FuseEdgesDLG_H