0029363: No history for shapes which were produced as a result of intersection
authoremv <emv@opencascade.com>
Tue, 12 Dec 2017 12:10:37 +0000 (15:10 +0300)
committerbugmaster <bugmaster@opencascade.com>
Wed, 20 Dec 2017 15:50:21 +0000 (18:50 +0300)
1. Implementation of the *Generated* method for the algorithms in Boolean Component.
In terms of these algorithms the shape from the arguments can have Generated shapes only if these new shapes have been obtained as a result of pure intersection (not overlapping) of this shape with any other shapes from arguments.
Thus, the Generated shapes are always:
* VERTICES created from the intersection points and may be Generated from edges and faces only;
* EDGES created from the intersection edges and may be Generated from faces only.

So, only EDGES and FACES could have information about Generated shapes. For all other types of shapes the list of Generated shapes will be empty.

2. Optimization and simplification of the Modified and IsDeleted methods based on the correct filling of the BOPAlgo_BuilderShape::myImagesResult map.

3. Provide history of unification of the solids in the CellsBuilder algorithm.

4. Update of the documentation of Boolean Operations User guide with new chapter "History Information" describing rules for filling history for operations in Boolean Component.

5. Test cases for the issue. New grid "history" has been added into "boolean" category.

17 files changed:
dox/dev_guides/upgrade/upgrade.md
dox/user_guides/boolean_operations/boolean_operations.md
src/BOPAlgo/BOPAlgo_Builder.hxx
src/BOPAlgo/BOPAlgo_BuilderShape.cxx
src/BOPAlgo/BOPAlgo_Builder_4.cxx
src/BOPAlgo/BOPAlgo_CellsBuilder.cxx
src/BOPAlgo/BOPAlgo_CellsBuilder.hxx
src/BOPAlgo/BOPAlgo_Section.cxx
src/BOPAlgo/BOPAlgo_Section.hxx
tests/boolean/grids.list
tests/boolean/history/A1 [new file with mode: 0644]
tests/boolean/history/A2 [new file with mode: 0644]
tests/boolean/history/A3 [new file with mode: 0644]
tests/boolean/history/A4 [new file with mode: 0644]
tests/boolean/history/A5 [new file with mode: 0644]
tests/boolean/history/A6 [new file with mode: 0644]
tests/bugs/caf/bug24869

index 7a3d447..5812e38 100644 (file)
@@ -1520,3 +1520,7 @@ Multiple changes have been applied to lights management within TKV3d and TKOpenG
   but it is now possible defining light of any type by creating base class Graphic3d_CLight directly.
   Dedicated classes only hides visibility of unrelated light properties depending on its type.
 * Calling V3d_Viewer::UpdateLights() is no more required after modifying light sources properties (color, position, etc.).
+
+@subsection upgrade_730_BOPAlgo_Section Changes in BOPAlgo_Section
+
+The public method *BuildSection()* in the class *BOPAlgo_Section* has became protected. The methods *Perform()* or *PerformWithFiller()* should be called for construction of the result of SECTION operation.
index 2668447..27bf539 100644 (file)
@@ -2929,6 +2929,159 @@ Warning: The positioning of the shapes leads to creation of small edges without
 ~~~~
 
 
+@section occt_algorithms_history History Information
+
+The chapter describes the rules for filling the History Information (or just History) for the arguments of the operations in Boolean Component.
+The History is available only for the VERTICES, EDGES, FACES and SOLIDS from the input arguments.
+
+The History allows tracking the modification of the input shapes during the operation. It consists of the following information:
+* Information about Deleted shapes;
+* Information about Modified shapes;
+* Information about Generated shapes;
+
+All History information is filled basing on the result of current operation. History cannot return any shapes not contained in the result.
+Thus if the result of the operation is empty shape, all input shapes will be considered as Deleted and none will have Modified and Generated shapes.
+
+@subsection occt_algorithms_history_del Deleted shapes
+
+The shape is considered as Deleted if the result shape do not contain the shape itself and none of its splits.
+For example, the result of CUT operation of two overlapping planar faces (see the example below) does not contain any parts from the tool face. Thus, the tool faces is considered as Deleted.
+If the faces are not fully coinciding, the result must contain some parts of the object face. In this case object face will be considered as not deleted.
+But if the faces are fully coinciding, the result must be empty, and both faces will be considered as Deleted.
+
+To get the information about Deleted shapes it is necessary to use the method *Standard_Boolean IsDeleted(const TopoDS_Shape& theS)*.
+
+To get the information about Deleted shapes in DRAW it is necessary to use the command *bisdeleted shape*.
+
+Example of the overlapping faces:
+
+~~~~
+plane p 0 0 0 0 0 1
+mkface f1 p -10 10 -10 10
+mkface f2 p 0 20 -10 10
+
+bclearobjects
+bcleartools
+baddobjects f1
+baddtools f2
+bfillds
+bbop r 2
+
+bisdeleted f1
+# Not deleted
+
+bisdeleted f2
+# Deleted
+~~~~
+
+@subsection occt_algorithms_history_modif Modified shapes
+
+The shape is considered as Modified if the result shape contains any of the splits of the shape, not the shape itself. The shape can be modified only into the shapes with same dimension.
+The splits of the shape contained in the result shape are Modified from the shape.
+
+For example, in the FUSE operation of two edges intersecting in one point (see the example below), both edges will be split by the intersection point. All these splits will be contained in the result.
+Thus, each of the input edges will be Modified into its two splits.
+But in the CUT operation on the same edges, the tool edge will be Deleted from the result and, thus, will not have any Modified shapes.
+
+To get the information about Modified shapes it is necessary to use the method *const TopTools_ListOfShape& Modified(const TopoDS_Shape& theS)*.
+The list of Modified elements will contain only those which are contained in the result of the operation. If the list is empty the shape has not been modified and it is necessary to check if it has been Deleted.
+
+To get the information about Modified shapes in DRAW it is necessary to use the command *bmodified modif shape*.
+
+Example of the intersecting edges:
+
+~~~~
+line l1 0 0 0 1 0 0
+mkedge e1 l1 -10 10
+
+line l2 0 0 0 0 1 0
+mkedge e2 l2 -10 10
+
+bclearobjects
+bcleartools
+baddobjects e1
+baddtools e2
+bfillds
+
+# fuse operation
+bbop r 1
+
+bmodified m1 e1
+nbshapes m1
+# EDGES: 2
+
+bmodified m2 e2
+nbshapes m2
+# EDGES: 2
+
+# cut operation
+bbop r 2
+
+bmodified m1 e1
+nbshapes m1
+# EDGES: 2
+
+bmodified m2 e2
+# The shape has not been modified
+
+~~~~
+
+
+@subsection occt_algorithms_history_gen Generated shapes
+
+In terms of the algorithms in Boolean Component the shape from the arguments can have Generated shapes only if these new shapes have been obtained as a result of pure intersection (not overlapping)
+of this shape with any other shapes from arguments. Thus, the Generated shapes are always:
+* VERTICES created from the intersection points and may be Generated from edges and faces only;
+* EDGES created from the intersection edges and may be Generated from faces only.
+
+So, only EDGES and FACES could have information about Generated shapes. For all other types of shapes the list of Generated shapes will be empty.
+
+For example, the two intersecting edges will both have the intersection vertices Generated from them.
+
+To get the information about Generated shapes it is necessary to use the method *const TopTools_ListOfShape& Generated(const TopoDS_Shape& theS)*.
+The list of Generated elements will contain only those which are contained in the result of the operation. If the list is empty no new shapes have been Generated from the shape.
+
+To get the information about Generated shapes in DRAW it is necessary to use the command *bgenerated gen shape*.
+
+Example of interfering faces
+
+~~~~
+plane p1 0 0 0 0 0 1
+mkface f1 p1 -10 10 -10 10
+
+plane p2 0 0 0 1 0 0
+mkface f2 p2 -10 10 -10 10
+
+bclearobjects
+bcleartools
+baddobjects f1
+baddtools f2
+bfillds
+
+# fuse operation
+bbop r 1
+
+bgenerated gf1 f1
+nbshapes gf1
+# EDGES: 1
+
+bgenerated gf2 f2
+nbshapes gf2
+# EDGES: 1
+
+
+# common operation - result is empty
+bbop r 0
+
+bgenerated gf1 f1
+# No shapes were generated from the shape
+
+bgenerated gf2 f2
+# No shapes were generated from the shape
+
+~~~~
+
+
 @section occt_algorithms_11b Usage 
 
 The chapter contains some examples of the OCCT Boolean Component usage. The usage is possible on two levels: C++ and Tcl. 
index 3ccbad0..6f46abb 100644 (file)
@@ -172,17 +172,39 @@ public: //! @name Performing the operation
 
 public: //! @name History methods
 
-  //! Returns the  list of shapes generated from the
-  //! shape theS.
+  //! Returns the  list of shapes generated from the shape theS.
   Standard_EXPORT virtual const TopTools_ListOfShape& Generated (const TopoDS_Shape& theS) Standard_OVERRIDE;
 
