diff --git a/Geo/GModelIO_OCC.cpp b/Geo/GModelIO_OCC.cpp
index c38c76aa4f4126124d56a4e0670ad532678adc3f..e3ab6001247af2179dcd2417e24cbf207aaa867a 100644
--- a/Geo/GModelIO_OCC.cpp
+++ b/Geo/GModelIO_OCC.cpp
@@ -1921,7 +1921,8 @@ bool OCC_Internals::applyBooleanOperator
   }
 
   TopoDS_Shape result;
-  std::vector<TopTools_ListOfShape> mapInOut;
+  bool hasModified = false, hasGenerated = false;
+  std::vector<TopTools_ListOfShape> mapModified, mapGenerated;
   std::vector<bool> mapDeleted;
   try{
     switch(op){
@@ -1939,15 +1940,19 @@ bool OCC_Internals::applyBooleanOperator
           return false;
         }
         result = fuse.Shape();
+        hasGenerated = fuse.HasGenerated();
+        hasModified = fuse.HasModified();
         TopTools_ListIteratorOfListOfShape it(objectShapes);
         for(; it.More(); it.Next()){
-          mapInOut.push_back(fuse.Modified(it.Value()));
+          mapModified.push_back(fuse.Modified(it.Value()));
           mapDeleted.push_back(fuse.IsDeleted(it.Value()));
+          mapGenerated.push_back(fuse.Generated(it.Value()));
         }
         TopTools_ListIteratorOfListOfShape it2(toolShapes);
         for(; it2.More(); it2.Next()){
-          mapInOut.push_back(fuse.Modified(it2.Value()));
+          mapModified.push_back(fuse.Modified(it2.Value()));
           mapDeleted.push_back(fuse.IsDeleted(it2.Value()));
+          mapGenerated.push_back(fuse.Generated(it2.Value()));
         }
       }
       break;
@@ -1965,15 +1970,19 @@ bool OCC_Internals::applyBooleanOperator
           return false;
         }
         result = common.Shape();
+        hasGenerated = common.HasGenerated();
+        hasModified = common.HasModified();
         TopTools_ListIteratorOfListOfShape it(objectShapes);
         for(; it.More(); it.Next()){
-          mapInOut.push_back(common.Modified(it.Value()));
+          mapModified.push_back(common.Modified(it.Value()));
           mapDeleted.push_back(common.IsDeleted(it.Value()));
+          mapGenerated.push_back(common.Generated(it.Value()));
         }
         TopTools_ListIteratorOfListOfShape it2(toolShapes);
         for(; it2.More(); it2.Next()){
-          mapInOut.push_back(common.Modified(it2.Value()));
+          mapModified.push_back(common.Modified(it2.Value()));
           mapDeleted.push_back(common.IsDeleted(it2.Value()));
+          mapGenerated.push_back(common.Generated(it2.Value()));
         }
       }
       break;
@@ -1993,38 +2002,45 @@ bool OCC_Internals::applyBooleanOperator
           return false;
         }
         result = cut.Shape();
+        hasGenerated = cut.HasGenerated();
+        hasModified = cut.HasModified();
         TopTools_ListIteratorOfListOfShape it(objectShapes);
         for(; it.More(); it.Next()){
-          mapInOut.push_back(cut.Modified(it.Value()));
+          mapModified.push_back(cut.Modified(it.Value()));
           mapDeleted.push_back(cut.IsDeleted(it.Value()));
+          mapGenerated.push_back(cut.Generated(it.Value()));
         }
         TopTools_ListIteratorOfListOfShape it2(toolShapes);
         for(; it2.More(); it2.Next()){
-          mapInOut.push_back(cut.Modified(it2.Value()));
+          mapModified.push_back(cut.Modified(it2.Value()));
           mapDeleted.push_back(cut.IsDeleted(it2.Value()));
+          mapGenerated.push_back(cut.Generated(it2.Value()));
         }
       }
       break;
 
     case OCC_Internals::Fragments :
       {
-        BRepAlgoAPI_BuilderAlgo generalFuse;
-        generalFuse.SetRunParallel(parallel);
+        BRepAlgoAPI_BuilderAlgo fragments;
+        fragments.SetRunParallel(parallel);
         objectShapes.Append(toolShapes);
         toolShapes.Clear();
-        generalFuse.SetArguments(objectShapes);
+        fragments.SetArguments(objectShapes);
         if(tolerance > 0.0)
-          generalFuse.SetFuzzyValue(tolerance);
-        generalFuse.Build();
-        if(!generalFuse.IsDone()){
+          fragments.SetFuzzyValue(tolerance);
+        fragments.Build();
+        if(!fragments.IsDone()){
           Msg::Error("Boolean fragments failed");
           return false;
         }
-        result = generalFuse.Shape();
+        result = fragments.Shape();
+        hasGenerated = fragments.HasGenerated();
+        hasModified = fragments.HasModified();
         TopTools_ListIteratorOfListOfShape it(objectShapes);
         for(; it.More(); it.Next()){
-          mapInOut.push_back(generalFuse.Modified(it.Value()));
-          mapDeleted.push_back(generalFuse.IsDeleted(it.Value()));
+          mapModified.push_back(fragments.Modified(it.Value()));
+          mapDeleted.push_back(fragments.IsDeleted(it.Value()));
+          mapGenerated.push_back(fragments.Generated(it.Value()));
         }
       }
       break;
@@ -2035,10 +2051,16 @@ bool OCC_Internals::applyBooleanOperator
     return false;
   }
 
