Salome HOME
0022775: [CEA 1091] Add an option on GetNonBlocks to retrieve quadrangular faces...
authorskv <skv@opencascade.com>
Thu, 22 Jan 2015 09:14:55 +0000 (12:14 +0300)
committervsr <vsr@opencascade.com>
Mon, 26 Jan 2015 11:17:02 +0000 (14:17 +0300)
20 files changed:
doc/salome/gui/GEOM/images/measures10.png [changed mode: 0755->0644]
doc/salome/gui/GEOM/images/measures2.png
doc/salome/gui/GEOM/images/measures2a.png
doc/salome/gui/GEOM/input/check_compound_of_blocks.doc
doc/salome/gui/GEOM/input/get_non_blocks.doc
idl/GEOM_Gen.idl
src/AdvancedEngine/AdvancedEngine_IOperations.cxx
src/BlockFix/BlockFix_CheckTool.cxx
src/BlockFix/BlockFix_CheckTool.hxx
src/GEOMGUI/GEOM_msg_en.ts
src/GEOMImpl/GEOMImpl_IBlocksOperations.cxx
src/GEOMImpl/GEOMImpl_IBlocksOperations.hxx
src/GEOM_I/GEOM_IBlocksOperations_i.cc [changed mode: 0755->0644]
src/GEOM_I/GEOM_IBlocksOperations_i.hh
src/GEOM_I_Superv/GEOM_Superv_i.cc
src/GEOM_SWIG/geomBuilder.py
src/MeasureGUI/MeasureGUI_CheckCompoundOfBlocksDlg.cxx
src/MeasureGUI/MeasureGUI_CheckCompoundOfBlocksDlg.h
src/MeasureGUI/MeasureGUI_GetNonBlocksDlg.cxx
src/MeasureGUI/MeasureGUI_GetNonBlocksDlg.h

old mode 100755 (executable)
new mode 100644 (file)
index 091b2c0..7a05b55
Binary files a/doc/salome/gui/GEOM/images/measures10.png and b/doc/salome/gui/GEOM/images/measures10.png differ
index 21e5218a40ea5f27255b8b25ccf88bde62af74ef..a9e064b5e852679d46b4477b1f71e6770a487c9e 100644 (file)
Binary files a/doc/salome/gui/GEOM/images/measures2.png and b/doc/salome/gui/GEOM/images/measures2.png differ
index 3068f49b196e2092a190ac13b284bb72b49b41bd..718c60f9044d47e8b0ccb09697c44ee201867b63 100644 (file)
Binary files a/doc/salome/gui/GEOM/images/measures2a.png and b/doc/salome/gui/GEOM/images/measures2a.png differ
index e9893b8e53f577be45e3d4e1b98516535a619a7a..7151dcff7b27f3e73980b9f277ac296e76c63d9f 100644 (file)
@@ -8,7 +8,10 @@ This operation checks whether a shape is a compound of glued blocks.
 
 To be considered as a compound of blocks, the given shape must satisfy the
 following conditions:
-- Each element of the compound should be a Block (6 faces and 12 edges);
+- Each element of the compound should be a Block (6 quadrangle faces);
+- Each quadrangle face is a face that has 1 wire with 4 edges. If there are
+more than 4 edges in a single wire and C1 continuity mode is switched on,
+a face is quadrangular if it has 4 bounds of C1 continuity.
 - Blocks can be connected only via an entire quadrangle face or an entire edge;
 - The compound should be connected;
 - Each couple of connecting quadrangle faces should be glued.
@@ -16,8 +19,10 @@ following conditions:
 
 In this dialog:
 
-- \b Object - the checked object. \b Selection button allows picking it in the viewer or in the object browser. 
-- \b Errors list informs of possible errors, for example:. 
+- \b Object - the checked object. \b Selection button allows picking it in the viewer or in the object browser.
+- <b>Use C1 criterion</b> - option that shitches on/off the C1 continuity mode.
+- <b>Angular Tolerance</b> - angular tolerance to check C1 continuity between neighbor edges in a wire.
+- \b Errors list informs of possible errors, for example:
        - Not a block;
        - Not glued;
        - Not connected;
@@ -26,7 +31,7 @@ In this dialog:
 
 
 \n <b>TUI Command:</b>
-<em>geompy.CheckCompoundOfBlocks(Compound).</em> Checks if the shape
+<em>geompy.CheckCompoundOfBlocks(Compound, theIsUseC1 = False, theAngTolerance = 1.e-12).</em> Checks if the shape
 is a valid compound of blocks. If it is true, then the validity flag
 is returned, and encountered errors are printed in the python console.
 
index 79f6ba0219ef9b3b633145648cad4ad9e74f8cb6..e2b566dd30431580ae53f5be5f6aac1fa4573e47 100644 (file)
@@ -5,24 +5,45 @@
 
 This operation retrieves all non-block solids and non-quadrangular faces from the selected shape.
 
-A non-block solid is a solid that does not have 6 faces, or has 6 faces, but some of them are not quadrangular.
+A block solid is a solid that has 6 quadrangular faces.
+
+A quadrangular face is a face that has 1 wire with 4 edges. If there are
+more than 4 edges in a single wire and C1 continuity mode is switched on,
+a face is quadrangular if it has 4 bounds of C1 continuity.
+
+All solids and faces from a shape that do not satisfy these conditions are
+returned by this operation.
 
 \image html measures2.png
 
-\b Preview option shows non block solids and faces in the viewer. 
+It is possible to select an \b Object to be explored, to check or uncheck
+<b>Use C1 criterion</b> option and to set the <b>Angular Tolerance</b>
+to check C1 continuity between neighbor edges in a wire.
 
-Press \b Apply or <b>Apply and Close</b> button to publish non block solids and faces in the Object
-Browser under the processed object. Solids and faces are published separately in two groups. 
+\b Preview option shows non-block solids and non-quadrangular faces in the viewer. 
+
+Press \b Apply or <b>Apply and Close</b> button to publish non-block solids
+and non-quadrangular faces in the Object Browser under the processed object.
+Solids and faces are published separately in two groups. 
 
 If no bad sub-shapes have been found, the corresponding warning is shown. 
 
 \image html measures2a.png
 
 \n <b>TUI Command:</b>
-<em>geompy.GetNonBlocks(Compound).</em> Returns a tuple of two GEOM_Objects. 
-
-The first object is a group of all non block solids; the second object is a group of all non
-quadrangular faces.
+<em>geompy.GetNonBlocks(theShape, theIsUseC1 = False, theAngTolerance = 1.e-12).</em> \n
+where \n
+\em theShape is the shape to explore, \n
+\em theIsUseC1 is the flag to check if there are 4 bounds on a face
+    taking into account C1 continuity, \n
+\em theAngTolerance the angular tolerance to check if two neighbor edges are
+    codirectional in the common vertex with this tolerance. This parameter is
+    used only if \em theIsUseC1 is set to True.
+
+This command returns a tuple of two GEOM_Objects. 
+
+The first object is a group of all non-block solids; the second object is a group
+of all non-quadrangular faces.
 
 See also a \ref tui_get_non_blocks_page "TUI example".
 
index a85830009c4e448fed8158f1c566bf3ffedc5623..2917f62cfb22424241cdf8fd88611578d3366552 100644 (file)
@@ -2770,10 +2770,14 @@ module GEOM
      *  - The glue between two quadrangle faces should be applied.
      *    \note Single block is also accepted as a valid compound of blocks.
      *  \param theCompound The compound to check.
+     *  \param theToleranceC1 the tolerance to check if two neighbor edges are
+     *         collinear in the common vertex with this tolerance. Negative
+     *         value means that C1 criterion is not used (old implementation).
      *  \param theErrors Structure, containing discovered errors and incriminated sub-shapes.
      *  \return TRUE, if the given shape is a compound of blocks.
      */
     boolean CheckCompoundOfBlocks (in GEOM_Object theCompound,
+                                   in double      theToleranceC1,
                                    out BCErrors   theErrors);
 
     /*!
@@ -2790,12 +2794,17 @@ module GEOM
      *  \brief Retrieve all non blocks solids and faces from a shape.
      *
      *  \param theShape The shape to explore.
+     *  \param theToleranceC1 the tolerance to check if two neighbor edges are
+     *         collinear in the common vertex with this tolerance. Negative
+     *         value means that C1 criterion is not used (old implementation).
      *  \param theNonQuads Output parameter. Group of all non quadrangular faces.
      *
      *  \return Group of all non block solids (= not 6 faces, or with 6
      *          faces, but with the presence of non-quadrangular faces).
      */