-  //! Returns the list of shapes modified from the shape
-  //! theS.
+  //! Returns the list of shapes modified from the shape theS.
   Standard_EXPORT virtual const TopTools_ListOfShape& Modified (const TopoDS_Shape& theS) Standard_OVERRIDE;
 
   //! Returns true if the shape theS has been deleted.
   Standard_EXPORT virtual Standard_Boolean IsDeleted (const TopoDS_Shape& theS) Standard_OVERRIDE;
 
+protected: //! @name History methods
+
+  //! Prepare information for history support.
+  Standard_EXPORT virtual void PrepareHistory() Standard_OVERRIDE;
+
+  //! Prepare history information for the input shapes taking into account possible
+  //! operation-specific modifications.
+  //! For instance, in the CellsBuilder operation, additionally to splitting input shapes
+  //! the splits of the shapes (or the shapes themselves) may be unified during removal of internal
+  //! boundaries. In this case each split should be linked to the unified shape.
+  //!
+  //! To have correct history information, the method should be redefined in each operation
+  //! where such additional modification is possible. The input shape <theS> should be the one from arguments,
+  //! and the returning list should contain all final elements to which the input shape has evolved,
+  //! including those not contained in the result shape.
+  //!
+  //! The method returns pointer to the list of modified elements.
+  //! NULL pointer means that the shape has not been modified at all.
+  //!
+  //! The General Fuse operation does not perform any other modification than splitting the input
+  //! shapes basing on their intersection information. This information is contained in myImages map.
+  //! Thus, here the method returns only splits (if any) contained in this map.
+  Standard_EXPORT virtual const TopTools_ListOfShape* LocModified(const TopoDS_Shape& theS);
+
 
 public: //! @name Images/Origins
 
@@ -217,9 +239,6 @@ protected: //! @name Methods for building the result
   //! it will be necessary to override this method.
   Standard_EXPORT virtual void PerformInternal1 (const BOPAlgo_PaveFiller& thePF);
 
-  //! Prepare information for history support.
-  Standard_EXPORT virtual void PrepareHistory() Standard_OVERRIDE;
-
   //! Builds the result of operation.
   //! The method is called for each of the arguments type and
   //! adds into the result the splits of the arguments of that type.
