0027199: Unifysamedomain regression issue in OCCT 7
authorisn <isn@opencascade.com>
Thu, 14 Jul 2016 14:39:03 +0000 (17:39 +0300)
committerbugmaster <bugmaster@opencascade.com>
Thu, 21 Jul 2016 08:16:35 +0000 (11:16 +0300)
Allow to process the compounds in UnifySameDomain algorithm. Earlier only faces from shells were allowed to be unified.

Test case for issue #27199

src/ShapeUpgrade/ShapeUpgrade_UnifySameDomain.cxx
src/ShapeUpgrade/ShapeUpgrade_UnifySameDomain.hxx
tests/bugs/modalg_6/bug27199 [new file with mode: 0644]

index 66312ef..776b55d 100644 (file)
@@ -134,6 +134,41 @@ static Standard_Boolean IsLikeSeam(const TopoDS_Edge& anEdge,
   return Standard_False;
 }
 
+static Standard_Boolean CheckSharedEdgeOri(const TopoDS_Face& theF1,
+                                           const TopoDS_Face& theF2,
+                                           const TopoDS_Edge& theE)
+{
+  TopAbs_Orientation anEOri = theE.Orientation();
+  if (anEOri == TopAbs_EXTERNAL || anEOri == TopAbs_INTERNAL)
+    return Standard_False;
+
+  TopExp_Explorer Exp(theF1, TopAbs_EDGE);
+  for (;Exp.More();Exp.Next())
+  {
+    const TopoDS_Shape& aCE = Exp.Current();
+    if (aCE.IsSame(theE))
+    {
+      anEOri = aCE.Orientation(); 
+      break;
+    }
+  }
+
+  for (Exp.Init(theF2, TopAbs_EDGE);Exp.More();Exp.Next())
+  {
+    const TopoDS_Shape& aCE = Exp.Current();
+    if (aCE.IsSame(theE))
+    {
+      if (aCE.Orientation() == TopAbs::Reverse(anEOri))
+        return Standard_True;
+      else
+        return Standard_False;
+    }
+  }
+
+  return Standard_False;
+
+}
+
 //=======================================================================
 //function : AddOrdinaryEdges
 //purpose  : auxilary
@@ -1170,465 +1205,485 @@ void ShapeUpgrade_UnifySameDomain::UnifyFaces()
   // creating map of edge faces for the whole shape
   TopTools_IndexedDataMapOfShapeListOfShape aGMapEdgeFaces;
   TopExp::MapShapesAndAncestors(myShape, TopAbs_EDGE, TopAbs_FACE, aGMapEdgeFaces);
-
-  // processing each shell
+  
+  // unify faces in each shell separately
   TopExp_Explorer exps;
-  for (exps.Init(myShape, TopAbs_SHELL); exps.More(); exps.Next()) {
-    TopoDS_Shell aShell = TopoDS::Shell(exps.Current());
-
-    // creating map of edge faces for the shell
-    TopTools_IndexedDataMapOfShapeListOfShape aMapEdgeFaces;
-    TopExp::MapShapesAndAncestors(aShell, TopAbs_EDGE, TopAbs_FACE, aMapEdgeFaces);
-
-    // map of processed shapes
-    TopTools_MapOfShape aProcessed;
-
-    Standard_Integer NbModif = 0;
-    Standard_Boolean hasFailed = Standard_False;
-    Standard_Real tol = Precision::Confusion();
-
-    // count faces
-    Standard_Integer nbf = 0;
-    TopExp_Explorer exp;
-    TopTools_MapOfShape mapF;
-    for (exp.Init(aShell, TopAbs_FACE); exp.More(); exp.Next()) {
-      if (mapF.Add(exp.Current()))
-        nbf++;
-    }
+  for (exps.Init(myShape, TopAbs_SHELL); exps.More(); exps.Next())
+    IntUnifyFaces(exps.Current(), aGMapEdgeFaces, Standard_False);
+
+  // gather all faces out of shells in one compound and unify them at once
+  BRep_Builder aBB;
+  TopoDS_Compound aCmp;
+  aBB.MakeCompound(aCmp);
+  Standard_Integer nbf = 0;
+  for (exps.Init(myShape, TopAbs_FACE, TopAbs_SHELL); exps.More(); exps.Next(), nbf++)
+    aBB.Add(aCmp, exps.Current());
+
+  if (nbf > 0)
+    IntUnifyFaces(aCmp, aGMapEdgeFaces, Standard_True);
+  
+  myShape = myContext->Apply(myShape);
+}
 