-    GEOM_Object GetNonBlocks (in GEOM_Object theShape, out GEOM_Object theNonQuads);
+    GEOM_Object GetNonBlocks (in GEOM_Object  theShape,
+                              in double       theToleranceC1,
+                              out GEOM_Object theNonQuads);
 
     /*!
      *  \brief Remove all seam and degenerated edges from \a theShape.
index 5d1b969995fee701998cb4b88ebbda543826ca3d..ad7650b00065f58628329c1c92108f9cc500c3c4 100644 (file)
@@ -1583,7 +1583,7 @@ bool AdvancedEngine_IOperations::MakePipeTShapePartition(Handle(GEOM_Object) the
 
     // Last verification: result should be a block
     std::list<GEOMImpl_IBlocksOperations::BCError> errList;
-    if (!myBlocksOperations->CheckCompoundOfBlocks(Te3,errList)) {
+    if (!myBlocksOperations->CheckCompoundOfBlocks(Te3, -1, errList)) {
       SetErrorCode("TShape is not a compound of block");
       return false;
     }
index 32c0714be12bc8ddfe723351794ca404b496ab0a..36e527550605b9afac35c33dc370a3fa6b2eef37 100644 (file)
 
 #include <BRep_Tool.hxx>
 
+#include <Geom_Curve.hxx>
+
+#include <gp_Pnt.hxx>
+#include <gp_Vec.hxx>
+
 #include <TopExp.hxx>
 #include <TopExp_Explorer.hxx>
 
 #include <TopoDS_Face.hxx>
 #include <TopoDS_Solid.hxx>
 #include <TopoDS_Shape.hxx>
+#include <TopoDS_Vertex.hxx>
 
 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
+#include <TopTools_IndexedMapOfShape.hxx>
 #include <TopTools_MapOfShape.hxx>
 #include <TopTools_ListOfShape.hxx>
 #include <TopTools_ListIteratorOfListOfShape.hxx>
@@ -49,6 +56,7 @@
 BlockFix_CheckTool::BlockFix_CheckTool( )
 {
   myHasCheck = Standard_False;
+  myAngTolerance = -1.;
   myPossibleBlocks.Clear();
 }
 
@@ -63,6 +71,17 @@ void BlockFix_CheckTool::SetShape(const TopoDS_Shape& aShape)
   myPossibleBlocks.Clear();
 }
 
+//=======================================================================
+//function : SetAngTolerance
+//purpose  :
+//=======================================================================
+void BlockFix_CheckTool::SetAngTolerance(const Standard_Real theTolerance)
+{
+  myHasCheck     = Standard_False;
+  myAngTolerance = theTolerance;
+  myPossibleBlocks.Clear();
+}
+
 //=======================================================================
 //function : Perform
 //purpose  :
@@ -159,7 +178,6 @@ void BlockFix_CheckTool::Perform()
     if (nbe < 12)
       IsBlock = Standard_False;
     if (nbe > 12) {
-      IsBlock = Standard_False;
       // check edges unification
       // creating map of edge faces
       TopTools_IndexedDataMapOfShapeListOfShape aMapEdgeFaces;
@@ -194,9 +212,19 @@ void BlockFix_CheckTool::Perform()
         Standard_Integer i = 1;
         for (; i <= aMapFacesEdges.Extent(); i++) {
           const TopTools_ListOfShape& ListEdges = aMapFacesEdges.FindFromIndex(i);
-          if (ListEdges.Extent() > 1) break;
+          if (ListEdges.Extent() > 1) {
+            if (myAngTolerance < 0.) {
+              break;
+            }
+
+            // Check if edges have C1 continuity.
+            if (!isC1(ListEdges)) {
+              break;
+            }
+          }
         }
         if (i <= aMapFacesEdges.Extent()) {
+          IsBlock = Standard_False;
           MayBeUE = Standard_True;
           break;
         }
@@ -265,3 +293,84 @@ void BlockFix_CheckTool::DumpCheckResult(Standard_OStream& S) const
     S<<"             number of impossible blocks = "<<nbtmp<<endl;
   }
 }
+
+//=======================================================================
+//function : isC1
+//purpose  :
+//=======================================================================
+Standard_Boolean BlockFix_CheckTool::isC1
+          (const TopTools_ListOfShape &theEdges) const
+{
+  // Fill the map vertex - list of ancestor edges
+  TopTools_IndexedDataMapOfShapeListOfShape aMapVE;
+  TopTools_ListIteratorOfListOfShape        anIter(theEdges);
+  TopTools_MapOfShape                       aMapFence;
+  Standard_Integer                          i;
+  Standard_Integer                          aNbVtx;
+
+  for (; anIter.More(); anIter.Next()) {
+    TopTools_IndexedMapOfShape  aMapVtx;
+    const TopoDS_Shape         &anEdge = anIter.Value();
+
+    if (aMapFence.Add(anEdge)) {
+      TopExp::MapShapes(anEdge, TopAbs_VERTEX, aMapVtx);
+      aNbVtx = aMapVtx.Extent();
+
+      for (i = 1; i <= aNbVtx; ++i) {
+        const TopoDS_Shape &aVtx = aMapVtx.FindKey(i);
+
+        if (!aMapVE.Contains(aVtx)) {
+          aMapVE.Add(aVtx, TopTools_ListOfShape());
+        }
+
+        aMapVE.ChangeFromKey(aVtx).Append(anEdge);
+      }
+    }
+  }
+
+  // Check C1 continuity.
+  Standard_Integer aNbEnds = 0;
+
+  for (i = 1, aNbVtx = aMapVE.Extent(); i <= aNbVtx; ++i) {
+    const TopTools_ListOfShape &anEdges  = aMapVE.FindFromIndex(i);
+    Standard_Integer            aNbEdges = anEdges.Extent();
+
+    if (aNbEdges == 1) {
+      ++aNbEnds;
+    } else if (aNbEdges == 2) {
+      TopoDS_Vertex      aCommonVtx = TopoDS::Vertex(aMapVE.FindKey(i));
+      TopoDS_Edge        anEdge1    = TopoDS::Edge(anEdges.First());
+      TopoDS_Edge        anEdge2    = TopoDS::Edge(anEdges.Last());
+      Standard_Real      aParam1    = BRep_Tool::Parameter(aCommonVtx, anEdge1);
+      Standard_Real      aParam2    = BRep_Tool::Parameter(aCommonVtx, anEdge2);
+      Standard_Real      aPar[2];
+      Handle(Geom_Curve) aCurve1    =
+        BRep_Tool::Curve(anEdge1, aPar[0], aPar[1]);
+      Handle(Geom_Curve) aCurve2    =
+        BRep_Tool::Curve(anEdge2, aPar[0], aPar[1]);
+      gp_Pnt             aPnt;
+      gp_Vec             aVec1;
+      gp_Vec             aVec2;
+
+      aCurve1->D1(aParam1, aPnt, aVec1);
+      aCurve2->D1(aParam2, aPnt, aVec2);
+
+      if (anEdge1.Orientation() != anEdge2.Orientation()) {
+        // Orientations are different. One vector should be reversed.
+        aVec1.Reverse();
+      }
+
+      const Standard_Real anAngle = aVec1.Angle(aVec2);
+
+      if (anAngle > myAngTolerance) {
+        // There is no C1 continuity.
+        break;
+      }
+    } else {
+      // Non-manifold case.
+      break;
+    }
+  }
+
+  return (i > aNbVtx && aNbEnds == 2);
+}
index 83bd5b3c158942595f2a0b051b29506ee126ca1b..66711433c9b2d94c7cf422121265f1ca292ddd6b 100644 (file)
@@ -30,6 +30,7 @@
 #include <Standard_OStream.hxx>
 
 class TopoDS_Shape;
+class TopTools_ListOfShape;
 
 #include <Standard.hxx>
 #include <Standard_Macro.hxx>
@@ -38,14 +39,20 @@ class BlockFix_CheckTool {
 
 public:
   Standard_EXPORT BlockFix_CheckTool();
-  Standard_EXPORT void SetShape(const TopoDS_Shape& aShape) ;
+  Standard_EXPORT void SetShape(const TopoDS_Shape& aShape);
+  Standard_EXPORT void SetAngTolerance(const Standard_Real theTolerance);
   Standard_EXPORT void Perform() ;
   Standard_EXPORT Standard_Integer NbPossibleBlocks() const;
   Standard_EXPORT TopoDS_Shape PossibleBlock(const Standard_Integer num) const;
   Standard_EXPORT void DumpCheckResult(Standard_OStream& S) const;
 
 private:
-  TopoDS_Shape myShape;
+
+  Standard_Boolean isC1(const TopTools_ListOfShape &theEdges) const;
+
+private:
+  TopoDS_Shape     myShape;
+  Standard_Real    myAngTolerance;
   Standard_Boolean myHasCheck;
   Standard_Integer myNbSolids;
   Standard_Integer myNbBlocks;
index 06cb15a74c071a260c0e206a28cc4996213dac93..22961d63e9467176c35a5c3d84894686ec8ac122 100644 (file)
@@ -407,6 +407,10 @@ Please, select face, shell or solid and try again</translation>
         <source>GEOM_NONBLOCKS</source>
         <translation>NonBlocksGroup</translation>
     </message>
+    <message>
+        <source>GEOM_USE_C1_CRITERION</source>
+        <translation>Use C1 criterion</translation>
+    </message>
     <message>
         <source>GEOM_CHECK_INFOS</source>
         <translation>Object And Its Topological Information</translation>
index cca9f381f3b9586673588f7f03f042312cf646e4..2a733c51e22ea048d7f36b67027af3e6a8dc3dde 100644 (file)
@@ -88,6 +88,7 @@
 #include <Bnd_Box.hxx>
 #include <GProp_GProps.hxx>
 
+#include <Geom_Curve.hxx>
 #include <Geom_Surface.hxx>
 #include <ShapeAnalysis_Surface.hxx>
 
 #include <Standard_Failure.hxx>
 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
 
+
+/**
+ * This function returns Standard_True if the face is quadrangular. It means
+ * that it has only 1 wire with 4 edges. If there are more then 4 edges in
+ * the wire and theToleranceC1 is not negative the new implementation is used.
+ * According to it the face is quadrangular if it is quadrangular according to
+ * an old implementation or if it has a single wire with more then 4 edges
+ * that form exactly 4 bounds of C1 continuity with the given tolerance.
+ *
+ * \param theFace the face to be checked
+ * \param theToleranceC1 if negative, it is not used; otherwise it is used
+ *        to check if two neighbor edges of face have C1 continuity.
+ * \return Standard_True if the face is quadrangular; Standard_False otherwise.
+ */
+static Standard_Boolean IsQuadrangle(const TopoDS_Face   &theFace,
+                                     const Standard_Real  theToleranceC1)
+{
+  TopExp_Explorer aFExp (theFace, TopAbs_WIRE);
+
+  if (!aFExp.More()) {
+    // no wire in the face
+    return Standard_False;
+  }
+
+  TopoDS_Shape aWire = aFExp.Current();
+
+  aFExp.Next();
+
+  if (aFExp.More()) {
+    // multiple wires in the face
+    return Standard_False;
+  }
+
+  // Check number of edges in the face
+  Standard_Integer    aNbEdges = 0;
+  TopTools_MapOfShape aMapEdges;
+  TopExp_Explorer     aWExp(aWire, TopAbs_EDGE);
+
+  for (; aWExp.More(); aWExp.Next()) {
+    if (aMapEdges.Add(aWExp.Current())) {
+      aNbEdges++;
+
+      if (aNbEdges > 4) {
+        break;
+      }
+    }
+  }
+
+  if (aNbEdges < 4) {
+    return Standard_False;
+  }
+
+  if (aNbEdges > 4) {
+    if (theToleranceC1 < 0.) {
+      return Standard_False;
+    }
+
+    // Check if a wire has 4 bounds of C1 continuity.
+    BRepTools_WireExplorer aWireExp(TopoDS::Wire(aWire), theFace);
+    TopTools_ListOfShape   anEdges;
+
+    for (aNbEdges = 0; aWireExp.More(); aWireExp.Next()) {
+      const TopoDS_Edge &anEdge = aWireExp.Current();
+
+      // Skip degenerated edges.
+      if (!BRep_Tool::Degenerated(anEdge)) {
+        anEdges.Append(anEdge);
+        ++aNbEdges;
+      }
+    }
+
+    if (aNbEdges < 4) {
+      return Standard_False;
+    }
+
+    // Compute number of sharp corners.
+    anEdges.Append(anEdges.First()); // To make a loop.
+
+    TopTools_ListIteratorOfListOfShape anIter(anEdges);
+    Standard_Real      aPar[2];
+    Standard_Integer   aNbCorners = 0;
+    TopoDS_Edge        anEdge1    = TopoDS::Edge(anEdges.First());
+    Handle(Geom_Curve) aCurve1    = BRep_Tool::Curve(anEdge1, aPar[0], aPar[1]);
+    Handle(Geom_Curve) aCurve2;
+    TopoDS_Edge        anEdge2;
+    TopoDS_Vertex      aCommonVtx;
+    gp_Pnt             aPnt;
+    gp_Vec             aVec1;
+    gp_Vec             aVec2;
+    Standard_Boolean   isReversed1 = (anEdge1.Orientation() == TopAbs_REVERSED);
+    Standard_Boolean   isReversed2;
+
+    for (anIter.Next(); anIter.More(); anIter.Next()) {
+      TopoDS_Edge anEdge2 = TopoDS::Edge(anIter.Value());
+
+      if (!TopExp::CommonVertex(anEdge1, anEdge2, aCommonVtx)) {
+        // NEVERREACHED
+        return Standard_False;
+      }
+
+      // Check the angle between tangent vectors of 2 curves at this point.
+      Standard_Real aParam1 = BRep_Tool::Parameter(aCommonVtx, anEdge1);
+      Standard_Real aParam2 = BRep_Tool::Parameter(aCommonVtx, anEdge2);
+
+      aCurve2     = BRep_Tool::Curve(anEdge2, aPar[0], aPar[1]);
+      isReversed2 = (anEdge2.Orientation() == TopAbs_REVERSED);
+      aCurve1->D1(aParam1, aPnt, aVec1);
+      aCurve2->D1(aParam2, aPnt, aVec2);
+
+      if (isReversed1) {
+        aVec1.Reverse();
+      }
+
+      if (isReversed2) {
+        aVec2.Reverse();
+      }
+      const Standard_Real anAngle = aVec1.Angle(aVec2);
+
+      if (anAngle > theToleranceC1) {
+        ++aNbCorners;
+
+        if (aNbCorners > 4) {
+          break;
+        }
+      }
+
+      // Go to the next couple of edges.
+      anEdge1     = anEdge2;
+      aCurve1     = aCurve2;
+      isReversed1 = isReversed2;
+    }
+
+    // Check the total number of corners.
+    if (aNbCorners != 4) {
+      return Standard_False;
+    }
+  }
+
+  return Standard_True;
+}
+
 //=============================================================================
 /*!
  *   constructor:
@@ -1647,7 +1789,8 @@ void GEOMImpl_IBlocksOperations::AddBlocksFrom (const TopoDS_Shape&   theShape,
                                                 TopTools_ListOfShape& BLO,
                                                 TopTools_ListOfShape& NOT,
                                                 TopTools_ListOfShape& EXT,
-                                                TopTools_ListOfShape& NOQ)
+                                                TopTools_ListOfShape& NOQ,
+                                                const Standard_Real   theToleranceC1)
 {
   TopAbs_ShapeEnum aType = theShape.ShapeType();
   switch (aType) {
@@ -1656,7 +1799,7 @@ void GEOMImpl_IBlocksOperations::AddBlocksFrom (const TopoDS_Shape&   theShape,
     {
       TopoDS_Iterator It (theShape);
       for (; It.More(); It.Next()) {
-        AddBlocksFrom(It.Value(), BLO, NOT, EXT, NOQ);
+        AddBlocksFrom(It.Value(), BLO, NOT, EXT, NOQ, theToleranceC1);
       }
     }
     break;
@@ -1665,6 +1808,7 @@ void GEOMImpl_IBlocksOperations::AddBlocksFrom (const TopoDS_Shape&   theShape,
       // Check, if there are seam or degenerated edges
       BlockFix_CheckTool aTool;
       aTool.SetShape(theShape);
+      aTool.SetAngTolerance(theToleranceC1);
       aTool.Perform();
       if (aTool.NbPossibleBlocks() > 0) {
         EXT.Append(theShape);
@@ -1676,41 +1820,12 @@ void GEOMImpl_IBlocksOperations::AddBlocksFrom (const TopoDS_Shape&   theShape,
         TopExp_Explorer expF (theShape, TopAbs_FACE);
 
         for (; expF.More(); expF.Next()) {
-          if (mapFaces.Add(expF.Current())) {
-            nbFaces++;
-            //0021483//if (nbFaces > 6) break;
+          TopoDS_Face aF = TopoDS::Face(expF.Current());
 
-            // get wire
-            TopoDS_Shape aF = expF.Current();
-            TopExp_Explorer wires (aF, TopAbs_WIRE);
-            if (!wires.More()) {
-              // no wire in the face
-              hasNonQuadr = Standard_True;
-              NOQ.Append(aF);//0021483
-              //0021483//break;
-              continue;
-            }
-            TopoDS_Shape aWire = wires.Current();
-            wires.Next();
-            if (wires.More()) {
-              // multiple wires in the face
-              hasNonQuadr = Standard_True;
-              NOQ.Append(aF);//0021483
-              //0021483//break;
-              continue;
-            }
+          if (mapFaces.Add(aF)) {
+            nbFaces++;
 
-            // Check number of edges in the face
-            Standard_Integer nbEdges = 0;
-            TopTools_MapOfShape mapEdges;
-            TopExp_Explorer expW (aWire, TopAbs_EDGE);
-            for (; expW.More(); expW.Next()) {
-              if (mapEdges.Add(expW.Current())) {
-                nbEdges++;
-                if (nbEdges > 4) break;
-              }
-            }
-            if (nbEdges != 4) {
+            if (!IsQuadrangle(aF, theToleranceC1)) {
               hasNonQuadr = Standard_True;
               NOQ.Append(aF);//0021483
             }
@@ -1732,34 +1847,10 @@ void GEOMImpl_IBlocksOperations::AddBlocksFrom (const TopoDS_Shape&   theShape,
       TopTools_MapOfShape mapFaces;
       TopExp_Explorer expF (theShape, TopAbs_FACE);
       for (; expF.More(); expF.Next()) {
-        if (mapFaces.Add(expF.Current())) {
-          // get wire
-          TopoDS_Shape aF = expF.Current();
-          TopExp_Explorer wires (aF, TopAbs_WIRE);
-          if (!wires.More()) {
-            // no wire in the face
-            NOQ.Append(aF);//0021483
-            continue;
-          }
-          TopoDS_Shape aWire = wires.Current();
-          wires.Next();
-          if (wires.More()) {
-            // multiple wires in the face
-            NOQ.Append(aF);//0021483
-            continue;
-          }
+        TopoDS_Face aF = TopoDS::Face(expF.Current());
 
-          // Check number of edges in the face
-          Standard_Integer nbEdges = 0;
-          TopTools_MapOfShape mapEdges;
-          TopExp_Explorer expW (aWire, TopAbs_EDGE);
-          for (; expW.More(); expW.Next()) {
-            if (mapEdges.Add(expW.Current())) {
-              nbEdges++;
-              if (nbEdges > 4) break;
-            }
-          }
-          if (nbEdges != 4) {
+        if (mapFaces.Add(aF)) {
+          if (!IsQuadrangle(aF, theToleranceC1)) {
             NOQ.Append(aF);//0021483
           }
         }
@@ -1771,99 +1862,6 @@ void GEOMImpl_IBlocksOperations::AddBlocksFrom (const TopoDS_Shape&   theShape,
   }
 }
 
-void AddBlocksFromOld (const TopoDS_Shape&   theShape,
-                       TopTools_ListOfShape& BLO,
-                       TopTools_ListOfShape& NOT,
-                       TopTools_ListOfShape& DEG,
-                       TopTools_ListOfShape& SEA)
-{
-  TopAbs_ShapeEnum aType = theShape.ShapeType();
-  switch (aType) {
-  case TopAbs_COMPOUND:
-  case TopAbs_COMPSOLID:
-    {
-      TopoDS_Iterator It (theShape);
-      for (; It.More(); It.Next()) {
-        AddBlocksFromOld(It.Value(), BLO, NOT, DEG, SEA);
-      }
-    }
-    break;
-  case TopAbs_SOLID:
-    {
-      TopTools_MapOfShape mapFaces;
-      TopExp_Explorer expF (theShape, TopAbs_FACE);
-      Standard_Integer nbFaces = 0;
-      Standard_Boolean hasNonQuadr = Standard_False;
-      Standard_Boolean hasDegenerated = Standard_False;
-      Standard_Boolean hasSeam = Standard_False;
-      for (; expF.More(); expF.Next()) {
-        if (mapFaces.Add(expF.Current())) {
-          nbFaces++;
-          if (nbFaces > 6) break;
-
-          // Check number of edges in the face
-          Standard_Integer nbEdges = 0;
-          TopTools_MapOfShape mapEdges;
-
-          // get wire
-          TopoDS_Shape aF = expF.Current();
-          TopExp_Explorer wires (aF, TopAbs_WIRE);
-          if (!wires.More()) {
-            // no wire in the face
-            hasNonQuadr = Standard_True;
-            break;
-          }
-          TopoDS_Shape aWire = wires.Current();
-          wires.Next();
-          if (wires.More()) {
-            // multiple wires in the face
-            hasNonQuadr = Standard_True;
-            break;
-          }
-
-          // iterate on wire
-          BRepTools_WireExplorer aWE (TopoDS::Wire(aWire), TopoDS::Face(aF));
-          for (; aWE.More(); aWE.Next(), nbEdges++) {
-            if (BRep_Tool::Degenerated(aWE.Current())) {
-              // degenerated edge found
-              hasDegenerated = Standard_True;
-//              break;
-            }
-            if (mapEdges.Contains(aWE.Current())) {
-              // seam edge found
-              hasSeam = Standard_True;
-//              break;
-            }
-            mapEdges.Add(aWE.Current());
-          }
-          if (nbEdges != 4) {
-            hasNonQuadr = Standard_True;
-          }
-        }
-      }
-      if (nbFaces == 6) {
-        if (hasDegenerated || hasSeam) {
-          if (hasDegenerated) {
-            DEG.Append(theShape);
-          }
-          if (hasSeam) {
-            SEA.Append(theShape);
-          }
-        } else if (hasNonQuadr) {
-          NOT.Append(theShape);
-        } else {
-          BLO.Append(theShape);
-        }
-      } else {
-        NOT.Append(theShape);
-      }
-    }
-    break;
-  default:
-    NOT.Append(theShape);
-  }
-}
-
 #define REL_NOT_CONNECTED 0
 #define REL_OK            1
 #define REL_NOT_GLUED     2
@@ -2086,158 +2084,6 @@ Standard_Boolean HasAnyConnection (const Standard_Integer         theBlockIndex,
   return Standard_False;
 }
 
-//=============================================================================
-/*!
- *  CheckCompoundOfBlocksOld
- */
-//=============================================================================
-Standard_Boolean GEOMImpl_IBlocksOperations::CheckCompoundOfBlocksOld
-                                                (Handle(GEOM_Object) theCompound,
-                                                 std::list<BCError>&      theErrors)
-{
-  SetErrorCode(KO);
-
-  if (theCompound.IsNull()) return Standard_False;
-  TopoDS_Shape aBlockOrComp = theCompound->GetValue();
-
-  Standard_Boolean isCompOfBlocks = Standard_True;
-
-  // Map sub-shapes and their indices
-  TopTools_IndexedMapOfShape anIndices;
-  TopExp::MapShapes(aBlockOrComp, anIndices);
-
-  // 1. Report non-blocks
-  TopTools_ListOfShape NOT; // Not blocks
-  TopTools_ListOfShape DEG; // Hexahedral solids, having degenerated edges
-  TopTools_ListOfShape SEA; // Hexahedral solids, having seam edges
-  TopTools_ListOfShape BLO; // All blocks from the given compound
-  AddBlocksFromOld(aBlockOrComp, BLO, NOT, DEG, SEA);
-
-  if (NOT.Extent() > 0) {
-    isCompOfBlocks = Standard_False;
-    BCError anErr;
-    anErr.error = NOT_BLOCK;
-    TopTools_ListIteratorOfListOfShape it (NOT);
-    for (; it.More(); it.Next()) {
-      anErr.incriminated.push_back(anIndices.FindIndex(it.Value()));
-    }
-    theErrors.push_back(anErr);
-  }
-
-  if (DEG.Extent() > 0 || SEA.Extent() > 0) {
-    isCompOfBlocks = Standard_False;
-    BCError anErr;
-    anErr.error = EXTRA_EDGE;
-
-    TopTools_ListIteratorOfListOfShape itDEG (DEG);
-    for (; itDEG.More(); itDEG.Next()) {
-      anErr.incriminated.push_back(anIndices.FindIndex(itDEG.Value()));
-    }
-
-    TopTools_ListIteratorOfListOfShape itSEA (SEA);
-    for (; itSEA.More(); itSEA.Next()) {
-      anErr.incriminated.push_back(anIndices.FindIndex(itSEA.Value()));
-    }
-
-    theErrors.push_back(anErr);
-  }
-
-  Standard_Integer nbBlocks = BLO.Extent();
-  if (nbBlocks == 0) {
-    isCompOfBlocks = Standard_False;
-    SetErrorCode(OK);
-    return isCompOfBlocks;
-  }
-  if (nbBlocks == 1) {
-    SetErrorCode(OK);
-    return isCompOfBlocks;
-  }
-
-  // Convert list of blocks into array for easy and fast access
-  Standard_Integer ibl = 1;
-  TopTools_Array1OfShape aBlocks (1, nbBlocks);
-  TopTools_ListIteratorOfListOfShape BLOit (BLO);
-  for (; BLOit.More(); BLOit.Next(), ibl++) {
-    aBlocks.SetValue(ibl, BLOit.Value());
-  }
-
-  // 2. Find relations between all blocks,
-  //    report connection errors (NOT_GLUED and INVALID_CONNECTION)
-  TColStd_Array2OfInteger aRelations (1, nbBlocks, 1, nbBlocks);
-  aRelations.Init(REL_NOT_CONNECTED);
-
-  Standard_Integer row = 1;
-  for (row = 1; row <= nbBlocks; row++) {
-    TopoDS_Shape aBlock = aBlocks.Value(row);
-
-    Standard_Integer col = row + 1;
-    for (; col <= nbBlocks; col++) {
-      Standard_Integer aRel = BlocksRelation(aBlock, aBlocks.Value(col));
-      if (aRel != REL_NOT_CONNECTED) {
-        aRelations.SetValue(row, col, aRel);
-        aRelations.SetValue(col, row, aRel);
-        if (aRel == REL_NOT_GLUED) {
-          // report connection error
-          isCompOfBlocks = Standard_False;
-          BCError anErr;
-          anErr.error = NOT_GLUED;
-          anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(row)));
-          anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(col)));
-          theErrors.push_back(anErr);
-        } else if (aRel == REL_COLLISION_VV ||
-                   aRel == REL_COLLISION_FF ||
-                   aRel == REL_COLLISION_EE ||
-                   aRel == REL_UNKNOWN) {
-          // report connection error
-          isCompOfBlocks = Standard_False;
-          BCError anErr;
-          anErr.error = INVALID_CONNECTION;
-          anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(row)));
-          anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(col)));
-          theErrors.push_back(anErr);
-        } else {
-        }
-      }
-    }
-  }
-
-  // 3. Find largest set of connected (good connection or not glued) blocks
-  TColStd_MapOfInteger aProcessedMap;
-  TColStd_MapOfInteger aLargestSet;
-  TColStd_MapOfInteger aCurrentSet;
-  for (ibl = 1; ibl <= nbBlocks; ibl++) {
-    if (!aProcessedMap.Contains(ibl)) {
-      aCurrentSet.Clear();
-      FindConnected(ibl, aRelations, aProcessedMap, aCurrentSet);
-      if (aCurrentSet.Extent() > aLargestSet.Extent()) {
-        aLargestSet = aCurrentSet;
-      }
-    }
-  }
-
-  // 4. Report all blocks, isolated from <aLargestSet>
-  BCError anErr;
-  anErr.error = NOT_CONNECTED;
-  Standard_Boolean hasIsolated = Standard_False;
-  for (ibl = 1; ibl <= nbBlocks; ibl++) {
-    if (!aLargestSet.Contains(ibl)) {
-      aProcessedMap.Clear();
-      if (!HasAnyConnection(ibl, aLargestSet, aRelations, aProcessedMap)) {
-        // report connection absence
-        hasIsolated = Standard_True;
-        anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(ibl)));
-      }
-    }
-  }
-  if (hasIsolated) {
-    isCompOfBlocks = Standard_False;
-    theErrors.push_back(anErr);
-  }
-
-  SetErrorCode(OK);
-  return isCompOfBlocks;
-}
-
 //=============================================================================
 /*!
  *  PrintBCErrors
@@ -2294,6 +2140,7 @@ TCollection_AsciiString GEOMImpl_IBlocksOperations::PrintBCErrors
 //=============================================================================
 Standard_Boolean GEOMImpl_IBlocksOperations::CheckCompoundOfBlocks
                                               (Handle(GEOM_Object) theCompound,
+                                               const Standard_Real theToleranceC1,
                                                std::list<BCError>& theErrors)
 {
   SetErrorCode(KO);
@@ -2312,7 +2159,7 @@ Standard_Boolean GEOMImpl_IBlocksOperations::CheckCompoundOfBlocks
   TopTools_ListOfShape EXT; // Hexahedral solids, having degenerated and/or seam edges
   TopTools_ListOfShape BLO; // All blocks from the given compound
   TopTools_ListOfShape NOQ; // All non-quadrangular faces
-  AddBlocksFrom(aBlockOrComp, BLO, NOT, EXT, NOQ);
+  AddBlocksFrom(aBlockOrComp, BLO, NOT, EXT, NOQ, theToleranceC1);
 
   // Report non-blocks
   if (NOT.Extent() > 0) {
@@ -2478,7 +2325,8 @@ Standard_Boolean GEOMImpl_IBlocksOperations::CheckCompoundOfBlocks
  */
 //=============================================================================
 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetNonBlocks
