]> SALOME platform Git repositories - modules/geom.git/commitdiff
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)
committerskv <skv@opencascade.com>
Thu, 22 Jan 2015 09:14:55 +0000 (12:14 +0300)
12 files changed:
doc/salome/gui/GEOM/images/measures2.png
doc/salome/gui/GEOM/images/measures2a.png
doc/salome/gui/GEOM/input/get_non_blocks.doc
idl/GEOM_Gen.idl
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_SWIG/geomBuilder.py
src/MeasureGUI/MeasureGUI_GetNonBlocksDlg.cxx
src/MeasureGUI/MeasureGUI_GetNonBlocksDlg.h

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 79f6ba0219ef9b3b633145648cad4ad9e74f8cb6..e1b687effbbf3e718d354bc8b1930e3a820671f1 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 faces and 12 edges.
+
+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 8863bae2696b537bc7257d2d8c73dce00ec46bf9..890d9b52ba83f1d22c4184c741b6cc367ec41d61 100644 (file)
@@ -2781,12 +2781,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 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..8eb8f09da895767c789f60697b8a3885106de316 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;
@@ -1676,41 +1819,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 +1846,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 +1861,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 +2083,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
@@ -2312,7 +2157,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, -1.);
 
   // Report non-blocks
   if (NOT.Extent() > 0) {
@@ -2478,7 +2323,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 +2337,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..34162d6ed240873f6325fdaff864678049e2b558 100644 (file)
@@ -125,16 +125,14 @@ 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,
                                                           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 +146,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..572cdd7
@@ -749,6 +749,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 +766,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..482ea8a8e21603cb927b36855d3fdd739bc970e1 100644 (file)
@@ -122,6 +122,7 @@ class GEOM_I_EXPORT GEOM_IBlocksOperations_i :
                       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 93e6da9073c92f8949bc82b86397d8401f624ea3..652b4173b2be4307512abcb39596a21addc039a1 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".
@@ -11431,6 +11431,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.
@@ -11438,17 +11444,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.
@@ -11457,13 +11473,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 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