]> SALOME platform Git repositories - modules/geom.git/commitdiff
Salome HOME
22752: [EDF] Provide explicit feedback on what has been done by Shape Processing...
authoreap <eap@opencascade.com>
Wed, 10 Dec 2014 16:07:28 +0000 (19:07 +0300)
committereap <eap@opencascade.com>
Wed, 10 Dec 2014 16:12:15 +0000 (19:12 +0300)
+ 22757: [EDF] Vertex on Edge --- allow projecting several points at once

41 files changed:
doc/salome/examples/repairing_operations_ex10.py
doc/salome/gui/GEOM/images/divedgebypoint.png
doc/salome/gui/GEOM/images/repair8.png
doc/salome/gui/GEOM/input/add_point_on_edge_operation.doc
idl/GEOM_Gen.idl
src/GEOM/GEOM_Function.cxx
src/GEOM/GEOM_Function.hxx
src/GEOMGUI/GEOM_msg_en.ts
src/GEOMImpl/CMakeLists.txt
src/GEOMImpl/GEOMImpl_HealingDriver.cxx
src/GEOMImpl/GEOMImpl_HealingDriver.hxx
src/GEOMImpl/GEOMImpl_IHealing.hxx
src/GEOMImpl/GEOMImpl_IHealingOperations.cxx
src/GEOMImpl/GEOMImpl_IHealingOperations.hxx
src/GEOMImpl/GEOMImpl_PolylineDumper.cxx
src/GEOM_I/CMakeLists.txt
src/GEOM_I/GEOM_IHealingOperations_i.cc
src/GEOM_I/GEOM_IHealingOperations_i.hh
src/GEOM_SWIG/geomBuilder.py
src/RepairGUI/RepairGUI.cxx
src/RepairGUI/RepairGUI.h
src/RepairGUI/RepairGUI_ChangeOrientationDlg.cxx
src/RepairGUI/RepairGUI_CloseContourDlg.cxx
src/RepairGUI/RepairGUI_DivideEdgeDlg.cxx
src/RepairGUI/RepairGUI_DivideEdgeDlg.h
src/RepairGUI/RepairGUI_LimitToleranceDlg.cxx
src/RepairGUI/RepairGUI_RemoveHolesDlg.cxx
src/RepairGUI/RepairGUI_RemoveIntWiresDlg.cxx
src/RepairGUI/RepairGUI_ShapeProcessDlg.cxx
src/RepairGUI/RepairGUI_SuppressFacesDlg.cxx
src/ShHealOper/CMakeLists.txt
src/ShHealOper/ShHealOper_ChangeOrientation.cxx
src/ShHealOper/ShHealOper_CloseContour.cxx
src/ShHealOper/ShHealOper_EdgeDivide.cxx
src/ShHealOper/ShHealOper_FillHoles.cxx
src/ShHealOper/ShHealOper_ModifStats.hxx [new file with mode: 0644]
src/ShHealOper/ShHealOper_RemoveInternalWires.cxx
src/ShHealOper/ShHealOper_ShapeProcess.cxx
src/ShHealOper/ShHealOper_ShapeProcess.hxx
src/ShHealOper/ShHealOper_Tool.cxx
src/ShHealOper/ShHealOper_Tool.hxx

index c2dbc160f0b13cedfcf5b40e987210ba4c03e3a2..6b8e4280eedc67846992c7fa9f69e756d9819feb 100644 (file)
@@ -33,10 +33,11 @@ for point in edge_points:
 # Variant 2: using DivideEdgeByPoint()
  
 box  = geompy.MakeBox(0,0,0, 10,10,10, theName="box")
-p    = geompy.MakeVertex( 3, -2, 1, theName="point to project" )
-edge = geompy.GetEdgeNearPoint( box, p, theName="edge to split")
+p1   = geompy.MakeVertex( 3, -2, 1, theName="point 1 to project" )
+p2   = geompy.MakeVertex( 7, -2, 1, theName="point 2 to project" )
+edge = geompy.GetEdgeNearPoint( box, p1, theName="edge to split")
 
-div  = geompy.DivideEdgeByPoint( box, edge, p, theName="box (edge divided)")
+div  = geompy.DivideEdgeByPoint( box, edge, [p1, p2], theName="box (edge divided)")
 
 
 salome.sg.updateObjBrowser(1) 
index cb80833cdf8a5f33b4b3e336c49d07aeb57a5a1b..4258a1657e61ebcd9ce6b04466930ef286d3069f 100644 (file)
Binary files a/doc/salome/gui/GEOM/images/divedgebypoint.png and b/doc/salome/gui/GEOM/images/divedgebypoint.png differ
index 5c30a97603cb9c2924d1071a9427888f5340fd37..c15f31345dbc4bc90e6a66bf2d4bab7fb2858091 100644 (file)
Binary files a/doc/salome/gui/GEOM/images/repair8.png and b/doc/salome/gui/GEOM/images/repair8.png differ
index 587f1b9681460fc831624ff12ad2ab546a74e026..187cefbcd32284196cfbca0bc504a0e84648a652 100644 (file)
@@ -5,7 +5,7 @@
 \n To <b>Add Point on Edge</b> in the <b>Main Menu</b> select
 <b>Repair - > Add Point on Edge</b>.
 
-This operation splits an edge in two new edges.
+This operation splits an edge in two or more new edges.
 This operation is available in <b>OCC Viewer</b> only.
 
 The \b Result will be a \b GEOM_Object.
@@ -41,17 +41,17 @@ The \b Result will be a \b GEOM_Object.
     \image html repair8.png
     \n\n
   </li>
-  <li>We can select a point that will be projected to the selected
-    edge to find the location of the new vertex.
+  <li>We can select several points that will be projected to the selected
+    edge to find the location of new vertices.
     <p>
-    <b>TUI Command:</b> <em>geompy.DivideEdgeByPoint(Shape, Edge, Point)</em>
+    <b>TUI Command:</b> <em>geompy.DivideEdgeByPoint(Shape, Edge, Points)</em>
     <ul>
       <li> \em Shape is a shape which contains an edge to be divided</li>
       <li>\em Edge is an edge to be divided (or it's ID, if it is = -1,
         then \em Shape should be an edge itself).</li>
-      <li> \em Point is a point to project to \a Edge. </li>
+      <li> \em Points is a list of points to project to \a Edge. </li>
     </ul>
-    \b Arguments: Name + 1 Edge + 1 Point.
+    \b Arguments: Name + 1 Edge + 1 or more Points.
 
     \image html divedgebypoint.png
 
index 0880b9fd6cf541449b9dc37a1afc92cf18031f51..dc9cf2f92c4e13746f0ead3fab1c5ad13cb13fa0 100644 (file)
@@ -205,7 +205,6 @@ module GEOM
     SI_ALL      // all interferences
   };
 
-
  /*!
    * \brief Object creation parameters
    *
@@ -214,7 +213,6 @@ module GEOM
   struct Parameter
   {
     string name;
-    //any value;
     string value;
   };
   typedef sequence<Parameter> Parameters;
@@ -225,6 +223,16 @@ module GEOM
     Parameters params;
   };
 
+  /*!
+   * \brief Reporting on shape healing
+   */
+  struct ModifInfo
+  {
+    string name;  // what changed
+    long   count; // how many times
+  };
+  typedef sequence<ModifInfo> ModifStatistics;
+
 
   typedef sequence<string>       string_array;
   typedef sequence<short>        short_array;
@@ -2042,7 +2050,7 @@ module GEOM
      *  \param theEdges List of edges for gluing.
      *  \return New GEOM_Object containing copies of theShapes without some edges.
      */
-    GEOM_Object MakeGlueEdgesByList (in ListOfGO theShape,
+    GEOM_Object MakeGlueEdgesByList (in ListOfGO theShapes,
                                      in double   theTolerance,
                                      in ListOfGO theEdges);
 
@@ -3785,7 +3793,7 @@ module GEOM
 
     /*!
      *  Sewing of the given object.
-     *  \param theObject Shape to be processed.
+     *  \param theObjects Shapes to be processed.
      *  \param theTolerance Required tolerance value.
      *  \return New GEOM_Object, containing processed shape.
      */
@@ -3793,7 +3801,7 @@ module GEOM
 
     /*!
      *  Sewing of the given object. Allows non-manifold sewing.
-     *  \param theObject Shape to be processed.
+     *  \param theObjects Shapes to be processed.
      *  \param theTolerance Required tolerance value.
      *  \return New GEOM_Object, containing processed shape.
      */
@@ -3822,17 +3830,17 @@ module GEOM
                             in double theValue, in boolean isByParameter);
 
     /*!
-     *  \brief Addition of a point to a given edge of \a theObject by projecting
-     *         another point to the given edge.
+     *  \brief Addition of points to a given edge of \a theObject by projecting
+     *         other points to the given edge.
      *  \param theObject Shape to be processed.
      *  \param theEdgeIndex Index of edge to be divided within theObject's shape,
      *                      if -1, then theObject itself is the edge.
-     *  \param thePoint Point to project to theEdgeIndex-th edge.
+     *  \param thePoints Points to project to theEdgeIndex-th edge.
      *  \return New GEOM_Object, containing the processed shape.
      */
     GEOM_Object DivideEdgeByPoint (in GEOM_Object theObject,
                                    in short       theEdgeIndex,
-                                   in GEOM_Object thePoint);
+                                   in ListOfGO    thePoints);
 
     /*!
      *  \brief Suppress the vertices in the wire in case if adjacent edges are C1 continuous.
@@ -3846,13 +3854,13 @@ module GEOM
 
     /*!
      *  \brief Get a list of wires (wrapped in GEOM_Object-s),
-     *  that constitute a free boundary of the given shape.
-     *  \param theObject Shapes to get free boundary of.
+     *  that constitute a free boundary of the given shapes.
+     *  \param theObjects Shapes to get free boundary of.
      *  \param theClosedWires Output. Closed wires on the free boundary of the given shape.
      *  \param theOpenWires Output. Open wires on the free boundary of the given shape.
      *  \return FALSE, if an error(s) occured during the method execution.
      */
-    boolean GetFreeBoundary (in ListOfGO theObjects,
+    boolean GetFreeBoundary (in  ListOfGO theObjects,
                              out ListOfGO theClosedWires,
                              out ListOfGO theOpenWires);
 
@@ -3872,6 +3880,12 @@ module GEOM
      */
     GEOM_Object LimitTolerance (in GEOM_Object theObject, in double theTolerance);
 
+
+    /*!
+     *  \brief Return information on what has been done by the last called healing method.
+     *  \return ModifStatistics, information container.
+     */
+    ModifStatistics GetStatistics();
   };
 
  // # GEOM_IInsertOperations:
index 458e0a0bc75079623e12f8a53a5d664ff1401bf6..e96a3a52cc4c39a2d9793236015ea86d7811f48b 100644 (file)
@@ -62,6 +62,8 @@
 #include <TCollection_AsciiString.hxx>
 #include <TCollection_ExtendedString.hxx>
 
+#include <cstdlib>
+
 #include <Standard_Failure.hxx>
 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
 
@@ -76,6 +78,7 @@
 #define HISTORY_LABEL 4
 #define SUBSHAPES_LABEL 5 // 0020756: GetGroups
 #define NAMING_LABEL 6 // 0020750: Naming during STEP import
+#define CALLBACK_LABEL 1 // TDataStd_Comment
 
 #ifdef KEEP_ORIENTATION_0021251
 #define ORIENTATION_LABEL 7 // 0021251: TNaming_NamedShape doesn't store orientation
@@ -124,7 +127,7 @@ Handle(GEOM_Function) GEOM_Function::GetFunction(const TDF_Label& theEntry)
  */
 //=============================================================================
 GEOM_Function::GEOM_Function(const TDF_Label& theEntry, const Standard_GUID& theGUID, int theType)