-                                     (Handle(GEOM_Object) theShape,
+                                     (Handle(GEOM_Object)  theShape,
+                                      const Standard_Real  theToleranceC1,
                                       Handle(GEOM_Object)& theNonQuads)
 {
   SetErrorCode(KO);
@@ -2491,7 +2339,7 @@ Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetNonBlocks
   TopTools_ListOfShape NOT; // Not blocks
   TopTools_ListOfShape EXT; // Hexahedral solids, having degenerated and/or seam edges
   TopTools_ListOfShape NOQ; // All non-quadrangular faces
-  AddBlocksFrom(aShape, BLO, NOT, EXT, NOQ);
+  AddBlocksFrom(aShape, BLO, NOT, EXT, NOQ, theToleranceC1);
 
   if (NOT.IsEmpty() && EXT.IsEmpty() && NOQ.IsEmpty()) {
     SetErrorCode("NOT_FOUND_ANY");
index 8a03b6e23f5bc6d5c62958a1922e9e37d7e47f26..568872a083e0e260570349c79c1a5262b78979f7 100644 (file)
@@ -125,16 +125,15 @@ class GEOMImpl_IBlocksOperations : public GEOM_IOperations {
     std::list<int>   incriminated;
   };
 
-  Standard_EXPORT Standard_Boolean CheckCompoundOfBlocksOld (Handle(GEOM_Object) theCompound,
-                                                             std::list<BCError>& theErrors);
-
   Standard_EXPORT Standard_Boolean CheckCompoundOfBlocks (Handle(GEOM_Object) theCompound,
+                                                          const Standard_Real theToleranceC1,
                                                           std::list<BCError>& theErrors);
 
   Standard_EXPORT TCollection_AsciiString PrintBCErrors (Handle(GEOM_Object)       theCompound,
                                                          const std::list<BCError>& theErrors);
 
-  Standard_EXPORT Handle(GEOM_Object) GetNonBlocks (Handle(GEOM_Object) theShape,
+  Standard_EXPORT Handle(GEOM_Object) GetNonBlocks (Handle(GEOM_Object)  theShape,
+                                                    const Standard_Real  theToleranceC1,
                                                     Handle(GEOM_Object)& theNonQuads);
 
   Standard_EXPORT Handle(GEOM_Object) RemoveExtraEdges (Handle(GEOM_Object) theShape,
@@ -148,7 +147,8 @@ class GEOMImpl_IBlocksOperations : public GEOM_IOperations {
                                              TopTools_ListOfShape& BLO,
                                              TopTools_ListOfShape& NOT,
                                              TopTools_ListOfShape& EXT,
-                                             TopTools_ListOfShape& NOQ);
+                                             TopTools_ListOfShape& NOQ,
+                                             const Standard_Real  theToleranceC1 = -1.);
 
   // Extract blocks from blocks compounds
   Standard_EXPORT Handle(TColStd_HSequenceOfTransient) ExplodeCompoundOfBlocks
old mode 100755 (executable)
new mode 100644 (file)
index 55a9c3c..513ffa7
@@ -614,6 +614,7 @@ CORBA::Boolean GEOM_IBlocksOperations_i::IsCompoundOfBlocks
 //=============================================================================
 CORBA::Boolean GEOM_IBlocksOperations_i::CheckCompoundOfBlocks
                                           (GEOM::GEOM_Object_ptr theCompound,
+                                           const CORBA::Double   theToleranceC1,
                                            GEOM::GEOM_IBlocksOperations::BCErrors_out theErrors)
 {
   CORBA::Boolean isComp = false;
@@ -627,7 +628,8 @@ CORBA::Boolean GEOM_IBlocksOperations_i::CheckCompoundOfBlocks
 
   //Check
   std::list<GEOMImpl_IBlocksOperations::BCError> errList;
-  isComp = GetOperations()->CheckCompoundOfBlocks(aCompound, errList);
+  isComp = GetOperations()->CheckCompoundOfBlocks
+    (aCompound, theToleranceC1, errList);
   if (!GetOperations()->IsDone())
     return isComp;
 
@@ -749,6 +751,7 @@ char* GEOM_IBlocksOperations_i::PrintBCErrors
 //=============================================================================
 GEOM::GEOM_Object_ptr GEOM_IBlocksOperations_i::GetNonBlocks
                                       (GEOM::GEOM_Object_ptr theShape,
+                                       const CORBA::Double   theToleranceC1,
                                        GEOM::GEOM_Object_out theNonQuads)
 {
   GEOM::GEOM_Object_var aGEOMObject;
@@ -765,7 +768,8 @@ GEOM::GEOM_Object_ptr GEOM_IBlocksOperations_i::GetNonBlocks
 
   //Get the result
   Handle(GEOM_Object) aFaces;
-  Handle(GEOM_Object) anObject = GetOperations()->GetNonBlocks(aShape, aFaces);
+  Handle(GEOM_Object) anObject =
+    GetOperations()->GetNonBlocks(aShape, theToleranceC1, aFaces);
   if (!GetOperations()->IsDone())
     return aGEOMObject._retn();
 
index fa457b56692605c2ded47949bf4fbd490ce4e453..7755eeb640b7b5828af10fb044f79e70a7952d66 100644 (file)
@@ -116,12 +116,14 @@ class GEOM_I_EXPORT GEOM_IBlocksOperations_i :
                                     CORBA::Long&          theNbBlocks);
 
   CORBA::Boolean CheckCompoundOfBlocks (GEOM::GEOM_Object_ptr theCompound,
+                                        const CORBA::Double   theToleranceC1,
                                        GEOM::GEOM_IBlocksOperations::BCErrors_out theErrors);
 
   char* PrintBCErrors (GEOM::GEOM_Object_ptr theCompound,
                       const GEOM::GEOM_IBlocksOperations::BCErrors& theErrors);
 
   GEOM::GEOM_Object_ptr GetNonBlocks (GEOM::GEOM_Object_ptr theShape,
+                                      const CORBA::Double   theToleranceC1,
                                       GEOM::GEOM_Object_out theNonQuads);
 
   GEOM::GEOM_Object_ptr RemoveExtraEdges (GEOM::GEOM_Object_ptr theShape,
index 867a5c6f7cea632c19746847fad64ae03b00bc4a..0324e6e59bda01f69228d32c2c90427ebd9af8e7 100644 (file)
@@ -2713,7 +2713,7 @@ CORBA::Boolean GEOM_Superv_i::CheckCompoundOfBlocks
   beginService( " GEOM_Superv_i::CheckCompoundOfBlocks" );
   MESSAGE("GEOM_Superv_i::CheckCompoundOfBlocks");
   getBlocksOp();
-  CORBA::Boolean aRes = myBlocksOp->CheckCompoundOfBlocks(theCompound, theErrors);
+  CORBA::Boolean aRes = myBlocksOp->CheckCompoundOfBlocks(theCompound, -1., theErrors);
   endService( " GEOM_Superv_i::CheckCompoundOfBlocks" );
   return aRes;
 }
index bb6519a93548cd0f39c18123377679222a368bb1..be89ae1a32728d249a204d974d8b9cf3b21f646a 100644 (file)
@@ -80,7 +80,7 @@
 ## # create and publish cylinder
 ## cyl = geompy.MakeCylinderRH(100, 100, "cylinder")
 ## # get non blocks from cylinder
-## g1, g2 = geompy.GetNonBlocks(cyl, "nonblock")
+## g1, g2 = geompy.GetNonBlocks(cyl, theName="nonblock")
 ## @endcode
 ##
 ## Above example will publish both result compounds (first with non-hexa solids and
@@ -88,7 +88,7 @@
 ## However, if second command is invoked as
 ##
 ## @code
-## g1, g2 = geompy.GetNonBlocks(cyl, ("nonhexa", "nonquad"))
+## g1, g2 = geompy.GetNonBlocks(cyl, theName=("nonhexa", "nonquad"))
 ## @endcode
 ##
 ## ... the first compound will be published with "nonhexa" name, and second will be named "nonquad".
@@ -11425,36 +11425,62 @@ class geomBuilder(object, GEOM._objref_GEOM_Gen):
         ## Check, if the compound of blocks is given.
         #  To be considered as a compound of blocks, the
         #  given shape must satisfy the following conditions:
-        #  - Each element of the compound should be a Block (6 faces and 12 edges).
+        #  - Each element of the compound should be a Block (6 faces).
+        #  - Each face should be a quadrangle, i.e. it should have only 1 wire
+        #       with 4 edges. If <VAR>theIsUseC1</VAR> is set to True and
+        #       there are more than 4 edges in the only wire of a face,
+        #       this face is considered to be quadrangle if it has 4 bounds
+        #       (1 or more edge) of C1 continuity.
         #  - A connection between two Blocks should be an entire quadrangle face or an entire edge.
         #  - The compound should be connexe.
         #  - The glue between two quadrangle faces should be applied.
         #  @param theCompound The compound to check.
+        #  @param theIsUseC1 Flag to check if there are 4 bounds on a face
+        #         taking into account C1 continuity.
+        #  @param theAngTolerance the angular tolerance to check if two neighbor
+        #         edges are codirectional in the common vertex with this
+        #         tolerance. This parameter is used only if
+        #         <VAR>theIsUseC1</VAR> is set to True.
         #  @return TRUE, if the given shape is a compound of blocks.
         #  If theCompound is not valid, prints all discovered errors.
         #
         #  @ref tui_measurement_tools_page "Example 1"
         #  \n @ref swig_CheckCompoundOfBlocks "Example 2"
         @ManageTransactions("BlocksOp")
-        def CheckCompoundOfBlocks(self,theCompound):
+        def CheckCompoundOfBlocks(self,theCompound, theIsUseC1 = False,
+                                  theAngTolerance = 1.e-12):
             """
             Check, if the compound of blocks is given.
             To be considered as a compound of blocks, the
             given shape must satisfy the following conditions:
-            - Each element of the compound should be a Block (6 faces and 12 edges).
+            - Each element of the compound should be a Block (6 faces).
+            - Each face should be a quadrangle, i.e. it should have only 1 wire
+                 with 4 edges. If theIsUseC1 is set to True and
+                 there are more than 4 edges in the only wire of a face,
+                 this face is considered to be quadrangle if it has 4 bounds
+                 (1 or more edge) of C1 continuity.
             - A connection between two Blocks should be an entire quadrangle face or an entire edge.
             - The compound should be connexe.
             - The glue between two quadrangle faces should be applied.
 
             Parameters:
                 theCompound The compound to check.
+                theIsUseC1 Flag to check if there are 4 bounds on a face
+                           taking into account C1 continuity.
+                theAngTolerance the angular tolerance to check if two neighbor
+                           edges are codirectional in the common vertex with this
+                           tolerance. This parameter is used only if
+                           theIsUseC1 is set to True.
 
             Returns:
                 TRUE, if the given shape is a compound of blocks.
                 If theCompound is not valid, prints all discovered errors.
             """
             # Example: see GEOM_Spanner.py
-            (IsValid, BCErrors) = self.BlocksOp.CheckCompoundOfBlocks(theCompound)
+            aTolerance = -1.0
+            if theIsUseC1:
+                aTolerance = theAngTolerance
+            (IsValid, BCErrors) = self.BlocksOp.CheckCompoundOfBlocks(theCompound, aTolerance)
             RaiseIfFailed("CheckCompoundOfBlocks", self.BlocksOp)
             if IsValid == 0:
                 Descr = self.BlocksOp.PrintBCErrors(theCompound, BCErrors)
@@ -11463,6 +11489,12 @@ class geomBuilder(object, GEOM._objref_GEOM_Gen):
 
         ## Retrieve all non blocks solids and faces from \a theShape.
         #  @param theShape The shape to explore.
+        #  @param theIsUseC1 Flag to check if there are 4 bounds on a face
+        #         taking into account C1 continuity.
+        #  @param theAngTolerance the angular tolerance to check if two neighbor
+        #         edges are codirectional in the common vertex with this
+        #         tolerance. This parameter is used only if
+        #         <VAR>theIsUseC1</VAR> is set to True.
         #  @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.
@@ -11470,17 +11502,27 @@ class geomBuilder(object, GEOM._objref_GEOM_Gen):
         #  @return A tuple of two GEOM_Objects. The first object is a group of all
         #          non block solids (= not 6 faces, or with 6 faces, but with the
         #          presence of non-quadrangular faces). The second object is a
-        #          group of all non quadrangular faces.
+        #          group of all non quadrangular faces (= faces with more then
+        #          1 wire or, if <VAR>theIsUseC1</VAR> is set to True, faces
+        #          with 1 wire with not 4 edges that do not form 4 bounds of
+        #          C1 continuity).
         #
         #  @ref tui_measurement_tools_page "Example 1"
         #  \n @ref swig_GetNonBlocks "Example 2"
         @ManageTransactions("BlocksOp")
-        def GetNonBlocks (self, theShape, theName=None):
+        def GetNonBlocks (self, theShape, theIsUseC1 = False,
+                          theAngTolerance = 1.e-12, theName=None):
             """
             Retrieve all non blocks solids and faces from theShape.
 
             Parameters:
                 theShape The shape to explore.
+                theIsUseC1 Flag to check if there are 4 bounds on a face
+                           taking into account C1 continuity.
+                theAngTolerance the angular tolerance to check if two neighbor
+                           edges are codirectional in the common vertex with this
+                           tolerance. This parameter is used only if
+                           theIsUseC1 is set to True.
                 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.
@@ -11489,13 +11531,19 @@ class geomBuilder(object, GEOM._objref_GEOM_Gen):
                 A tuple of two GEOM_Objects. The first object is a group of all
                 non block solids (= not 6 faces, or with 6 faces, but with the
                 presence of non-quadrangular faces). The second object is a
-                group of all non quadrangular faces.
+                group of all non quadrangular faces (= faces with more then
+                1 wire or, if <VAR>theIsUseC1</VAR> is set to True, faces
+                with 1 wire with not 4 edges that do not form 4 bounds of
+                C1 continuity).
 
             Usage:
                 (res_sols, res_faces) = geompy.GetNonBlocks(myShape1)
             """
             # Example: see GEOM_Spanner.py
-            aTuple = self.BlocksOp.GetNonBlocks(theShape)
+            aTolerance = -1.0
+            if theIsUseC1:
+                aTolerance = theAngTolerance
+            aTuple = self.BlocksOp.GetNonBlocks(theShape, aTolerance)
             RaiseIfFailed("GetNonBlocks", self.BlocksOp)
             self._autoPublish(aTuple, theName, ("groupNonHexas", "groupNonQuads"))
             return aTuple
index 8d7961412765ad02225d303a9b7aff54f7afb835..eee95b56b0fe355eff832d3fde1757bfae8fe127 100644 (file)
@@ -26,7 +26,6 @@
 //
 #include "MeasureGUI.h"
 #include "MeasureGUI_CheckCompoundOfBlocksDlg.h"
-#include "MeasureGUI_Widgets.h"
 
 #include <SUIT_Session.h>
 #include <SUIT_ResourceMgr.h>
@@ -43,6 +42,8 @@
 #include <GEOMBase.h>
 #include <GEOMImpl_Types.hxx>
 
+#include <QListWidget>
+
 #define TEXTEDIT_FONT_FAMILY "Courier"
 #define TEXTEDIT_FONT_SIZE 11
 
 //            true to construct a modal dialog.
 //=================================================================================
 MeasureGUI_CheckCompoundOfBlocksDlg::MeasureGUI_CheckCompoundOfBlocksDlg( GeometryGUI* GUI, QWidget* parent )
-  : GEOMBase_Skeleton( GUI, parent, false )
+  : GEOMBase_Skeleton(GUI, parent, false),
+    myObjectName     (0),
+    mySelButton      (0),
+    myUseC1Check     (0),
+    myTolLbl         (0),
+    mySpinTol        (0),
+    myTextView       (0),
+    myListBox1       (0),
+    myListBox2       (0)
 {
   SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr();
   QPixmap image0( aResMgr->loadPixmap( "GEOM", tr( "ICON_DLG_CHECK_COMPOUND_OF_BLOCKS" ) ) );
@@ -70,29 +79,55 @@ MeasureGUI_CheckCompoundOfBlocksDlg::MeasureGUI_CheckCompoundOfBlocksDlg( Geomet
   mainFrame()->RadioButton3->setAttribute( Qt::WA_DeleteOnClose );
   mainFrame()->RadioButton3->close();
 
-  myGrp = new MeasureGUI_1Sel1TextView2ListBox( centralWidget() );
-  myGrp->GroupBox1->setTitle( tr( "GEOM_CHECK_INFOS" ) );
-  myGrp->TextLabel1->setText( tr( "GEOM_OBJECT" ) );
-
-  myGrp->TextView1->setReadOnly( true );
-  QFont aFont( TEXTEDIT_FONT_FAMILY, TEXTEDIT_FONT_SIZE );
-  aFont.setStyleHint( QFont::TypeWriter, QFont::PreferAntialias );
-  myGrp->TextView1->setFont( aFont );
-
-  myGrp->PushButton1->setIcon( image1 );
-  myGrp->LineEdit1->setReadOnly( true );
-
-  myGrp->TextLabel2->setText( tr( "GEOM_CHECK_BLOCKS_COMPOUND_ERRORS" ) );
-  myGrp->TextLabel3->setText( tr( "GEOM_CHECK_BLOCKS_COMPOUND_SUBSHAPES" ) );
-
-  myGrp->ListBox2->setSelectionMode( QAbstractItemView::ExtendedSelection );
+  QGroupBox   *aGrpParams    =
+    new QGroupBox(tr("GEOM_CHECK_INFOS"), centralWidget());
+  QGridLayout *aParamsLayout = new QGridLayout(aGrpParams);
+  QLabel      *anObjLbl      = new QLabel(tr("GEOM_OBJECT"), aGrpParams);
+  QLabel      *anErrorsLbl   =
+    new QLabel(tr("GEOM_CHECK_BLOCKS_COMPOUND_ERRORS"), aGrpParams);
+  QLabel      *aNonBlocksLbl =
+    new QLabel(tr("GEOM_CHECK_BLOCKS_COMPOUND_SUBSHAPES"), aGrpParams);
+
+  myObjectName = new QLineEdit(aGrpParams);
+  mySelButton  = new QPushButton(aGrpParams);
+  myUseC1Check = new QCheckBox(tr("GEOM_USE_C1_CRITERION"), aGrpParams);
+  myTolLbl     = new QLabel(tr("GEOM_ANGULAR_TOLERANCE"), aGrpParams);
+  mySpinTol    = new SalomeApp_DoubleSpinBox(aGrpParams);
+  myTextView   = new QTextBrowser(aGrpParams);
+  myListBox1   = new QListWidget(aGrpParams);
+  myListBox2   = new QListWidget(aGrpParams);
+
+  myObjectName->setReadOnly(true);
+  mySelButton->setIcon(image1);
+  mySelButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+  myUseC1Check->setText(tr("GEOM_USE_C1_CRITERION"));
+  myUseC1Check->setChecked(true);
+  myTextView->setReadOnly(true);
+  myListBox2->setSelectionMode(QAbstractItemView::ExtendedSelection);
+
+  // Set text view font.
+  QFont aFont(TEXTEDIT_FONT_FAMILY, TEXTEDIT_FONT_SIZE);
+
+  aFont.setStyleHint(QFont::TypeWriter, QFont::PreferAntialias);
+  myTextView->setFont(aFont);
+
+  aParamsLayout->setMargin(9);
+  aParamsLayout->setSpacing(6);
+  aParamsLayout->addWidget(anObjLbl,      0, 0);
+  aParamsLayout->addWidget(mySelButton,   0, 1);
+  aParamsLayout->addWidget(myObjectName,  0, 2);
+  aParamsLayout->addWidget(myUseC1Check,  1, 0, 1, 3);
+  aParamsLayout->addWidget(myTolLbl,      2, 0);
+  aParamsLayout->addWidget(mySpinTol,     2, 1, 1, 2);
+  aParamsLayout->addWidget(myTextView,    3, 0, 1, 3);
+  aParamsLayout->addWidget(anErrorsLbl,   4, 0);
+  aParamsLayout->addWidget(myListBox1,    5, 0, 1, 2);
+  aParamsLayout->addWidget(aNonBlocksLbl, 4, 2);
+  aParamsLayout->addWidget(myListBox2,    5, 2);
 
   QVBoxLayout* layout = new QVBoxLayout( centralWidget() );
   layout->setMargin( 0 ); layout->setSpacing( 6 );
-  layout->addWidget( myGrp );
-
-  connect( myGrp->ListBox1, SIGNAL( itemSelectionChanged() ), SLOT( onErrorsListSelectionChanged() ) );
-  connect( myGrp->ListBox2, SIGNAL( itemSelectionChanged() ), SLOT( onSubShapesListSelectionChanged() ) );
+  layout->addWidget( aGrpParams );
 
   /***************************************************************/
 
@@ -116,14 +151,24 @@ MeasureGUI_CheckCompoundOfBlocksDlg::~MeasureGUI_CheckCompoundOfBlocksDlg()
 //=================================================================================
 void MeasureGUI_CheckCompoundOfBlocksDlg::Init()
 {
-  myEditCurrentArgument = myGrp->LineEdit1;
+  /* init variables */
+  double SpecificStep = 0.0001;
+  double aDefaultTol  = Precision::Angular();
+
+  initSpinBox(mySpinTol, aDefaultTol, MAX_NUMBER, SpecificStep, "ang_tol_precision");
+  mySpinTol->setValue(aDefaultTol);
+  myEditCurrentArgument = myObjectName;
 
   // signals and slots connections
   connect( buttonOk(),    SIGNAL( clicked() ), this, SLOT( ClickOnOk() ) );
   connect( buttonApply(), SIGNAL( clicked() ), this, SLOT( ClickOnApply() ) );
 
-  connect( myGrp->LineEdit1,   SIGNAL( returnPressed() ), this, SLOT( LineEditReturnPressed() ) );
-  connect( myGrp->PushButton1, SIGNAL( clicked() ),       this, SLOT( SetEditCurrentArgument() ) );
+  connect(myObjectName, SIGNAL(returnPressed()),        this, SLOT(LineEditReturnPressed()));
+  connect(mySelButton,  SIGNAL(clicked()),              this, SLOT(SetEditCurrentArgument()));
+  connect(myListBox1,   SIGNAL(itemSelectionChanged()), this, SLOT(onErrorsListSelectionChanged()));
+  connect(myListBox2,   SIGNAL(itemSelectionChanged()), this, SLOT(onSubShapesListSelectionChanged()));
+  connect(myUseC1Check, SIGNAL(clicked()),              this, SLOT(SetUseC1Tolerance()));
+  connect(mySpinTol,    SIGNAL(valueChanged(double)),   this, SLOT(processObject()));
 
   connect( myGeomGUI->getApp()->selectionMgr(), SIGNAL( currentSelectionChanged() ),
            this, SLOT( SelectionIntoArgument() ) );
@@ -172,7 +217,7 @@ void MeasureGUI_CheckCompoundOfBlocksDlg::SelectionIntoArgument()
   aSelMgr->selectedObjects(aSelList);
 
   if (aSelList.Extent() != 1) {
-    myGrp->LineEdit1->setText( "" );
+    myObjectName->setText( "" );
     processObject();
     return;
   }
@@ -181,13 +226,13 @@ void MeasureGUI_CheckCompoundOfBlocksDlg::SelectionIntoArgument()
     GEOMBase::ConvertIOinGEOMObject( aSelList.First() );
 
   if ( aSelectedObject->_is_nil() ) {
-    myGrp->LineEdit1->setText( "" );
+    myObjectName->setText( "" );
     processObject();
     return;
   }
 
   myObj = aSelectedObject;
-  myGrp->LineEdit1->setText( GEOMBase::GetName( myObj ) );
+  myObjectName->setText( GEOMBase::GetName( myObj ) );
   processObject();
   DISPLAY_PREVIEW_MACRO;
 }
@@ -198,11 +243,22 @@ void MeasureGUI_CheckCompoundOfBlocksDlg::SelectionIntoArgument()
 //=================================================================================
 void MeasureGUI_CheckCompoundOfBlocksDlg::SetEditCurrentArgument()
 {
-  myGrp->LineEdit1->setFocus();
-  myEditCurrentArgument = myGrp->LineEdit1;
+  myObjectName->setFocus();
+  myEditCurrentArgument = myObjectName;
   SelectionIntoArgument();
 }
 
+//=================================================================================
+// function : SetUseC1Tolerance()
+// purpose  :
+//=================================================================================
+void MeasureGUI_CheckCompoundOfBlocksDlg::SetUseC1Tolerance()
+{
+  myTolLbl->setEnabled(myUseC1Check->isChecked());
+  mySpinTol->setEnabled(myUseC1Check->isChecked());
+  processObject();
+}
+
 //=================================================================================
 // function : LineEditReturnPressed()
 // purpose  :
@@ -210,8 +266,8 @@ void MeasureGUI_CheckCompoundOfBlocksDlg::SetEditCurrentArgument()
 void MeasureGUI_CheckCompoundOfBlocksDlg::LineEditReturnPressed()
 {
   QLineEdit* send = (QLineEdit*)sender();
-  if ( send == myGrp->LineEdit1 ) {
-    myEditCurrentArgument = myGrp->LineEdit1;
+  if ( send == myObjectName ) {
+    myEditCurrentArgument = myObjectName;
     GEOMBase_Skeleton::LineEditReturnPressed();
   }
 }
@@ -245,7 +301,13 @@ bool MeasureGUI_CheckCompoundOfBlocksDlg::getBCErrors( bool& theIsCompoundOfBloc
     GEOM::GEOM_IBlocksOperations_var anOper = GEOM::GEOM_IBlocksOperations::_narrow( getOperation() );
     try {
       GEOM::GEOM_IBlocksOperations::BCErrors_var aErrs;
-      theIsCompoundOfBlocks = anOper->CheckCompoundOfBlocks( myObj, aErrs );
+      double aC1Tol = -1.;
+
+      if (myUseC1Check->isChecked()) {
+        aC1Tol = mySpinTol->value();
+      }
+
+      theIsCompoundOfBlocks = anOper->CheckCompoundOfBlocks( myObj, aC1Tol, aErrs );
       if (anOper->IsDone() && aErrs->length() > 0)
       //if (anOper->IsDone() && !aErrs._is_nil())
         theErrors = aErrs;
@@ -270,9 +332,9 @@ void MeasureGUI_CheckCompoundOfBlocksDlg::processObject()
   GEOM::GEOM_IBlocksOperations::BCErrors aErrs;
   if ( !getBCErrors( isCompoundOfBlocks, aErrs ) ) {
     aMsg += tr( "GEOM_CHECK_BLOCKS_COMPOUND_FAILED" );
-    myGrp->TextView1->setText( aMsg );
-    myGrp->ListBox1->clear();
-    myGrp->ListBox2->clear();
+    myTextView->setText( aMsg );
+    myListBox1->clear();
+    myListBox2->clear();
     erasePreview();
     return;
   }
@@ -287,7 +349,7 @@ void MeasureGUI_CheckCompoundOfBlocksDlg::processObject()
     buttonOk()->setEnabled( true );
     buttonApply()->setEnabled( true );
   }
-  myGrp->TextView1->setText( aMsg );
+  myTextView->setText( aMsg );
 
   QStringList aErrList;
   QString aErrStr( "" );
@@ -321,9 +383,9 @@ void MeasureGUI_CheckCompoundOfBlocksDlg::processObject()
       aErrList.append( aErrStr );
   }
 
-  myGrp->ListBox1->clear();
-  myGrp->ListBox2->clear();
-  myGrp->ListBox1->addItems( aErrList );
+  myListBox1->clear();
+  myListBox2->clear();
+  myListBox1->addItems( aErrList );
 }
 
 //=================================================================================
@@ -342,19 +404,19 @@ GEOM::GEOM_IOperations_ptr MeasureGUI_CheckCompoundOfBlocksDlg::createOperation(
 void MeasureGUI_CheckCompoundOfBlocksDlg::onErrorsListSelectionChanged()
 {
   erasePreview();
-  int aCurItem = myGrp->ListBox1->currentRow();
+  int aCurItem = myListBox1->currentRow();
   if ( aCurItem < 0 )
     return;
   bool isCompoundOfBlocks;
   GEOM::GEOM_IBlocksOperations::BCErrors aErrs;
   if ( !getBCErrors( isCompoundOfBlocks, aErrs ) ) {
-    myGrp->TextView1->setText( "" );
-    myGrp->ListBox1->clear();
-    myGrp->ListBox2->clear();
+    myTextView->setText( "" );
+    myListBox1->clear();
+    myListBox2->clear();
     return;
   }
 
-  myGrp->ListBox2->clear();
+  myListBox2->clear();
 
   if (aCurItem < aErrs.length()) {
     GEOM::GEOM_IBlocksOperations::BCError aErr = aErrs[aCurItem];
@@ -371,7 +433,7 @@ void MeasureGUI_CheckCompoundOfBlocksDlg::onErrorsListSelectionChanged()
           aSubShapeList.append( QString( "%1_%2" ).arg( aType ).arg( aObjLst[i] ) );
       }
     }
-    myGrp->ListBox2->addItems( aSubShapeList );
+    myListBox2->addItems( aSubShapeList );
   }
 }
 
@@ -382,12 +444,12 @@ void MeasureGUI_CheckCompoundOfBlocksDlg::onErrorsListSelectionChanged()
 void MeasureGUI_CheckCompoundOfBlocksDlg::onSubShapesListSelectionChanged()
 {
   erasePreview();
-  int aErrCurItem = myGrp->ListBox1->currentRow();
+  int aErrCurItem = myListBox1->currentRow();
   if ( aErrCurItem < 0 )
     return;
   QList<int> aIds;
-  for ( int i = 0, n = myGrp->ListBox2->count(); i < n; i++ ) {
-    if ( myGrp->ListBox2->item( i )->isSelected() )
+  for ( int i = 0, n = myListBox2->count(); i < n; i++ ) {
+    if ( myListBox2->item( i )->isSelected() )
       aIds.append( i );
   }
   if ( aIds.count() < 1 )
@@ -395,9 +457,9 @@ void MeasureGUI_CheckCompoundOfBlocksDlg::onSubShapesListSelectionChanged()
   bool isCompoundOfBlocks;
   GEOM::GEOM_IBlocksOperations::BCErrors aErrs;
   if ( !getBCErrors( isCompoundOfBlocks, aErrs ) ) {
-    myGrp->TextView1->setText( "" );
-    myGrp->ListBox1->clear();
-    myGrp->ListBox2->clear();
+    myTextView->setText( "" );
+    myListBox1->clear();
+    myListBox2->clear();
     return;
   }
 
@@ -433,6 +495,15 @@ void MeasureGUI_CheckCompoundOfBlocksDlg::onSubShapesListSelectionChanged()
   }
 }
 
+//=================================================================================
+// function : onDisplayPreview
+// purpose  : 
+//=================================================================================
+void MeasureGUI_CheckCompoundOfBlocksDlg::onDisplayPreview()
+{
+  DISPLAY_PREVIEW_MACRO;
+}
+
 //=================================================================================
 // function : activateSelection
 // purpose  : activate selection of faces, shells, and solids
@@ -459,9 +530,9 @@ void MeasureGUI_CheckCompoundOfBlocksDlg::enterEvent( QEvent* )
 // function : isValid
 // purpose  :
 //=================================================================================
-bool MeasureGUI_CheckCompoundOfBlocksDlg::isValid( QString)
+bool MeasureGUI_CheckCompoundOfBlocksDlg::isValid( QString &msg)
 {
-  return !myObj->_is_nil();
+  return !myObj->_is_nil() && mySpinTol->isValid(msg, !IsPreview());
 }
 
 //=================================================================================
index e6a93c4f07e124f6144c766b43e4f5ff705687e9..b2d43ca1fc9009a2da0860b76667094ed4112eb1 100644 (file)
 
 #include <GEOMBase_Skeleton.h>
 
-class MeasureGUI_1Sel1TextView2ListBox;
+class QCheckBox;
+class QLabel;
+class QLineEdit;
+class QListWidget;
+class QPushButton;
+class QTextBrowser;
+class SalomeApp_DoubleSpinBox;
 
 //=================================================================================
 // class    : MeasureGUI_CheckCompoundOfBlocksDlg
@@ -47,7 +53,7 @@ public:
 protected:
   // redefined from GEOMBase_Helper and GEOMBase_Skeleton
   virtual GEOM::GEOM_IOperations_ptr  createOperation();
-  virtual bool                        isValid( QString& );
+  virtual bool                        isValid( QString &msg );
   virtual bool                        execute( ObjectList& );
   virtual void                        processObject();
 
@@ -61,6 +67,8 @@ private slots:
   
   void                                onErrorsListSelectionChanged();
   void                                onSubShapesListSelectionChanged();
+  void                                SetUseC1Tolerance();
+  void                                onDisplayPreview();
   
 private:
   void                                Init();
@@ -71,7 +79,14 @@ private:
 
 private:
   GEOM::GEOM_Object_var               myObj;
-  MeasureGUI_1Sel1TextView2ListBox*   myGrp;
+  QLineEdit                          *myObjectName;
+  QPushButton                        *mySelButton;
+  QCheckBox                          *myUseC1Check;
+  QLabel                             *myTolLbl;
+  SalomeApp_DoubleSpinBox            *mySpinTol;
+  QTextBrowser                       *myTextView;
+  QListWidget                        *myListBox1;
+  QListWidget                        *myListBox2;
 };
 
 #endif // MEASUREGUI_CHECKCOMPOUNDOFBLOCKSDLG_H
index 5c04f273aa8b766af40fbe653709ce9ac72474d7..6ef248017cebcfd7a1ec98834e2514120b379f9e 100644 (file)
@@ -25,7 +25,6 @@
 
 #include "MeasureGUI_GetNonBlocksDlg.h"
 
-#include <DlgRef.h>
 #include <GEOMBase.h>
 
 #include <GeometryGUI.h>
 #include <SUIT_Session.h>
 #include <SUIT_ResourceMgr.h>
 #include <SalomeApp_Application.h>
+#include <SalomeApp_DoubleSpinBox.h>
 #include <LightApp_SelectionMgr.h>
 #include <SalomeApp_Tools.h>
 
+#include <QCheckBox>
+#include <QGridLayout>
+#include <QGroupBox>
+#include <QLineEdit>
+#include <QPushButton>
+#include <QRadioButton>
+#include <QVBoxLayout>
+
 //=================================================================================
 // class    : MeasureGUI_GetNonBlocksDlg()
 // purpose  : Constructs a MeasureGUI_GetNonBlocksDlg which is a child of 'parent',
 //            true to construct a modal dialog.
 //=================================================================================
 MeasureGUI_GetNonBlocksDlg::MeasureGUI_GetNonBlocksDlg (GeometryGUI* theGeometryGUI, QWidget* parent)
-  : GEOMBase_Skeleton(theGeometryGUI, parent, false)
+  : GEOMBase_Skeleton(theGeometryGUI, parent, false),
+    myObjectName     (0),
+    mySelButton      (0),
+    myUseC1Check     (0),
+    myTolLbl         (0),
+    mySpinTol        (0)
 {
   QPixmap image0 (SUIT_Session::session()->resourceMgr()->loadPixmap("GEOM", tr("ICON_DLG_GETNONBLOCKS")));
   QPixmap image1 (SUIT_Session::session()->resourceMgr()->loadPixmap("GEOM", tr("ICON_SELECT")));
@@ -58,16 +71,36 @@ MeasureGUI_GetNonBlocksDlg::MeasureGUI_GetNonBlocksDlg (GeometryGUI* theGeometry
   mainFrame()->RadioButton2->close();
   mainFrame()->RadioButton3->setAttribute(Qt::WA_DeleteOnClose);
   mainFrame()->RadioButton3->close();
-
-  myGrp = new DlgRef_1Sel (centralWidget());
-  myGrp->GroupBox1->setTitle(tr("GEOM_GETNONBLOCKS"));
-  myGrp->TextLabel1->setText(tr("GEOM_OBJECT"));
-  myGrp->PushButton1->setIcon(image1);
-  myGrp->LineEdit1->setReadOnly(true);
+  
+  QGroupBox   *aGrpParams    =
+    new QGroupBox(tr("GEOM_GETNONBLOCKS"), centralWidget());
+  QGridLayout *aParamsLayout = new QGridLayout(aGrpParams);
+  QLabel      *anObjLbl      = new QLabel(tr("GEOM_OBJECT"), aGrpParams);
+
+  myObjectName = new QLineEdit(aGrpParams);
+  mySelButton  = new QPushButton(aGrpParams);
+  myUseC1Check = new QCheckBox(tr("GEOM_USE_C1_CRITERION"), aGrpParams);
+  myTolLbl     = new QLabel(tr("GEOM_ANGULAR_TOLERANCE"), aGrpParams);
+  mySpinTol    = new SalomeApp_DoubleSpinBox(aGrpParams);
+
+  myObjectName->setReadOnly(true);
+  mySelButton->setIcon(image1);
+  mySelButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+  myUseC1Check->setText(tr("GEOM_USE_C1_CRITERION"));
+  myUseC1Check->setChecked(true);
+
+  aParamsLayout->setMargin(9);
+  aParamsLayout->setSpacing(6);
+  aParamsLayout->addWidget(anObjLbl,     0, 0);
+  aParamsLayout->addWidget(mySelButton,  0, 1);
+  aParamsLayout->addWidget(myObjectName, 0, 2);
+  aParamsLayout->addWidget(myUseC1Check, 1, 0, 1, 3);
+  aParamsLayout->addWidget(myTolLbl,     2, 0);
+  aParamsLayout->addWidget(mySpinTol,    2, 1, 1, 2);
 
   QVBoxLayout* layout = new QVBoxLayout(centralWidget());
   layout->setMargin(0); layout->setSpacing(6);
-  layout->addWidget(myGrp);
+  layout->addWidget(aGrpParams);
 
   /***************************************************************/
 
@@ -94,14 +127,20 @@ void MeasureGUI_GetNonBlocksDlg::Init()
   showOnlyPreviewControl();
 
   /* init variables */
-  myEditCurrentArgument = myGrp->LineEdit1;
+  double SpecificStep = 0.0001;
+  double aDefaultTol  = Precision::Angular();
 
-   /* signals and slots connections */
-  connect(buttonOk(),    SIGNAL(clicked()), this, SLOT(ClickOnOk()));
-  connect(buttonApply(), SIGNAL(clicked()), this, SLOT(ClickOnApply()));
+  initSpinBox(mySpinTol, aDefaultTol, MAX_NUMBER, SpecificStep, "ang_tol_precision");
+  mySpinTol->setValue(aDefaultTol);
+  myEditCurrentArgument = myObjectName;
 
-  connect(myGrp->LineEdit1,   SIGNAL(returnPressed()), this, SLOT(LineEditReturnPressed()));
-  connect(myGrp->PushButton1, SIGNAL(clicked()),       this, SLOT(SetEditCurrentArgument()));
+   /* signals and slots connections */
+  connect(buttonOk(),    SIGNAL(clicked()),            this, SLOT(ClickOnOk()));
+  connect(buttonApply(), SIGNAL(clicked()),            this, SLOT(ClickOnApply()));
+  connect(myUseC1Check,  SIGNAL(clicked()),            this, SLOT(SetUseC1Tolerance()));
+  connect(mySpinTol,     SIGNAL(valueChanged(double)), this, SLOT(processPreview()));
+  connect(myObjectName,  SIGNAL(returnPressed()),      this, SLOT(LineEditReturnPressed()));
+  connect(mySelButton,   SIGNAL(clicked()),            this, SLOT(SetEditCurrentArgument()));
 
   connect(((SalomeApp_Application*)(SUIT_Session::session()->activeApplication()))->selectionMgr(),
            SIGNAL(currentSelectionChanged()), this, SLOT(SelectionIntoArgument()));
@@ -171,11 +210,22 @@ void MeasureGUI_GetNonBlocksDlg::SelectionIntoArgument()
 //=================================================================================
 void MeasureGUI_GetNonBlocksDlg::SetEditCurrentArgument()
 {
-  myGrp->LineEdit1->setFocus();
-  myEditCurrentArgument = myGrp->LineEdit1;
+  myObjectName->setFocus();
+  myEditCurrentArgument = myObjectName;
   SelectionIntoArgument();
 }
 
+//=================================================================================
+// function : SetUseC1Tolerance()
+// purpose  :
+//=================================================================================
+void MeasureGUI_GetNonBlocksDlg::SetUseC1Tolerance()
+{
+  myTolLbl->setEnabled(myUseC1Check->isChecked());
+  mySpinTol->setEnabled(myUseC1Check->isChecked());
+  processPreview();
+}
+
 //=================================================================================
 // function : LineEditReturnPressed()
 // purpose  :
@@ -183,8 +233,8 @@ void MeasureGUI_GetNonBlocksDlg::SetEditCurrentArgument()
 void MeasureGUI_GetNonBlocksDlg::LineEditReturnPressed()
 {
   QLineEdit* send = (QLineEdit*)sender();
-  if (send == myGrp->LineEdit1) {
-    myEditCurrentArgument = myGrp->LineEdit1;
+  if (send == myObjectName) {
+    myEditCurrentArgument = myObjectName;
     GEOMBase_Skeleton::LineEditReturnPressed();
   }
 }
@@ -211,10 +261,11 @@ void MeasureGUI_GetNonBlocksDlg::ActivateThisDialog()
 void MeasureGUI_GetNonBlocksDlg::processObject()
 {
   if (myObj->_is_nil()) {
+    myObjectName->setText("");
     erasePreview();
   }
   else {
-    myGrp->LineEdit1->setText(GEOMBase::GetName(myObj));
+    myObjectName->setText(GEOMBase::GetName(myObj));
 
     processPreview();
   }
@@ -243,9 +294,9 @@ GEOM::GEOM_IOperations_ptr MeasureGUI_GetNonBlocksDlg::createOperation()
 // function : isValid
 // purpose  :
 //=================================================================================
-bool MeasureGUI_GetNonBlocksDlg::isValid (QString&)
+bool MeasureGUI_GetNonBlocksDlg::isValid (QString &msg)
 {
-  return !myObj->_is_nil();
+  return !myObj->_is_nil() && mySpinTol->isValid(msg, !IsPreview());
 }
 
 //=================================================================================
@@ -256,7 +307,13 @@ bool MeasureGUI_GetNonBlocksDlg::execute (ObjectList& objects)
 {
   GEOM::GEOM_IBlocksOperations_var anOper = GEOM::GEOM_IBlocksOperations::_narrow(getOperation());
   GEOM::GEOM_Object_var aNonQuads;
-  GEOM::GEOM_Object_var anObj = anOper->GetNonBlocks(myObj, aNonQuads);
+  double aC1Tol = -1.;
+
+  if (myUseC1Check->isChecked()) {
+    aC1Tol = mySpinTol->value();
+  }
+
+  GEOM::GEOM_Object_var anObj = anOper->GetNonBlocks(myObj, aC1Tol, aNonQuads);
   //mainFrame()->ResultName->setText(tr("GEOM_NONBLOCKS"));
 
   if (!anObj->_is_nil())
index 5282c8cd6e888180839292c79f47c75c4d619a96..f6f59b6805ba6ebd4a8d787abb399a2d0a09540e 100644 (file)
 
 #include <GEOMBase_Skeleton.h>
 
-class DlgRef_1Sel;
+class QCheckBox;
+class QLabel;
+class QLineEdit;
+class QPushButton;
+class SalomeApp_DoubleSpinBox;
 
 //=================================================================================
 // class    : MeasureGUI_GetNonBlocksDlg
@@ -45,7 +49,7 @@ public:
 protected:
   // redefined from GEOMBase_Helper
   virtual GEOM::GEOM_IOperations_ptr  createOperation();
-  virtual bool                        isValid (QString&);
+  virtual bool                        isValid (QString &msg);
   virtual bool                        execute (ObjectList&);
   virtual GEOM::GEOM_Object_ptr       getFather (GEOM::GEOM_Object_ptr);
 
@@ -56,6 +60,7 @@ private slots:
   void                                LineEditReturnPressed();
   void                                SelectionIntoArgument();
   void                                SetEditCurrentArgument();
+  void                                SetUseC1Tolerance();
   
 private:
   void                                Init();
@@ -64,7 +69,11 @@ private:
 
 private:
   GEOM::GEOM_Object_var               myObj;
-  DlgRef_1Sel*                        myGrp;
+  QLineEdit                          *myObjectName;
+  QPushButton                        *mySelButton;
+  QCheckBox                          *myUseC1Check;
+  QLabel                             *myTolLbl;
+  SalomeApp_DoubleSpinBox            *mySpinTol;
 };
 
 #endif // MEASUREGUI_GETNONBLOCKSDLG_H