0030470: Modeling Algorithms - Invalid result of offset operation in mode "Complete...
authoremv <emv@opencascade.com>
Tue, 5 Feb 2019 11:58:41 +0000 (14:58 +0300)
committerapn <apn@opencascade.com>
Thu, 7 Mar 2019 15:07:29 +0000 (18:07 +0300)
The fix is intended to obtain the correct result of offset operation in which the result contained only the small inverse part of the shape, which clearly should not have been included in the result at all.

The fix adds treatment of the inverted edges while removing the inside faces (collapsed ones) - RemoveInsideFaces method:
- Removing the invalid hanging blocks containing the inverted edges.
- Considering the face containing the inverted edges as the invalid one.

Test cases for the issue.

src/BRepOffset/BRepOffset_MakeOffset_1.cxx
tests/offset/shape_type_i_c/XS4 [new file with mode: 0644]
tests/offset/shape_type_i_c/XS5 [new file with mode: 0644]
tests/offset/shape_type_i_c/XS6 [new file with mode: 0644]
tests/offset/shape_type_i_c/XS7 [new file with mode: 0644]
tests/offset/shape_type_i_c/XS8 [new file with mode: 0644]
tests/offset/shape_type_i_c/XS9 [new file with mode: 0644]
tests/offset/shape_type_i_c/XT1 [new file with mode: 0644]
tests/offset/shape_type_i_c/XT2 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZC7
tests/offset/shape_type_i_c/begin

index a4e1c43..cda7b25 100644 (file)
@@ -179,7 +179,8 @@ static
                         const TopTools_MapOfShape& theEdgesInvalidByVertex,
                         const TopTools_MapOfShape& theMFHoles,
                         TopTools_IndexedMapOfShape& theMFInvInHole,
-                        TopTools_ListOfShape& theInvFaces);
+                        TopTools_ListOfShape& theInvFaces,
+                        TopTools_ListOfShape& theInvertedFaces);
 
 static
   void FindFacesInsideHoleWires(const TopoDS_Face& theFOrigin,
@@ -238,6 +239,8 @@ static
                          TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
                          const TopTools_DataMapOfShapeShape& theArtInvFaces,
                          const TopTools_IndexedMapOfShape& theInvEdges,
+                         const TopTools_MapOfShape& theInvertedEdges,
+                         const TopTools_ListOfShape& theInvertedFaces,
                          const TopTools_IndexedMapOfShape& theMFToCheckInt,
                          const TopTools_IndexedMapOfShape& theMFInvInHole,
                          const TopoDS_Shape& theFHoles,
@@ -258,6 +261,7 @@ static
                           const TopTools_DataMapOfShapeShape& theDMFImF,
                           const TopTools_IndexedMapOfShape& theMFInv,
                           const TopTools_IndexedMapOfShape& theInvEdges,
+                          const TopTools_MapOfShape& theInvertedEdges,
                           TopTools_MapOfShape& theMFToRem);
 
 static
@@ -596,6 +600,21 @@ static
   void AppendToList(TopTools_ListOfShape& theL,
                     const TopoDS_Shape& theS);
 
+template <class ContainerType, class FenceMapType>
+static Standard_Boolean TakeModified(const TopoDS_Shape& theS,
+                                     const TopTools_DataMapOfShapeListOfShape& theImages,
+                                     ContainerType& theMapOut,
+                                     FenceMapType* theMFence);
+
+template <class ContainerType>
+static Standard_Boolean TakeModified(const TopoDS_Shape& theS,
+                                     const TopTools_DataMapOfShapeListOfShape& theImages,
+                                     ContainerType& theMapOut)
+{
+  TopTools_MapOfShape* aDummy = NULL;
+  return TakeModified (theS, theImages, theMapOut, aDummy);
+}
+
 //=======================================================================
 //function : BuildSplitsOfTrimmedFaces
 //purpose  : Building splits of already trimmed faces
@@ -988,6 +1007,12 @@ void BuildSplitsOfFaces(const TopTools_ListOfShape& theLF,
   }
 #endif
 
+#ifdef OFFSET_DEBUG
+  // Show all obtained splits of faces
+  TopoDS_Compound aCFIm1;
+  BRep_Builder().MakeCompound(aCFIm1);
+#endif
+
   // Build Edge-Face connectivity map to find faces which removal
   // may potentially lead to creation of the holes in the faces
   // preventing from obtaining closed volume in the result