-    // processing each face
-    mapF.Clear();
-    for (exp.Init(aShell, TopAbs_FACE); exp.More(); exp.Next()) {
-      TopoDS_Face aFace = TopoDS::Face(exp.Current().Oriented(TopAbs_FORWARD));
 
-      if (aProcessed.Contains(aFace))
-        continue;
+void ShapeUpgrade_UnifySameDomain::IntUnifyFaces(const TopoDS_Shape& theInpShape,
+   const TopTools_IndexedDataMapOfShapeListOfShape& theGMapEdgeFaces,
+   Standard_Boolean IsCheckSharedEdgeOri)
+{
+  // creating map of edge faces for the shape
+  TopTools_IndexedDataMapOfShapeListOfShape aMapEdgeFaces;
+  TopExp::MapShapesAndAncestors(theInpShape, TopAbs_EDGE, TopAbs_FACE, aMapEdgeFaces);
 
-      Standard_Integer dummy;
-      TopTools_SequenceOfShape edges;
-      AddOrdinaryEdges(edges,aFace,dummy);
+  // map of processed shapes
+  TopTools_MapOfShape aProcessed;
 
-      TopTools_SequenceOfShape faces;
-      faces.Append(aFace);
+  Standard_Integer NbModif = 0;
+  Standard_Boolean hasFailed = Standard_False;
+  Standard_Real tol = Precision::Confusion();
 
-      //surface and location to construct result
-      TopLoc_Location aBaseLocation;
-      Handle(Geom_Surface) aBaseSurface = BRep_Tool::Surface(aFace,aBaseLocation);
-      aBaseSurface = ClearRts(aBaseSurface);
+  // count faces
+  Standard_Integer nbf = 0;
+  TopExp_Explorer exp;
+  TopTools_MapOfShape mapF;
+  for (exp.Init(theInpShape, TopAbs_FACE); exp.More(); exp.Next()) {
+    if (mapF.Add(exp.Current()))
+      nbf++;
+  }
 
-      // find adjacent faces to union
-      Standard_Integer i;
-      for (i = 1; i <= edges.Length(); i++) {
-        TopoDS_Edge edge = TopoDS::Edge(edges(i));
-        if (BRep_Tool::Degenerated(edge))
-          continue;
+  // processing each face
+  mapF.Clear();
+  for (exp.Init(theInpShape, TopAbs_FACE); exp.More(); exp.Next()) {
+    TopoDS_Face aFace = TopoDS::Face(exp.Current().Oriented(TopAbs_FORWARD));
+
+    if (aProcessed.Contains(aFace))
+      continue;
+
+    Standard_Integer dummy;
+    TopTools_SequenceOfShape edges;
+    AddOrdinaryEdges(edges,aFace,dummy);
+
+    TopTools_SequenceOfShape faces;
+    faces.Append(aFace);
 
-        // get connectivity of the edge in the global shape
-        const TopTools_ListOfShape& aGList = aGMapEdgeFaces.FindFromKey(edge);
-        if (!myAllowInternal && aGList.Extent() != 2) {
-          // non mainfold case is not processed unless myAllowInternal
+    //surface and location to construct result
+    TopLoc_Location aBaseLocation;
+    Handle(Geom_Surface) aBaseSurface = BRep_Tool::Surface(aFace,aBaseLocation);
+    aBaseSurface = ClearRts(aBaseSurface);
+
+    // find adjacent faces to union
+    Standard_Integer i;
+    for (i = 1; i <= edges.Length(); i++) {
+      TopoDS_Edge edge = TopoDS::Edge(edges(i));
+      if (BRep_Tool::Degenerated(edge))
+        continue;
+
+      // get connectivity of the edge in the global shape
+      const TopTools_ListOfShape& aGList = theGMapEdgeFaces.FindFromKey(edge);
+      if (!myAllowInternal && aGList.Extent() != 2) {
+        // non mainfold case is not processed unless myAllowInternal
+        continue;
+      }
+      // process faces connected through the edge in the current shape
+      const TopTools_ListOfShape& aList = aMapEdgeFaces.FindFromKey(edge);
+      TopTools_ListIteratorOfListOfShape anIter(aList);
+      for (; anIter.More(); anIter.Next()) {
+        TopoDS_Face anCheckedFace = TopoDS::Face(anIter.Value().Oriented(TopAbs_FORWARD));
+        if (anCheckedFace.IsSame(aFace))
           continue;
-        }
-        // process faces connected through the edge in the current shell
-        const TopTools_ListOfShape& aList = aMapEdgeFaces.FindFromKey(edge);
-        TopTools_ListIteratorOfListOfShape anIter(aList);
-        for (; anIter.More(); anIter.Next()) {
-          TopoDS_Face anCheckedFace = TopoDS::Face(anIter.Value().Oriented(TopAbs_FORWARD));
-          if (anCheckedFace.IsSame(aFace))
-            continue;
 
-          if (aProcessed.Contains(anCheckedFace))
-            continue;
+        if (aProcessed.Contains(anCheckedFace))
+          continue;
 
-          if (IsSameDomain(aFace,anCheckedFace)) {
+        if (IsCheckSharedEdgeOri && !CheckSharedEdgeOri(aFace, anCheckedFace, edge) )
+          continue;
 
-            // hotfix for 27271: prevent merging along periodic direction.
-            if (IsLikeSeam(edge, aFace, aBaseSurface))
-              continue;
+        if (IsSameDomain(aFace,anCheckedFace)) {
 
-            // replacing pcurves
-            TopoDS_Face aMockUpFace;
-            BRep_Builder B;
-            B.MakeFace(aMockUpFace,aBaseSurface,aBaseLocation,0.);
-            MovePCurves(aMockUpFace,anCheckedFace);
+          // hotfix for 27271: prevent merging along periodic direction.
+          if (IsLikeSeam(edge, aFace, aBaseSurface))
+            continue;
 
-            if (AddOrdinaryEdges(edges,aMockUpFace,dummy)) {
-              // sequence edges is modified
-              i = dummy;
-            }
+          // replacing pcurves
+          TopoDS_Face aMockUpFace;
+          BRep_Builder B;
+          B.MakeFace(aMockUpFace,aBaseSurface,aBaseLocation,0.);
+          MovePCurves(aMockUpFace,anCheckedFace);
 
-            faces.Append(anCheckedFace);
-            aProcessed.Add(anCheckedFace);
-            break;
+          if (AddOrdinaryEdges(edges,aMockUpFace,dummy)) {
+            // sequence edges is modified
+            i = dummy;
           }
+
+          faces.Append(anCheckedFace);
+          aProcessed.Add(anCheckedFace);
+          break;
         }
       }
+    }
 
-      if (faces.Length() > 1) {
-        // fill in the connectivity map for selected faces
-        TopTools_IndexedDataMapOfShapeListOfShape aMapEF;
-        for (i = 1; i <= faces.Length(); i++) {
-          TopExp::MapShapesAndAncestors(faces(i), TopAbs_EDGE, TopAbs_FACE, aMapEF);
-        }
+    if (faces.Length() > 1) {
+      // fill in the connectivity map for selected faces
+      TopTools_IndexedDataMapOfShapeListOfShape aMapEF;
+      for (i = 1; i <= faces.Length(); i++) {
+        TopExp::MapShapesAndAncestors(faces(i), TopAbs_EDGE, TopAbs_FACE, aMapEF);
+      }
 
-        // Collect multiconnected edges, i.e. edges that are internal to
-        // the set of selected faces and have connections to other faces.
-        TopTools_ListOfShape aMultEdges;
-        for (i = 1; i <= aMapEF.Extent(); i++) {
-          const TopTools_ListOfShape& aLF = aMapEF(i);
-          if (aLF.Extent() == 2) {
-            const TopoDS_Shape& aE = aMapEF.FindKey(i);
-            const TopTools_ListOfShape& aGLF = aGMapEdgeFaces.FindFromKey(aE);
-            if (aGLF.Extent() > 2) {
-              aMultEdges.Append(aE);
-            }
+      // Collect multiconnected edges, i.e. edges that are internal to
+      // the set of selected faces and have connections to other faces.
+      TopTools_ListOfShape aMultEdges;
+      for (i = 1; i <= aMapEF.Extent(); i++) {
+        const TopTools_ListOfShape& aLF = aMapEF(i);
+        if (aLF.Extent() == 2) {
+          const TopoDS_Shape& aE = aMapEF.FindKey(i);
+          const TopTools_ListOfShape& aGLF = theGMapEdgeFaces.FindFromKey(aE);
+          if (aGLF.Extent() > 2) {
+            aMultEdges.Append(aE);
           }
         }
-        if (!aMultEdges.IsEmpty()) {
-          if (!myAllowInternal) {
-            // Remove from the selection the faces containing multiconnected edges
-            TopTools_MapOfShape anAvoidFaces;
-            TopTools_ListIteratorOfListOfShape it(aMultEdges);
-            for (; it.More(); it.Next()) {
-              const TopoDS_Shape& aE = it.Value();
-              const TopTools_ListOfShape& aLF = aMapEF.FindFromKey(aE);
-              anAvoidFaces.Add(aLF.First());
-              anAvoidFaces.Add(aLF.Last());
-            }
-            for (i = 1; i <= faces.Length(); ) {
-              if (anAvoidFaces.Contains(faces(i))) {
-                // update the boundaries of merged area, for that
-                // remove from 'edges' the edges of this face and add to 'edges' 
-                // the edges of this face that were not present in 'edges' before
-                TopExp_Explorer ex(faces(i), TopAbs_EDGE);
-                for (; ex.More(); ex.Next()) {
-                  TopoDS_Shape aE = ex.Current();
-                  Standard_Integer j;
-                  for (j = 1; j <= edges.Length(); j++) {
-                    if (edges(j).IsSame(aE))
-                      break;
-                  }
-                  if (j <= edges.Length())
-                    edges.Remove(j);
-                  else
-                    edges.Append(aE);
+      }
+      if (!aMultEdges.IsEmpty()) {
+        if (!myAllowInternal) {
+          // Remove from the selection the faces containing multiconnected edges
+          TopTools_MapOfShape anAvoidFaces;
+          TopTools_ListIteratorOfListOfShape it(aMultEdges);
+          for (; it.More(); it.Next()) {
+            const TopoDS_Shape& aE = it.Value();
+            const TopTools_ListOfShape& aLF = aMapEF.FindFromKey(aE);
+            anAvoidFaces.Add(aLF.First());
+            anAvoidFaces.Add(aLF.Last());
+          }
+          for (i = 1; i <= faces.Length(); ) {
+            if (anAvoidFaces.Contains(faces(i))) {
+              // update the boundaries of merged area, for that
+              // remove from 'edges' the edges of this face and add to 'edges' 
+              // the edges of this face that were not present in 'edges' before
+              TopExp_Explorer ex(faces(i), TopAbs_EDGE);
+              for (; ex.More(); ex.Next()) {
+                TopoDS_Shape aE = ex.Current();
+                Standard_Integer j;
+                for (j = 1; j <= edges.Length(); j++) {
+                  if (edges(j).IsSame(aE))
+                    break;
                 }
-                faces.Remove(i);
+                if (j <= edges.Length())
+                  edges.Remove(j);
+                else
+                  edges.Append(aE);
               }
-              else
-                i++;
+              faces.Remove(i);
             }
+            else
+              i++;
           }
-          else {
-            // add multiconnected edges as internal in new face
-            TopTools_ListIteratorOfListOfShape it(aMultEdges);
-            for (; it.More(); it.Next()) {
-              const TopoDS_Shape& aE = it.Value();
-              edges.Append(aE.Oriented(TopAbs_INTERNAL));
-            }
+        }
+        else {
+          // add multiconnected edges as internal in new face
+          TopTools_ListIteratorOfListOfShape it(aMultEdges);
+          for (; it.More(); it.Next()) {
+            const TopoDS_Shape& aE = it.Value();
+            edges.Append(aE.Oriented(TopAbs_INTERNAL));
           }
         }
       }
+    }
 
-      // all faces collected in the sequence. Perform union of faces
-      if (faces.Length() > 1) {
-        NbModif++;
-        TopoDS_Face aResult;
-        BRep_Builder B;
-        B.MakeFace(aResult,aBaseSurface,aBaseLocation,0);
-        Standard_Integer nbWires = 0;
-
-        TopoDS_Face tmpF = TopoDS::Face(myContext->Apply(faces(1).Oriented(TopAbs_FORWARD)));
-        // connecting wires
-        while (edges.Length()>0) {
-
-          Standard_Boolean isEdge3d = Standard_False;
-          nbWires++;
-          TopTools_MapOfShape aVertices;
-          TopoDS_Wire aWire;
-          B.MakeWire(aWire);
-
-          TopoDS_Edge anEdge = TopoDS::Edge(edges(1));
-          edges.Remove(1);
-          // collect internal edges in separate wires
-          Standard_Boolean isInternal = (anEdge.Orientation() == TopAbs_INTERNAL);
-
-          isEdge3d |= !BRep_Tool::Degenerated(anEdge);
-          B.Add(aWire,anEdge);
-          TopoDS_Vertex V1,V2;
-          TopExp::Vertices(anEdge,V1,V2);
-          aVertices.Add(V1);
-          aVertices.Add(V2);
-
-          Standard_Boolean isNewFound = Standard_False;
-          do {
-            isNewFound = Standard_False;
-            for(Standard_Integer j = 1; j <= edges.Length(); j++) {
-              anEdge = TopoDS::Edge(edges(j));
-              // check if the current edge orientation corresponds to the first one
-              Standard_Boolean isCurrInternal = (anEdge.Orientation() == TopAbs_INTERNAL);
-              if (isCurrInternal != isInternal)
-                continue;
-              TopExp::Vertices(anEdge,V1,V2);
-              if(aVertices.Contains(V1) || aVertices.Contains(V2)) {
-                isEdge3d |= !BRep_Tool::Degenerated(anEdge);
-                aVertices.Add(V1);
-                aVertices.Add(V2);
-                B.Add(aWire,anEdge);
-                edges.Remove(j);
-                j--;
-                isNewFound = Standard_True;
-              }
-            }
-          } while (isNewFound);
-
-          // sorting any type of edges
-          aWire.Closed (BRep_Tool::IsClosed (aWire));
-          aWire = TopoDS::Wire(myContext->Apply(aWire));
-
-          Handle(ShapeFix_Wire) sfw = new ShapeFix_Wire(aWire,tmpF,Precision::Confusion());
-          sfw->FixReorder();
-          Standard_Boolean isDegRemoved = Standard_False;
-          if(!sfw->StatusReorder ( ShapeExtend_FAIL )) {
-            // clear degenerated edges if at least one with 3d curve exist
-            if(isEdge3d) {
-              Handle(ShapeExtend_WireData) sewd = sfw->WireData();
-              for(Standard_Integer j = 1; j<=sewd->NbEdges();j++) {
-                TopoDS_Edge E = sewd->Edge(j);
-                if(BRep_Tool::Degenerated(E)) {
-                  sewd->Remove(j);
-                  isDegRemoved = Standard_True;
-                  j--;
-                }
-              }
+    // all faces collected in the sequence. Perform union of faces
+    if (faces.Length() > 1) {
+      NbModif++;
+      TopoDS_Face aResult;
+      BRep_Builder B;
+      B.MakeFace(aResult,aBaseSurface,aBaseLocation,0);
+      Standard_Integer nbWires = 0;
+
+      TopoDS_Face tmpF = TopoDS::Face(myContext->Apply(faces(1).Oriented(TopAbs_FORWARD)));
+      // connecting wires
+      while (edges.Length()>0) {
+
+        Standard_Boolean isEdge3d = Standard_False;
+        nbWires++;
+        TopTools_MapOfShape aVertices;
+        TopoDS_Wire aWire;
+        B.MakeWire(aWire);
+
+        TopoDS_Edge anEdge = TopoDS::Edge(edges(1));
+        edges.Remove(1);
+        // collect internal edges in separate wires
+        Standard_Boolean isInternal = (anEdge.Orientation() == TopAbs_INTERNAL);
+
+        isEdge3d |= !BRep_Tool::Degenerated(anEdge);
+        B.Add(aWire,anEdge);
+        TopoDS_Vertex V1,V2;
+        TopExp::Vertices(anEdge,V1,V2);
+        aVertices.Add(V1);
+        aVertices.Add(V2);
+
+        Standard_Boolean isNewFound = Standard_False;
+        do {
+          isNewFound = Standard_False;
+          for(Standard_Integer j = 1; j <= edges.Length(); j++) {
+            anEdge = TopoDS::Edge(edges(j));
+            // check if the current edge orientation corresponds to the first one
+            Standard_Boolean isCurrInternal = (anEdge.Orientation() == TopAbs_INTERNAL);
+            if (isCurrInternal != isInternal)
+              continue;
+            TopExp::Vertices(anEdge,V1,V2);
+            if(aVertices.Contains(V1) || aVertices.Contains(V2)) {
+              isEdge3d |= !BRep_Tool::Degenerated(anEdge);
+              aVertices.Add(V1);
+              aVertices.Add(V2);
+              B.Add(aWire,anEdge);
+              edges.Remove(j);
+              j--;
+              isNewFound = Standard_True;
             }
-            sfw->FixShifted();
-            if(isDegRemoved)
-              sfw->FixDegenerated();
-          }
-          TopoDS_Wire aWireFixed = sfw->Wire();
-          //aContext->Replace(aWire,aWireFixed);
-          myContext->Replace(aWire,aWireFixed);
-          //for history
-          /*
-          if (!myOldNewMap.IsBound(aWire))
-          {
-            TopTools_ListOfShape EmptyList;
-            myOldNewMap.Bind(aWire, EmptyList);
           }
-          myOldNewMap(aWire).Clear();
-          myOldNewMap(aWire).Append(aWireFixed);
-          */
-          /////////////
-          
-          // add resulting wire
+        } while (isNewFound);
+
+        // sorting any type of edges
+        aWire.Closed (BRep_Tool::IsClosed (aWire));
+        aWire = TopoDS::Wire(myContext->Apply(aWire));
+
+        Handle(ShapeFix_Wire) sfw = new ShapeFix_Wire(aWire,tmpF,Precision::Confusion());
+        sfw->FixReorder();
+        Standard_Boolean isDegRemoved = Standard_False;
+        if(!sfw->StatusReorder ( ShapeExtend_FAIL )) {
+          // clear degenerated edges if at least one with 3d curve exist
           if(isEdge3d) {
-            B.Add(aResult,aWireFixed);
-          }
-          else  {
-            // sorting edges
-            Handle(ShapeExtend_WireData) sbwd = sfw->WireData();
-            Standard_Integer nbEdges = sbwd->NbEdges();
-            // sort degenerated edges and create one edge instead of several ones
-            ShapeAnalysis_WireOrder sawo(Standard_False, 0);
-            ShapeAnalysis_Edge sae;
-            Standard_Integer aLastEdge = nbEdges;
-            for(Standard_Integer j = 1; j <= nbEdges; j++) {
-              Standard_Real f,l;
-              //smh protection on NULL pcurve
-              Handle(Geom2d_Curve) c2d;
-              if(!sae.PCurve(sbwd->Edge(j),tmpF,c2d,f,l)) {
-                aLastEdge--;
-                continue;
+            Handle(ShapeExtend_WireData) sewd = sfw->WireData();
+            for(Standard_Integer j = 1; j<=sewd->NbEdges();j++) {
+              TopoDS_Edge E = sewd->Edge(j);
+              if(BRep_Tool::Degenerated(E)) {
+                sewd->Remove(j);
+                isDegRemoved = Standard_True;
+                j--;
               }
-              sawo.Add(c2d->Value(f).XY(),c2d->Value(l).XY());
             }
-            sawo.Perform();
-
-            // constructind one degenerative edge
-            gp_XY aStart, anEnd, tmp;
-            Standard_Integer nbFirst = sawo.Ordered(1);
-            TopoDS_Edge anOrigE = TopoDS::Edge(sbwd->Edge(nbFirst).Oriented(TopAbs_FORWARD));
-            ShapeBuild_Edge sbe;
-            TopoDS_Vertex aDummyV;
-            TopoDS_Edge E = sbe.CopyReplaceVertices(anOrigE,aDummyV,aDummyV);
-            sawo.XY(nbFirst,aStart,tmp);
-            sawo.XY(sawo.Ordered(aLastEdge),tmp,anEnd);
-
-            gp_XY aVec = anEnd-aStart;
-            Handle(Geom2d_Line) aLine = new Geom2d_Line(aStart,gp_Dir2d(anEnd-aStart));
-
-            B.UpdateEdge(E,aLine,tmpF,0.);
-            B.Range(E,tmpF,0.,aVec.Modulus());
-            Handle(Geom_Curve) C3d;
-            B.UpdateEdge(E,C3d,0.);
-            B.Degenerated(E,Standard_True);
-            TopoDS_Wire aW;
-            B.MakeWire(aW);
-            B.Add(aW,E);
-            aW.Closed (Standard_True);
-            B.Add(aResult,aW);
           }
+          sfw->FixShifted();
+          if(isDegRemoved)
+            sfw->FixDegenerated();
         }
-
-        // perform substitution of face
-        //aContext->Replace(aContext->Apply(aFace),aResult);
-        myContext->Replace(myContext->Apply(aFace),aResult);
+        TopoDS_Wire aWireFixed = sfw->Wire();
+        //aContext->Replace(aWire,aWireFixed);
+        myContext->Replace(aWire,aWireFixed);
         //for history
         /*
-        if (!myOldNewMap.IsBound(aFace))
+        if (!myOldNewMap.IsBound(aWire))
         {
-          TopTools_ListOfShape EmptyList;
-          myOldNewMap.Bind(aFace, EmptyList);
+        TopTools_ListOfShape EmptyList;
+        myOldNewMap.Bind(aWire, EmptyList);
         }
-        myOldNewMap(aFace).Clear();
-        myOldNewMap(aFace).Append(aResult);
+        myOldNewMap(aWire).Clear();
+        myOldNewMap(aWire).Append(aWireFixed);
         */
         /////////////
 
-        ShapeFix_Face sff (aResult);
-        //Intializing by tolerances
-        sff.SetPrecision(Precision::Confusion());
-        sff.SetMinTolerance(tol);
-        sff.SetMaxTolerance(1.);
-        //Setting modes
-        sff.FixOrientationMode() = 0;
-        //sff.FixWireMode() = 0;
-        //sff.SetContext(aContext);
-        sff.SetContext(myContext);
-        // Applying the fixes
-        sff.Perform();
-        if(sff.Status(ShapeExtend_FAIL))
-        hasFailed = Standard_True;
-
-        // breaking down to several faces
-        //TopoDS_Shape theResult = aContext->Apply(aResult);
-        TopoDS_Shape theResult = myContext->Apply(aResult);
-        for (TopExp_Explorer aFaceExp (theResult,TopAbs_FACE); aFaceExp.More(); aFaceExp.Next()) {
-          TopoDS_Face aCurrent = TopoDS::Face(aFaceExp.Current().Oriented(TopAbs_FORWARD));
-          Handle(TColGeom_HArray2OfSurface) grid = new TColGeom_HArray2OfSurface ( 1, 1, 1, 1 );
-          grid->SetValue ( 1, 1, aBaseSurface );
-          Handle(ShapeExtend_CompositeSurface) G = new ShapeExtend_CompositeSurface ( grid );
-          ShapeFix_ComposeShell CompShell;
-          CompShell.Init ( G, aBaseLocation, aCurrent, ::Precision::Confusion() );//myPrecision
-          //CompShell.SetContext( aContext );
-          CompShell.SetContext( myContext );
-
-          TopTools_SequenceOfShape parts, anIntWires;
-          ShapeFix_SequenceOfWireSegment wires;
-          for(TopExp_Explorer W_Exp(aCurrent,TopAbs_WIRE);W_Exp.More();W_Exp.Next()) {
-            const TopoDS_Wire& aWire = TopoDS::Wire(W_Exp.Current());
-            // check if the wire is ordinary (contains non-internal edges)
-            Standard_Boolean isInternal = Standard_True;
-            for (TopoDS_Iterator it(aWire); it.More() && isInternal; it.Next())
-              isInternal = (it.Value().Orientation() == TopAbs_INTERNAL);
-            if (isInternal)
-            {
-              // place internal wire separately
-              anIntWires.Append(aWire);
-            }
-            else
-            {
-              Handle(ShapeExtend_WireData) sbwd =
-                new ShapeExtend_WireData (aWire);
-              ShapeFix_WireSegment seg ( sbwd, TopAbs_REVERSED );
-              wires.Append(seg);
+        // add resulting wire
+        if(isEdge3d) {
+          B.Add(aResult,aWireFixed);
+        }
+        else  {
+          // sorting edges
+          Handle(ShapeExtend_WireData) sbwd = sfw->WireData();
+          Standard_Integer nbEdges = sbwd->NbEdges();
+          // sort degenerated edges and create one edge instead of several ones
+          ShapeAnalysis_WireOrder sawo(Standard_False, 0);
+          ShapeAnalysis_Edge sae;
+          Standard_Integer aLastEdge = nbEdges;
+          for(Standard_Integer j = 1; j <= nbEdges; j++) {
+            Standard_Real f,l;
+            //smh protection on NULL pcurve
+            Handle(Geom2d_Curve) c2d;
+            if(!sae.PCurve(sbwd->Edge(j),tmpF,c2d,f,l)) {
+              aLastEdge--;
+              continue;
             }
+            sawo.Add(c2d->Value(f).XY(),c2d->Value(l).XY());
           }
+          sawo.Perform();
+
+          // constructind one degenerative edge
+          gp_XY aStart, anEnd, tmp;
+          Standard_Integer nbFirst = sawo.Ordered(1);
+          TopoDS_Edge anOrigE = TopoDS::Edge(sbwd->Edge(nbFirst).Oriented(TopAbs_FORWARD));
+          ShapeBuild_Edge sbe;
+          TopoDS_Vertex aDummyV;
+          TopoDS_Edge E = sbe.CopyReplaceVertices(anOrigE,aDummyV,aDummyV);
+          sawo.XY(nbFirst,aStart,tmp);
+          sawo.XY(sawo.Ordered(aLastEdge),tmp,anEnd);
+
+          gp_XY aVec = anEnd-aStart;
+          Handle(Geom2d_Line) aLine = new Geom2d_Line(aStart,gp_Dir2d(anEnd-aStart));
+
+          B.UpdateEdge(E,aLine,tmpF,0.);
+          B.Range(E,tmpF,0.,aVec.Modulus());
+          Handle(Geom_Curve) C3d;
+          B.UpdateEdge(E,C3d,0.);
+          B.Degenerated(E,Standard_True);
+          TopoDS_Wire aW;
+          B.MakeWire(aW);
+          B.Add(aW,E);
+          aW.Closed (Standard_True);
+          B.Add(aResult,aW);
+        }
+      }
 
-          CompShell.DispatchWires ( parts,wires );
-          for (Standard_Integer j=1; j <= parts.Length(); j++ ) {
-            ShapeFix_Face aFixOrient(TopoDS::Face(parts(j)));
-            //aFixOrient.SetContext(aContext);
-            aFixOrient.SetContext(myContext);
-            aFixOrient.FixOrientation();
-            // put internal wires to faces
-            putIntWires(parts(j), anIntWires);
-          }
+      // perform substitution of face
+      //aContext->Replace(aContext->Apply(aFace),aResult);
+      myContext->Replace(myContext->Apply(aFace),aResult);
+      //for history
+      /*
+      if (!myOldNewMap.IsBound(aFace))
+      {
+      TopTools_ListOfShape EmptyList;
+      myOldNewMap.Bind(aFace, EmptyList);
+      }
+      myOldNewMap(aFace).Clear();
+      myOldNewMap(aFace).Append(aResult);
+      */
+      /////////////
 
-          TopoDS_Shape CompRes;
-          if ( parts.Length() !=1 ) {
-            TopoDS_Shell S;
-            B.MakeShell ( S );
-            for ( i=1; i <= parts.Length(); i++ )
-              B.Add ( S, parts(i) );
-            S.Closed (BRep_Tool::IsClosed (S));
-            CompRes = S;
-          }
-          else CompRes = parts(1);
+      ShapeFix_Face sff (aResult);
+      //Intializing by tolerances
+      sff.SetPrecision(Precision::Confusion());
+      sff.SetMinTolerance(tol);
+      sff.SetMaxTolerance(1.);
+      //Setting modes
+      sff.FixOrientationMode() = 0;
+      //sff.FixWireMode() = 0;
+      //sff.SetContext(aContext);
+      sff.SetContext(myContext);
+      // Applying the fixes
+      sff.Perform();
+      if(sff.Status(ShapeExtend_FAIL))
+        hasFailed = Standard_True;
 
-          //aContext->Replace(aCurrent,CompRes);
-          myContext->Replace(aCurrent,CompRes);
-          //for history
-          /*
-          if (!myOldNewMap.IsBound(aCurrent))
+      // breaking down to several faces
+      //TopoDS_Shape theResult = aContext->Apply(aResult);
+      TopoDS_Shape theResult = myContext->Apply(aResult);
+      for (TopExp_Explorer aFaceExp (theResult,TopAbs_FACE); aFaceExp.More(); aFaceExp.Next()) {
+        TopoDS_Face aCurrent = TopoDS::Face(aFaceExp.Current().Oriented(TopAbs_FORWARD));
+        Handle(TColGeom_HArray2OfSurface) grid = new TColGeom_HArray2OfSurface ( 1, 1, 1, 1 );
+        grid->SetValue ( 1, 1, aBaseSurface );
+        Handle(ShapeExtend_CompositeSurface) G = new ShapeExtend_CompositeSurface ( grid );
+        ShapeFix_ComposeShell CompShell;
+        CompShell.Init ( G, aBaseLocation, aCurrent, ::Precision::Confusion() );//myPrecision
+        //CompShell.SetContext( aContext );
+        CompShell.SetContext( myContext );
+
+        TopTools_SequenceOfShape parts, anIntWires;
+        ShapeFix_SequenceOfWireSegment wires;
+        for(TopExp_Explorer W_Exp(aCurrent,TopAbs_WIRE);W_Exp.More();W_Exp.Next()) {
+          const TopoDS_Wire& aWire = TopoDS::Wire(W_Exp.Current());
+          // check if the wire is ordinary (contains non-internal edges)
+          Standard_Boolean isInternal = Standard_True;
+          for (TopoDS_Iterator it(aWire); it.More() && isInternal; it.Next())
+            isInternal = (it.Value().Orientation() == TopAbs_INTERNAL);
+          if (isInternal)
           {
-            TopTools_ListOfShape EmptyList;
-            myOldNewMap.Bind(aCurrent, EmptyList);
+            // place internal wire separately
+            anIntWires.Append(aWire);
+          }
+          else
+          {
+            Handle(ShapeExtend_WireData) sbwd =
+              new ShapeExtend_WireData (aWire);
+            ShapeFix_WireSegment seg ( sbwd, TopAbs_REVERSED );
+            wires.Append(seg);
           }
-          myOldNewMap(aCurrent).Clear();
-          myOldNewMap(aCurrent).Append(CompRes);
-          */
-          /////////////
         }
 
-        // remove the remaining faces
-        for(i = 2; i <= faces.Length(); i++)
-        { 
-          myOldShapes.Bind(faces(i), theResult);
-          myContext->Remove(faces(i));
+        CompShell.DispatchWires ( parts,wires );
+        for (Standard_Integer j=1; j <= parts.Length(); j++ ) {
+          ShapeFix_Face aFixOrient(TopoDS::Face(parts(j)));
+          //aFixOrient.SetContext(aContext);
+          aFixOrient.SetContext(myContext);
+          aFixOrient.FixOrientation();
+          // put internal wires to faces
+          putIntWires(parts(j), anIntWires);
         }
-      }
-    } // end processing each face
-
-    //TopoDS_Shape aResult = Shape;
-    if (NbModif > 0 && !hasFailed) {
-      //TopoDS_Shape aResult = aContext->Apply(aShell);
-      TopoDS_Shape aResult = myContext->Apply(aShell);
-
-      ShapeFix_Edge sfe;
-      if (!myContext.IsNull()) sfe.SetContext(myContext);
-      for (exp.Init(aResult,TopAbs_EDGE); exp.More(); exp.Next()) {
-        TopoDS_Edge E = TopoDS::Edge(exp.Current());
-        sfe.FixVertexTolerance (E);
-        // ptv add fix same parameter
-        sfe.FixSameParameter(E, Precision::Confusion());
-      }
 
-      myContext->Replace(aShell, aResult);
-      //for history
-      /*
-      if (!myOldNewMap.IsBound(aShell))
-      {
+        TopoDS_Shape CompRes;
+        if ( parts.Length() !=1 ) {
+          TopoDS_Shell S;
+          B.MakeShell ( S );
+          for ( i=1; i <= parts.Length(); i++ )
+            B.Add ( S, parts(i) );
+          S.Closed (BRep_Tool::IsClosed (S));
+          CompRes = S;
+        }
+        else CompRes = parts(1);
+
+        //aContext->Replace(aCurrent,CompRes);
+        myContext->Replace(aCurrent,CompRes);
+        //for history
+        /*
+        if (!myOldNewMap.IsBound(aCurrent))
+        {
         TopTools_ListOfShape EmptyList;
-        myOldNewMap.Bind(aShell, EmptyList);
+        myOldNewMap.Bind(aCurrent, EmptyList);
+        }
+        myOldNewMap(aCurrent).Clear();
+        myOldNewMap(aCurrent).Append(CompRes);
+        */
+        /////////////
       }
-      myOldNewMap(aShell).Clear();
-      myOldNewMap(aShell).Append(aResult);
-      */
-      /////////////
+
+      // remove the remaining faces
+      for(i = 2; i <= faces.Length(); i++)
+      { 
+        myOldShapes.Bind(faces(i), theResult);
+        myContext->Remove(faces(i));
+      }
+    }
+  } // end processing each face
+
+  //TopoDS_Shape aResult = Shape;
+  if (NbModif > 0 && !hasFailed) {
+    //TopoDS_Shape aResult = aContext->Apply(aShell);
+    TopoDS_Shape aResult = myContext->Apply(theInpShape);
+
+    ShapeFix_Edge sfe;
+    if (!myContext.IsNull()) sfe.SetContext(myContext);
+    for (exp.Init(aResult,TopAbs_EDGE); exp.More(); exp.Next()) {
+      TopoDS_Edge E = TopoDS::Edge(exp.Current());
+      sfe.FixVertexTolerance (E);
+      // ptv add fix same parameter
+      sfe.FixSameParameter(E, Precision::Confusion());
     }
-    //else
+
+    myContext->Replace(theInpShape, aResult);
+    //for history
+    /*
+    if (!myOldNewMap.IsBound(aShell))
     {
-      for (exp.Init(aShell, TopAbs_FACE); exp.More(); exp.Next()) {
-        TopoDS_Face aFace = TopoDS::Face(exp.Current().Oriented(TopAbs_FORWARD));
-        Handle(ShapeFix_Wire) sfw = new ShapeFix_Wire;
-        sfw->SetContext(myContext);
-        sfw->SetPrecision(Precision::Confusion());
-        sfw->SetMinTolerance(Precision::Confusion());
-        sfw->SetMaxTolerance(1.);
-        sfw->SetFace(aFace);
-        for (TopoDS_Iterator iter (aFace,Standard_False); iter.More(); iter.Next()) {
-          TopoDS_Wire wire = TopoDS::Wire(iter.Value());
-          sfw->Load(wire);
-          sfw->FixReorder();
-          sfw->FixShifted();
-        }
+    TopTools_ListOfShape EmptyList;
+    myOldNewMap.Bind(aShell, EmptyList);
+    }
+    myOldNewMap(aShell).Clear();
+    myOldNewMap(aShell).Append(aResult);
+    */
+    /////////////
+  }
+  //else
+  {
+    for (exp.Init(theInpShape, TopAbs_FACE); exp.More(); exp.Next()) {
+      TopoDS_Face aFace = TopoDS::Face(exp.Current().Oriented(TopAbs_FORWARD));
+      Handle(ShapeFix_Wire) sfw = new ShapeFix_Wire;
+      sfw->SetContext(myContext);
+      sfw->SetPrecision(Precision::Confusion());
+      sfw->SetMinTolerance(Precision::Confusion());
+      sfw->SetMaxTolerance(1.);
+      sfw->SetFace(aFace);
+      for (TopoDS_Iterator iter (aFace,Standard_False); iter.More(); iter.Next()) {
+        TopoDS_Wire wire = TopoDS::Wire(iter.Value());
+        sfw->Load(wire);
+        sfw->FixReorder();
+        sfw->FixShifted();
       }
     }
-  } // end processing each shell
+  }
 
-  myShape = myContext->Apply(myShape);
 }
 
 //=======================================================================
index 452a727..de185b6 100644 (file)
@@ -24,6 +24,7 @@
 #include <Standard_Boolean.hxx>
 #include <MMgt_TShared.hxx>
 #include <TopTools_DataMapOfShapeShape.hxx>
+#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
 class ShapeBuild_ReShape;
 class TopoDS_Shape;
 
@@ -94,6 +95,9 @@ protected:
 
 private:
 
+  void IntUnifyFaces(const TopoDS_Shape& theInpShape,
+                     const TopTools_IndexedDataMapOfShapeListOfShape& theGMapEdgeFaces,
+                     Standard_Boolean IsCheckSharedEdgeOri);
 
   TopoDS_Shape myInitShape;
   Standard_Boolean myUnifyFaces;
diff --git a/tests/bugs/modalg_6/bug27199 b/tests/bugs/modalg_6/bug27199
new file mode 100644 (file)
index 0000000..d3defa4
--- /dev/null
@@ -0,0 +1,19 @@
+puts "========"
+puts "OCC27199"
+puts "========"
+puts ""
+##############################################
+# Unifysamedomain regression issue in OCCT 7
+##############################################
+
+restore [locate_data_file bug27199_i1_i2.brep] sh
+
+explode sh
+bop sh_1 sh_2
+bopfuse r
+unifysamedom result r
+checkshape result
+
+checknbshapes result -face 1
+
+checkview -display result -2d -path ${imagedir}/${test_image}.png