-  // if we specify the tag explicitly, or if there is a problem, don't try to
-  // preserve numbering
-  if(tag >= 0 || objectDimTags.size() + toolDimTags.size() != mapInOut.size()){
-    if(tag < 0) Msg::Error("Wrong shape count in boolean operation");
+  int numModified = 0;
+  for(unsigned int i = 0; i < mapModified.size(); i++)
+    numModified += mapModified[i].Extent();
+
+  // don't try to preserve numbering if we specify the tag explicitly, or if
+  // there is a problem
+  bool bug1 = (objectDimTags.size() + toolDimTags.size() != mapModified.size());
+  bool bug2 = (numModified == 0) && hasModified; // happens for some fuse cases!?
+  if(tag >= 0 || bug1 || bug2){
+    if(bug1) Msg::Error("Wrong shape count in boolean operation");
     if(removeObject){
       for(unsigned int i = 0; i < objectDimTags.size(); i++){
         int d = objectDimTags[i].first;
@@ -2062,33 +2084,38 @@ bool OCC_Internals::applyBooleanOperator
   for(unsigned int i = 0; i < objectDimTags.size(); i++){
     int dim = objectDimTags[i].first;
     int tag = objectDimTags[i].second;
-    if(mapDeleted[i]){
+    if(mapDeleted[i] && !mapGenerated[i].Extent()){
       if(removeObject && isBound(dim, tag)){
         unbind(find(dim, tag), dim, tag, true); // recursive
       }
     }
-    else if(mapInOut[i].Extent() == 0){
+    else if(mapModified[i].Extent() == 0){
       // the shape has not been modified, don't touch it
       outDimTags.push_back(std::pair<int, int>(dim, tag));
     }
-    else if(mapInOut[i].Extent() == 1){
+    else if(mapModified[i].Extent() == 1){
       if(removeObject){
         // the shape has been replaced by a single shape, keep the same tag
         if(isBound(dim, tag)){
           unbind(find(dim, tag), dim, tag, true); // recursive
         }
-        bind(mapInOut[i].First(), dim, tag, true); // recursive
+        bind(mapModified[i].First(), dim, tag, true); // recursive
         outDimTags.push_back(std::pair<int, int>(dim, tag));
       }
       else{
-        toBind.push_back(mapInOut[i].First());
+        toBind.push_back(mapModified[i].First());
       }
     }
     else{
       if(removeObject && isBound(dim, tag)){
         unbind(find(dim, tag), dim, tag, true); // recursive
       }
-      TopTools_ListIteratorOfListOfShape it(mapInOut[i]);
+      TopTools_ListIteratorOfListOfShape it(mapModified[i]);
+      for(; it.More(); it.Next())
+        toBind.push_back(it.Value());
+    }
+    {
+      TopTools_ListIteratorOfListOfShape it(mapGenerated[i]);
       for(; it.More(); it.Next())
         toBind.push_back(it.Value());
     }
@@ -2098,33 +2125,38 @@ bool OCC_Internals::applyBooleanOperator
     int k = objectDimTags.size() + i;
     int dim = toolDimTags[i].first;
     int tag = toolDimTags[i].second;
-    if(mapDeleted[k]){
+    if(mapDeleted[k] && !mapGenerated[k].Extent()){
       if(removeTool && isBound(dim, tag)){
         unbind(find(dim, tag), dim, tag, true); // recursive
       }
     }
-    else if(mapInOut[k].Extent() == 0){
+    else if(mapModified[k].Extent() == 0){
       // the shape has not been modified, don't touch it
       outDimTags.push_back(std::pair<int, int>(dim, tag));
     }
-    else if(mapInOut[k].Extent() == 1){
+    else if(mapModified[k].Extent() == 1){
       if(removeTool){
         // the shape has been replaced by a single shape, keep the same tag
         if(isBound(dim, tag)){
           unbind(find(dim, tag), dim, tag, true); // recursive
         }
-        bind(mapInOut[k].First(), dim, tag, true); // recursive
+        bind(mapModified[k].First(), dim, tag, true); // recursive
         outDimTags.push_back(std::pair<int, int>(dim, tag));
       }
       else{
-        toBind.push_back(mapInOut[k].First());
+        toBind.push_back(mapModified[k].First());
       }
     }
     else{
       if(removeTool && isBound(dim, tag)){
         unbind(find(dim, tag), dim, tag, true); // recursive
       }
-      TopTools_ListIteratorOfListOfShape it(mapInOut[k]);
+      TopTools_ListIteratorOfListOfShape it(mapModified[k]);
+      for(; it.More(); it.Next())
+        toBind.push_back(it.Value());
+    }
+    {
+      TopTools_ListIteratorOfListOfShape it(mapGenerated[k]);
       for(; it.More(); it.Next())
         toBind.push_back(it.Value());
     }