@@ -997,7 +1022,12 @@ void BuildSplitsOfFaces(const TopTools_ListOfShape& theLF,
   {
     TopTools_ListIteratorOfListOfShape itLFIm(theFImages(i));
     for (; itLFIm.More(); itLFIm.Next())
+    {
       TopExp::MapShapesAndAncestors(itLFIm.Value(), TopAbs_EDGE, TopAbs_FACE, anEFMap);
+#ifdef OFFSET_DEBUG
+      BRep_Builder().Add(aCFIm1, itLFIm.Value());
+#endif
+    }
   }
 
   TopTools_ListOfShape anEmptyList;
@@ -1006,6 +1036,8 @@ void BuildSplitsOfFaces(const TopTools_ListOfShape& theLF,
   // all hole faces
   TopoDS_Compound aFHoles;
   aBB.MakeCompound(aFHoles);
+  // Find the faces containing only the inverted edges and the invalid ones
+  TopTools_ListOfShape anInvertedFaces;
   // find invalid faces
   // considering faces containing only invalid edges as invalid
   aItLF.Initialize(aLFDone);
@@ -1044,7 +1076,7 @@ void BuildSplitsOfFaces(const TopTools_ListOfShape& theLF,
       // find invalid faces
       FindInvalidFaces(aLFImages, theInvEdges, theValidEdges, aDMFLVE, aDMFLIE,
                        *pLNE, *pLIVE, theInvertedEdges, aMEdgeInvalidByVertex,
-                       aMFHoles, aMFInvInHole, aLFInv);
+                       aMFHoles, aMFInvInHole, aLFInv, anInvertedFaces);
     }
     //
     if (aLFInv.Extent()) {
@@ -1095,8 +1127,8 @@ void BuildSplitsOfFaces(const TopTools_ListOfShape& theLF,
   //
   // remove inside faces
   TopTools_IndexedMapOfShape aMEInside;
-  RemoveInsideFaces(theFImages, theInvFaces, theArtInvFaces, theInvEdges,
-                    aMFToCheckInt, aMFInvInHole, aFHoles, theSSInterfs,
+  RemoveInsideFaces(theFImages, theInvFaces, theArtInvFaces, theInvEdges, theInvertedEdges,
+                    anInvertedFaces, aMFToCheckInt, aMFInvInHole, aFHoles, theSSInterfs,
                     aMERemoved, aMEInside, theSolids);
   //
   // make compound of valid splits
@@ -1819,7 +1851,8 @@ void FindInvalidFaces(TopTools_ListOfShape& theLFImages,
                       const TopTools_MapOfShape& theEdgesInvalidByVertex,
                       const TopTools_MapOfShape& theMFHoles,
                       TopTools_IndexedMapOfShape& theMFInvInHole,
-                      TopTools_ListOfShape& theInvFaces)
+                      TopTools_ListOfShape& theInvFaces,
+                      TopTools_ListOfShape& theInvertedFaces)
 {
   // The face should be considered as invalid in the following cases:
   // 1. It has been reverted, i.e. at least two not connected edges 
@@ -1832,7 +1865,8 @@ void FindInvalidFaces(TopTools_ListOfShape& theLFImages,
   // The face will be kept in the following cases:
   // 1. Some of the edges are valid for this face.
   Standard_Boolean bHasValid, bAllValid, bAllInvalid, bHasReallyInvalid, bAllInvNeutral;
-  Standard_Boolean bValid, bValidLoc, bInvalid, bInvalidLoc, bNeutral;
+  Standard_Boolean bValid, bValidLoc, bInvalid, bInvalidLoc, bNeutral, bInverted;
+  Standard_Boolean bIsInvalidByInverted;
   Standard_Integer i, aNbChecked;
   //
   // neutral edges
@@ -1849,7 +1883,7 @@ void FindInvalidFaces(TopTools_ListOfShape& theLFImages,
     aMEValInverted.Add(aItLE.Value());
   }
   //
-  Standard_Boolean bCheckInverted = (theLFImages.Extent() == 1);
+  Standard_Boolean bTreatInvertedAsInvalid = (theLFImages.Extent() == 1);
   //
   // neutral edges to remove
   TopTools_IndexedMapOfShape aMENRem;
@@ -1883,6 +1917,7 @@ void FindInvalidFaces(TopTools_ListOfShape& theLFImages,
     bAllInvalid = Standard_True;
     bHasReallyInvalid = Standard_False;
     bAllInvNeutral = Standard_True;
+    bIsInvalidByInverted = Standard_True;
     aNbChecked = 0;
     //
     const TopoDS_Wire& aWIm = BRepTools::OuterWire(aFIm);
@@ -1909,17 +1944,19 @@ void FindInvalidFaces(TopTools_ListOfShape& theLFImages,
       bNeutral = aMEN.Contains(aEIm);
       bValidLoc = aMVE.Contains(aEIm);
       //
-      if (!bInvalid && bCheckInverted) {
-        bInvalid = theMEInverted.Contains(aEIm);
+      bInverted = theMEInverted.Contains(aEIm);
+      if (!bInvalid && bTreatInvertedAsInvalid) {
+        bInvalid = bInverted;
       }
       //
       if (bValidLoc && (bNeutral || aMEValInverted.Contains(aEIm))) {
         bHasValid = Standard_True;
       }
       //
-      bAllValid = bAllValid && bValidLoc;
-      bAllInvalid = bAllInvalid && bInvalid;
-      bAllInvNeutral = bAllInvNeutral && bAllInvalid && bNeutral;
+      bAllValid &= bValidLoc;
+      bAllInvalid &= bInvalid;
+      bAllInvNeutral &= (bAllInvalid && bNeutral);
+      bIsInvalidByInverted &= (bInvalidLoc || bInverted);
     }
     //
     if (!aNbChecked) {
@@ -1954,6 +1991,12 @@ void FindInvalidFaces(TopTools_ListOfShape& theLFImages,
       continue;
     }
     //
+    if (bIsInvalidByInverted && !(bHasValid || bAllValid))
+    {
+      // The face contains only the inverted and locally invalid edges
+      theInvertedFaces.Append(aFIm);
+    }
+
     if (!bAllInvNeutral) {
       aLFPT.Append(aFIm);
     }
@@ -2003,7 +2046,7 @@ void FindInvalidFaces(TopTools_ListOfShape& theLFImages,
       bNeutral = aMEN.Contains(aEIm);
       bValidLoc = aMVE.Contains(aEIm);
       //
-      if (!bInvalid && bCheckInverted) {
+      if (!bInvalid && bTreatInvertedAsInvalid) {
         bInvalid = theMEInverted.Contains(aEIm);
       }
       //
@@ -2873,6 +2916,8 @@ void RemoveInsideFaces(TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
                        TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
                        const TopTools_DataMapOfShapeShape& theArtInvFaces,
                        const TopTools_IndexedMapOfShape& theInvEdges,
+                       const TopTools_MapOfShape& theInvertedEdges,
+                       const TopTools_ListOfShape& theInvertedFaces,
                        const TopTools_IndexedMapOfShape& theMFToCheckInt,
                        const TopTools_IndexedMapOfShape& theMFInvInHole,
                        const TopoDS_Shape& theFHoles,
@@ -2932,6 +2977,9 @@ void RemoveInsideFaces(TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
   aMV.SetArguments(aLS);
   aMV.SetIntersect(Standard_True);
   aMV.Perform();
+  if (aMV.HasErrors())
+    return;
+
   //
   // get shapes connection for using in the rebuilding process
   // for the cases in which some of the intersection left undetected
@@ -3016,19 +3064,21 @@ void RemoveInsideFaces(TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
       TopExp::MapShapes(aFIm, TopAbs_EDGE, aMEBoundary);
     }
   }
-  //
+
+  // Tool for getting the splits of faces
+  const TopTools_DataMapOfShapeListOfShape& aMVIms = aMV.Images();
+
   // update invalid faces with images
   aNb = aMFInv.Extent();
   for (i = 1; i <= aNb; ++i) {
     const TopoDS_Shape& aFInv = aMFInv(i);
-    const TopTools_ListOfShape& aLFInvIm = aMV.Modified(aFInv);
-    TopTools_ListIteratorOfListOfShape aItLFInvIm(aLFInvIm);
-    for (; aItLFInvIm.More(); aItLFInvIm.Next()) {
-      const TopoDS_Shape& aFInvIm = aItLFInvIm.Value();
-      aMFInv.Add(aFInvIm);
-    }
+    TakeModified(aFInv, aMVIms, aMFInv);
   }
-  //
+
+  // Take into account the faces invalid by inverted edges
+  for (TopTools_ListOfShape::Iterator itLF(theInvertedFaces); itLF.More(); itLF.Next())
+    TakeModified(itLF.Value(), aMVIms, aMFInv);
+
   // check if the invalid faces inside the holes are really invalid:
   // check its normal direction - if it has changed relatively the
   // original face the offset face is invalid and should be kept for rebuilding
@@ -3082,10 +3132,14 @@ void RemoveInsideFaces(TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
       //
       if (aFS.Orientation() == TopAbs_INTERNAL) {
         aMFToRem.Add(aFS);
+        continue;
       }
-      //
-      bAllRemoved = bAllRemoved && aMFToRem.Contains(aFS);
-      bAllInv = bAllInv && (aMFToRem.Contains(aFS) || aMFInv.Contains(aFS));
+
+      if (aMFToRem.Contains(aFS))
+        continue;
+
+      bAllRemoved = false;
+      bAllInv &= aMFInv.Contains(aFS);
     }
     //
     if (bAllInv && !bAllRemoved) {
@@ -3116,7 +3170,7 @@ void RemoveInsideFaces(TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
   }
 
   // Remove the invalid hanging parts external to the solids
-  RemoveHangingParts(aMV, aDMFImF, aMFInv, theInvEdges, aMFToRem);
+  RemoveHangingParts(aMV, aDMFImF, aMFInv, theInvEdges, theInvertedEdges, aMFToRem);
 
   // Remove newly found internal and hanging faces
   RemoveValidSplits(aMFToRem, theFImages, aMV, theMERemoved);
@@ -3302,6 +3356,7 @@ void RemoveHangingParts(const BOPAlgo_MakerVolume& theMV,
                         const TopTools_DataMapOfShapeShape& theDMFImF,
                         const TopTools_IndexedMapOfShape& theMFInv,
                         const TopTools_IndexedMapOfShape& theInvEdges,
+                        const TopTools_MapOfShape& theInvertedEdges,
                         TopTools_MapOfShape& theMFToRem)
 {
   // Map the faces of the result solids to filter them from avoided faces
@@ -3323,22 +3378,7 @@ void RemoveHangingParts(const BOPAlgo_MakerVolume& theMV,
     for (; anExpF.More(); anExpF.Next())
     {
       const TopoDS_Shape& aF = anExpF.Current();
-      const TopTools_ListOfShape* pLFIm = aMVIms.Seek(aF);
-      if (pLFIm)
-      {
-        TopTools_ListIteratorOfListOfShape aItLFIm(*pLFIm);
-        for (; aItLFIm.More(); aItLFIm.Next())
-        {
-          const TopoDS_Shape& aFIm = aItLFIm.Value();
-          if (!aMFS.Contains(aFIm))
-            aBB.Add(aCFHangs, aFIm);
-        }
-      }
-      else
-      {
-        if (!aMFS.Contains(aF))
-          aBB.Add(aCFHangs, aF);
-      }
+      TakeModified(aF, aMVIms, aCFHangs, &aMFS);
     }
   }
 
@@ -3364,27 +3404,41 @@ void RemoveHangingParts(const BOPAlgo_MakerVolume& theMV,
   // Update invalid edges with intersection results
   TopTools_MapOfShape aMEInv;
   Standard_Integer i, aNbE = theInvEdges.Extent();
-  for (i = 1; i <= aNbE; ++i) {
-    const TopoDS_Shape& aEInv = theInvEdges(i);
-    const TopTools_ListOfShape *pLEIm = aMVIms.Seek(aEInv);
-    if (pLEIm)
-    {
-      TopTools_ListIteratorOfListOfShape aItLEIm(*pLEIm);
-      for (; aItLEIm.More(); aItLEIm.Next())
-        aMEInv.Add(aItLEIm.Value());
-    }
-    else
-      aMEInv.Add(aEInv);
-  }
+  for (i = 1; i <= aNbE; ++i)
+    TakeModified(theInvEdges(i), aMVIms, aMEInv);
+
+  // Update inverted edges with intersection results
+  TopTools_MapOfShape aMEInverted;
+  for (TopTools_MapIteratorOfMapOfShape itM(theInvertedEdges); itM.More(); itM.Next())
+    TakeModified(itM.Value(), aMVIms, aMEInverted);
 
   // Tool for getting the origins of the splits
   const TopTools_DataMapOfShapeListOfShape& aMVOrs = theMV.Origins();
 
+  // Find hanging blocks to remove
+  TopTools_ListOfShape aBlocksToRemove;
+
   TopTools_ListIteratorOfListOfShape aItLCBH(aLCBHangs);
   for (; aItLCBH.More(); aItLCBH.Next())
   {
     const TopoDS_Shape& aCBH = aItLCBH.Value();
 
+    // Remove the block containing the inverted edges
+    Standard_Boolean bHasInverted = Standard_False;
+    TopExp_Explorer anExpE(aCBH, TopAbs_EDGE);
+    for (; anExpE.More() && !bHasInverted; anExpE.Next())
+    {
+      const TopoDS_Shape& aE = anExpE.Current();
+      bHasInverted = !aDMEF      .Contains(aE) &&
+                      aMEInverted.Contains(aE);
+    }
+
+    if (bHasInverted)
+    {
+      aBlocksToRemove.Append(aCBH);
+      continue;
+    }
+
     // Check the block to contain invalid split
     Standard_Boolean bHasInvalidFace = Standard_False;
     // Check connectivity to invalid parts
@@ -3406,7 +3460,7 @@ void RemoveHangingParts(const BOPAlgo_MakerVolume& theMV,
       if (!bIsConnected)
       {
         // check edges
-        TopExp_Explorer anExpE(aF, TopAbs_EDGE);
+        anExpE.Init(aF, TopAbs_EDGE);
         for (; anExpE.More() && !bIsConnected; anExpE.Next())
         {
           const TopoDS_Shape& aE = anExpE.Current();
@@ -3419,17 +3473,20 @@ void RemoveHangingParts(const BOPAlgo_MakerVolume& theMV,
           }
         }
         // check vertices
-        TopExp_Explorer anExpV(aF, TopAbs_VERTEX);
-        for (; anExpV.More() && !bIsConnected; anExpV.Next())
+        if (!bIsConnected)
         {
-          const TopoDS_Shape& aV = anExpV.Current();
-          const TopTools_ListOfShape *pLE = aDMVE.Seek(aV);
-          if (pLE)
+          TopExp_Explorer anExpV(aF, TopAbs_VERTEX);
+          for (; anExpV.More() && !bIsConnected; anExpV.Next())
           {
-            TopTools_ListIteratorOfListOfShape aItLE(*pLE);
-            for (; aItLE.More() && !bIsConnected; aItLE.Next())
-              bIsConnected = !aBlockME.Contains(aItLE.Value()) &&
-                              aMEInv  .Contains(aItLE.Value());
+            const TopoDS_Shape& aV = anExpV.Current();
+            const TopTools_ListOfShape *pLE = aDMVE.Seek(aV);
+            if (pLE)
+            {
+              TopTools_ListIteratorOfListOfShape aItLE(*pLE);
+              for (; aItLE.More() && !bIsConnected; aItLE.Next())
+                bIsConnected = !aBlockME.Contains(aItLE.Value()) &&
+                                aMEInv  .Contains(aItLE.Value());
+            }
           }
         }
       }
@@ -3458,12 +3515,17 @@ void RemoveHangingParts(const BOPAlgo_MakerVolume& theMV,
       (!bIsConnected || aMOffsetF.Extent() == 1);
 
     if (bRemove)
-    {
-      // remove the block
-      anExpF.Init(aCBH, TopAbs_FACE);
-      for (; anExpF.More(); anExpF.Next())
-        theMFToRem.Add(anExpF.Current());
-    }
+      aBlocksToRemove.Append(aCBH);
+  }
+
+  // remove the invalidated blocks
+  aItLCBH.Initialize(aBlocksToRemove);
+  for (; aItLCBH.More(); aItLCBH.Next())
+  {
+    const TopoDS_Shape& aCBH = aItLCBH.Value();
+    TopExp_Explorer anExpF(aCBH, TopAbs_FACE);
+    for (; anExpF.More(); anExpF.Next())
+      theMFToRem.Add(anExpF.Current());
   }
 }
 
@@ -6924,13 +6986,16 @@ void UpdateImages(const TopTools_ListOfShape& theLA,
                   TopTools_MapOfShape& theModified)
 {
   TopTools_ListIteratorOfListOfShape aIt(theLA);
-  for (; aIt.More(); aIt.Next()) {
+  for (; aIt.More(); aIt.Next())
+  {
     const TopoDS_Shape& aS = aIt.Value();
     //
     TopTools_ListOfShape* pLSIm = theImages.ChangeSeek(aS);
-    if (!pLSIm) {
+    if (!pLSIm)
+    {
       const TopTools_ListOfShape& aLSIm = theGF.Modified(aS);
-      if (aLSIm.Extent()) {
+      if (aLSIm.Extent())
+      {
         theImages.Bind(aS, aLSIm);
         theModified.Add(aS);
       }
@@ -6944,27 +7009,14 @@ void UpdateImages(const TopTools_ListOfShape& theLA,
     //
     // check modifications of the images
     TopTools_ListIteratorOfListOfShape aIt1(*pLSIm);
-    for (; aIt1.More(); aIt1.Next()) {
+    for (; aIt1.More(); aIt1.Next())
+    {
       const TopoDS_Shape& aSIm = aIt1.Value();
-      const TopTools_ListOfShape& aLSIm1 = theGF.Modified(aSIm);
-      if (aLSIm1.IsEmpty()) {
-        if (aMFence.Add(aSIm)) {
-          aLSImNew.Append(aSIm);
-        }
-      }
-      else {
-        TopTools_ListIteratorOfListOfShape aIt2(aLSIm1);
-        for (; aIt2.More(); aIt2.Next()) {
-          const TopoDS_Shape& aSImIm = aIt2.Value();
-          if (aMFence.Add(aSImIm)) {
-            aLSImNew.Append(aSImIm);
-          }
-        }
-        bModified = Standard_True;
-      }
+      bModified |= TakeModified(aSIm, theGF.Images(), aLSImNew, &aMFence);
     }
     //
-    if (bModified) {
+    if (bModified)
+    {
       *pLSIm = aLSImNew;
       theModified.Add(aS);
     }
@@ -7099,3 +7151,61 @@ void AppendToList(TopTools_ListOfShape& theList,
   }
   theList.Append(theShape);
 }
+
+//=======================================================================
+//function : AddToContainer
+//purpose  : Set of methods to add a shape into container
+//=======================================================================
+static void AddToContainer(const TopoDS_Shape& theS,
+                           TopTools_ListOfShape& theList)
+{
+  theList.Append(theS);
+}
+static Standard_Boolean AddToContainer(const TopoDS_Shape& theS,
+                                       TopTools_MapOfShape& theMap)
+{
+  return theMap.Add(theS);
+}
+static Standard_Boolean AddToContainer(const TopoDS_Shape& theS,
+                                       TopTools_IndexedMapOfShape& theMap)
+{
+  const Standard_Integer aNb = theMap.Extent();
+  const Standard_Integer anInd = theMap.Add(theS);
+  return anInd > aNb;
+}
+static void AddToContainer(const TopoDS_Shape& theS,
+                           TopoDS_Shape& theSOut)
+{
+  BRep_Builder().Add(theSOut, theS);
+}
+
+//=======================================================================
+//function : TakeModified
+//purpose  : Check if the shape has images in the given images map.
+//           Puts in the output map either the images or the shape itself.
+//=======================================================================
+template <class ContainerType, class FenceMapType>
+Standard_Boolean TakeModified(const TopoDS_Shape& theS,
+                              const TopTools_DataMapOfShapeListOfShape& theImages,
+                              ContainerType& theContainer,
+                              FenceMapType* theMFence)
+{
+  const TopTools_ListOfShape *pLSIm = theImages.Seek(theS);
+  if (pLSIm)
+  {
+    TopTools_ListIteratorOfListOfShape itLSIm(*pLSIm);
+    for (; itLSIm.More(); itLSIm.Next())
+    {
+      const TopoDS_Shape& aSIm = itLSIm.Value();
+      if (!theMFence || AddToContainer(aSIm, *theMFence))
+        AddToContainer(aSIm, theContainer);
+    }
+    return Standard_True;
+  }
+  else
+  {
+    if (!theMFence || AddToContainer(theS, *theMFence))
+      AddToContainer(theS, theContainer);
+    return Standard_False;
+  }
+}
diff --git a/tests/offset/shape_type_i_c/XS4 b/tests/offset/shape_type_i_c/XS4
new file mode 100644 (file)
index 0000000..9375d76
--- /dev/null
@@ -0,0 +1,54 @@
+restore [locate_data_file bug30470_input.brep] s
+
+# perform offset operation with increasing offset value
+
+# set props and nb reference values to compare with
+
+# area volume nb_wire nb_face
+set ref_values { { 2.1809e+06  4.43828e+07 50 49 } \
+                 { 2.13057e+06 4.65386e+07 50 49 } \
+                 { 2.0795e+06  4.86437e+07 50 49 } \
+                 { 2.02768e+06 5.06974e+07 50 49 } \
+                 { 1.97511e+06 5.26988e+07 50 49 } \
+                 { 1.9218e+06  5.46473e+07 50 49 } \
+                 { 1.86774e+06 5.65422e+07 50 49 } \
+                 { 1.81293e+06 5.83826e+07 50 49 } \
+                 { 1.81346e+06 6.01887e+07 23 23 } \
+                 { 1.82605e+06 6.20098e+07 25 25 } \
+                 { 1.83436e+06 6.384e+07   25 25 } \
+                 { 1.84239e+06 6.56784e+07 25 25 } \
+                 { 1.85014e+06 6.75247e+07 25 25 } \
+                 { 1.85761e+06 6.93786e+07 27 27 } \
+                 { 1.86443e+06 7.12397e+07 27 27 } \
+                 { 1.87034e+06 7.31071e+07 27 27 } \
+                 { 1.87534e+06 7.498e+07   27 27 } \
+                 { 1.87945e+06 7.68575e+07 27 27 } \
+                 { 1.88264e+06 7.87386e+07 27 27 } \
+                 { 1.88494e+06 8.06225e+07 27 27 } \
+                 { 1.88632e+06 8.25082e+07 27 27 } \
+                 { 1.88681e+06 8.43948e+07 27 27 } \
+                 { 1.88638e+06 8.62815e+07 27 27 } \
+                 { 1.88506e+06 8.81673e+07 27 27 } \
+                 { 1.88659e+06 9.0052e+07  25 25 } \
+                 { 1.89452e+06 9.19426e+07 25 25 } \
+                 { 1.90186e+06 9.38408e+07 25 25 } \
+                 { 1.90862e+06 9.57461e+07 25 25 } \
+                 { 1.91479e+06 9.76578e+07 25 25 } \
+                 { 1.9206e+06  9.95755e+07 27 26 } \
+                 { 1.92646e+06 1.01499e+08 27 26 } \
+                 { 1.93235e+06 1.03428e+08 27 26 } \
+                 { 1.9383e+06  1.05364e+08 27 26 } \
+                 { 1.94429e+06 1.07305e+08 27 26 } \
+                 { 1.95032e+06 1.09252e+08 27 26 } \
+                 { 1.95641e+06 1.11206e+08 27 26 } \
+                 { 1.96254e+06 1.13165e+08 27 26 } \
+                 { 1.96871e+06 1.15131e+08 27 26 } \
+                 { 1.97494e+06 1.17103e+08 27 26 } \
+                 { 1.9812e+06  1.19081e+08 27 26 } }
+
+perform_offset_increasing s 1 40 1 $ref_values
+
+copy r17 result
+copy r17_unif result_unif
+
+checkview -display result_unif -2d -path ${imagedir}/${test_image}.png
diff --git a/tests/offset/shape_type_i_c/XS5 b/tests/offset/shape_type_i_c/XS5
new file mode 100644 (file)
index 0000000..03d1ac0
--- /dev/null
@@ -0,0 +1,54 @@
+restore [locate_data_file bug30470_input_trim1.brep] s
+
+# perform offset operation with increasing offset value
+
+# set props and nb reference values to compare with
+
+# area volume nb_wire nb_face
+set ref_values { { 1.31124e+06 2.58872e+07 43 42 } \
+                 { 1.27726e+06 2.71815e+07 43 42 } \
+                 { 1.24279e+06 2.84416e+07 43 42 } \
+                 { 1.20783e+06 2.96669e+07 43 42 } \
+                 { 1.17237e+06 3.08571e+07 43 42 } \
+                 { 1.13642e+06 3.20115e+07 43 42 } \
+                 { 1.09997e+06 3.31297e+07 43 42 } \
+                 { 1.06303e+06 3.42113e+07 43 42 } \
+                 { 1.06451e+06 3.52701e+07 19 19 } \
+                 { 1.07229e+06 3.63398e+07 21 21 } \
+                 { 1.07578e+06 3.74139e+07 21 21 } \
+                 { 1.07899e+06 3.84913e+07 21 21 } \
+                 { 1.08193e+06 3.95718e+07 21 21 } \
+                 { 1.0846e+06  4.06551e+07 21 21 } \
+                 { 1.08699e+06 4.17409e+07 21 21 } \
+                 { 1.0891e+06  4.28289e+07 21 21 } \
+                 { 1.09094e+06 4.3919e+07  21 21 } \
+                 { 1.0925e+06  4.50107e+07 21 21 } \
+                 { 1.09379e+06 4.61039e+07 21 21 } \
+                 { 1.09481e+06 4.71982e+07 21 21 } \
+                 { 1.09555e+06 4.82934e+07 21 21 } \
+                 { 1.09601e+06 4.93892e+07 21 21 } \
+                 { 1.0962e+06  5.04853e+07 21 21 } \
+                 { 1.09611e+06 5.15815e+07 21 21 } \
+                 { 1.09952e+06 5.26781e+07 19 19 } \
+                 { 1.10994e+06 5.37829e+07 19 19 } \
+                 { 1.12041e+06 5.4898e+07  19 19 } \
+                 { 1.13093e+06 5.60237e+07 19 19 } \
+                 { 1.1415e+06  5.71599e+07 19 19 } \
+                 { 1.15211e+06 5.83067e+07 19 19 } \
+                 { 1.16276e+06 5.94641e+07 19 19 } \
+                 { 1.17347e+06 6.06323e+07 19 19 } \
+                 { 1.18422e+06 6.18111e+07 19 19 } \
+                 { 1.19502e+06 6.30007e+07 19 19 } \
+                 { 1.20586e+06 6.42011e+07 19 19 } \
+                 { 1.21675e+06 6.54124e+07 19 19 } \
+                 { 1.22769e+06 6.66347e+07 19 19 } \
+                 { 1.23867e+06 6.78678e+07 19 19 } \
+                 { 1.2497e+06  6.9112e+07  19 19 } \
+                 { 1.26077e+06 7.03672e+07 19 19 } }
+
+perform_offset_increasing s 1 40 1 $ref_values
+
+copy r17 result
+copy r17_unif result_unif
+
+checkview -display result_unif -2d -path ${imagedir}/${test_image}.png
diff --git a/tests/offset/shape_type_i_c/XS6 b/tests/offset/shape_type_i_c/XS6
new file mode 100644 (file)
index 0000000..d130c77
--- /dev/null
@@ -0,0 +1,54 @@
+restore [locate_data_file bug30470_input_trim2.brep] s
+
+# perform offset operation with increasing offset value
+
+# set props and nb reference values to compare with
+
+# area volume nb_wire nb_face
+set ref_values { { 1.0108e+06   1.99437e+07  33 32 } \
+                 { 981289       2.09398e+07  33 32 } \
+                 { 951548       2.19062e+07  33 32 } \
+                 { 921582       2.28428e+07  33 32 } \
+                 { 891389       2.37493e+07  33 32 } \
+                 { 860971       2.46255e+07  33 32 } \
+                 { 830326       2.54712e+07  33 32 } \
+                 { 799456       2.62861e+07  33 32 } \
+                 { 800096       2.70819e+07  16 16 } \
+                 { 808054       2.78866e+07  17 17 } \
+                 { 813891       2.86976e+07  17 17 } \
+                 { 819610       2.95143e+07  17 17 } \
+                 { 825212       3.03368e+07  17 17 } \
+                 { 830698       3.11647e+07  17 17 } \
+                 { 836069       3.19981e+07  17 17 } \
+                 { 841324       3.28368e+07  17 17 } \
+                 { 846463       3.36807e+07  17 17 } \
+                 { 851486       3.45297e+07  17 17 } \
+                 { 856393       3.53837e+07  17 17 } \
+                 { 861185       3.62425e+07  17 17 } \
+                 { 865860       3.7106e+07   17 17 } \
+                 { 870420       3.79741e+07  17 17 } \
+                 { 874865       3.88468e+07  17 17 } \
+                 { 879193       3.97238e+07  17 17 } \
+                 { 885288       4.06055e+07  16 16 } \
+                 { 894915       4.14956e+07  16 16 } \
+                 { 904587       4.23953e+07  16 16 } \
+                 { 914305       4.33047e+07  16 16 } \
+                 { 924067       4.42239e+07  16 16 } \
+                 { 933874       4.51529e+07  16 16 } \
+                 { 943726       4.60917e+07  16 16 } \
+                 { 953623       4.70404e+07  16 16 } \
+                 { 963565       4.7999e+07   16 16 } \
+                 { 973552       4.89675e+07  16 16 } \
+                 { 983584       4.99461e+07  16 16 } \
+                 { 993661       5.09347e+07  16 16 } \
+                 { 1.00378e+06  5.19334e+07  16 16 } \
+                 { 1.01395e+06  5.29423e+07  16 16 } \
+                 { 1.02416e+06  5.39613e+07  16 16 } \
+                 { 1.03442e+06  5.49906e+07  16 16 } }
+
+perform_offset_increasing s 1 40 1 $ref_values
+
+copy r17 result
+copy r17_unif result_unif
+
+checkview -display result_unif -2d -path ${imagedir}/${test_image}.png
diff --git a/tests/offset/shape_type_i_c/XS7 b/tests/offset/shape_type_i_c/XS7
new file mode 100644 (file)
index 0000000..2843892
--- /dev/null
@@ -0,0 +1,54 @@
+restore [locate_data_file bug30470_input_trim3.brep] s
+
+# perform offset operation with increasing offset value
+
+# set props and nb reference values to compare with
+
+# area volume nb_wire nb_face
+set ref_values { { 773892 1.5856e+07  23 22 } \
+                 { 749115 1.66175e+07 23 22 } \
+                 { 724383 1.73543e+07 23 22 } \
+                 { 699696 1.80663e+07 23 22 } \
+                 { 675053 1.87537e+07 23 22 } \
+                 { 650456 1.94164e+07 23 22 } \
+                 { 625904 2.00546e+07 23 22 } \
+                 { 601396 2.06682e+07 23 22 } \
+                 { 601493 2.12666e+07 13 13 } \
+                 { 609929 2.18723e+07 13 13 } \
+                 { 618409 2.24865e+07 13 13 } \
+                 { 626935 2.31091e+07 13 13 } \
+                 { 635505 2.37403e+07 13 13 } \
+                 { 644121 2.43802e+07 13 13 } \
+                 { 652781 2.50286e+07 13 13 } \
+                 { 661486 2.56857e+07 13 13 } \
+                 { 670236 2.63516e+07 13 13 } \
+                 { 679032 2.70262e+07 13 13 } \
+                 { 687872 2.77097e+07 13 13 } \
+                 { 696757 2.8402e+07  13 13 } \
+                 { 705687 2.91032e+07 13 13 } \
+                 { 714662 2.98134e+07 13 13 } \
+                 { 723682 3.05325e+07 13 13 } \
+                 { 732747 3.12607e+07 13 13 } \
+                 { 741857 3.1998e+07  13 13 } \
+                 { 751012 3.27445e+07 13 13 } \
+                 { 760212 3.35001e+07 13 13 } \
+                 { 769456 3.42649e+07 13 13 } \
+                 { 778746 3.5039e+07  13 13 } \
+                 { 788081 3.58224e+07 13 13 } \
+                 { 797461 3.66152e+07 13 13 } \
+                 { 806885 3.74174e+07 13 13 } \
+                 { 816355 3.8229e+07  13 13 } \
+                 { 825869 3.90501e+07 13 13 } \
+                 { 835429 3.98807e+07 13 13 } \
+                 { 845033 4.07209e+07 13 13 } \
+                 { 854683 4.15708e+07 13 13 } \
+                 { 864377 4.24303e+07 13 13 } \
+                 { 874116 4.32996e+07 13 13 } \
+                 { 883901 4.41786e+07 13 13 } }
+
+perform_offset_increasing s 1 40 1 $ref_values
+
+copy r17 result
+copy r17_unif result_unif
+
+checkview -display result_unif -2d -path ${imagedir}/${test_image}.png
diff --git a/tests/offset/shape_type_i_c/XS8 b/tests/offset/shape_type_i_c/XS8
new file mode 100644 (file)
index 0000000..7552036
--- /dev/null
@@ -0,0 +1,54 @@
+restore [locate_data_file bug30470_input_trim4.brep] s
+
+# perform offset operation with increasing offset value
+
+# set props and nb reference values to compare with
+
+# area volume nb_wire nb_face
+set ref_values { { 289134 4.40968e+06 16 16 } \
+                 { 288310 4.69842e+06 16 16 } \
+                 { 287307 4.98625e+06 16 16 } \
+                 { 286126 5.27298e+06 16 16 } \
+                 { 284767 5.55844e+06 16 16 } \
+                 { 283229 5.84245e+06 16 16 } \
+                 { 281513 6.12484e+06 16 16 } \
+                 { 279618 6.40542e+06 16 16 } \
+                 { 284722 6.68669e+06 9  9  } \
+                 { 292308 6.9752e+06  9  9  } \
+                 { 299985 7.27133e+06 9  9  } \
+                 { 307754 7.5752e+06  9  9  } \
+                 { 315614 7.88687e+06 9  9  } \
+                 { 323566 8.20645e+06 9  9  } \
+                 { 331611 8.53403e+06 9  9  } \
+                 { 339748 8.86971e+06 9  9  } \
+                 { 347978 9.21356e+06 9  9  } \
+                 { 356301 9.56569e+06 9  9  } \
+                 { 364716 9.92619e+06 9  9  } \
+                 { 373224 1.02952e+07 9  9  } \
+                 { 381824 1.06727e+07 9  9  } \
+                 { 390517 1.10588e+07 9  9  } \
+                 { 399302 1.14537e+07 9  9  } \
+                 { 408180 1.18575e+07 9  9  } \
+                 { 417150 1.22701e+07 9  9  } \
+                 { 426213 1.26918e+07 9  9  } \
+                 { 435369 1.31226e+07 9  9  } \
+                 { 444617 1.35626e+07 9  9  } \
+                 { 453958 1.40118e+07 9  9  } \
+                 { 463391 1.44705e+07 9  9  } \
+                 { 472917 1.49387e+07 9  9  } \
+                 { 482536 1.54164e+07 9  9  } \
+                 { 492247 1.59038e+07 9  9  } \
+                 { 502050 1.64009e+07 9  9  } \
+                 { 511947 1.69079e+07 9  9  } \
+                 { 521935 1.74248e+07 9  9  } \
+                 { 532017 1.79518e+07 9  9  } \
+                 { 542190 1.84889e+07 9  9  } \
+                 { 552457 1.90362e+07 9  9  } \
+                 { 562816 1.95938e+07 9  9  } }
+
+perform_offset_increasing s 1 40 1 $ref_values
+
+copy r17 result
+copy r17_unif result_unif
+
+checkview -display result_unif -2d -path ${imagedir}/${test_image}.png
diff --git a/tests/offset/shape_type_i_c/XS9 b/tests/offset/shape_type_i_c/XS9
new file mode 100644 (file)
index 0000000..46e9515
--- /dev/null
@@ -0,0 +1,54 @@
+restore [locate_data_file bug30470_input_trim5.brep] s
+
+# perform offset operation with increasing offset value
+
+# set props and nb reference values to compare with
+
+# area volume nb_wire nb_face
+set ref_values { { 253148 3.95828e+06 17 17 } \
+                 { 250484 4.21012e+06 17 17 } \
+                 { 247598 4.45918e+06 17 17 } \
+                 { 244489 4.70524e+06 17 17 } \
+                 { 241158 4.94808e+06 17 17 } \
+                 { 237603 5.18748e+06 17 17 } \
+                 { 233826 5.42321e+06 17 17 } \
+                 { 229826 5.65506e+06 17 17 } \
+                 { 232781 5.88547e+06 10 10 } \
+                 { 238173 6.12094e+06 10 10 } \
+                 { 243612 6.36183e+06 10 10 } \
+                 { 249098 6.60818e+06 10 10 } \
+                 { 254631 6.86004e+06 10 10 } \
+                 { 260212 7.11746e+06 10 10 } \
+                 { 265841 7.38048e+06 10 10 } \
+                 { 271519 7.64915e+06 10 10 } \
+                 { 277245 7.92353e+06 10 10 } \
+                 { 283018 8.20366e+06 10 10 } \
+                 { 288841 8.48958e+06 10 10 } \
+                 { 294711 8.78136e+06 10 10 } \
+                 { 300630 9.07902e+06 10 10 } \
+                 { 306597 9.38263e+06 10 10 } \
+                 { 312612 9.69223e+06 10 10 } \
+                 { 318675 1.00079e+07 10 10 } \
+                 { 324787 1.03296e+07 10 10 } \
+                 { 330946 1.06575e+07 10 10 } \
+                 { 337154 1.09915e+07 10 10 } \
+                 { 343411 1.13318e+07 10 10 } \
+                 { 349715 1.16783e+07 10 10 } \
+                 { 356068 1.20312e+07 10 10 } \
+                 { 362469 1.23905e+07 10 10 } \
+                 { 368918 1.27562e+07 10 10 } \
+                 { 375415 1.31283e+07 10 10 } \
+                 { 381961 1.3507e+07  10 10 } \
+                 { 388555 1.38923e+07 10 10 } \
+                 { 395197 1.42842e+07 10 10 } \
+                 { 401887 1.46827e+07 10 10 } \
+                 { 408625 1.50879e+07 10 10 } \
+                 { 415412 1.55e+07    10 10 } \
+                 { 422247 1.59188e+07 10 10 } }
+
+perform_offset_increasing s 1 40 1 $ref_values
+
+copy r17 result
+copy r17_unif result_unif
+
+checkview -display result_unif -2d -path ${imagedir}/${test_image}.png
diff --git a/tests/offset/shape_type_i_c/XT1 b/tests/offset/shape_type_i_c/XT1
new file mode 100644 (file)
index 0000000..2567e28
--- /dev/null
@@ -0,0 +1,20 @@
+puts "TODO CR27414 ALL: Error : The area of result shape is"
+puts "TODO CR27414 ALL: Error : The volume of result shape is"
+puts "TODO CR27414 ALL: Error :  is WRONG because number of"
+
+polyline p 0 0 0 0 0 10 2 0 10 2 0 2 3 0 6 5 0 6 5 0 0 0 0 0
+mkplane f p
+prism s f 0 5 0
+
+offsetparameter 1e-7 c i r
+offsetload s 1
+explode s f
+offsetonface s_4 6
+offsetperform result
+
+checkprops result -s 410 -v 504
+
+unifysamedom result_unif result
+checknbshapes result_unif -vertex 12 -edge 18 -wire 8 -face 8 -shell 1 -solid 1
+
+checkview -display result_unif -2d -path ${imagedir}/${test_image}.png
diff --git a/tests/offset/shape_type_i_c/XT2 b/tests/offset/shape_type_i_c/XT2
new file mode 100644 (file)
index 0000000..35b34b8
--- /dev/null
@@ -0,0 +1,16 @@
+polyline p 0 0 0 0 0 10 2 0 10 2 0 2 3 0 6 5 0 6 5 0 0 0 0 0
+mkplane f p
+prism s f 0 5 0
+
+offsetparameter 1e-7 c i r
+offsetload s 1
+explode s f
+offsetonface s_4 4.5
+offsetperform result
+
+checkprops result -s 410 -v 504
+
+unifysamedom result_unif result
+checknbshapes result_unif -vertex 12 -edge 18 -wire 8 -face 8 -shell 1 -solid 1
+
+checkview -display result_unif -2d -path ${imagedir}/${test_image}.png
index eb86413..86335bb 100644 (file)
@@ -1,11 +1,10 @@
-puts "TODO OCC27414 ALL: Error: The command cannot be built"
-puts "TODO OCC27414 ALL: gives an empty result"
-puts "TODO OCC27414 ALL: TEST INCOMPLETE"
+puts "TODO CR27414 ALL: Error : The area of result shape is"
+puts "TODO CR27414 ALL: Faulty shapes in variables faulty_1 to faulty_"
 
 restore [locate_data_file bug26917_M2_trim34.brep] s
 
 OFFSETSHAPE 8 {} $calcul $type
 
-checkprops result -v 0
+checkprops result -s 0
 
 checknbshapes result -shell 1
index f6dbca5..5597787 100644 (file)
@@ -1,4 +1,147 @@
-#Shell no rough and rounded mode
-
+# Mode - Complete
 set calcul "c"
+# Join type - Intersection
 set type "i"
+
+proc compare_prop_values {prop m_res m_ref} {
+  if { ($m_ref != 0 && abs (($m_ref - $m_res) / double($m_ref)) > 1.e-2) || ($m_res == 0 && $m_ref != 0) } {
+    puts "Error: The $prop of result shape is $m_res, expected $m_ref"
+    return 0
+  } else {
+    puts "OK: The $prop of result shape is as expected"
+    return 1
+  }
+}
+
+proc compare_nbs {entity nb_res nb_ref} {
+  if {$nb_res != $nb_ref} {
+    puts "Error: number of $entity entities in the result shape is $nb_res, expected $nb_ref"
+    return 0
+  } else {
+    puts "OK: number of $entity entities in the result shape is as expected"
+    return 1
+  }
+}
+
+proc perform_offset {theShape theValue} {
+  upvar $theShape TheShape
+  
+  global r${theValue}
+  global r${theValue}_unif
+
+  tcopy TheShape sx
+  offsetparameter 1.e-7 c i r
+  offsetload sx ${theValue}
+  offsetperform r${theValue}
+  
+  if {![catch { checkshape r${theValue} } ] } {
+    unifysamedom r${theValue}_unif r${theValue}
+    return 1
+  }
+  return 0
+}
+
+proc perform_offsets {theShape theOffsetValues theRefValues} {
+
+  upvar $theShape TheShape
+  
+  set nbRefValues [llength $theRefValues]
+  
+  set failed_operations {}
+  set statistics {}
+
+  set i 0
+  
+  foreach offset $theOffsetValues { 
+    
+    global r${offset}
+    global r${offset}_unif
+
+    set operation_done [perform_offset TheShape ${offset}]
+    
+    # stats
+    set area_value 0
+    set volume_value 0
+    set nbwires_value 0
+    set nbfaces_value 0
+    
+    set checks_res {}
+    
+    if { $operation_done } {
+   
+      set area_value [lindex [sprops r${offset}] 2]
+      set volume_value [lindex [vprops r${offset}] 2]
+      
+      set check 0
+      set refs {}
+      
+      if { $nbRefValues > $i } {
+        set refs [lindex $theRefValues $i]
+        if { [llength $refs] == 4} {
+          set check 1
+        }
+      }
+      
+      if { $check } {
+        lappend checks_res [compare_prop_values "area" ${area_value} [lindex $refs 0]]
+        lappend checks_res [compare_prop_values "volume" ${volume_value} [lindex $refs 1]]
+      }
+
+      set nbshapes_value [nbshapes r${offset}_unif]
+      set nbwires_value [lindex $nbshapes_value 13]
+      set nbfaces_value [lindex $nbshapes_value 16]
+      set nbshells_value [lindex $nbshapes_value 19]
+      set nbsolids_value [lindex $nbshapes_value 22]
+    
+      if { $check } {
+        lappend checks_res [compare_nbs "wire" $nbwires_value [lindex $refs 2]]
+        lappend checks_res [compare_nbs "face" $nbfaces_value [lindex $refs 3]]
+      }
+      
+      lappend checks_res [compare_nbs "shell" $nbshells_value 1]
+      lappend checks_res [compare_nbs "solid" $nbsolids_value 1]
+    }
+
+    set OK $operation_done
+    
+    if {$OK == 1} {
+      foreach x $checks_res {
+        if {$x == 0} {
+          set OK 0
+          break
+        }
+      }
+    }
+    
+    set status "OK"
+    if { $OK == 0 } {
+      puts "Error: operation with offset value ${offset} has failed"
+      
+      lappend failed_operations ${offset}
+      set status "KO"
+    }
+    
+    lappend statistics "Offset value ${offset} - $status: area - ${area_value};\t volume - ${volume_value};\t wires - ${nbwires_value};\t faces - ${nbfaces_value}"
+    incr i
+  }
+  
+  if {[llength $failed_operations] > 0} {
+    puts "Operations with following offset values have failed: $failed_operations"
+  }
+  
+  puts "Statistics:"
+  foreach str $statistics { puts "\t$str" }
+}
+
+proc perform_offset_increasing {theShape theMinVal theStopVal theStep theRefValues} {
+
+  upvar $theShape TheShape
+
+  set values {}
+  
+  for {set i $theMinVal} {$i <= $theStopVal} {set i [expr $i + $theStep]} {
+    lappend values $i
+  }
+  
+  perform_offsets TheShape $values $theRefValues
+}