-: _label(theEntry)
+  : _label(theEntry), _isCallBackData(false)
 {
   TFunction_Function::Set(theEntry, theGUID);
   TDataStd_Integer::Set(theEntry, theType);
@@ -139,6 +142,21 @@ GEOM_Function::GEOM_Function(const TDF_Label& theEntry, const Standard_GUID& the
   aRoot->Append(aNode);
 }
 
+//================================================================================
+/*!
+ * \brief 
+ * 
+ * 
+ */
+//================================================================================
+
+GEOM_Function::~GEOM_Function()
+{
+  if ( _isCallBackData ) {
+    _label.FindChild( CALLBACK_LABEL ).ForgetAttribute( TDataStd_Comment::GetID() );
+  }
+}
+
 //================================================================================
 /*!
  * \brief Retuns true if this function is the last one in the study
@@ -928,5 +946,45 @@ TDF_Label GEOM_Function::GetNamingEntry (const Standard_Boolean create)
   return _label.FindChild(NAMING_LABEL, create);
 }
 
+//================================================================================
+/*!
+ * Save a pointer to a data holder intended to pass temporary data Driver -> Operation.
+ * This method should be called by Operation to set the data holder.
+ * An instance of GEOM_Function that sets the data holder will remove the
+ * corresponding OCAF attribute at it's destruction
+ */
+//================================================================================
+
+void GEOM_Function::SetCallBackData( void* data )
+{
+  std::ostringstream strm;
+  strm << (long long) data;
+  TCollection_ExtendedString string( strm.str().c_str() );
+
+  TDF_Label aChild = _label.FindChild(CALLBACK_LABEL);
+  TDataStd_Comment::Set(aChild, string);
+
+  _isCallBackData = true; // I will remove TDataStd_Comment at destruction
+}
+
+//================================================================================
+/*!
+ * Returns a pointer to a data holder intended to pass data Driver -> Operation.
+ * This method should be called by Driver to get the data holder to fill it in.
+ * Returns NULL if the Operation have not set the data holder.
+ */
+//================================================================================
+
+void* GEOM_Function::GetCallBackData()
+{
+  Handle(TDataStd_Comment) aComment;
+  TDF_Label aChild = _label.FindChild( CALLBACK_LABEL );
+  if(!aChild.FindAttribute(TDataStd_Comment::GetID(), aComment)) return NULL;
+  TCollection_AsciiString string( aComment->Get() );
+
+  long long address = atoll( string.ToCString() );
+  return reinterpret_cast<void*> ( address );
+}
+
 IMPLEMENT_STANDARD_HANDLE (GEOM_Function, Standard_Transient);
 IMPLEMENT_STANDARD_RTTIEXT(GEOM_Function, Standard_Transient );
index 688324dae0c173c3edd72a87364e78513e8bde17..3d2a4ec96e99705b40302ac8bf40af8bf9c1aef9 100644 (file)
@@ -56,7 +56,7 @@ public:
 
 
   Standard_EXPORT GEOM_Function(const TDF_Label& theEntry, const Standard_GUID& theGUID, int theType);
-  Standard_EXPORT ~GEOM_Function() {}
+  Standard_EXPORT ~GEOM_Function();
 
   Standard_EXPORT TDF_Label GetOwnerEntry();
 
@@ -152,6 +152,17 @@ public:
   //Returns a list of references to other function arguments at position thePosition
   Standard_EXPORT Handle(TColStd_HSequenceOfTransient) GetReferenceList (int thePosition);
 
+  // Save a pointer to a data holder intended to pass data Driver -> Operation.
+  // This method should be called by Operation to set the data holder.
+  // An instance of GEOM_Function that sets the data holder will remove the
+  // corresponding OCAF attribute at it's destruction
+  Standard_EXPORT void SetCallBackData( void* data );
+
+  // Returns a pointer to a data holder intended to pass data Driver -> Operation.
+  // This method should be called by Driver to get the data holder to fill it in.
+  // Returns NULL if the Operation have not set the data holder.
+  Standard_EXPORT void* GetCallBackData();
+
   //Sets a TopoDS_Shape argument at position thePosition
   //void SetShape(int thePosition, const TopoDS_Shape& theShape);
 
@@ -190,6 +201,7 @@ public:
 
   TDF_Label _label;
   bool      _isDone;
+  bool      _isCallBackData;
 };
 
 #endif
index b5e65a385cda4884aee8807193ebdae8f5acfb94..31679839b0b291eb9470230cb524079b759473f6 100644 (file)
@@ -44,7 +44,7 @@ Do you still want to delete these objects?</translation>
     </message>
     <message>
         <source>DEVIDE_EDGE_BY_PROJ_POINT</source>
-        <translation>Point to project</translation>
+        <translation>Points to project</translation>
     </message>
     <message>
         <source>ERROR_SHAPE_TYPE</source>
@@ -569,7 +569,7 @@ Please, select face, shell or solid and try again</translation>
     </message>
     <message>
         <source>GEOM_DIVIDE_EDGE_TITLE</source>
-        <translation>Addition of point</translation>
+        <translation>Addition of points</translation>
     </message>
     <message>
         <source>GEOM_DX</source>
@@ -5232,6 +5232,18 @@ shells and solids on the other hand.</translation>
         <source>GEOM_NO_SHAPES_SELECTED</source>
         <translation>There are no shapes that meet filtering parameters</translation>
     </message>
+    <message>
+        <source>GEOM_HEALING_STATS_TITLE</source>
+        <translation>What is done</translation>
+    </message>
+    <message>
+        <source>GEOM_HEALING_STATS_COL_1</source>
+        <translation>Count</translation>
+    </message>
+    <message>
+        <source>GEOM_HEALING_STATS_COL_2</source>
+        <translation>Modication</translation>
+    </message>
 </context>
 <context>
     <name>GeometryGUI</name>
index 3822d2912c5c4508080c9baec1221610d294cccb..42b467403252297a8cdb69a3ee0605f17bf34c36 100755 (executable)
@@ -33,6 +33,7 @@ INCLUDE_DIRECTORIES(
   ${PROJECT_SOURCE_DIR}/src/SKETCHER
   ${PROJECT_SOURCE_DIR}/src/ARCHIMEDE
   ${PROJECT_SOURCE_DIR}/src/XAO
+  ${PROJECT_SOURCE_DIR}/src/ShHealOper
   ${CMAKE_CURRENT_SOURCE_DIR}
   )
 
index 48bca409576ade6ac9c8d0992a10136492605214..51154eb638b116c43c4ae70a04c6a7b3169ade0f 100644 (file)
@@ -216,6 +216,8 @@ Standard_Boolean GEOMImpl_HealingDriver::ShapeProcess (GEOMImpl_IHealing* theHI,
   if (!aHealer.isDone())
     raiseNotDoneExeption( ShHealOper_NotError );
 
+  SaveStatistics( aHealer );
+
   return Standard_True;
 }
 
@@ -223,9 +225,9 @@ Standard_Boolean GEOMImpl_HealingDriver::ShapeProcess (GEOMImpl_IHealing* theHI,
 //function :  SupressFaces
 //purpose  :
 //=======================================================================
-void SuppressFacesRec (const TopTools_SequenceOfShape& theShapesFaces,
-                       const TopoDS_Shape&             theOriginalShape,
-                       TopoDS_Shape&                   theOutShape)
+void GEOMImpl_HealingDriver::SuppressFacesRec (const TopTools_SequenceOfShape& theShapesFaces,
+                                               const TopoDS_Shape&             theOriginalShape,
+                                               TopoDS_Shape&                   theOutShape) const
 {
   if ((theOriginalShape.ShapeType() != TopAbs_COMPOUND &&
        theOriginalShape.ShapeType() != TopAbs_COMPSOLID))
@@ -307,6 +309,21 @@ Standard_Boolean GEOMImpl_HealingDriver::SuppressFaces (GEOMImpl_IHealing* theHI
       theOutShape = GEOMImpl_GlueDriver::GlueFaces(aSh, Precision::Confusion(), Standard_True);
     }
   }
+  // count removed faces
+  TopTools_IndexedMapOfShape faces;
+  TopExp::MapShapes(theOriginalShape, TopAbs_FACE, faces);
+  int nbBefore = faces.Extent();
+  faces.Clear();
+  TopExp::MapShapes(theOutShape, TopAbs_FACE, faces);
+  int nbAfter = faces.Extent();
+
+  if ( nbAfter < nbBefore )
+  {
+    ShHealOper_Tool tool;
+    ShHealOper_ModifStats& stats = tool.GetStatistics();
+    stats.AddModif( "Face removed", nbBefore - nbAfter );
+    SaveStatistics( tool );
+  }
 
   return Standard_True;
 }
@@ -347,6 +364,8 @@ Standard_Boolean GEOMImpl_HealingDriver::CloseContour (GEOMImpl_IHealing* theHI,
   else
     raiseNotDoneExeption( aHealer.GetErrorStatus() );
 
+  SaveStatistics( aHealer );
+
   return aResult;
 }
 
@@ -383,6 +402,8 @@ Standard_Boolean GEOMImpl_HealingDriver::RemoveIntWires (GEOMImpl_IHealing* theH
   else
     raiseNotDoneExeption( aHealer.GetErrorStatus() );
 
+  SaveStatistics( aHealer );
+
   return aResult;
 }
 
@@ -419,6 +440,8 @@ Standard_Boolean GEOMImpl_HealingDriver::RemoveHoles (GEOMImpl_IHealing* theHI,
   else
     raiseNotDoneExeption( aHealer.GetErrorStatus() );
 
+  SaveStatistics( aHealer );
+
   return aResult;
 }
 
@@ -464,6 +487,8 @@ Standard_Boolean GEOMImpl_HealingDriver::Sew (GEOMImpl_IHealing*  theHI,
   else
     raiseNotDoneExeption( aHealer.GetErrorStatus() );
 
+  SaveStatistics( aHealer );
+
   return aResult;
 }
 