index ebeb2c9..f6b4876 100644 (file)
 {
   myHistShapes.Clear();
   myMapShape.Clear();
+  myImagesResult.Clear();
   myHasDeleted=Standard_False;
   myHasGenerated=Standard_False;
   myHasModified=Standard_False;
index a495287..91b3dab 100644 (file)
@@ -17,9 +17,9 @@
 
 
 #include <BOPAlgo_Builder.hxx>
-#include <BOPAlgo_PaveFiller.hxx>
 #include <BOPDS_DS.hxx>
 #include <BOPTools_AlgoTools.hxx>
+#include <BOPTools_AlgoTools3D.hxx>
 #include <IntTools_Context.hxx>
 #include <TopExp.hxx>
 #include <TopoDS_Iterator.hxx>
 //purpose  : 
 //=======================================================================
 const TopTools_ListOfShape& BOPAlgo_Builder::Generated
-  (const TopoDS_Shape&)
+  (const TopoDS_Shape& theS)
 {
+  // The rules for Generated shapes are these:
+  // 1. The EDGE may be generated from the FACES as an intersection edge;
+  // 2. The VERTEX may be generated from the EDGES and FACES as an intersection vertex.
+  //
+  // The list of generated elements will contain only those which are contained
+  // in the result of the operation.
+
   myHistShapes.Clear();
+
+  if (!myHasGenerated)
+    return myHistShapes;
+
+  if (theS.IsNull())
+    return myHistShapes;
+
+  // Only EDGES and FACES should be considered
+  TopAbs_ShapeEnum aType = theS.ShapeType();
+  if (aType != TopAbs_EDGE && aType != TopAbs_FACE)
+    // Wrong type
+    return myHistShapes;
+
+  // Check that DS contains the shape, i.e. it is from the arguments of the operation
+  Standard_Integer nS = myDS->Index(theS);
+  if (nS < 0)
+    // Unknown shape
+    return myHistShapes;
+
+  // Check that the shape has participated in any intersections
+  const BOPDS_ShapeInfo& aSI = myDS->ShapeInfo(nS);
+  if (!aSI.HasReference())
+    // Untouched shape
+    return myHistShapes;
+
+  // Analyze all types of Interferences which can produce
+  // new vertices - Edge/Edge and Edge/Face
+  BOPDS_VectorOfInterfEE& aEEs = myDS->InterfEE();
+  BOPDS_VectorOfInterfEF& aEFs = myDS->InterfEF();
+
+  // Fence map to avoid duplicates in the list of Generated;
+  TColStd_MapOfInteger aMFence;
+
+  // Analyze each interference and find those in which the given shape has participated
+
+  // No need to analyze Edge/Edge interferences for the shapes of type FACE
+  Standard_Boolean isFace = (aType == TopAbs_FACE);
+
+  for (Standard_Integer k = (isFace ? 1 : 0); k < 2; ++k)
+  {
+    Standard_Integer aNbLines = !k ? aEEs.Length() : aEFs.Length();
+    for (Standard_Integer i = 0; i < aNbLines; ++i)
+    {
+      BOPDS_Interf *aInt = !k ? (BOPDS_Interf*)(&aEEs(i)) : (BOPDS_Interf*)(&aEFs(i));
+      if (!aInt->HasIndexNew())
+        // No new vertices created
+        continue;
+
+      if (!aInt->Contains(nS))
+        continue;
+
+      Standard_Integer nVNew = aInt->IndexNew();
+      myDS->HasShapeSD(nVNew, nVNew);
+      if (!aMFence.Add(nVNew))
+        continue;
+
+      // Get the new vertex
+      const TopoDS_Shape& aVNew = myDS->Shape(nVNew);
+
+      // Check that the result shape contains vertex
+      if (myMapShape.Contains(aVNew))
+        // Save the vertex as generated
+        myHistShapes.Append(aVNew);
+    }
+  }
+
+  if (!isFace)
+    return myHistShapes;
+
+  // For the FACE it is also necessary to collect all
+  // section elements created in FACE/FACE interferences.
+  // This information is available in the FaceInfo structure.
+  const BOPDS_FaceInfo& aFI = myDS->FaceInfo(nS);
+
+  // Section edges of the face
+  const BOPDS_IndexedMapOfPaveBlock& aMPBSc = aFI.PaveBlocksSc();
+  // Save section edges contained in the result shape
+  Standard_Integer aNb = aMPBSc.Extent();
+  for (Standard_Integer i = 1; i <= aNb; ++i)
+  {
+    const TopoDS_Shape& aENew = myDS->Shape(aMPBSc(i)->Edge());
+    if (myMapShape.Contains(aENew))
+      myHistShapes.Append(aENew);
+  }
+
+  // Section vertices of the face
+  const TColStd_MapOfInteger& aMVSc = aFI.VerticesSc();
+  // Save section vertices contained in the result shape
+  TColStd_MapOfInteger::Iterator aItM(aMVSc);
+  for (; aItM.More(); aItM.Next())
+  {
+    const TopoDS_Shape& aVNew = myDS->Shape(aItM.Value());
+    if (myMapShape.Contains(aVNew))
+      myHistShapes.Append(aVNew);
+  }
+
   return myHistShapes;
 }
 //=======================================================================
@@ -44,99 +147,59 @@ const TopTools_ListOfShape& BOPAlgo_Builder::Generated
 const TopTools_ListOfShape& BOPAlgo_Builder::Modified
   (const TopoDS_Shape& theS)
 {
-  Standard_Boolean bHasImage, bToReverse;
-  TopAbs_ShapeEnum aType;
-  TopTools_ListIteratorOfListOfShape aIt;
-  //
   myHistShapes.Clear();
-  //
-  if (theS.IsNull()) {
+
+  if (!myHasModified)
+    // No modified elements
     return myHistShapes;
-  }
-  //
-  bHasImage=myImages.IsBound(theS);
-  if (!bHasImage) {
+
+  const TopTools_ListOfShape* pLSp = myImagesResult.Seek(theS);
+  if (!pLSp)
+    // No track in the result -> no modified
     return myHistShapes;
+
+  // For modification check if the shape is not linked to itself
+  if (pLSp->Extent() == 1)
+  {
+    if (theS.IsSame(pLSp->First()) && !myImages.IsBound(theS))
+      // Shape is not modified
+      return myHistShapes;
   }
-  //
-  aType=theS.ShapeType();
-  //
-  if (!(aType==TopAbs_EDGE   || aType==TopAbs_FACE || 
-      aType==TopAbs_VERTEX || aType==TopAbs_SOLID)) {
-    return myHistShapes;
-  } 
-  //
-  //PrepareHistory();
-  //
-  const TopTools_ListOfShape& aLSp=myImages.Find(theS);
-  aIt.Initialize(aLSp);
-  for (; aIt.More(); aIt.Next()) {
-    TopoDS_Shape aSp=aIt.Value();
-    if (myShapesSD.IsBound(aSp)) {
-      aSp = myShapesSD.Find(aSp);
-    }
-    //
-    if (myMapShape.Contains(aSp)) {
-      //
-      if (aType==TopAbs_VERTEX || aType==TopAbs_SOLID) {
-        aSp.Orientation(theS.Orientation());
-      }
-      else {
-        bToReverse=
-          BOPTools_AlgoTools::IsSplitToReverse(aSp, theS, myContext);
-        if (bToReverse) {
-          aSp.Reverse();
-        }
-      }
-      //
-      myHistShapes.Append(aSp);
-    }
+
+  // Iterate on all splits and save them with proper orientation into the result list
+  TopTools_ListIteratorOfListOfShape aIt(*pLSp);
+  for (; aIt.More(); aIt.Next())
+  {
+    TopoDS_Shape aSp = aIt.Value();
+    // Use the orientation of the input shape
+    TopAbs_ShapeEnum aType = aSp.ShapeType();
+    if (aType == TopAbs_VERTEX || aType == TopAbs_SOLID)
+      aSp.Orientation(theS.Orientation());
+    else if (BOPTools_AlgoTools::IsSplitToReverse(aSp, theS, myContext))
+      aSp.Reverse();
+
+    myHistShapes.Append(aSp);
   }
-  //
+
   return myHistShapes;
 }
 //=======================================================================
 //function : IsDeleted
 //purpose  : 
 //=======================================================================
-Standard_Boolean BOPAlgo_Builder::IsDeleted
-  (const TopoDS_Shape& theS)
+Standard_Boolean BOPAlgo_Builder::IsDeleted(const TopoDS_Shape& theS)
 {
-  Standard_Boolean bRet;
-  TopAbs_ShapeEnum aType;
-  TopTools_ListIteratorOfListOfShape aIt;
-  //
-  bRet = Standard_True;
-  //
-  if (theS.IsNull()) {
-    return bRet;
-  }
-  //
-  aType = theS.ShapeType();
-  if (!(aType==TopAbs_EDGE || aType==TopAbs_FACE || 
-      aType==TopAbs_VERTEX || aType==TopAbs_SOLID)) {
-    return bRet;
-  }
-  //
-  if (!myImages.IsBound(theS)) {
-    bRet = !myMapShape.Contains(theS);
-    return bRet;
-  }
-  //
-  const TopTools_ListOfShape& aLSp = myImages.Find(theS);
-  aIt.Initialize(aLSp);
-  for (; aIt.More(); aIt.Next()) {
-    const TopoDS_Shape& aSp = aIt.Value();
-    const TopoDS_Shape& aSpR = myShapesSD.IsBound(aSp) ? 
-      myShapesSD.Find(aSp) : aSp;
-    //
-    if (myMapShape.Contains(aSpR)) {                   
-      bRet = Standard_False;
-      break;
-    }
-  }
-  //
-  return bRet;
+  // The shape is considered as Deleted if the result shape
+  // does not contain the shape itself and none of its splits
+  return myHasDeleted && !myImagesResult.Contains(theS);
+}
+//=======================================================================
+//function : LocModified
+//purpose  : 
+//=======================================================================
+const TopTools_ListOfShape* BOPAlgo_Builder::LocModified(const TopoDS_Shape& theS)
+{
+  return myImages.Seek(theS);
 }
 //=======================================================================
 //function : PrepareHistory
@@ -144,85 +207,100 @@ Standard_Boolean BOPAlgo_Builder::IsDeleted
 //=======================================================================
 void BOPAlgo_Builder::PrepareHistory()
 {
-  if (!myFlagHistory) {
+  if (!myFlagHistory)
+  {
+    // Clearing
+    BOPAlgo_BuilderShape::PrepareHistory();
     return;
   }
-  //
-  if(myShape.IsNull()) {
+
+  // Clearing from previous operations
+  BOPAlgo_BuilderShape::PrepareHistory();
+  myFlagHistory = Standard_True;
+
+  if (myShape.IsNull() ||
+      BOPTools_AlgoTools3D::IsEmptyShape(myShape))
+  {
+    // The result shape is a null shape or empty shape,
+    // thus, no modified, no generated, all deleted
+    myHasModified = Standard_False;
+    myHasGenerated = Standard_False;
+    myHasDeleted = Standard_True;
     return;
   }
-  //
-  Standard_Boolean bHasImage;
-  TopAbs_ShapeEnum aType;
-  TopTools_MapOfShape aMS;
-  TopTools_ListIteratorOfListOfShape aIt;
-  TopTools_MapIteratorOfMapOfShape aItM;
-  //
-  // 1. Clearing 
-  BOPAlgo_BuilderShape::PrepareHistory();
-  //
-  // 2. myMapShape - all shapes of result with theirs sub-shapes 
+
+  // Map the result shape
   TopExp::MapShapes(myShape, myMapShape);
-  //
-  // 3. MS - all argument shapes with theirs sub-shapes
-  const TopTools_ListOfShape& aArguments=myDS->Arguments();
-  aIt.Initialize(aArguments);
-  for (; aIt.More(); aIt.Next()) {
-    const TopoDS_Shape& aSx=aIt.Value();
-    TopExp::MapShapes(aSx, aMS);
-  }
-  //
-  // 4. Treatment
-  aItM.Initialize(aMS);
-  for (; aItM.More(); aItM.Next()) {
-    const TopoDS_Shape& aSx=aItM.Key();
-    aType = aSx.ShapeType();
-    if (!(aType == TopAbs_VERTEX || aType == TopAbs_EDGE || 
-          aType == TopAbs_FACE   || aType == TopAbs_SOLID)) {
+
+  // Among all input shapes find those that have any trace in the result
+  // and save them into myImagesResult map with connection to parts
+  // kept in the result shape.
+  // Also, set the proper values to the history flags:
+  // - myHasDeleted for Deleted shapes;
+  // - myHasModified for Modified shapes;
+  // - myHasGenerated for Generated shapes.
+  Standard_Integer aNbS = myDS->NbSourceShapes();
+  for (Standard_Integer i = 0; i < aNbS; ++i)
+  {
+    const TopoDS_Shape& aS = myDS->Shape(i);
+
+    // History information is only available for the shapes of type
+    // VERTEX, EDGE, FACE and SOLID. Skip all shapes of different type.
+    TopAbs_ShapeEnum aType = aS.ShapeType();
+    if (!(aType == TopAbs_VERTEX ||
+          aType == TopAbs_EDGE   ||
+          aType == TopAbs_FACE   ||
+          aType == TopAbs_SOLID))
       continue;
+
+    // Check if the shape has any splits
+    const TopTools_ListOfShape* pLSp = LocModified(aS);
+    if (!pLSp)
+    {
+      // No splits, check if the result shape contains the shape itself
+      if (myMapShape.Contains(aS))
+        // Shape has passed into result without modifications -> link the shape to itself
+        myImagesResult(myImagesResult.Add(aS, TopTools_ListOfShape())).Append(aS);
+      else
+        // No trace of the shape in the result -> Deleted element is found
+        myHasDeleted = Standard_True;
     }
-    //
-    // 4.1 .myImagesResult
-    bHasImage=myImages.IsBound(aSx); 
-    //
-    TopTools_ListOfShape aLSx;
-    if (!bHasImage) {
-      if (myMapShape.Contains(aSx)) {
-        aLSx.Append(aSx);
-        myImagesResult.Add(aSx, aLSx);
-      }
-    }
-    else {
-      const TopTools_ListOfShape& aLSp=myImages.Find(aSx);
-      aIt.Initialize(aLSp);
-      for (; aIt.More(); aIt.Next()) {
-        const TopoDS_Shape& aSp=aIt.Value();
-        if (myMapShape.Contains(aSp)) {
-          aLSx.Append(aSp);
+    else
+    {
+      // Find all splits of the shape which are kept in the result
+      TopTools_ListOfShape *pLSpKept = NULL;
+      TopTools_ListIteratorOfListOfShape aIt(*pLSp);
+      for (; aIt.More(); aIt.Next())
+      {
+        const TopoDS_Shape& aSp = aIt.Value();
+
+        // Check if the result shape contains the split
+        if (myMapShape.Contains(aSp))
+        {
+          if (!pLSpKept)
+            pLSpKept = &myImagesResult(myImagesResult.Add(aS, TopTools_ListOfShape()));
+
+          // Link the shape to the split
+          pLSpKept->Append(aSp);
         }
       }
-      myImagesResult.Add(aSx, aLSx);
-    }
-    // <- A
-    //
-    // 4.2 As it was 
-    if (!myHasDeleted) {
-      myHasDeleted=IsDeleted(aSx);
-    }
-    //
-    if (!myHasModified && bHasImage) {
-      if (aType==TopAbs_EDGE   || aType==TopAbs_FACE || 
-          aType==TopAbs_VERTEX || aType==TopAbs_SOLID) {
+
+      if (pLSpKept)
+        // Modified element is found
         myHasModified = Standard_True;
-      } 
+      else
+        // Deleted element is found
+        myHasDeleted = Standard_True;
     }
-    //
-    if (!myHasGenerated) {
-      if (aType==TopAbs_FACE) {
-        const TopTools_ListOfShape& aLG = Generated(aSx);
-        myHasGenerated = aLG.Extent() > 0;
-      }
+
+    // Until first found, check if the shape has Generated elements
+    if (!myHasGenerated)
+    {
+      // Temporarily set the HasGenerated flag to TRUE to look for the shapes generated from aS.
+      // Otherwise, the method Generated will always be returning an empty list, assuming that the
+      // operation has no generated elements at all.
+      myHasGenerated = Standard_True;
+      myHasGenerated = (Generated(aS).Extent() > 0);
     }
   }
-  myFlagHistory=Standard_True;
 }
index c6cd55e..f9c33b6 100644 (file)
 
 #include <BOPAlgo_CellsBuilder.hxx>
 
-#include <TopoDS_Compound.hxx>
-
-#include <BRep_Builder.hxx>
-
-#include <TopExp.hxx>
-#include <TopExp_Explorer.hxx>
-
-#include <BOPTools_AlgoTools.hxx>
-
-#include <BOPAlgo_BuilderSolid.hxx>
 #include <BOPAlgo_Alerts.hxx>
-
+#include <BOPAlgo_BuilderSolid.hxx>
+#include <BOPDS_DS.hxx>
+#include <BOPTools_AlgoTools.hxx>
+#include <BOPTools_AlgoTools3D.hxx>
+#include <BRep_Builder.hxx>
+#include <ShapeUpgrade_UnifySameDomain.hxx>
 #include <TColStd_MapOfInteger.hxx>
 #include <TopExp.hxx>
-
-#include <ShapeUpgrade_UnifySameDomain.hxx>
+#include <TopExp_Explorer.hxx>
+#include <TopoDS_Compound.hxx>
 
 
 static
@@ -939,118 +934,54 @@ Standard_Boolean BOPAlgo_CellsBuilder::RemoveInternals(const TopTools_ListOfShap
       //
       theLSNew.Append(aSNew);
       bRemoved = Standard_True;
+
+      // Save information about the fuse of the solids into a history map
+      aItS.Initialize(aCB);
+      for (; aItS.More(); aItS.Next())
+        myMapModified.Bind(aItS.Value(), aSNew);
     }
   }
   return bRemoved;
 }
 
 //=======================================================================
-//function : IsDeleted
+//function : LocModified
 //purpose  : 
 //=======================================================================
-Standard_Boolean BOPAlgo_CellsBuilder::IsDeleted(const TopoDS_Shape& theS)
+const TopTools_ListOfShape* BOPAlgo_CellsBuilder::LocModified(const TopoDS_Shape& theS)
 {
-  Standard_Boolean bRet = Standard_True;
-  if (theS.IsNull()) {
-    return bRet;
-  }
-  //
-  TopAbs_ShapeEnum aType = theS.ShapeType();
-  if (!(aType==TopAbs_EDGE || aType==TopAbs_FACE || 
-      aType==TopAbs_VERTEX || aType==TopAbs_SOLID)) {
-    return bRet;
-  }
-  //
-  Standard_Boolean bHasImage, bHasModified;
-  //
-  bHasImage = myImages.IsBound(theS);
-  bHasModified = myMapModified.IsBound(theS);
-  if (!bHasImage && !bHasModified) {
-    bRet = !myMapShape.Contains(theS);
-    return bRet;
-  }
-  //
-  if (bHasModified) {
-    const TopoDS_Shape& aSG = myMapModified.Find(theS);
-    if (myMapShape.Contains(aSG)) {
-      bRet = Standard_False;
-      return bRet;
-    }
-  }
-  //
-  if (bHasImage) {
-    const TopTools_ListOfShape& aLSp = myImages.Find(theS);
-    TopTools_ListIteratorOfListOfShape aIt(aLSp);
-    for (; aIt.More(); aIt.Next()) {
-      const TopoDS_Shape& aSp = aIt.Value();
-      const TopoDS_Shape& aSpR = myShapesSD.IsBound(aSp) ? 
-        myShapesSD.Find(aSp) : aSp;
-      //
-      const TopoDS_Shape& aSpRG = myMapModified.IsBound(aSpR) ?
-        myMapModified.Find(aSpR) : aSpR;
-      if (myMapShape.Contains(aSpRG)) {
-        bRet = Standard_False;
-        break;
-      }
-    }
-  }
-  //
-  return bRet;
-}
+  // Get shape's modification coming from GF operation
+  const TopTools_ListOfShape* pLSp = BOPAlgo_Builder::LocModified(theS);
+  if (myMapModified.IsEmpty())
+    // No local modifications
+    return pLSp;
 
-//=======================================================================
-//function : Modified
-//purpose  : 
-//=======================================================================
-const TopTools_ListOfShape& BOPAlgo_CellsBuilder::Modified(const TopoDS_Shape& theS)
-{
   myHistShapes.Clear();
-  if (theS.IsNull()) {
-    return myHistShapes;
-  }
-  //
-  TopAbs_ShapeEnum aType = theS.ShapeType();
-  if (!(aType==TopAbs_EDGE || aType==TopAbs_FACE || aType==TopAbs_VERTEX)) {
-    return myHistShapes;
-  }
-  //
-  Standard_Boolean bHasModified = myMapModified.IsBound(theS);
-  if (bHasModified) {
-    const TopoDS_Shape& aSG = myMapModified.Find(theS);
-    if (myMapShape.Contains(aSG)) {
-      myHistShapes.Append(aSG);
-    }
-    return myHistShapes;
-  }
-  //
-  Standard_Boolean bHasImage = myImages.IsBound(theS);
-  if (!bHasImage) {
-    return myHistShapes;
+
+  // Check if the shape (or its splits) has participated in unification
+  if (!pLSp)
+  {
+    // No splits from GF operation.
+    // Check if the shape has been unified with other shapes
+    const TopoDS_Shape* pSU = myMapModified.Seek(theS);
+    if (!pSU)
+      return NULL;
+
+    myHistShapes.Append(*pSU);
   }
-  //
-  TopTools_MapOfShape aMFence;
-  const TopTools_ListOfShape& aLSp = myImages.Find(theS);
-  TopTools_ListIteratorOfListOfShape aIt(aLSp);
-  for (; aIt.More(); aIt.Next()) {
-    const TopoDS_Shape aSp = aIt.Value();
-    const TopoDS_Shape& aSpR = myShapesSD.IsBound(aSp) ? 
-      myShapesSD.Find(aSp) : aSp;
-    //
-    if (myMapModified.IsBound(aSpR)) {
-      const TopoDS_Shape& aSG = myMapModified.Find(aSpR);
-      if (myMapShape.Contains(aSG)) {
-        if (aMFence.Add(aSG)) {
-          myHistShapes.Append(aSG);
-        }
-      }
-    }
-    else if (aMFence.Add(aSpR))
+  else
+  {
+    // Process all GF splits and check them for local unification with other shapes
+    TopTools_ListIteratorOfListOfShape aIt(*pLSp);
+    for (; aIt.More(); aIt.Next())
     {
-      myHistShapes.Append(aSpR);
+      const TopoDS_Shape* pSp = &aIt.Value();
+      const TopoDS_Shape* pSU = myMapModified.Seek(*pSp);
+      if (pSU) pSp = pSU;
+      myHistShapes.Append(*pSp);
     }
   }
-  //
-  return myHistShapes;
+  return &myHistShapes;
 }
 
 //=======================================================================
index d7450b0..a538580 100644 (file)
@@ -90,8 +90,6 @@
 //! IsDeleted() and Modified().<br>
 //! In DRAW Test Harness it is available through the same
 //! commands as for Boolean Operations (bmodified, bgenerated and bisdeleted).<br>
-//! There could be Generated shapes only after removing of the internal boundaries
-//! between faces and edges, i.e. after using ShapeUpgrade_UnifySameDomain tool.<br>
 //!
 //! The algorithm can return the following Error Statuses:
 //! - Error status acquired in the General Fuse algorithm.
@@ -238,15 +236,13 @@ class BOPAlgo_CellsBuilder : public BOPAlgo_Builder
   //! Makes the Containers of proper type from the parts added to result.
   Standard_EXPORT void MakeContainers();
 
-  //! Returns the list of shapes generated from the shape theS.
-  Standard_EXPORT virtual const TopTools_ListOfShape& Modified(const TopoDS_Shape& theS) Standard_OVERRIDE;
-  
-  //! Returns true if the shape theS has been deleted.
-  Standard_EXPORT virtual Standard_Boolean IsDeleted (const TopoDS_Shape& theS) Standard_OVERRIDE;
-
  protected:
 
-   //! Redefined method Prepare - no need to prepare history
+  //! Prepare information for history support taking into account
+  //! local modification map of unified elements - myMapModified.
+  Standard_EXPORT virtual const TopTools_ListOfShape* LocModified(const TopoDS_Shape& theS) Standard_OVERRIDE;
+
+  //! Redefined method Prepare - no need to prepare history
   //! information on the default result as it is empty compound.
   Standard_EXPORT virtual void Prepare() Standard_OVERRIDE;
 
@@ -269,11 +265,11 @@ class BOPAlgo_CellsBuilder : public BOPAlgo_Builder
                                                    const TopTools_MapOfShape& theMapKeepBnd = TopTools_MapOfShape());
 
   // fields
-  TopoDS_Shape myAllParts;
-  TopTools_IndexedDataMapOfShapeListOfShape myIndex;
-  TopTools_DataMapOfIntegerListOfShape myMaterials;
-  TopTools_DataMapOfShapeInteger myShapeMaterial;
-  TopTools_DataMapOfShapeShape myMapModified;
+  TopoDS_Shape myAllParts;                           //!< All split parts of the arguments
+  TopTools_IndexedDataMapOfShapeListOfShape myIndex; //!< Connection map from all splits parts to the argument shapes from which they were created
+  TopTools_DataMapOfIntegerListOfShape myMaterials;  //!< Map of assigned materials (material -> list of shape)
+  TopTools_DataMapOfShapeInteger myShapeMaterial;    //!< Map of assigned materials (shape -> material)
+  TopTools_DataMapOfShapeShape myMapModified;        //!< Local modification map to track unification of the splits
 };
 
 #endif //_BOPAlgo_CellsBuilder_HeaderFile
index 4a9cde8..26ec591 100644 (file)
@@ -15,7 +15,6 @@
 
 #include <BOPAlgo_Section.hxx>
 #include <BOPAlgo_Alerts.hxx>
-#include <BOPAlgo_BuilderSolid.hxx>
 #include <BOPAlgo_PaveFiller.hxx>
 #include <BOPDS_CommonBlock.hxx>
 #include <BOPDS_DS.hxx>
@@ -26,7 +25,6 @@
 #include <BOPDS_VectorOfFaceInfo.hxx>
 #include <BOPDS_VectorOfListOfPaveBlock.hxx>
 #include <BOPTools_AlgoTools.hxx>
-#include <BOPTools_AlgoTools3D.hxx>
 #include <BRep_Builder.hxx>
 #include <BRep_Tool.hxx>
 #include <TopAbs_ShapeEnum.hxx>
@@ -36,7 +34,6 @@
 #include <TopoDS_Edge.hxx>
 #include <TopoDS_Iterator.hxx>
 #include <TopoDS_Shape.hxx>
-#include <TopTools_DataMapOfShapeShape.hxx>
 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
 #include <TopTools_IndexedMapOfShape.hxx>
 #include <TopTools_ListOfShape.hxx>
@@ -357,44 +354,3 @@ void BOPAlgo_Section::BuildSection()
   //
   myShape=aRC;
 }
-//=======================================================================
-//function : Generated
-//purpose  : 
-//=======================================================================
-const TopTools_ListOfShape& BOPAlgo_Section::Generated
-  (const TopoDS_Shape& theS)
-{
-  myHistShapes.Clear();
-  if (theS.IsNull()) {
-    return myHistShapes;
-  }
-  //
-  TopAbs_ShapeEnum aType = theS.ShapeType();
-  if (aType != TopAbs_FACE) {
-    return myHistShapes;
-  }
-  //
-  Standard_Integer nS = myDS->Index(theS);
-  if (nS < 0) {
-    return myHistShapes;
-  }
-  //
-  if (!myDS->HasFaceInfo(nS)) {
-    return myHistShapes;
-  }
-  //
-  //collect section edges of the face theS
-  Standard_Integer i, aNb, nSp;
-  //
-  const BOPDS_FaceInfo& aFI = myDS->FaceInfo(nS);
-  const BOPDS_IndexedMapOfPaveBlock& aMPBSc = aFI.PaveBlocksSc();
-  aNb = aMPBSc.Extent();
-  for (i = 1; i <= aNb; ++i) {
-    const Handle(BOPDS_PaveBlock)& aPB = aMPBSc(i);
-    nSp = aPB->Edge();
-    const TopoDS_Shape& aSp = myDS->Shape(nSp);
-    myHistShapes.Append(aSp);
-  }
-  //
-  return myHistShapes;
-}
index a62873e..588b4b3 100644 (file)
@@ -43,26 +43,20 @@ public:
   //! Empty constructor
   Standard_EXPORT BOPAlgo_Section();
   Standard_EXPORT virtual ~BOPAlgo_Section();
-  
-  //! Empty constructor
-  //!
-  //! protected methods
-  Standard_EXPORT BOPAlgo_Section(const Handle(NCollection_BaseAllocator)& theAllocator);
-  
-  Standard_EXPORT virtual void BuildSection();
-  
-  //! Returns the  list of shapes generated from the
-  //! shape theS.
-  Standard_EXPORT virtual const TopTools_ListOfShape& Generated (const TopoDS_Shape& theS) Standard_OVERRIDE;
 
+  //! Constructor with allocator
+  Standard_EXPORT BOPAlgo_Section(const Handle(NCollection_BaseAllocator)& theAllocator);
 
 protected:
 
+  //! Checks the data before performing the operation
   Standard_EXPORT virtual void CheckData() Standard_OVERRIDE;
-  
-  //! Performs calculations using prepared Filler
-  //! object <thePF>
-  Standard_EXPORT virtual void PerformInternal1 (const BOPAlgo_PaveFiller& thePF) Standard_OVERRIDE;
+
+  //! Combine the result of section operation
+  Standard_EXPORT virtual void BuildSection();
+
+  //! Performs calculations using prepared Filler object <thePF>
+  Standard_EXPORT virtual void PerformInternal1(const BOPAlgo_PaveFiller& thePF) Standard_OVERRIDE;
 
 private:
 
index 87d08f1..5130780 100644 (file)
@@ -26,4 +26,5 @@
 026 gdml_public
 027 gdml_private
 028 cells_test
-029 splitter
\ No newline at end of file
+029 splitter
+030 history
\ No newline at end of file
diff --git a/tests/boolean/history/A1 b/tests/boolean/history/A1
new file mode 100644 (file)
index 0000000..55600bd
--- /dev/null
@@ -0,0 +1,163 @@
+puts "Check History of Boolean operations"
+
+puts "Case with intersecting circles (two intersection points)"
+
+circle c1 0 0 0 10
+mkedge e1 c1
+
+circle c2 10 0 0 10
+mkedge e2 c2
+
+bclearobjects
+bcleartools
+baddobjects e1
+baddtools e2
+bfillds
+
+puts "Common operation"
+bbop rcom 0
+
+# check that both e1 and e2 have been deleted
+if {[string trim [bisdeleted e1]] != "Deleted"} {
+  puts "Error: Incorrect information about Deleted shapes"
+}
+
+if {[string trim [bisdeleted e2]] != "Deleted"} {
+  puts "Error: Incorrect information about Deleted shapes"
+}
+
+# check that none of the e1 and e2 have been Modified
+if {[string trim [bmodified rm e1]] != "The shape has not been modified"} {
+  puts "Error: Incorrect information about Modified shapes"
+}
+
+if {[string trim [bmodified rm e2]] != "The shape has not been modified"} {
+  puts "Error: Incorrect information about Modified shapes"
+}
+
+# check that none of the e1 and e2 have Generated shapes
+if {[string trim [bgenerated rg e1]] != "No shapes were generated from the shape"} {
+  puts "Error: Incorrect information about Generated shapes"
+}
+
+if {[string trim [bgenerated rg e2]] != "No shapes were generated from the shape"} {
+  puts "Error: Incorrect information about Generated shapes"
+}
+
+
+puts "Fuse operation"
+bbop rfuse 1
+
+# check that both e1 and e2 have not been deleted
+if {[string trim [bisdeleted e1]] != "Not deleted"} {
+  puts "Error: Incorrect information about Deleted shapes"
+}
+
+if {[string trim [bisdeleted e2]] != "Not deleted"} {
+  puts "Error: Incorrect information about Deleted shapes"
+}
+
+# check that both e1 and e2 have been Modified
+bmodified rm e1
+checknbshapes rm -edge 3 -m "Information about modification of e1"
+
+bmodified rm e2
+checknbshapes rm -edge 3 -m "Information about modification of e2"
+
+# check that both e1 and e2 have Generated vertices
+bgenerated rg e1
+checknbshapes rg -vertex 2 -m "Information about shapes Generated from e1"
+
+bgenerated rg e2
+checknbshapes rg -vertex 2 -m "Information about shapes Generated from e2"
+
+
+puts "CUT operation"
+bbop rcut 2
+
+# check that e1 has not been deleted
+if {[string trim [bisdeleted e1]] != "Not deleted"} {
+  puts "Error: Incorrect information about Deleted shapes"
+}
+
+# check that e2 has been deleted
+if {[string trim [bisdeleted e2]] != "Deleted"} {
+  puts "Error: Incorrect information about Deleted shapes"
+}
+
+# check that e1 has been modified
+bmodified rm e1
+checknbshapes rm -edge 3 -m "Information about modification of e1"
+
+# check that e2 has not been modified
+if {[string trim [bmodified rm e2]] != "The shape has not been modified"} {
+  puts "Error: Incorrect information about Modified shapes"
+}
+
+# check that both e1 and e2 have Generated vertices
+bgenerated rg e1
+checknbshapes rg -vertex 2 -m "Information about shapes Generated from e1"
+
+bgenerated rg e2
+checknbshapes rg -vertex 2 -m "Information about shapes Generated from e2"
+
+
+puts "TUC operation"
+bbop rtuc 3
+
+# check that e1 has been deleted
+if {[string trim [bisdeleted e1]] != "Deleted"} {
+  puts "Error: Incorrect information about Deleted shapes"
+}
+
+# check that e2 has not been deleted
+if {[string trim [bisdeleted e2]] != "Not deleted"} {
+  puts "Error: Incorrect information about Deleted shapes"
+}
+
+# check that e1 has not been modified
+if {[string trim [bmodified rm e1]] != "The shape has not been modified"} {
+  puts "Error: Incorrect information about Modified shapes"
+}
+
+# check that e2 has been modified
+bmodified rm e2
+checknbshapes rm -edge 3 -m "Information about modification of e1"
+
+
+# check that both e1 and e2 have Generated vertices
+bgenerated rg e1
+checknbshapes rg -vertex 2 -m "Information about shapes Generated from e1"
+
+bgenerated rg e2
+checknbshapes rg -vertex 2 -m "Information about shapes Generated from e2"
+
+
+
+puts "SECTION operation"
+bbop rsec 4
+
+# check that both e1 and e2 have been deleted
+if {[string trim [bisdeleted e1]] != "Deleted"} {
+  puts "Error: Incorrect information about Deleted shapes"
+}
+
+if {[string trim [bisdeleted e2]] != "Deleted"} {
+  puts "Error: Incorrect information about Deleted shapes"
+}
+
+# check that none of the e1 and e2 have been Modified 
+if {[string trim [bmodified rm e1]] != "The shape has not been modified"} {
+  puts "Error: Incorrect information about Modified shapes"
+}
+
+if {[string trim [bmodified rm e2]] != "The shape has not been modified"} {
+  puts "Error: Incorrect information about Modified shapes"
+}
+
+# check that both e1 and e2 have Generated vertices
+bgenerated rg e1
+checknbshapes rg -vertex 2 -m "Information about shapes Generated from e1"
+
+bgenerated rg e2
+checknbshapes rg -vertex 2 -m "Information about shapes Generated from e2"
diff --git a/tests/boolean/history/A2 b/tests/boolean/history/A2
new file mode 100644 (file)
index 0000000..844d71e
--- /dev/null
@@ -0,0 +1,163 @@
+puts "Check History of Boolean operations"
+
+puts "Case with intersecting planes (two intersection edges)"
+
+plane p 0 0 0 0 0 1
+mkface f1 p -10 10 -10 10
+
+polyline p -5 0 -5 -5 0 10 5 0 10 5 0 -5 2 0 -5 2 0 5 -2 0 5 -2 0 -5 -5 0 -5
+mkplane f2 p
+
+bclearobjects
+bcleartools
+baddobjects f1
+baddtools f2
+bfillds
+
+puts "Common operation"
+bbop rcom 0
+
+# check that both f1 and f2 have been deleted
+if {[string trim [bisdeleted f1]] != "Deleted"} {
+  puts "Error: Incorrect information about Deleted shapes"
+}
+
+if {[string trim [bisdeleted f2]] != "Deleted"} {
+  puts "Error: Incorrect information about Deleted shapes"
+}
+
+# check that none of the f1 and f2 have been Modified
+if {[string trim [bmodified rm f1]] != "The shape has not been modified"} {
+  puts "Error: Incorrect information about Modified shapes"
+}
+
+if {[string trim [bmodified rm f2]] != "The shape has not been modified"} {
+  puts "Error: Incorrect information about Modified shapes"
+}
+
+# check that none of the f1 and f2 have Generated shapes
+if {[string trim [bgenerated rg f1]] != "No shapes were generated from the shape"} {
+  puts "Error: Incorrect information about Generated shapes"
+}
+
+if {[string trim [bgenerated rg f2]] != "No shapes were generated from the shape"} {
+  puts "Error: Incorrect information about Generated shapes"
+}
+
+
+puts "Fuse operation"
+bbop rfuse 1
+
+# check that both f1 and f2 have not been deleted
+if {[string trim [bisdeleted f1]] != "Not deleted"} {
+  puts "Error: Incorrect information about Deleted shapes"
+}
+
+if {[string trim [bisdeleted f2]] != "Not deleted"} {
+  puts "Error: Incorrect information about Deleted shapes"
+}
+
+# check that both f1 and f2 have been Modified
+bmodified rm f1
+checknbshapes rm -face 1 -m "Information about modification of f1"
+
+bmodified rm f2
+checknbshapes rm -face 3 -m "Information about modification of f2"
+
+# check that both f1 and f2 have Generated edges
+bgenerated rg f1
+checknbshapes rg -edge 2 -m "Information about shapes Generated from f1"
+
+bgenerated rg f1
+checknbshapes rg -edge 2 -m "Information about shapes Generated from f2"
+
+
+puts "CUT operation"
+bbop rcut 2
+
+# check that f1 has not been deleted
+if {[string trim [bisdeleted f1]] != "Not deleted"} {
+  puts "Error: Incorrect information about Deleted shapes"
+}
+
+# check that f2 has been deleted
+if {[string trim [bisdeleted f2]] != "Deleted"} {
+  puts "Error: Incorrect information about Deleted shapes"
+}
+
+# check that f1 has been modified
+bmodified rm f1
+checknbshapes rm -face 1 -m "Information about modification of f1"
+
+# check that f2 has not been modified
+if {[string trim [bmodified rm f2]] != "The shape has not been modified"} {
+  puts "Error: Incorrect information about Modified shapes"
+}
+
+# check that both f1 and f2 have Generated edges
+bgenerated rg f1
+checknbshapes rg -edge 2 -m "Information about shapes Generated from f1"
+
+bgenerated rg f2
+checknbshapes rg -edge 2 -m "Information about shapes Generated from f2"
+
+
+puts "TUC operation"
+bbop rtuc 3
+
+# check that f1 has been deleted
+if {[string trim [bisdeleted f1]] != "Deleted"} {
+  puts "Error: Incorrect information about Deleted shapes"
+}
+
+# check that f2 has not been deleted
+if {[string trim [bisdeleted f2]] != "Not deleted"} {
+  puts "Error: Incorrect information about Deleted shapes"
+}
+
+# check that f1 has not been modified
+if {[string trim [bmodified rm f1]] != "The shape has not been modified"} {
+  puts "Error: Incorrect information about Modified shapes"
+}
+
+# check that f2 has been modified
+bmodified rm f2
+checknbshapes rm -face 3 -m "Information about modification of f1"
+
+
+# check that both f1 and f2 have Generated vertices
+bgenerated rg f1
+checknbshapes rg -edge 2 -m "Information about shapes Generated from f1"
+
+bgenerated rg f2
+checknbshapes rg -edge 2 -m "Information about shapes Generated from f2"
+
+
+
+puts "SECTION operation"
+bbop rsec 4
+
+# check that both f1 and f2 have been deleted
+if {[string trim [bisdeleted f1]] != "Deleted"} {
+  puts "Error: Incorrect information about Deleted shapes"
+}
+
+if {[string trim [bisdeleted f2]] != "Deleted"} {
+  puts "Error: Incorrect information about Deleted shapes"
+}
+
+# check that none of the f1 and f2 have been Modified 
+if {[string trim [bmodified rm f1]] != "The shape has not been modified"} {
+  puts "Error: Incorrect information about Modified shapes"
+}
+
+if {[string trim [bmodified rm f2]] != "The shape has not been modified"} {
+  puts "Error: Incorrect information about Modified shapes"
+}
+
+# check that both f1 and f2 have Generated vertices
+bgenerated rg f1
+checknbshapes rg -edge 2 -m "Information about shapes Generated from f1"
+
+bgenerated rg f2
+checknbshapes rg -edge 2 -m "Information about shapes Generated from f2"
diff --git a/tests/boolean/history/A3 b/tests/boolean/history/A3
new file mode 100644 (file)
index 0000000..418c7b2
--- /dev/null
@@ -0,0 +1,171 @@
+puts "Check History of Boolean operations"
+
+puts "Case with overlapping planar faces"
+
+plane p 0 0 0 0 0 1
+mkface f1 p -10 10 -10 10
+mkface f2 p 0 20 -10 10
+
+bclearobjects
+bcleartools
+baddobjects f1
+baddtools f2
+bfillds
+
+puts "Common operation"
+bbop rcom 0
+
+
+# check that both f1 and f2 have not been deleted
+if {[string trim [bisdeleted f1]] != "Not deleted"} {
+  puts "Error: Incorrect information about Deleted shapes"
+}
+
+if {[string trim [bisdeleted f2]] != "Not deleted"} {
+  puts "Error: Incorrect information about Deleted shapes"
+}
+
+# check that both f1 and f2 have been Modified into the same face
+bmodified rm1 f1
+checknbshapes rm1 -face 1 -m "Information about modification of f1"
+
+bmodified rm2 f2
+checknbshapes rm2 -face 1 -m "Information about modification of f2"
+
+compound rm1 rm2 cm
+checknbshapes cm -face 1 -m "Information about modification of f1 and f2"
+
+
+# check that none of the f1 and f2 have Generated shapes
+if {[string trim [bgenerated rg f1]] != "No shapes were generated from the shape"} {
+  puts "Error: Incorrect information about Generated shapes"
+}
+
+if {[string trim [bgenerated rg f2]] != "No shapes were generated from the shape"} {
+  puts "Error: Incorrect information about Generated shapes"
+}
+
+
+puts "Fuse operation"
+bbop rfuse 1
+
+# check that both f1 and f2 have not been deleted
+if {[string trim [bisdeleted f1]] != "Not deleted"} {
+  puts "Error: Incorrect information about Deleted shapes"
+}
+
+if {[string trim [bisdeleted f2]] != "Not deleted"} {
+  puts "Error: Incorrect information about Deleted shapes"
+}
+
+# check that both f1 and f2 have been Modified
+bmodified rm f1
+checknbshapes rm -face 2 -m "Information about modification of f1"
+
+bmodified rm f2
+checknbshapes rm -face 2 -m "Information about modification of f2"
+
+# check that none of the f1 and f2 have Generated shapes
+if {[string trim [bgenerated rg f1]] != "No shapes were generated from the shape"} {
+  puts "Error: Incorrect information about Generated shapes"
+}
+
+if {[string trim [bgenerated rg f2]] != "No shapes were generated from the shape"} {
+  puts "Error: Incorrect information about Generated shapes"
+}
+
+
+puts "CUT operation"
+bbop rcut 2
+
+# check that f1 has not been deleted
+if {[string trim [bisdeleted f1]] != "Not deleted"} {
+  puts "Error: Incorrect information about Deleted shapes"
+}
+
+# check that f2 has been deleted
+if {[string trim [bisdeleted f2]] != "Deleted"} {
+  puts "Error: Incorrect information about Deleted shapes"
+}
+
+# check that f1 has been modified
+bmodified rm f1
+checknbshapes rm -face 1 -m "Information about modification of f1"
+
+# check that f2 has not been modified
+if {[string trim [bmodified rm f2]] != "The shape has not been modified"} {
+  puts "Error: Incorrect information about Modified shapes"
+}
+
+# check that none of the f1 and f2 have Generated shapes
+if {[string trim [bgenerated rg f1]] != "No shapes were generated from the shape"} {
+  puts "Error: Incorrect information about Generated shapes"
+}
+
+if {[string trim [bgenerated rg f2]] != "No shapes were generated from the shape"} {
+  puts "Error: Incorrect information about Generated shapes"
+}
+
+
+puts "TUC operation"
+bbop rtuc 3
+
+# check that f1 has been deleted
+if {[string trim [bisdeleted f1]] != "Deleted"} {
+  puts "Error: Incorrect information about Deleted shapes"
+}
+
+# check that f2 has not been deleted
+if {[string trim [bisdeleted f2]] != "Not deleted"} {
+  puts "Error: Incorrect information about Deleted shapes"
+}
+
+# check that f1 has not been modified
+if {[string trim [bmodified rm f1]] != "The shape has not been modified"} {
+  puts "Error: Incorrect information about Modified shapes"
+}
+
+# check that f2 has been modified
+bmodified rm f2
+checknbshapes rm -face 1 -m "Information about modification of f1"
+
+# check that none of the f1 and f2 have Generated shapes
+if {[string trim [bgenerated rg f1]] != "No shapes were generated from the shape"} {
+  puts "Error: Incorrect information about Generated shapes"
+}
+
+if {[string trim [bgenerated rg f2]] != "No shapes were generated from the shape"} {
+  puts "Error: Incorrect information about Generated shapes"
+}
+
+
+
+puts "SECTION operation"
+bbop rsec 4
+
+# check that both f1 and f2 have been deleted
+if {[string trim [bisdeleted f1]] != "Deleted"} {
+  puts "Error: Incorrect information about Deleted shapes"
+}
+
+if {[string trim [bisdeleted f2]] != "Deleted"} {
+  puts "Error: Incorrect information about Deleted shapes"
+}
+
+# check that none of the f1 and f2 have been Modified 
+if {[string trim [bmodified rm f1]] != "The shape has not been modified"} {
+  puts "Error: Incorrect information about Modified shapes"
+}
+
+if {[string trim [bmodified rm f2]] != "The shape has not been modified"} {
+  puts "Error: Incorrect information about Modified shapes"
+}
+
+# check that none of the f1 and f2 have Generated shapes
+if {[string trim [bgenerated rg f1]] != "No shapes were generated from the shape"} {
+  puts "Error: Incorrect information about Generated shapes"
+}
+
+if {[string trim [bgenerated rg f2]] != "No shapes were generated from the shape"} {
+  puts "Error: Incorrect information about Generated shapes"
+}
diff --git a/tests/boolean/history/A4 b/tests/boolean/history/A4
new file mode 100644 (file)
index 0000000..da71089
--- /dev/null
@@ -0,0 +1,37 @@
+puts "Check History of General Fuse"
+
+puts "Case with an edge intersecting a face"
+
+polyline fw 0 0 0 10 0 0 10 10 0 0 10 0 0 0 0
+mkplane fs fw
+
+vertex ev1 5 5 5
+vertex ev2 5 5 -5
+edge es ev1 ev2
+
+bclearobjects
+bcleartools
+baddobjects fs
+baddtools es
+bfillds
+bbuild r
+
+bmodified fs_m fs
+checknbshapes fs_m -face 1 -m "Information about Modification of fs"
+
+bmodified es_m es
+checknbshapes es_m -edge 2 -m "Information about Modification of es"
+
+bgenerated fs_g fs
+checknbshapes fs_g -vertex 1 -m "Information about shapes Generated from fs"
+
+bgenerated es_g es
+checknbshapes es_g -vertex 1 -m "Information about shapes Generated from es"
+
+
+# In General Fuse operation there should be no Deleted elements
+foreach s [join [list es fs [explode es v] [explode fs e] [explode fs v]]] {
+  if {[string trim [bisdeleted $s]] != "Not deleted"} {
+    puts "Error: Incorrect information about Deleted shapes"
+  }
+}
diff --git a/tests/boolean/history/A5 b/tests/boolean/history/A5
new file mode 100644 (file)
index 0000000..5a3f637
--- /dev/null
@@ -0,0 +1,167 @@
+puts "Check History of Cells Builder"
+
+puts "Case with overlapping planar faces"
+
+circle c1 0 0 0 10
+circle c2 10 0 0 10
+circle c3 10 10 0 10
+
+mkedge e1 c1
+mkedge e2 c2
+mkedge e3 c3
+
+wire w1 e1
+wire w2 e2
+wire w3 e3
+
+mkplane f1 w1
+mkplane f2 w2
+mkplane f3 w3
+
+bclearobjects
+bcleartools
+baddobjects f1 f2 f3
+bfillds
+
+bcbuild rx
+
+bcremoveall
+
+# no history at this point
+
+# add to result all parts of f1 with material 1
+bcadd result f1 1 -m 1
+
+# check modification of f1
+bmodified rm1 f1
+checknbshapes rm1 -face 4 -m "Information about modification of f1"
+
+# check modification of f2
+bmodified rm2 f2
+checknbshapes rm2 -face 2 -m "Information about modification of f2"
+
+# check modification of f3
+bmodified rm3 f3
+checknbshapes rm3 -face 2 -m "Information about modification of f3"
+
+# make one face from result
+bcremoveint result
+
+# check modification of f1
+bmodified rm1u f1
+checknbshapes rm1u -face 1 -m "Information about modification of f1"
+
+# check modification of f2
+bmodified rm2u f2
+checknbshapes rm2u -face 1 -m "Information about modification of f2"
+
+# check modification of f3
+bmodified rm3u f3
+checknbshapes rm3u -face 1 -m "Information about modification of f3"
+
+compound rm1u rm2u rm3u cfu
+checknbshapes cfu -face 1 -m "Information about modification of f1, f2 and f3"
+
+
+bcremoveall
+# no history at this point
+
+# add to result all parts of f1 and f2 not contained in f3 with material 1
+bcadd result f1 1 f3 0 -m 1
+bcadd result f2 1 f3 0 -m 1
+
+# check modification of f1
+bmodified rm1 f1
+checknbshapes rm1 -face 2 -m "Information about modification of f1"
+
+# check modification of f2
+bmodified rm2 f2
+checknbshapes rm2 -face 2 -m "Information about modification of f2"
+
+# check modification of f3
+if {[string trim [bmodified rm3 f3]] != "The shape has not been modified"} {
+  puts "Error: Incorrect information about Modification of f3"
+}
+
+# check deletion of f1
+if {[string trim [bisdeleted f1]] != "Not deleted"} {
+  puts "Error: Incorrect information about Deletion of f1"
+}
+
+# check deletion of f2
+if {[string trim [bisdeleted f2]] != "Not deleted"} {
+  puts "Error: Incorrect information about Deletion of f2"
+}
+
+# check deletion of f3
+if {[string trim [bisdeleted f3]] != "Deleted"} {
+  puts "Error: Incorrect information about Deletion of f3"
+}
+
+# make one face from result
+bcremoveint result
+
+# check modification of f1
+bmodified rm1 f1
+checknbshapes rm1 -face 1 -m "Information about modification of f1"
+
+# check modification of f2
+bmodified rm2 f2
+checknbshapes rm2 -face 1 -m "Information about modification of f2"
+
+# check modification of f3
+if {[string trim [bmodified rm3 f3]] != "The shape has not been modified"} {
+  puts "Error: Incorrect information about Modification of f3"
+}
+
+# check deletion of f1
+if {[string trim [bisdeleted f1]] != "Not deleted"} {
+  puts "Error: Incorrect information about Deletion of f1"
+}
+
+# check deletion of f2
+if {[string trim [bisdeleted f2]] != "Not deleted"} {
+  puts "Error: Incorrect information about Deletion of f2"
+}
+
+# check deletion of f3
+if {[string trim [bisdeleted f3]] != "Deleted"} {
+  puts "Error: Incorrect information about Deletion of f3"
+}
+
+
+bcremoveall
+
+# add to result parts of f1 with material 1, and all other parts with material 2
+bcadd result f1 1 -m 1
+bcadd result f2 1 f1 0 -m 2
+bcadd result f3 1 f1 0 -m 2
+
+# at this point all splits of faces are contained in the result
+# check modification of f1
+bmodified rm1 f1
+checknbshapes rm1 -face 4 -m "Information about modification of f1"
+
+# check modification of f2
+bmodified rm2 f2
+checknbshapes rm2 -face 4 -m "Information about modification of f2"
+
+# check modification of f3
+bmodified rm3 f3
+checknbshapes rm3 -face 4 -m "Information about modification of f3"
+
+# unify faces with same material
+bcremoveint result
+
+# check modification of f1
+bmodified rm1u f1
+checknbshapes rm1u -face 1 -m "Information about modification of f1"
+
+# check modification of f2
+bmodified rm2u f2
+checknbshapes rm2u -face 2 -m "Information about modification of f2"
+
+# check modification of f3
+bmodified rm3u f3
+checknbshapes rm3u -face 2 -m "Information about modification of f3"
+
diff --git a/tests/boolean/history/A6 b/tests/boolean/history/A6
new file mode 100644 (file)
index 0000000..cbe9106
--- /dev/null
@@ -0,0 +1,173 @@
+puts "Check History of Cells Builder"
+
+puts "Case with three boxes"
+
+box b1 10 10 10
+box b2 5 0 0 10 10 10
+box b3 2.5 0 5 10 10 10
+
+bclearobjects
+bcleartools
+baddobjects b1 b2 b3
+bfillds
+
+bcbuild rx
+
+bcremoveall
+# no history at this point
+
+# add all parts into result
+bcaddall result
+
+# find all section edges using Generated history information
+compound ge
+foreach s {b1 b2 b3} {
+  foreach f [explode $s f] {
+    if {[string trim [bgenerated g $f]] == ""} {
+      add g ge
+    }
+  }
+}
+
+checknbshapes ge -edge 4 -m "Information about Generated shapes"
+
+
+bcremoveall
+# no history at this point
+
+# add to result all parts of b1 with material 1
+bcadd result b1 1 -m 1
+
+# check modification of b1
+bmodified rm1 b1
+checknbshapes rm1 -solid 4 -m "Information about modification of b1"
+
+# check modification of b2
+bmodified rm2 b2
+checknbshapes rm2 -solid 2 -m "Information about modification of b2"
+
+# check modification of b3
+bmodified rm3 b3
+checknbshapes rm3 -solid 2 -m "Information about modification of b3"
+
+# make one face from result
+bcremoveint result
+
+# check modification of b1
+bmodified rm1u b1
+checknbshapes rm1u -solid 1 -m "Information about modification of b1"
+
+# check modification of b2
+bmodified rm2u b2
+checknbshapes rm2u -solid 1 -m "Information about modification of b2"
+
+# check modification of b3
+bmodified rm3u b3
+checknbshapes rm3u -solid 1 -m "Information about modification of b3"
+
+compound rm1u rm2u rm3u cfu
+checknbshapes cfu -solid 1 -m "Information about modification of b1, b2 and b3"
+
+
+bcremoveall
+# no history at this point
+
+# add to result all parts of b1 and b2 not contained in b3 with material 1
+bcadd result b1 1 b3 0 -m 1
+bcadd result b2 1 b3 0 -m 1
+
+# check modification of b1
+bmodified rm1 b1
+checknbshapes rm1 -solid 2 -m "Information about modification of b1"
+
+# check modification of b2
+bmodified rm2 b2
+checknbshapes rm2 -solid 2 -m "Information about modification of b2"
+
+# check modification of b3
+if {[string trim [bmodified rm3 b3]] != "The shape has not been modified"} {
+  puts "Error: Incorrect information about Modification of b3"
+}
+
+# check deletion of b1
+if {[string trim [bisdeleted b1]] != "Not deleted"} {
+  puts "Error: Incorrect information about Deletion of b1"
+}
+
+# check deletion of b2
+if {[string trim [bisdeleted b2]] != "Not deleted"} {
+  puts "Error: Incorrect information about Deletion of b2"
+}
+
+# check deletion of b3
+if {[string trim [bisdeleted b3]] != "Deleted"} {
+  puts "Error: Incorrect information about Deletion of b3"
+}
+
+# make one face from result
+bcremoveint result
+
+# check modification of b1
+bmodified rm1 b1
+checknbshapes rm1 -solid 1 -m "Information about modification of b1"
+
+# check modification of b2
+bmodified rm2 b2
+checknbshapes rm2 -solid 1 -m "Information about modification of b2"
+
+# check modification of b3
+if {[string trim [bmodified rm3 b3]] != "The shape has not been modified"} {
+  puts "Error: Incorrect information about Modification of b3"
+}
+
+# check deletion of b1
+if {[string trim [bisdeleted b1]] != "Not deleted"} {
+  puts "Error: Incorrect information about Deletion of b1"
+}
+
+# check deletion of b2
+if {[string trim [bisdeleted b2]] != "Not deleted"} {
+  puts "Error: Incorrect information about Deletion of b2"
+}
+
+# check deletion of b3
+if {[string trim [bisdeleted b3]] != "Deleted"} {
+  puts "Error: Incorrect information about Deletion of b3"
+}
+
+
+bcremoveall
+
+# add to result parts of b1 with material 1, and all other parts with material 2
+bcadd result b1 1 -m 1
+bcadd result b2 1 b1 0 -m 2
+bcadd result b3 1 b1 0 -m 2
+
+# at this point all splits of faces are contained in the result
+# check modification of b1
+bmodified rm1 b1
+checknbshapes rm1 -solid 4 -m "Information about modification of b1"
+
+# check modification of b2
+bmodified rm2 b2
+checknbshapes rm2 -solid 4 -m "Information about modification of b2"
+
+# check modification of b3
+bmodified rm3 b3
+checknbshapes rm3 -solid 4 -m "Information about modification of b3"
+
+# unify faces with same material
+bcremoveint result
+
+# check modification of b1
+bmodified rm1u b1
+checknbshapes rm1u -solid 1 -m "Information about modification of b1"
+
+# check modification of b2
+bmodified rm2u b2
+checknbshapes rm2u -solid 2 -m "Information about modification of b2"
+
+# check modification of b3
+bmodified rm3u b3
+checknbshapes rm3u -solid 2 -m "Information about modification of b3"
+
index 60290ee..96209bd 100644 (file)
@@ -47,19 +47,19 @@ NewCommand D
 erase
 ExploreShape D $CS:2:1 R
 
-# should be 12 edges
+# should be 12 edges and 6 vertices
 set l1 [llength [directory R_*] ]
 
-# should be 12 faces
+# should be 18 faces
 set l2 [llength [directory oldR_*] ]
 
-if { ${l1} == 12 } {
+if { ${l1} == 18 } {
   puts "OK: Good edge number"
 } else {
   puts "Error: Bad edge number"
 }
 
-if { ${l2} == 12 } {
+if { ${l2} == 18 } {
   puts "OK: Good face number"
 } else {
   puts "Error: Bad face number"