@@ -546,12 +571,21 @@ Standard_Boolean GEOMImpl_HealingDriver::AddPointOnEdge (GEOMImpl_IHealing*  the
   {
     Handle(TColStd_HSequenceOfTransient) funs = theHI->GetShapes();
     if ( !funs.IsNull() && funs->Length() > 0 ) {
-      Handle(GEOM_Function) fun = Handle(GEOM_Function)::DownCast( funs->Value(1) );
-      if ( !fun.IsNull() )
-        pointToProject = fun->GetValue();
+      TopoDS_Compound vCompound;
+      BRep_Builder builder;
+      builder.MakeCompound( vCompound );
+      pointToProject = vCompound;
+      for ( int ind = 1; ind <= funs->Length(); ind++)
+      {
+        Handle(GEOM_Function) vFun = Handle(GEOM_Function)::DownCast(funs->Value(ind));
+        TopoDS_Shape vertex = vFun->GetValue();
+        if ( vertex.IsNull() )
+          Standard_NullObject::Raise("Null vertex given");
+        builder.Add( vCompound, vertex );
+      }
     }
   }
-  
+
   ShHealOper_EdgeDivide aHealer (theOriginalShape);
 
   Standard_Boolean aResult = Standard_False;
@@ -579,6 +613,8 @@ Standard_Boolean GEOMImpl_HealingDriver::AddPointOnEdge (GEOMImpl_IHealing*  the
   else
     raiseNotDoneExeption( aHealer.GetErrorStatus() );
 
+  SaveStatistics( aHealer );
+
   return aResult;
 }
 
@@ -600,6 +636,8 @@ Standard_Boolean GEOMImpl_HealingDriver::ChangeOrientation (GEOMImpl_IHealing* t
   else
     raiseNotDoneExeption( aHealer.GetErrorStatus() );
 
+  SaveStatistics( aHealer );
+
   return aResult;
 }
 
@@ -617,9 +655,10 @@ void GEOMImpl_HealingDriver::LimitTolerance (GEOMImpl_IHealing* theHI,
 
   // 1. Make a copy to prevent the original shape changes.
   TopoDS_Shape aShapeCopy;
-  TColStd_IndexedDataMapOfTransientTransient aMapTShapes;
-  TNaming_CopyShape::CopyTool(theOriginalShape, aMapTShapes, aShapeCopy);
-
+  {
+    TColStd_IndexedDataMapOfTransientTransient aMapTShapes;
+    TNaming_CopyShape::CopyTool(theOriginalShape, aMapTShapes, aShapeCopy);
+  }
   // 2. Limit tolerance.
   ShapeFix_ShapeTolerance aSFT;
   aSFT.LimitTolerance(aShapeCopy, aTol, aTol, TopAbs_SHAPE);
@@ -632,6 +671,68 @@ void GEOMImpl_HealingDriver::LimitTolerance (GEOMImpl_IHealing* theHI,
   BRepCheck_Analyzer ana (theOutShape, Standard_True);
   if (!ana.IsValid())
     StdFail_NotDone::Raise("Non valid shape result");
+
+  // 4. Collect statistics
+  {
+    ShHealOper_Tool tool;
+    ShHealOper_ModifStats& stats = tool.GetStatistics();
+
+    int nb[3] = { 0,0,0 };
+    TopTools_IndexedMapOfShape aShapes;
+    TopExp::MapShapes( theOutShape, TopAbs_VERTEX, aShapes);
+    for ( int i = 1; i <= aShapes.Extent(); ++i )
+    {
+      const TopoDS_Vertex& v = TopoDS::Vertex( aShapes( i ));
+      double tol = BRep_Tool::Tolerance( v );
+      if      ( tol < aTol ) nb[0]++;
+      else if ( tol > aTol ) nb[2]++;
+      else                   nb[1]++;
+    }
+    if ( nb[0] > 0 )
+      stats.AddModif( "Tolerance of vertex decreased for shape validity", nb[0] );
+    if ( nb[1] > 0 )
+      stats.AddModif( "Tolerance of vertex limited as requested", nb[1] );
+    if ( nb[2] > 0 )
+      stats.AddModif( "Tolerance of vertex increased for shape validity", nb[2] );
+
+    nb[0] = nb[1] = nb[2] = 0;
+    aShapes.Clear();
+    TopExp::MapShapes( theOutShape, TopAbs_EDGE, aShapes);
+    for ( int i = 1; i <= aShapes.Extent(); ++i )
+    {
+      const TopoDS_Edge& e = TopoDS::Edge( aShapes( i ));
+      double tol = BRep_Tool::Tolerance( e );
+      if      ( tol < aTol ) nb[0]++;
+      else if ( tol > aTol ) nb[2]++;
+      else                   nb[1]++;
+    }
+    if ( nb[0] > 0 )
+      stats.AddModif( "Tolerance of edge decreased for shape validity", nb[0] );
+    if ( nb[1] > 0 )
+      stats.AddModif( "Tolerance of edge limited as requested", nb[1] );
+    if ( nb[2] > 0 )
+      stats.AddModif( "Tolerance of edge increased for shape validity", nb[2] );
+
+    nb[0] = nb[1] = nb[2] = 0;
+    aShapes.Clear();
+    TopExp::MapShapes( theOutShape, TopAbs_FACE, aShapes);
+    for ( int i = 1; i <= aShapes.Extent(); ++i )
+    {
+      const TopoDS_Face& f = TopoDS::Face( aShapes( i ));
+      double tol = BRep_Tool::Tolerance( f );
+      if      ( tol < aTol ) nb[0]++;
+      else if ( tol > aTol ) nb[2]++;
+      else                   nb[1]++;
+    }
+    if ( nb[0] > 0 )
+      stats.AddModif( "Tolerance of face decreased for shape validity", nb[0] );
+    if ( nb[1] > 0 )
+      stats.AddModif( "Tolerance of face limited as requested", nb[1] );
+    if ( nb[2] > 0 )
+      stats.AddModif( "Tolerance of face increased for shape validity", nb[2] );
+
+    SaveStatistics( tool );
+  }
 }
 
 //=======================================================================
@@ -971,7 +1072,7 @@ GetCreationInformation(std::string&             theOperationName,
       AddParam( theParams, "Edge", "#" ) << aCI.GetIndex() << " of " << aCI.GetOriginal();
     else
       AddParam( theParams, "Edge", aCI.GetOriginal() );
-    AddParam( theParams, "Point", aCI.GetShapes() );
+    AddParam( theParams, "Points", aCI.GetShapes() );
     break;
   case CHANGE_ORIENTATION:
     theOperationName = "CHANGE_ORIENTATION";
@@ -997,6 +1098,33 @@ GetCreationInformation(std::string&             theOperationName,
   
   return true;
 }
+
+//================================================================================
+/*!
+ * \brief Pass a record of what is done to the operation
+ */
+//================================================================================
+
+void GEOMImpl_HealingDriver::SaveStatistics( const ShHealOper_Tool& healer, bool add ) const
+{
+  if ( healer.GetStatistics().GetData().empty() )
+    return;
+
+  if (Label().IsNull()) return;
+
+  Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label());
+  if (aFunction.IsNull()) return;
+
+  GEOMImpl_IHealing HI (aFunction);
+  ShHealOper_ModifStats * stats = HI.GetStatistics();
+  if ( !stats ) return;
+
+  if ( add )
+    stats->Add( healer.GetStatistics() );
+  else
+    *stats = healer.GetStatistics();
+}
+
 IMPLEMENT_STANDARD_HANDLE (GEOMImpl_HealingDriver,GEOM_BaseDriver);
 
 IMPLEMENT_STANDARD_RTTIEXT (GEOMImpl_HealingDriver,GEOM_BaseDriver);
index 5784acd1459abb0543b3a6f9938d9f57b31566eb..f738be6f4d1825339a54ceeb601fcce3f9307dbb 100644 (file)
 #include <Standard_CString.hxx>
 #endif
 
-class GEOMImpl_IHealing;
+#include "GEOM_BaseDriver.hxx"
 
+class GEOMImpl_IHealing;
+class ShHealOper_Tool;
+class TopTools_SequenceOfShape;
 
-#include "GEOM_BaseDriver.hxx"
 
 DEFINE_STANDARD_HANDLE( GEOMImpl_HealingDriver, GEOM_BaseDriver );
 
@@ -99,6 +101,9 @@ DEFINE_STANDARD_RTTI( GEOMImpl_HealingDriver )
 private:
   Standard_Boolean ShapeProcess  ( GEOMImpl_IHealing*, const TopoDS_Shape&, TopoDS_Shape& ) const;
   Standard_Boolean SuppressFaces ( GEOMImpl_IHealing*, const TopoDS_Shape&, TopoDS_Shape& ) const;
+  void             SuppressFacesRec (const TopTools_SequenceOfShape& theShapesFaces,
+                                     const TopoDS_Shape&             theOriginalShape,
+                                     TopoDS_Shape&                   theOutShape) 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;
@@ -108,6 +113,7 @@ private:
   Standard_Boolean ChangeOrientation( GEOMImpl_IHealing*, const TopoDS_Shape&, TopoDS_Shape& ) const;
   void             LimitTolerance( GEOMImpl_IHealing*, const TopoDS_Shape&, TopoDS_Shape& ) const;
 
+  void             SaveStatistics( const ShHealOper_Tool& healer, bool add=false ) const;
 };
 
 #endif
index d21962155cc91ca3007ed8333e974c035a70f89c..06e354db2b5e74f5b3c65dd76d6ac0be95fe9c7f 100755 (executable)
@@ -25,6 +25,7 @@
 #include <TColStd_HArray1OfInteger.hxx>
 #include <TColStd_HArray1OfExtendedString.hxx>
 #include "TColStd_HSequenceOfTransient.hxx"
+#include <ShHealOper_ModifStats.hxx>
 
 class GEOMImpl_IHealing
 {
@@ -41,7 +42,8 @@ public:
     ARG_DEV_EDGE_VALUE          =  8,
     ARG_IS_BY_PARAMETER         =  9,
     ARG_SUBSHAPE_INDEX          = 10,
-    ARG_LIST_SHAPES             = 11
+    ARG_LIST_SHAPES             = 11,
+    ARG_STATISTICS              =  4
   };
 
   GEOMImpl_IHealing(Handle(GEOM_Function) theFunction): _func(theFunction) {}
@@ -91,6 +93,17 @@ public:
     funs->Prepend( GetOriginal() );
     return funs;
   }
+
+  void SetStatistics( ShHealOper_ModifStats * ms )
+  {
+    if ( ms ) ms->Clear();
+    _func->SetCallBackData( (void*) ms );
+  }
+  ShHealOper_ModifStats * GetStatistics()
+  {
+    return (ShHealOper_ModifStats*) _func->GetCallBackData();
+  }
+
 private:
   Handle(GEOM_Function) _func;
 };
index 3a2b133052d3b55f86d381d145efd9f3bfb9eab2..3b8ab11472286772c9d47ed39919ab8846a8f1c2 100644 (file)
@@ -25,7 +25,6 @@
 #endif
 
 #include <Standard_Version.hxx>
-#include <Standard_Stream.hxx>
 
 #include <GEOMImpl_IHealingOperations.hxx>
 #include <GEOM_PythonDump.hxx>
@@ -35,6 +34,8 @@
 #include <GEOMImpl_IVector.hxx>
 #include <GEOMImpl_VectorDriver.hxx>
 #include <GEOMImpl_CopyDriver.hxx>
+#include <ShHealOper_ModifStats.hxx>
+#include <ShHealOper_ShapeProcess.hxx>
 
 #include <Basics_OCCTVersion.hxx>
 
 #include <Utils_ExceptHandlers.hxx>
 
 #include <BRep_Builder.hxx>
-#include <ShHealOper_ShapeProcess.hxx>
 #include <ShapeAnalysis_FreeBounds.hxx>
 #include <TColStd_HArray1OfExtendedString.hxx>
 #include <TColStd_HSequenceOfTransient.hxx>
 #include <TCollection_AsciiString.hxx>
-#include <TDF_Tool.hxx>
 #include <TopExp_Explorer.hxx>
 #include <TopTools_SequenceOfShape.hxx>
 #include <TopoDS_Compound.hxx>
@@ -64,6 +63,7 @@
 GEOMImpl_IHealingOperations::GEOMImpl_IHealingOperations (GEOM_Engine* theEngine, int theDocID)
 : GEOM_IOperations(theEngine, theDocID)
 {
+  myModifStats = new ShHealOper_ModifStats;
   MESSAGE("GEOMImpl_IHealingOperations::GEOMImpl_IHealingOperations");
 }
 
@@ -74,6 +74,7 @@ GEOMImpl_IHealingOperations::GEOMImpl_IHealingOperations (GEOM_Engine* theEngine
 //=============================================================================
 GEOMImpl_IHealingOperations::~GEOMImpl_IHealingOperations()
 {
+  delete myModifStats;
   MESSAGE("GEOMImpl_IHealingOperations::~GEOMImpl_IHealingOperations");
 }
 
@@ -134,6 +135,7 @@ Handle(GEOM_Object) GEOMImpl_IHealingOperations::ShapeProcess (Handle(GEOM_Objec
     HI.SetParameters( theParams );
     HI.SetValues( theValues );
   }
+  HI.SetStatistics( myModifStats );
 
   //Compute the translation
   try {
@@ -341,6 +343,7 @@ Handle(GEOM_Object) GEOMImpl_IHealingOperations::SuppressFaces
   GEOMImpl_IHealing HI (aFunction);
   HI.SetFaces(theFaces);
   HI.SetOriginal(aLastFunction);
+  HI.SetStatistics( myModifStats );
 
   //Compute the translation
   try {
@@ -409,6 +412,7 @@ Handle(GEOM_Object) GEOMImpl_IHealingOperations::CloseContour
   HI.SetWires( theWires );
   HI.SetIsCommonVertex( isCommonVertex );
   HI.SetOriginal( aLastFunction );
+  HI.SetStatistics( myModifStats );
 
   //Compute the translation
   try {
@@ -476,6 +480,7 @@ Handle(GEOM_Object) GEOMImpl_IHealingOperations::RemoveIntWires
   GEOMImpl_IHealing HI(aFunction);
   HI.SetWires( theWires );
   HI.SetOriginal( aLastFunction );
+  HI.SetStatistics( myModifStats );
 
   //Compute the translation
   try {
@@ -542,6 +547,7 @@ Handle(GEOM_Object) GEOMImpl_IHealingOperations::FillHoles (Handle(GEOM_Object)
   GEOMImpl_IHealing HI(aFunction);
   HI.SetWires( theWires );
   HI.SetOriginal( aLastFunction );
+  HI.SetStatistics( myModifStats );
 
   //Compute the translation
   try {
@@ -616,6 +622,7 @@ GEOMImpl_IHealingOperations::Sew (std::list<Handle(GEOM_Object)>& theObjects,
   HI.SetTolerance( theTolerance );
   HI.SetOriginal( theObjects.front()->GetLastFunction() ); objects->Remove(1);
   HI.SetShapes( objects );
+  HI.SetStatistics( myModifStats );
 
   //Compute the result
   try {
@@ -682,6 +689,7 @@ GEOMImpl_IHealingOperations::RemoveInternalFaces (std::list< Handle(GEOM_Object)
   GEOMImpl_IHealing HI (aFunction);
   HI.SetOriginal( theSolids.front()->GetLastFunction() ); objects->Remove(1);
   HI.SetShapes( objects );
+  HI.SetStatistics( myModifStats );
 
   //Compute the result
   try {
@@ -741,6 +749,7 @@ Handle(GEOM_Object) GEOMImpl_IHealingOperations::DivideEdge (Handle(GEOM_Object)
   HI.SetDevideEdgeValue( theValue );
   HI.SetIsByParameter( isByParameter );
   HI.SetOriginal( aLastFunction );
+  HI.SetStatistics( myModifStats );
 
   //Compute the translation
   try {
@@ -770,21 +779,26 @@ Handle(GEOM_Object) GEOMImpl_IHealingOperations::DivideEdge (Handle(GEOM_Object)
  */
 //=============================================================================
 Handle(GEOM_Object)
-GEOMImpl_IHealingOperations::DivideEdgeByPoint (Handle(GEOM_Object) theObject,
-                                                int theIndex,
-                                                Handle(GEOM_Object) thePoint)
+GEOMImpl_IHealingOperations::DivideEdgeByPoint (Handle(GEOM_Object)               theObject,
+                                                int                               theIndex,
+                                                std::list< Handle(GEOM_Object)> & thePoints)
 {
   // set error code, check parameters
   SetErrorCode(KO);
 
-  if (theObject.IsNull() || thePoint.IsNull())
+  if (theObject.IsNull() || thePoints.empty() )
     return NULL;
 
   Handle(GEOM_Function) aFunction, aLastFunction = theObject->GetLastFunction();
-  Handle(GEOM_Function) aPointFunc = thePoint->GetLastFunction();
-  if (aLastFunction.IsNull() || aPointFunc.IsNull())
+  if (aLastFunction.IsNull() )
     return NULL; //There is no function which creates an object to be processed
 
+  Handle(TColStd_HSequenceOfTransient) aPointFunc = GEOM_Object::GetLastFunctions( thePoints );
+  if ( aPointFunc.IsNull() || aPointFunc->IsEmpty() ) {
+    SetErrorCode("NULL argument points");
+    return NULL;
+  }
+
   // Add a new object
   Handle(GEOM_Object) aNewObject = GetEngine()->AddObject( GetDocID(), GEOM_COPY );
 
@@ -798,12 +812,11 @@ GEOMImpl_IHealingOperations::DivideEdgeByPoint (Handle(GEOM_Object) theObject,
 
   // prepare "data container" class IHealing
   GEOMImpl_IHealing HI(aFunction);
-  HI.SetIndex( theIndex );
-  HI.SetOriginal( aLastFunction );
+  HI.SetIndex     ( theIndex );
+  HI.SetOriginal  ( aLastFunction );
+  HI.SetShapes    ( aPointFunc );
 
-  Handle(TColStd_HSequenceOfTransient) funSeq = new TColStd_HSequenceOfTransient;
-  funSeq->Append( aPointFunc );
-  HI.SetShapes( funSeq );
+  HI.SetStatistics( myModifStats );
 
   //Compute the translation
   try {
@@ -822,7 +835,7 @@ GEOMImpl_IHealingOperations::DivideEdgeByPoint (Handle(GEOM_Object) theObject,
   //Make a Python command
   GEOM::TPythonDump(aFunction)
     << aNewObject << " = geompy.DivideEdgeByPoint(" << theObject
-    << ", " << theIndex << ", " << thePoint << ")";
+    << ", " << theIndex << ", " << thePoints << ")";
 
   SetErrorCode(OK);
   return aNewObject;
@@ -853,6 +866,7 @@ Handle(GEOM_Object) GEOMImpl_IHealingOperations::FuseCollinearEdgesWithinWire
   if (aFunction->GetDriverGUID() != GEOMImpl_HealingDriver::GetID()) return NULL;
 
   GEOMImpl_IHealing aCI (aFunction);
+  aCI.SetStatistics( myModifStats );
 
   Handle(GEOM_Function) aRefShape = theWire->GetLastFunction();
   if (aRefShape.IsNull()) return NULL;
@@ -1039,6 +1053,9 @@ Handle(GEOM_Object) GEOMImpl_IHealingOperations::ChangeOrientation (Handle(GEOM_
     // prepare "data container" class IVector
     GEOMImpl_IVector aVI (aFunction);
     aVI.SetCurve(aLastFunction);
+
+    myModifStats->Clear();
+    myModifStats->AddModif( "Vector reversed" );
   }
   else {
     //Add the function
@@ -1051,6 +1068,7 @@ Handle(GEOM_Object) GEOMImpl_IHealingOperations::ChangeOrientation (Handle(GEOM_
     // prepare "data container" class IHealing
     GEOMImpl_IHealing HI (aFunction);
     HI.SetOriginal(aLastFunction);
+    HI.SetStatistics( myModifStats );
   }
 
   //Compute the translation
@@ -1106,6 +1124,9 @@ Handle(GEOM_Object) GEOMImpl_IHealingOperations::ChangeOrientationCopy (Handle(G
     // prepare "data container" class IVector
     GEOMImpl_IVector aVI (aFunction);
     aVI.SetCurve(aLastFunction);
+
+    myModifStats->Clear();
+    myModifStats->AddModif( "Vector reversed" );
   }
   else {
     //Add the function
@@ -1118,6 +1139,7 @@ Handle(GEOM_Object) GEOMImpl_IHealingOperations::ChangeOrientationCopy (Handle(G
     // prepare "data container" class IHealing
     GEOMImpl_IHealing aHI (aFunction);
     aHI.SetOriginal(aLastFunction);
+    aHI.SetStatistics( myModifStats );
   }
 
   // Compute the result
@@ -1176,6 +1198,7 @@ Handle(GEOM_Object) GEOMImpl_IHealingOperations::LimitTolerance (Handle(GEOM_Obj
   GEOMImpl_IHealing HI (aFunction);
   HI.SetOriginal(aLastFunction);
   HI.SetTolerance(theTolerance);
+  HI.SetStatistics( myModifStats );
 
   // Compute
   try {
index e2af51e10cae0e8e38bdb29a8f4deb2fc25223d2..df2952a9a679709d473a993d2b08c0223235b4bc 100644 (file)
@@ -32,6 +32,8 @@
 
 #include <list>
 
+class ShHealOper_ModifStats;
+
 class GEOMImpl_IHealingOperations : public GEOM_IOperations {
  public:
   Standard_EXPORT GEOMImpl_IHealingOperations(GEOM_Engine* theEngine, int theDocID);
@@ -81,9 +83,9 @@ class GEOMImpl_IHealingOperations : public GEOM_IOperations {
                                                   double              theValue,
                                                   bool                isByParameter );
 
-  Standard_EXPORT Handle(GEOM_Object) DivideEdgeByPoint( Handle(GEOM_Object) theObject,
-                                                         int                 theIndex,
-                                                         Handle(GEOM_Object) thePoint );
+  Standard_EXPORT Handle(GEOM_Object) DivideEdgeByPoint( Handle(GEOM_Object)             theObject,
+                                                         int                             theIndex,
+                                                         std::list<Handle(GEOM_Object)>& thePoint );
 
   Standard_EXPORT Handle(GEOM_Object) FuseCollinearEdgesWithinWire
                                      (Handle(GEOM_Object) theWire,
@@ -102,6 +104,11 @@ class GEOMImpl_IHealingOperations : public GEOM_IOperations {
   Standard_EXPORT Handle(GEOM_Object) LimitTolerance( Handle(GEOM_Object) theObject,
                                                       double theTolerance );
 
+  const ShHealOper_ModifStats* GetStatistics() { return myModifStats; }
+
+private:
+
+  ShHealOper_ModifStats* myModifStats;
 };
 
 #endif
index 05fb9a61a796ddbadc08e1abb9215d79660fa29c..ba66b5f99ccada2e43c132a37346795d1b2c41e7 100644 (file)
@@ -152,7 +152,7 @@ void GEOMImpl_PolylineDumper::init()
     }
   }
 
-  char *aSeparator = "\n\t";
+  const char *aSeparator = "\n\t";
   Standard_Integer i;
   std::list <std::list <double> >::const_iterator anIt = myCoords.begin();
 
index d916ffe60b5febdab8b2c978b4641e183610a5ff..24b3731a58771b85bbf32c9f25bf155636e1eada 100755 (executable)
@@ -29,6 +29,7 @@ INCLUDE_DIRECTORIES(
   ${PROJECT_SOURCE_DIR}/src/GEOM
   ${PROJECT_SOURCE_DIR}/src/GEOMAlgo
   ${PROJECT_SOURCE_DIR}/src/GEOMUtils
+  ${PROJECT_SOURCE_DIR}/src/ShHealOper
   ${PROJECT_BINARY_DIR}/idl
   ${CMAKE_CURRENT_SOURCE_DIR}
   ${PROJECT_BINARY_DIR}
index cd04c762692feed87d0704c8683ed8465e8c75d8..53707cac8c299508a45018889ddf81154e166899 100644 (file)
 #include "GEOM_IHealingOperations_i.hh"
 #include "GEOM_Engine.hxx"
 #include "GEOM_Object.hxx"
+#include "ShHealOper_ModifStats.hxx"
 
-#include "utilities.h"
-#include "OpUtil.hxx"
-#include "Utils_ExceptHandlers.hxx"
+#include <utilities.h>
+#include <OpUtil.hxx>
+#include <Utils_ExceptHandlers.hxx>
 #include <Basics_Utils.hxx>
 
 #include <TColStd_HSequenceOfTransient.hxx>
@@ -439,7 +440,7 @@ GEOM::GEOM_Object_ptr GEOM_IHealingOperations_i::DivideEdge (GEOM::GEOM_Object_p
 GEOM::GEOM_Object_ptr
 GEOM_IHealingOperations_i::DivideEdgeByPoint (GEOM::GEOM_Object_ptr theObject,
                                               CORBA::Short          theIndex,
-                                              GEOM::GEOM_Object_ptr thePoint)
+                                              const GEOM::ListOfGO& thePoints)
 {
   GEOM::GEOM_Object_var aGEOMObject;
 
@@ -451,14 +452,14 @@ GEOM_IHealingOperations_i::DivideEdgeByPoint (GEOM::GEOM_Object_ptr theObject,
   if (anObject.IsNull())
     return aGEOMObject._retn();
 
-  // Get the point
-  Handle(GEOM_Object) aPoint = GetObjectImpl(thePoint);
-  if (aPoint.IsNull())
+  // Get the points
+  std::list< Handle(GEOM_Object) > aPoints;
+  if (! GetListOfObjectsImpl( thePoints, aPoints ))
     return aGEOMObject._retn();
 
   // Perform
   Handle(GEOM_Object) aNewObject =
-    GetOperations()->DivideEdgeByPoint( anObject, theIndex, aPoint );
+    GetOperations()->DivideEdgeByPoint( anObject, theIndex, aPoints );
   if (!GetOperations()->IsDone() || aNewObject.IsNull())
     return aGEOMObject._retn();
 
@@ -635,3 +636,26 @@ GEOM::GEOM_Object_ptr GEOM_IHealingOperations_i::LimitTolerance (GEOM::GEOM_Obje
 
   return GetObject(aNewObject);
 }
+
+//================================================================================
+/*!
+ * \brief Return information on what has been done by the last called healing method
+ */
+//================================================================================
+
+GEOM::ModifStatistics* GEOM_IHealingOperations_i::GetStatistics()
+{
+  const ShHealOper_ModifStats& stats = * GetOperations()->GetStatistics();
+  const std::set< ShHealOper_ModifStats::Datum >& modifs = stats.GetData();
+  std::set< ShHealOper_ModifStats::Datum >::const_iterator modif = modifs.begin();
+
+  GEOM::ModifStatistics_var statsVar = new GEOM::ModifStatistics();
+  statsVar->length( modifs.size() );
+  for ( int i = 0; modif != modifs.end(); ++modif, ++i )
+  {
+    statsVar[ i ].name = modif->myModif.c_str();
+    statsVar[ i ].count = modif->myCount;
+  }
+
+  return statsVar._retn();
+}
index 4d851973d51178c1f5a72103c25e9e6c6d79242c..c1da1d0060956890505a1beeca70c8089c74d1d2 100644 (file)
@@ -84,7 +84,7 @@ class GEOM_I_EXPORT GEOM_IHealingOperations_i :
 
    GEOM::GEOM_Object_ptr DivideEdgeByPoint (GEOM::GEOM_Object_ptr theObject,
                                             CORBA::Short          theIndex,
-                                            GEOM::GEOM_Object_ptr thePoint);
+                                            const GEOM::ListOfGO& thePoints);
 
    GEOM::GEOM_Object_ptr FuseCollinearEdgesWithinWire (GEOM::GEOM_Object_ptr theWire,
                                                        const GEOM::ListOfGO& theVertices);
@@ -101,6 +101,8 @@ class GEOM_I_EXPORT GEOM_IHealingOperations_i :
 
    ::GEOMImpl_IHealingOperations* GetOperations() { return (::GEOMImpl_IHealingOperations*)GetImpl(); }
 
+   GEOM::ModifStatistics* GetStatistics();
+   
 private:
          Handle(TColStd_HArray1OfInteger)        Convert( const GEOM::short_array& );
 
index 07535cdf9203e9cb4bd11c42213133780afb319e..32d7ca47ea09beb991f8d1f83cb059157a2fccac 100644 (file)
@@ -6830,12 +6830,12 @@ class geomBuilder(object, GEOM._objref_GEOM_Gen):
             self._autoPublish(anObj, theName, "divideEdge")
             return anObj
 
-        ## Addition of a point to a given edge of \a theObject by projecting
-        #  another point to the given edge.
+        ## Addition of points to a given edge of \a theObject by projecting
+        #  other points to the given edge.
         #  @param theObject Shape to be processed.
         #  @param theEdgeIndex Index of edge to be divided within theObject's shape,
         #                      if -1, then theObject itself is the edge.
-        #  @param thePoint Point to project to theEdgeIndex-th edge.
+        #  @param thePoints List of points to project to theEdgeIndex-th edge.
         #  @param theName Object name; when specified, this parameter is used
         #         for result publication in the study. Otherwise, if automatic
         #         publication is switched on, default value is used for result name.
@@ -6844,16 +6844,16 @@ class geomBuilder(object, GEOM._objref_GEOM_Gen):
         #
         #  @ref tui_add_point_on_edge "Example"
         @ManageTransactions("HealOp")
-        def DivideEdgeByPoint(self, theObject, theEdgeIndex, thePoint, theName=None):
+        def DivideEdgeByPoint(self, theObject, theEdgeIndex, thePoints, theName=None):
             """
-            Addition of a point to a given edge of \a theObject by projecting
-            another point to the given edge.
+            Addition of points to a given edge of \a theObject by projecting
+            other points to the given edge.
 
             Parameters:
                 theObject Shape to be processed.
                 theEdgeIndex The edge or its index to be divided within theObject's shape,
                              if -1, then theObject itself is the edge.
-                thePoint Point to project to theEdgeIndex-th edge.
+                thePoints List of points to project to theEdgeIndex-th edge.
                 theName Object name; when specified, this parameter is used
                         for result publication in the study. Otherwise, if automatic
                         publication is switched on, default value is used for result name.
@@ -6864,7 +6864,7 @@ class geomBuilder(object, GEOM._objref_GEOM_Gen):
             # Example: see GEOM_TestHealing.py
             if isinstance( theEdgeIndex, GEOM._objref_GEOM_Object ):
                 theEdgeIndex = self.GetSubShapeID( theObject, theEdgeIndex )
-            anObj = self.HealOp.DivideEdgeByPoint(theObject, theEdgeIndex, thePoint)
+            anObj = self.HealOp.DivideEdgeByPoint(theObject, theEdgeIndex, ToList( thePoints ))
             RaiseIfFailed("DivideEdgeByPoint", self.HealOp)
             self._autoPublish(anObj, theName, "divideEdge")
             return anObj
index cb060826078d111a619c74ae01ba538c381283aa..b65327e919eb9e885395cc1b00d09d971acff61b 100644 (file)
@@ -121,3 +121,98 @@ extern "C"
     return new RepairGUI( parent );
   }
 }
+
+//=====================================================================================
+// Statistics dialog
+//=====================================================================================
+
+#include <QDialog>
+#include <QHBoxLayout>
+#include <QHeaderView>
+#include <QPushButton>
+#include <QString>
+#include <QStringList>
+#include <QTableWidget>
+#include <QTableWidget>
+#include <QTableWidgetItem>
+#include <QVBoxLayout>
+
+namespace
+{
+  class StatsDlg : public QDialog
+  {
+  public:
+    StatsDlg( GEOM::ModifStatistics_var stats, QWidget* parent );
+  };
+
+  StatsDlg::StatsDlg( GEOM::ModifStatistics_var stats, QWidget* parent ): QDialog( parent )
+  {
+    setModal( false );
+    setAttribute( Qt::WA_DeleteOnClose, true );
+    setWindowTitle( tr( "GEOM_HEALING_STATS_TITLE" ) );
+    setMinimumWidth( 500 );
+
+    const int nbRows = stats->length();
+    const int nbCols = 2;
+    QTableWidget* table = new QTableWidget( nbRows, nbCols, this );
+    table->setEditTriggers( QAbstractItemView::NoEditTriggers );
+    table->horizontalHeader()->setResizeMode( 1, QHeaderView::Interactive );
+    table->horizontalHeader()->setStretchLastSection( true );
+
+    QStringList headers;
+    headers << tr( "GEOM_HEALING_STATS_COL_1" );
+    headers << tr( "GEOM_HEALING_STATS_COL_2" );
+    table->setHorizontalHeaderLabels( headers );
+
+    // buttons
+
+    QPushButton* okBtn = new QPushButton( tr( "GEOM_BUT_OK" ), this );
+    okBtn->setAutoDefault( true );
+    okBtn->setDefault( true );
+    okBtn->setFocus();
+    // QPushButton* helpBtn = new QPushButton( tr( "GEOM_BUT_HELP" ), this );
+    // helpBtn->setAutoDefault( true );
+
+    QHBoxLayout* btnLayout = new QHBoxLayout;
+    btnLayout->setMargin( 9 );
+    btnLayout->setSpacing( 6 );
+
+    btnLayout->addWidget( okBtn );
+    btnLayout->addStretch( 10 );
+    // btnLayout->addWidget( helpBtn );
+
+    QVBoxLayout* aLay = new QVBoxLayout( this );
+    aLay->setMargin( 9 );
+    aLay->setSpacing( 6 );
+    aLay->addWidget( table );
+    aLay->addLayout( btnLayout );
+
+    // fill the table
+    for ( int row = 0; row < nbRows; ++row )
+    {
+      table->setItem( row, 0, new QTableWidgetItem( QString::number( stats[ row ].count )));
+      table->setItem( row, 1, new QTableWidgetItem( tr( stats[ row ].name.in() )));
+    }
+
+    connect( okBtn,       SIGNAL( clicked() ), this, SLOT( reject() ));
+    //connect( helpBtn,     SIGNAL( clicked() ), this, SLOT( help() ));
+
+  }
+}
+
+//================================================================================
+/*!
+ * \brief Show a dialog providing info on what is done by healing
+ */
+//================================================================================
+
+void RepairGUI::ShowStatistics( GEOM::GEOM_IHealingOperations_var anOper, QWidget* parent )
+{
+  GEOM::ModifStatistics_var stats = anOper->GetStatistics();
+
+  if ( ! &stats.in() || stats->length() == 0 )
+    return;
+
+  StatsDlg* dlg = new StatsDlg( stats, parent );
+  dlg->exec();
+}
index df1eb9c45562469a9e57b3fea9622a03536600b2..26fa5fbbff0a8dde65fec850d69065f79340cde9 100644 (file)
@@ -29,6 +29,9 @@
 
 #include <GEOMGUI.h>
 
+#include <SALOMEconfig.h>
+#include CORBA_CLIENT_HEADER(GEOM_Gen)
+
 //=================================================================================
 // class    : RepairGUI
 // purpose  :
@@ -40,6 +43,7 @@ public:
   ~RepairGUI();
 
   bool OnGUIEvent( int, SUIT_Desktop* );
-};
 
+  static void ShowStatistics( GEOM::GEOM_IHealingOperations_var anOper, QWidget* parent );
+};
 #endif // REPAIRGUI_H
index 3d395463b4437adf36174864ab20192c9bf861ee..3d5bbcba9b53b50ee02e7f775b39a534746405ac 100644 (file)
 //
 #include "RepairGUI_ChangeOrientationDlg.h"
 
-#include <DlgRef.h>
-#include <GeometryGUI.h>
-#include <GEOMBase.h>
+#include "DlgRef.h"
+#include "GeometryGUI.h"
+#include "GEOMBase.h"
+#include "RepairGUI.h"
 
-#include <SalomeApp_Application.h>
 #include <LightApp_SelectionMgr.h>
-#include <SUIT_Session.h>
 #include <SUIT_ResourceMgr.h>
+#include <SUIT_Session.h>
+#include <SalomeApp_Application.h>
+#include <TopAbs.hxx>
 
-#include <GEOMImpl_Types.hxx>
+#include "GEOMImpl_Types.hxx"
 
-#include <TopAbs.hxx>
 
 //=================================================================================
 // class    : RepairGUI_ChangeOrientationDlg()
@@ -280,7 +281,11 @@ bool RepairGUI_ChangeOrientationDlg::execute( ObjectList& objects )
   }
 
   if ( !anObj->_is_nil() )
+  {
+    if ( !IsPreview() )
+      RepairGUI::ShowStatistics( anOper, this );
     objects.push_back( anObj._retn() );
+  }
 
   return true;
 }
index f57ad486800fe727ac20235049b3e9f6730a9f81..77e29a21164bf9d97165d6e20ec97ab6d248ddfd 100644 (file)
 //
 #include "RepairGUI_CloseContourDlg.h"
 
-#include <DlgRef.h>
-#include <GeometryGUI.h>
-#include <GEOMBase.h>
+#include "DlgRef.h"
+#include "GeometryGUI.h"
+#include "GEOMBase.h"
+#include "RepairGUI.h"
 
 #include <SUIT_Session.h>
 #include <SUIT_ResourceMgr.h>
@@ -325,8 +326,11 @@ bool RepairGUI_CloseContourDlg::execute (ObjectList& objects)
 
   bool aResult = !anObj->_is_nil();
   if (aResult)
+  {
+    if ( !IsPreview() )
+      RepairGUI::ShowStatistics( anOper, this );
     objects.push_back(anObj._retn());
-
+  }
   return aResult;
 }
 
index 62715108b23ab7b6095650ecb0b2441a8ce599a3..ad77079efd9c70911b62df29c12baa53816482db 100644 (file)
 //
 #include "RepairGUI_DivideEdgeDlg.h"
 
-#include <DlgRef.h>
-#include <GeometryGUI.h>
-#include <GEOMBase.h>
-#include <SalomeApp_DoubleSpinBox.h>
+#include "DlgRef.h"
+#include "GeometryGUI.h"
+#include "GEOMBase.h"
+#include "RepairGUI.h"
 
+#include <SalomeApp_DoubleSpinBox.h>
 #include <SalomeApp_Application.h>
 #include <LightApp_SelectionMgr.h>
 #include <SUIT_Session.h>
@@ -161,7 +162,7 @@ void RepairGUI_DivideEdgeDlg::Init()
   myEditCurrentArgument = GroupPoints->LineEdit1;
 
   myObject = GEOM::GEOM_Object::_nil();
-  myPoint.nullify();
+  myPoints.clear();
   myIndex  = -1;
   myProjectionOK = false;
 
@@ -231,11 +232,8 @@ void RepairGUI_DivideEdgeDlg::displayPreview()
       BRepBuilderAPI_MakeVertex mkVertex (aPnt);
       aShape = mkVertex.Shape();
     }
-    else if ( getConstructorId() == BY_POINT_PROJ && myPoint )
+    else if ( getConstructorId() == BY_POINT_PROJ && !myPoints.empty() )
     {
-      TopoDS_Shape aPoints;
-      GEOMBase::GetShape( myPoint.get(), aPoints, TopAbs_SHAPE );
-
       BRep_Builder builder;
       TopoDS_Compound compoundOfVV;
       builder.MakeCompound(compoundOfVV);
@@ -245,11 +243,13 @@ void RepairGUI_DivideEdgeDlg::displayPreview()
       aProjector.Init( aCurve, aFP, aLP );
 
       TopTools_MapOfShape vMap;
-      TopExp_Explorer vertex( aPoints, TopAbs_VERTEX );
-      for ( ; vertex.More(); vertex.Next() )
+      for ( int i = 0; i < myPoints.count(); ++i )
       {
-        if ( !vMap.Add( vertex.Current() )) continue;
-        gp_Pnt p = BRep_Tool::Pnt( TopoDS::Vertex( vertex.Current() ));
+        TopoDS_Shape aPoint;
+        GEOMBase::GetShape( myPoints[i].get(), aPoint, TopAbs_VERTEX );
+        if ( !vMap.Add( aPoint )) continue;
+
+        gp_Pnt p = BRep_Tool::Pnt( TopoDS::Vertex( aPoint ));
         aProjector.Perform( p );
         if ( aProjector.NbPoints() > 0 )
         {
@@ -296,13 +296,14 @@ bool RepairGUI_DivideEdgeDlg::ClickOnApply()
 
   initName();
 
-  myEditCurrentArgument->setText( "" );
+  GroupPoints->LineEdit1->setText( "" );
+  GroupPoints->LineEdit2->setText( "" );
   myObject = GEOM::GEOM_Object::_nil();
-  myPoint.nullify();
+  myPoints.clear();
   myIndex = -1;
   myProjectionOK = false;
 
-  ConstructorsClicked(getConstructorId());
+  GroupPoints->PushButton1->click();
 
   return true;
 }
@@ -322,10 +323,11 @@ void RepairGUI_DivideEdgeDlg::SelectionIntoArgument()
   {
     myObject = GEOM::GEOM_Object::_nil();
     myIndex = -1;
+    myProjectionOK = false;
   }
   else //if ( myEditCurrentArgument == GroupPoints->LineEdit2 )
   {
-    myPoint.nullify();
+    myPoints.clear();
     myProjectionOK = false;
   }
 
@@ -333,7 +335,7 @@ void RepairGUI_DivideEdgeDlg::SelectionIntoArgument()
   SALOME_ListIO aSelList;
   aSelMgr->selectedObjects(aSelList);
 
-  if ( aSelList.Extent() == 1 ) {
+  if ( toSelectObject && aSelList.Extent() == 1 ) {
     Handle(SALOME_InteractiveObject) anIO = aSelList.First();
     GEOM::GEOM_Object_var aSelectedObj = GEOMBase::ConvertIOinGEOMObject( anIO );
     if ( !CORBA::is_nil( aSelectedObj ) )
@@ -343,7 +345,7 @@ void RepairGUI_DivideEdgeDlg::SelectionIntoArgument()
       if ( GEOMBase::GetShape( aSelectedObj, aShape, TopAbs_SHAPE ) )
       {
         const int aType = aShape.ShapeType();
-        if ( aType <= TopAbs_EDGE || !toSelectObject ) // edge, wire, face, shell, solid, compound
+        if ( aType <= TopAbs_EDGE ) // edge, wire, face, shell, solid, compound
         {
           GEOM::short_array anIndexes;
 
@@ -354,34 +356,35 @@ void RepairGUI_DivideEdgeDlg::SelectionIntoArgument()
 
           if ( !aMap.IsEmpty() ) // sub-shape selection
           {
-            if ( toSelectObject ) {
-              myIndex = aMap( 1 );
-              myObject = aSelectedObj;
-              myEditCurrentArgument->setText( aName += QString( ":edge_%1" ).arg( myIndex ) );
-            }
-            else if (( myPoint = getSelected( TopAbs_VERTEX )))
-            {
-              myEditCurrentArgument->setText( aName += QString( ":vertex_%1" ).arg( aMap( 1 )));
-            }
+            myIndex = aMap( 1 );
+            myObject = aSelectedObj;
+            myEditCurrentArgument->setText( aName += QString( ":edge_%1" ).arg( myIndex ) );
           }
-          else if ( aType == TopAbs_EDGE && toSelectObject ) // single shape selection
+          else if ( aType == TopAbs_EDGE ) // single shape selection
           {
             myIndex = -1;
             myObject = aSelectedObj;
-            myEditCurrentArgument->setText( aName );
-          }
-          else if ( aType == TopAbs_VERTEX && !toSelectObject ) // single shape selection
-          {
-            myPoint = aSelectedObj;
-            myEditCurrentArgument->setText( aName );
+            myEditCurrentArgument->setText( GEOMBase::GetName( myObject ) );
           }
           else // face, shell, solid or compound was selected, and NOT its sub-shape.
           {
+            myIndex = -1;
+            myObject = GEOM::GEOM_Object::_nil();
           }
         }
       }
     }
   }
+  if ( !toSelectObject )
+  {
+    myPoints = getSelected( TopAbs_VERTEX, -1, /*strict=*/true );
+    if ( myPoints.empty() )
+      myEditCurrentArgument->setText( "" );
+    else if ( myPoints.count() == 1 )
+      myEditCurrentArgument->setText( GEOMBase::GetName( myPoints[0].get() ));
+    else
+      myEditCurrentArgument->setText( QObject::tr( "%1_vertices" ).arg( myPoints.count() ));
+  }
 
   displayPreview();
 }
@@ -487,7 +490,7 @@ bool RepairGUI_DivideEdgeDlg::isValid( QString& msg )
   }
   else if ( getConstructorId() == BY_POINT_PROJ )
   {
-    if (( ok = myPoint ) && !( ok = myProjectionOK ))
+    if (( ok = myPoints.count() ) && !( ok = myProjectionOK ))
       msg = tr("DEVIDE_EDGE_BAD_PROJ_MSG");
   }
   return !myObject->_is_nil() && ok;
@@ -502,10 +505,17 @@ bool RepairGUI_DivideEdgeDlg::execute( ObjectList& objects )
   GEOM::GEOM_IHealingOperations_var anOper = GEOM::GEOM_IHealingOperations::_narrow( getOperation() );
   GEOM::GEOM_Object_var anObj;
   if ( getConstructorId() == BY_PARAM )
+  {
     anObj = anOper->DivideEdge( myObject, myIndex, myValEdt->value(), getIsByParameter() );
+  }
   else
-    anObj = anOper->DivideEdgeByPoint( myObject, myIndex, myPoint.get() );
-
+  {
+    GEOM::ListOfGO_var objList = new GEOM::ListOfGO;
+    objList->length( myPoints.count() );
+    for ( int i = 0; i < myPoints.count(); ++i )
+      objList[i] = myPoints[i].copy();
+    anObj = anOper->DivideEdgeByPoint( myObject, myIndex, objList );
+  }
   bool aResult = !anObj->_is_nil();
   if ( aResult )
   {
@@ -517,6 +527,8 @@ bool RepairGUI_DivideEdgeDlg::execute( ObjectList& objects )
       aParameters << "";
       anObj->SetParameters(aParameters.join(":").toLatin1().constData());
     }
+    if ( !IsPreview() )
+      RepairGUI::ShowStatistics( anOper, this );
     objects.push_back( anObj._retn() );
   }
 
@@ -552,5 +564,6 @@ void RepairGUI_DivideEdgeDlg::initSelection()
 //=================================================================================
 void RepairGUI_DivideEdgeDlg::addSubshapesToStudy()
 {
-  GEOMBase::PublishSubObject( myPoint.get() );
+  for ( int i = 0; i < myPoints.count(); ++i )
+    GEOMBase::PublishSubObject( myPoints[i].get() );
 }
index 129c9895cea175c1fd69e973378514f8484d58f2..88cf5229dbaf362e93ff95072f1b31998992ec95 100644 (file)
@@ -62,7 +62,7 @@ private:
 
 private:
   GEOM::GEOM_Object_var              myObject;
-  GEOM::GeomObjPtr                   myPoint;
+  QList<GEOM::GeomObjPtr>            myPoints;
   bool                               myProjectionOK;
 
   DlgRef_2SelExt*                    GroupPoints;
index 69b37b9f6ab49e9bfbcab61bd8abf109344d6519..0b447d106757ac6566f67591dcd5ba74c366aafd 100644 (file)
 
 #include "RepairGUI_LimitToleranceDlg.h"
 
-#include <DlgRef.h>
-#include <GeometryGUI.h>
-#include <GEOMBase.h>
-#include <SalomeApp_DoubleSpinBox.h>
+#include "DlgRef.h"
+#include "GeometryGUI.h"
+#include "GEOMBase.h"
+#include "RepairGUI.h"
 
+#include <SalomeApp_DoubleSpinBox.h>
 #include <SalomeApp_Application.h>
 #include <LightApp_SelectionMgr.h>
 #include <SalomeApp_Study.h>
@@ -303,6 +304,8 @@ bool RepairGUI_LimitToleranceDlg::execute(ObjectList& objects)
     QStringList aParameters;
     aParameters << myTolEdt->text();
     anObj->SetParameters(aParameters.join(":").toLatin1().constData());
+    if ( !IsPreview() )
+      RepairGUI::ShowStatistics( anOper, this );
     objects.push_back(anObj._retn());
   }
 
index 56b5aa004710340279b3af763a8d647ee64c954e..92a3b0c76cdb8a771d2ffafc925237f41730ec3a 100644 (file)
 //
 #include "RepairGUI_RemoveHolesDlg.h"
 
-#include <DlgRef.h>
-#include <GeometryGUI.h>
-#include <GEOMBase.h>
+#include "DlgRef.h"
+#include "GeometryGUI.h"
+#include "GEOMBase.h"
+#include "RepairGUI.h"
 
 #include <SUIT_Session.h>
 #include <SUIT_ResourceMgr.h>
@@ -353,7 +354,11 @@ bool RepairGUI_RemoveHolesDlg::execute (ObjectList& objects)
     GEOM::GEOM_Object_var anObj = anOper->FillHoles(myObject, myWiresInd);
     aResult = !anObj->_is_nil();
     if (aResult)
+    {
+      if ( !IsPreview() )
+        RepairGUI::ShowStatistics( anOper, this );
       objects.push_back(anObj._retn());
+    }
   }
 
   return aResult;
index 927656c57fa719874b994bbd5f612d7e0aca7101..a60e6ed7233ddde96207da11031bbf2d9dadfded 100644 (file)
 //
 #include "RepairGUI_RemoveIntWiresDlg.h"
 
-#include <DlgRef.h>
-#include <GeometryGUI.h>
-#include <GEOMBase.h>
+#include "DlgRef.h"
+#include "GeometryGUI.h"
+#include "GEOMBase.h"
+#include "RepairGUI.h"
 
 #include <SUIT_Session.h>
 #include <SUIT_ResourceMgr.h>
@@ -312,8 +313,11 @@ bool RepairGUI_RemoveIntWiresDlg::execute (ObjectList& objects)
 
   bool aResult = !anObj->_is_nil();
   if (aResult)
+  {
+    if ( !IsPreview() )
+      RepairGUI::ShowStatistics( anOper, this );
     objects.push_back(anObj._retn());
-
+  }
   return aResult;
 }
 
index 926f1eb80514c853f3895b1baafab9dd4cc0fa09..e05f008d330b41afe3217612f9527fc673249c5e 100755 (executable)
 
 #include "RepairGUI_ShapeProcessDlg.h"
 
-#include <DlgRef.h>
-#include <GeometryGUI.h>
-#include <GEOMBase.h>
-#include <GEOMImpl_Types.hxx>
+#include "DlgRef.h"
+#include "GeometryGUI.h"
+#include "GEOMBase.h"
+#include "GEOMImpl_Types.hxx"
+#include "RepairGUI.h"
 
 #include <SalomeApp_Application.h>
 #include <SalomeApp_DoubleSpinBox.h>
@@ -652,6 +653,8 @@ bool RepairGUI_ShapeProcessDlg::execute( ObjectList& objects )
 
         aParameters << getTexts( aParams );
         anObj->SetParameters(aParameters.join(":").toLatin1().constData());
+
+        RepairGUI::ShowStatistics( anOper, this );
       }
       objects.push_back( anObj._retn() );
     }
index 43a0f629eba0ceea275b69078972bc432345d1a7..d7c297168ebef82a78345446a7fa42857da58abd 100644 (file)
 
 #include "RepairGUI_SuppressFacesDlg.h"
 
-#include <DlgRef.h>
-#include <GeometryGUI.h>
-#include <GEOMBase.h>
+#include "DlgRef.h"
+#include "GeometryGUI.h"
+#include "GEOMBase.h"
+#include "RepairGUI.h"
 
 #include <SUIT_Session.h>
 #include <SUIT_ResourceMgr.h>
@@ -376,8 +377,11 @@ bool RepairGUI_SuppressFacesDlg::execute (ObjectList& objects)
 
   bool aResult = !anObj->_is_nil();
   if (aResult)
+  {
+    if ( !IsPreview() )
+      RepairGUI::ShowStatistics( anOper, this );
     objects.push_back(anObj._retn());
-
+  }
   return aResult;
 }
 
index 8d2d3a2baaaac7a83845bd209e18757f2327163d..9def662799cd5b665e151c13d7885ee120dc353f 100755 (executable)
@@ -52,6 +52,7 @@ SET(ShHealOper_HEADERS
   ShHealOper_SplitCurve3d.hxx
   ShHealOper_ChangeOrientation.hxx
   ShHealOper_Tool.hxx
+  ShHealOper_ModifStats.hxx
   )
 # --- sources ---
 
index e48ba58d53c86af895a8cbb74cfabcf95669d7ba..04112efa718411e17aa1ae2647e7f80838f88ccd 100644 (file)
@@ -73,6 +73,7 @@ Standard_Boolean ShHealOper_ChangeOrientation::Perform()
     while (itr.More()) {
       B.Add(myResultShape,itr.Value().Reversed());
       itr.Next();
+      myStatistics.AddModif("Face reversed");
     }
   }
   else if (myInitShape.ShapeType() == TopAbs_FACE)
@@ -82,6 +83,7 @@ Standard_Boolean ShHealOper_ChangeOrientation::Perform()
     while (itr.More()) {
       B.Add(myResultShape,itr.Value());
       itr.Next();
+      myStatistics.AddModif("Wire reversed");
     }
     myResultShape.Reverse();
   }
@@ -105,12 +107,14 @@ Standard_Boolean ShHealOper_ChangeOrientation::Perform()
     if ( myInitShape.ShapeType() == TopAbs_EDGE )
     {
       myResultShape = reversedEdges.First();
+      myStatistics.AddModif("Edge reversed");
     }
     else
     {
       BRepBuilderAPI_MakeWire wire;
       wire.Add( reversedEdges );
       myResultShape = wire;
+      myStatistics.AddModif("Wire reversed");
     }
     // myResultShape = myInitShape.EmptyCopied();
     // TopoDS_Iterator itr (myInitShape);
@@ -132,6 +136,13 @@ Standard_Boolean ShHealOper_ChangeOrientation::Perform()
       myResultShape.Orientation(TopAbs_REVERSED);
     else
       myResultShape.Orientation(TopAbs_FORWARD);
+
+    switch( myResultShape.ShapeType() ) {
+    case TopAbs_SOLID    : myStatistics.AddModif("Solid reversed"); break;
+    case TopAbs_COMPSOLID: myStatistics.AddModif("Compsolid reversed"); break;
+    case TopAbs_COMPOUND : myStatistics.AddModif("Compound reversed"); break;
+    default:;
+    }
   }
 
   return true;
index 67c69b50e5f2425cc67d3f68b9cf23c9acc16760..0e9dfaa45b222a34c6331ac3e49a45185cc3863f 100644 (file)
@@ -252,10 +252,14 @@ Standard_Boolean ShHealOper_CloseContour::fixGaps(const Handle(ShapeExtend_WireD
         Standard_Integer ind1 = (ind2 >1 ? ind2 -1 : theWire->NbEdges());
         TopoDS_Edge aE1= theWire->Edge(ind1);
         TopoDS_Edge aE2= theWire->Edge(ind2);
-        if(!myModeVertex)
+        if(!myModeVertex) {
           buildEdge(aE1,aE2,theCommonFaces);
-        else
+          myStatistics.AddModif("An edge added to close a wire");
+        }
+        else {
           myMaxTolerance = RealLast();
+          myStatistics.AddModif("Tolerance of vertex increased to close a wire");
+        }
         if(ind2 == ind1) break;
       }
     }
@@ -268,8 +272,9 @@ Standard_Boolean ShHealOper_CloseContour::fixGaps(const Handle(ShapeExtend_WireD
 //function : checkOneFace
 //purpose  : 
 //=======================================================================
-Standard_Boolean ShHealOper_CloseContour::checkOneFace(const Handle(ShapeExtend_WireData)& theSewd,
-                                                       TopTools_SequenceOfShape& theCommonFaces) const
+Standard_Boolean
+ShHealOper_CloseContour::checkOneFace(const Handle(ShapeExtend_WireData)& theSewd,
+                                      TopTools_SequenceOfShape& theCommonFaces) const
 {
   TopTools_IndexedMapOfShape amapfaces;
   TopoDS_Edge aEdge1 = theSewd->Edge(1);
index 99de5efe557110b9eef53d1e4254ceb52f094429..d188ab1440a07965f5ca01d97326f3566dc9036f 100644 (file)
@@ -142,6 +142,7 @@ Standard_Boolean ShHealOper_EdgeDivide::Perform(const TopoDS_Shape& theEdge,
 
   TopTools_MapOfShape vMap;
   TopExp_Explorer vertex( thePoints, TopAbs_VERTEX );
+  std::set< double > params; // to exclude equal params
   for ( ; vertex.More(); vertex.Next() )
   {
     if ( !vMap.Add( vertex.Current() )) continue;
@@ -151,9 +152,24 @@ Standard_Boolean ShHealOper_EdgeDivide::Perform(const TopoDS_Shape& theEdge,
     {
       double     u = double( aProjector.LowerDistanceParameter() );
       double param = ( u - aFirst ) / ( aLast - aFirst );
-      aSeqValues->Append( param );
+      params.insert( param );
     }
   }
+  // remove too close params
+  params.insert( 0 );
+  params.insert( 1 );
+  std::set< double >::iterator p2 = params.begin(), p1 = p2++;
+  while ( p2 != params.end() )
+  {
+    if ( Abs( *p2 - *p1 ) < 1e-3 ) // compare normalized params 
+      params.erase( p1 );
+    p1 = p2++;
+  }
+  p1 = params.begin(); ++p1; // skip aFirst
+  p2 = params.end();   --p2; // skip aLast
+  for ( ; p1 != p2; ++p1 )
+    aSeqValues->Append( *p1 );
+
   myDone = build(aSeqValues);
   return myDone;
 }
@@ -219,7 +235,10 @@ Standard_Boolean ShHealOper_EdgeDivide::build(const Handle(TColStd_HSequenceOfRe
         myErrorStatus = ShHealOper_ErrorExecution;
   }
   if(isDone)
+  {
     myResultShape = myContext->Apply(myInitShape);
+    myStatistics.AddModif("Vertex added on edge", theValues->Length() );
+  }
   return isDone;
   
 }
index 114326a8b934a14f0a377ed0fd70319b2132214f..82f78cc2768d05b5662e7dba180767513bbdb4a2 100644 (file)
@@ -186,7 +186,10 @@ Standard_Boolean ShHealOper_FillHoles::Fill(const TopTools_SequenceOfShape& theF
       myDone = (addFace(aSurf,aWire,aCurves2d,aOrders,aSenses) || myDone);
   }
   if(myDone)
+  {
     myResultShape = myContext->Apply(myResultShape);
+    myStatistics.AddModif( "Face created to fill hole" , aSeqWires->Length() );
+  }
   return myDone;
 }
 
diff --git a/src/ShHealOper/ShHealOper_ModifStats.hxx b/src/ShHealOper/ShHealOper_ModifStats.hxx
new file mode 100644 (file)
index 0000000..ad043b8
--- /dev/null
@@ -0,0 +1,78 @@
+// Copyright (C) 2007-2014  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+// File      : ShHealOper_ModifStats.hxx
+// Created   : Mon Dec  1 15:29:48 2014
+
+#ifndef __ShHealOper_ModifStats_HXX__
+#define __ShHealOper_ModifStats_HXX__
+
+#include <string>
+#include <set>
+
+/*!
+ * \brief Structure describing modifications done in a shape
+ */
+class Standard_EXPORT ShHealOper_ModifStats
+{
+ public:
+
+  struct Standard_EXPORT Datum
+  {
+    std::string myModif; // what is done
+    mutable int myCount; // how many times (in how many sub-shapes)
+
+    Datum( const std::string& txt, int cnt=0 ): myModif( txt ), myCount(cnt) {}
+    bool operator< ( const Datum& o ) const { return myModif < o.myModif; }
+  };
+
+  // record a modification
+  void AddModif( const std::string& modifText, int nb=1 )
+  {
+    std::set< Datum >::iterator d = myData.insert( Datum( modifText )).first;
+    d->myCount += nb;
+  }
+
+  // add data from another ShHealOper_ModifStats
+  void Add( const ShHealOper_ModifStats& stats )
+  {
+    if ( myData.empty() ) myData = stats.myData;
+    else {
+      std::set< Datum >::const_iterator d = stats.myData.begin();
+      for ( ; d != stats.myData.end(); ++d )
+        AddModif( d->myModif, d->myCount );
+    }
+  }
+
+  // return all recorder modifications
+  const std::set< Datum >& GetData() const { return myData; }
+
+  // clear all statistics
+  void Clear() { myData.clear(); }
+
+ protected:
+
+  std::set< Datum > myData;
+
+};
+
+#endif
index 698cedaf9666e03ce7dad72b8cdc978b1cdc713e..f50da898d5e638f9b58adbe8069638ae1b18af14 100644 (file)
@@ -137,6 +137,9 @@ Standard_Boolean ShHealOper_RemoveInternalWires::removeWire(const TopoDS_Face& t
       }
     }
   }
+  if ( isremove )
+    myStatistics.AddModif( "Wire removed" );
+
   return isremove;
 }
 //=======================================================================
index fa516e924777db9356c6957b0815e04c0c603736..d991e1f7e1a3aacbc06b976cd0b8ea1f49e45dea 100644 (file)
 #include <TopoDS_Iterator.hxx>
 #include <TColStd_IndexedDataMapOfTransientTransient.hxx>
 #include <TNaming_CopyShape.hxx>
+#include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
+#include <ShapeExtend_MsgRegistrator.hxx>
+#include <ShapeExtend_DataMapOfShapeListOfMsg.hxx>
+#include <ShapeExtend_DataMapIteratorOfDataMapOfShapeListOfMsg.hxx>
+#include <Message_ListOfMsg.hxx>
+#include <Message_ListIteratorOfListOfMsg.hxx>
+#include <Message_Msg.hxx>
 
 //=======================================================================
 //function : ShHealOper_ShapeProcess()
@@ -52,8 +59,10 @@ ShHealOper_ShapeProcess::ShHealOper_ShapeProcess (  ) :
    //myResource = new Resource_Manager("ShHealing");
    myPrefix = "ShapeProcess";
    mySaveHistoryMode = Standard_False;
-   myLevel = TopAbs_FACE;
+   myLevel = TopAbs_EDGE;
    myDone = Standard_False;
+   myOperations.Context()->SetDetalisation ( TopAbs_EDGE );
+   myOperations.Context()->SetTraceLevel( 3 );
 }
 
 //=======================================================================
@@ -63,23 +72,22 @@ ShHealOper_ShapeProcess::ShHealOper_ShapeProcess (  ) :
 
 ShHealOper_ShapeProcess::ShHealOper_ShapeProcess (const TCollection_AsciiString& theNameResource,
                                                   const TCollection_AsciiString& thePrefix ) :
-       myOperations(theNameResource.ToCString(),thePrefix.ToCString())
+  myOperations(theNameResource.ToCString(),thePrefix.ToCString())
 {
   //myResource = new Resource_Manager(theNameResource);
   myPrefix = thePrefix;
   mySaveHistoryMode = Standard_False;
-  myLevel = TopAbs_FACE;
+  myLevel = TopAbs_EDGE;
   myDone = Standard_False;
 }
 
 //=======================================================================
 //function : Perform
-//purpose  : 
+//purpose  :
 //=======================================================================
-void ShHealOper_ShapeProcess::Perform(const TopoDS_Shape& theOldShape, 
-                                           TopoDS_Shape& theNewShape)
+void ShHealOper_ShapeProcess::Perform(const TopoDS_Shape& theOldShape,
+                                      TopoDS_Shape&       theNewShape)
 {
-  
   myMapModifications.Clear();
   //ShapeProcessAPI_ApplySequence aOperations(myResource,myPrefix.ToCString());
   //myDone = Standard_False;
@@ -99,12 +107,50 @@ void ShHealOper_ShapeProcess::Perform(const TopoDS_Shape& theOldShape,
   myDone = !anOldShape.IsSame(theNewShape);
   if(!myDone) {
     Standard_Real aendTol =aSatol.Tolerance(theNewShape,0);
-    myDone = (fabs(ainitTol - aendTol) > Precision::Confusion()); 
+    myDone = (fabs(ainitTol - aendTol) > Precision::Confusion());
+    if ( myDone ) {
+      if ( ainitTol > aendTol )
+        myStatistics.AddModif( "Tolerance fixed (decreased)" );
+      else
+        myStatistics.AddModif( "Tolerance fixed (increased)" );
+    }
   }
+
+  // fill myStatistics with messages
+  Handle(ShapeExtend_MsgRegistrator) msg = myOperations.Context()->Messages();
+  const ShapeExtend_DataMapOfShapeListOfMsg& shape2msg = msg->MapShape();
+  ShapeExtend_DataMapIteratorOfDataMapOfShapeListOfMsg s2msg( shape2msg );
+  for ( ; s2msg.More(); s2msg.Next() )
+  {
+    const Message_ListOfMsg & msgList = s2msg.Value();
+    Message_ListIteratorOfListOfMsg mIt( msgList );
+    for ( ; mIt.More(); mIt.Next() )
+    {
+      Message_Msg& m = mIt.Value();
+      TCollection_AsciiString txt = m.Get();
+      myStatistics.AddModif( txt.ToCString() );
+    }
+  }
+
+//   for (TopTools_DataMapIteratorOfDataMapOfShapeShape It (myOperations.Context()->Map()); It.More(); It.Next()) {
+//     TopoDS_Shape keyshape = It.Key(), valueshape = It.Value();
+// /*    if (keyshape.ShapeType() == TopAbs_SHELL) {
+//       if (valueshape.IsNull()) SN++;
+//       else SS++;
+//     }
+//     else if (keyshape.ShapeType() == TopAbs_FACE)*/ {
+//       if (valueshape.IsNull()) cout << "Removed" << endl;
+//       else {
+//         TopAbs::Print( keyshape.ShapeType(), cout ) << " -> ";
+//         TopAbs::Print( valueshape.ShapeType(), cout ) << " IsSame()=" << keyshape.IsSame(valueshape) << endl;
+//       }
+//     }
+//   }
+  
 }
 //=======================================================================
 //function : SetOperators
-//purpose  : 
+//purpose  :
 //=======================================================================
 
 void ShHealOper_ShapeProcess::SetOperators(const TColStd_SequenceOfAsciiString& theSeqOperators)
@@ -127,8 +173,8 @@ void ShHealOper_ShapeProcess::SetOperators(const TColStd_SequenceOfAsciiString&
 //purpose  : 
 //=======================================================================
 
-void  ShHealOper_ShapeProcess::SetParameter(const TCollection_AsciiString& theNameParam,
-                                    const TCollection_AsciiString& theVal)
+void ShHealOper_ShapeProcess::SetParameter(const TCollection_AsciiString& theNameParam,
+                                           const TCollection_AsciiString& theVal)
 {
   TCollection_AsciiString anameParam(myPrefix);
   anameParam += ".";
@@ -171,14 +217,14 @@ Standard_Boolean ShHealOper_ShapeProcess::GetOperators(TColStd_SequenceOfAsciiSt
 //=======================================================================
 
 Standard_Boolean ShHealOper_ShapeProcess::GetParameter(const TCollection_AsciiString& theNameParam,
-                                       TCollection_AsciiString& theVal)
+                                                       TCollection_AsciiString& theVal)
 {
   TCollection_AsciiString namePar(myPrefix);
   namePar += ".";
   namePar += theNameParam;
   if(!myOperations.Context()->ResourceManager()->Find(namePar.ToCString()))
     return Standard_False;
-  
+
   theVal = myOperations.Context()->ResourceManager()->Value(namePar.ToCString());
   return Standard_True;
 }
index f83f6e10ec63acd95c92e015d1a08b767a995ded..67616a5fd8e052ba799f652fdecfeb2ec59cb452 100644 (file)
 #include <ShapeProcessAPI_ApplySequence.hxx>
 #include <ShapeProcess_ShapeContext.hxx>
 
+#include "ShHealOper_Tool.hxx"
+
 ///  Class ShHealOper_ShapeProcess
 //Class for performing Shape healing operations on the shape.
 
-class ShHealOper_ShapeProcess 
+class ShHealOper_ShapeProcess : public ShHealOper_Tool
 {
  public:
   // ---------- PUBLIC METHODS ----------
index 6fb6133462728c9af9131600e1d4b7d8b221c91e..35a7924d48e5172d806fdac1ffefe0f48df6e3b2 100644 (file)
@@ -59,4 +59,5 @@ void ShHealOper_Tool::Init(const TopoDS_Shape& theShape)
   myErrorStatus =ShHealOper_NotError;
   myInitShape = theShape;
   myContext->Apply(myInitShape);
+  myStatistics.Clear();
 }
index a8bec37bd3eaade9f33bd6a4f98d77403a3c9fae..a06c5885af626f4155a74e83c4d67118edd02dac 100644 (file)
 #ifndef ShHealOper_Tool_HeaderFile
 #define ShHealOper_Tool_HeaderFile
 
-#include <MMgt_TShared.hxx>
 #include <ShapeBuild_ReShape.hxx>
 #include <TopoDS_Shape.hxx>
 
+#include "ShHealOper_ModifStats.hxx"
+
 ///  Class ShHealOper_Tool
 //
 //enumeration for definition of the status of the error if operation failed
@@ -69,12 +70,12 @@ class ShHealOper_Tool
   }
   //Returns modified shape obtained after operation from initial shape.
 
-  inline Standard_Boolean IsDone() const 
+  inline Standard_Boolean IsDone() const
   {
     return myDone;
   }
   //Returns status of the operation.
-  
+
   inline void SetContext(Handle(ShapeBuild_ReShape)& theContext)
   {
     myContext = theContext;
@@ -91,17 +92,31 @@ class ShHealOper_Tool
   {
     return myErrorStatus;
   }
- protected:
+
+  ShHealOper_ModifStats& GetStatistics()
+  {
+    return myStatistics;
+  }
+
+  const ShHealOper_ModifStats& GetStatistics() const
+  {
+    return myStatistics;
+  }
+  // Returns statistics of what is done
+
+protected:
   // ---------- PROTECTED FIELDS ----------
 
   Handle(ShapeBuild_ReShape) myContext;
-  TopoDS_Shape myInitShape;
-  TopoDS_Shape myResultShape;
-  Standard_Boolean myDone;
-  ShHealOper_Error myErrorStatus;
- public:
-// Declaration of CASCADE RTTI
-//DEFINE_STANDARD_RTTI (ShHealOper_Tool)
+  TopoDS_Shape               myInitShape;
+  TopoDS_Shape               myResultShape;
+  Standard_Boolean           myDone;
+  ShHealOper_Error           myErrorStatus;
+  ShHealOper_ModifStats      myStatistics;
+
+public:
+  // Declaration of CASCADE RTTI
+  //DEFINE_STANDARD_RTTI (ShHealOper_Tool)
 };
 
 // Definition of HANDLE object using Standard_DefineHandle.hxx