]> OCCT Git - occt-copy.git/commitdiff
0027035: General fuse algorithm loses face CR27035_680
authornbv <nbv@opencascade.com>
Wed, 17 Feb 2016 07:31:18 +0000 (10:31 +0300)
committernbv <nbv@opencascade.com>
Wed, 17 Feb 2016 13:58:29 +0000 (16:58 +0300)
Porting the fix for issue #27035 to OCCT 6.8.0.

(cherry picked from commit f6f844dc652a256f1aa73c92fea2cf2756bea348)
(cherry picked from commit 6dd894d85532a447fd54f59c4504ddd76a99b658)

Addition correction in order to avoid compiler warnings/errors.

src/BOPAlgo/BOPAlgo_Builder_2.cxx
src/BOPTools/BOPTools_AlgoTools2D.cdl
src/BOPTools/BOPTools_AlgoTools2D.cxx
src/GeomLib/GeomLib.cdl
src/GeomLib/GeomLib.cxx
tests/bugs/modalg_2/bug472_3
tests/bugs/modalg_5/bug27035 [new file with mode: 0644]

index eb24e6b96d2fa7559983f4d1247a76688383155f..e5dc03295c696a86f4cb8e2ca7e23920ca1ce633 100644 (file)
@@ -59,6 +59,7 @@
 #include <BOPTools_ListOfCoupleOfShape.hxx>
 #include <BOPTools_MapOfSet.hxx>
 #include <BOPTools_DataMapOfShapeSet.hxx>
+#include <GeomLib.hxx>
 
 
 static
@@ -284,6 +285,9 @@ void BOPAlgo_Builder::BuildSplitFaces()
     }
     //
     const TopoDS_Face& aF=(*(TopoDS_Face*)(&aSI.Shape()));
+    Standard_Boolean isUClosed = Standard_False,
+                     isVClosed = Standard_False,
+                     isChecked = Standard_False;
     //
     bHasFaceInfo=myDS->HasFaceInfo(i);
     if(!bHasFaceInfo) {
@@ -321,8 +325,6 @@ void BOPAlgo_Builder::BuildSplitFaces()
     for (; aExp.More(); aExp.Next()) {
       const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&aExp.Current()));
       anOriE=aE.Orientation();
-      bIsDegenerated=BRep_Tool::Degenerated(aE);
-      bIsClosed=BRep_Tool::IsClosed(aE, aF);
       //
       if (!myImages.IsBound(aE)) {
         if (anOriE==TopAbs_INTERNAL) {
@@ -335,8 +337,32 @@ void BOPAlgo_Builder::BuildSplitFaces()
         else {
           aLE.Append(aE);
         }
+
+        continue;
+      }
+
+      if(!isChecked)
+      {
+        const Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aF);
+        GeomLib::IsClosed(aSurf, BRep_Tool::Tolerance(aE),
+          isUClosed, isVClosed);
+
+        isChecked = Standard_True;
+      }
+
+      bIsClosed = Standard_False;
+
+      if((isUClosed || isVClosed) && BRep_Tool::IsClosed(aE, aF)) 
+      {
+
+        Standard_Boolean isUIso = Standard_False, isVIso = Standard_False;
+        BOPTools_AlgoTools2D::IsEdgeIsoline(aE, aF, isUIso, isVIso);
+
+        bIsClosed = ((isUClosed && isUIso) || (isVClosed && isVIso));
       }
-      else {//else 1
+
+      bIsDegenerated=BRep_Tool::Degenerated(aE);
+
         const BOPCol_ListOfShape& aLIE=myImages.Find(aE);
         aIt.Initialize(aLIE);
         for (; aIt.More(); aIt.Next()) {
@@ -376,7 +402,6 @@ void BOPAlgo_Builder::BuildSplitFaces()
           }
           aLE.Append(aSp);
         }// for (; aIt.More(); aIt.Next()) {
-      }// else 1
     }// for (; aExp.More(); aExp.Next()) {
     // 
     //
index e62abb1a50b77f94fa03682926300389ee6d9de3..f4aafceaae80347c5be0c64bc80e3fb4662b47db 100644 (file)
@@ -196,5 +196,13 @@ is
           ---Purpose:   
           --- Make empty  P-Curve <aC> of relevant to <PC> type  
           ---
+          
+    IsEdgeIsoline(myclass; 
+                  theE: Edge from TopoDS;
+                  theF: Face from TopoDS;
+                  isTheUIso, isTheVIso: in out Boolean from Standard);
+          --- Purpose: Checks if CurveOnSurface of theE on theF matches with
+           --         isoline of theF surface. Sets corresponding values for
+           --         isTheUIso and isTheVIso variables. 
 
 end AlgoTools2D;
index 712caa7eab345b1edd7b19f363f40c1f06481ec0..4bbb43c900559b33a49fd9b94a33003070af3154 100644 (file)
@@ -833,3 +833,39 @@ Standard_Real MaxToleranceEdge (const TopoDS_Face& aF)
   }
   return aTolMax;
 }
+
+//=======================================================================
+//function : IsEdgeIsoline
+//purpose  : 
+//=======================================================================
+void BOPTools_AlgoTools2D::IsEdgeIsoline( const TopoDS_Edge& theE,
+                                          const TopoDS_Face& theF,
+                                          Standard_Boolean& isTheUIso,
+                                          Standard_Boolean& isTheVIso)
+{
+  isTheUIso = isTheVIso = Standard_False;
+
+  gp_Vec2d aT;
+  gp_Pnt2d aP;
+  Standard_Real aFirst = 0.0, aLast = 0.0;
+  const Handle(Geom2d_Curve) aPC = BRep_Tool::CurveOnSurface(theE, theF, aFirst, aLast);
+
+  aPC->D1(0.5*(aFirst+aLast), aP, aT);
+
+  const Standard_Real aSqMagn = aT.SquareMagnitude();
+  if(aSqMagn <= gp::Resolution())
+    return;
+
+  //Normalyze aT
+  aT /= sqrt(aSqMagn);
+
+  //sin(da) ~ da, when da->0.
+  const Standard_Real aTol = Precision::Angular();
+  const gp_Vec2d aRefVDir(0.0, 1.0), aRefUDir(1.0, 0.0);
+
+  const Standard_Real aDPv = aT.CrossMagnitude(aRefVDir),
+                      aDPu = aT.CrossMagnitude(aRefUDir);
+
+  isTheUIso = (aDPv <= aTol);
+  isTheVIso = (aDPu <= aTol);
+}
index cc19f58dd953dc38c6377772c5a9d8ad8ed9f442..2dd259652cefd79d45a5e9b0e823d7e1ab5ae353 100644 (file)
@@ -287,6 +287,35 @@ is
      --                  1 for  quasysingular (ex.: sphere  pole) 
      --                  2 for conical singular  point      
      --                  3 if computation impossible  (for ex. DU||DV - tangent isolines)
+     
+    IsClosed(S: Surface from Geom ; Tol: Real from Standard;
+              isUClosed, isVClosed: in out Boolean from Standard);
+    --- Purpose: This method defines if opposite boundaries of surface
+     --          coincide with given tolerance
+    
+    IsBSplUClosed(S: BSplineSurface from Geom; U1, U2, Tol: Real from Standard)
+              returns Boolean from  Standard;
+    --- Purpose: Returns true if the poles of U1-isoline and the poles of
+     --          U2-isoline of surface are identical according to tolerance criterion.
+     --          For rational surfaces Weights(i)*Poles(i) are checked.
+    
+    IsBSplVClosed(S: BSplineSurface from Geom; V1, V2, Tol: Real from Standard)
+              returns Boolean from  Standard;
+    --- Purpose: Returns true if the poles of V1-isoline and the poles of
+     --          V2-isoline of surface are identical according to tolerance criterion.
+     --          For rational surfaces Weights(i)*Poles(i) are checked.
+     
+    IsBzUClosed(S: BezierSurface from Geom; U1, U2, Tol: Real from Standard)
+              returns Boolean from  Standard;
+    --- Purpose: Returns true if the poles of U1-isoline and the poles of
+     --          U2-isoline of surface are identical according to tolerance criterion.
+    
+    IsBzVClosed(S: BezierSurface from Geom; V1, V2, Tol: Real from Standard)
+              returns Boolean from  Standard;
+    --- Purpose: Returns true if the poles of V1-isoline and the poles of
+     --          V2-isoline of surface are identical according to tolerance criterion.
+        
+     
 
 
 end GeomLib;
index 90fff069666065bf022c0c59fb20d1200ae8b72a..bcab45cfd7a1dc7da6e97a0d99e5abcf8c0bb99a 100644 (file)
 
 #include <Standard_ConstructionError.hxx>
 
+static Standard_Boolean CompareWeightPoles(const TColgp_Array1OfPnt& thePoles1, 
+                                           const TColStd_Array1OfReal* const theW1,
+                                           const TColgp_Array1OfPnt& thePoles2,
+                                           const TColStd_Array1OfReal* const theW2,
+                                           const Standard_Real theTol);
+
 //=======================================================================
 //function : ComputeLambda
 //purpose  : Calcul le facteur lambda qui minimise la variation de vittesse
@@ -2439,4 +2445,358 @@ Standard_Integer GeomLib::NormEstim(const Handle(Geom_Surface)& S,
   return 3;
 }
  
+//=======================================================================
+//function : IsClosed
+//purpose  : 
+//=======================================================================
+void GeomLib::IsClosed (const Handle(Geom_Surface)& S, 
+                        const Standard_Real Tol,
+                        Standard_Boolean& isUClosed, Standard_Boolean& isVClosed) 
+{
+  isUClosed = Standard_False;
+  isVClosed = Standard_False;
+  //
+  GeomAdaptor_Surface aGAS(S);
+  GeomAbs_SurfaceType aSType = aGAS.GetType();
+  //
+  Standard_Real Tol2 = Tol * Tol;
+  switch (aSType)
+  {
+    case GeomAbs_Plane:
+    {
+      return;
+    }
+    case GeomAbs_Cylinder:
+    case GeomAbs_SurfaceOfExtrusion:
+    {
+      Standard_Real u1 = aGAS.FirstUParameter(), u2 = aGAS.LastUParameter();
+      Standard_Real v1 = aGAS.FirstVParameter();
+      if(Precision::IsInfinite(v1))
+        v1 = 0.;
+      gp_Pnt p1 = aGAS.Value(u1, v1);
+      gp_Pnt p2 = aGAS.Value(u2, v1);
+      isUClosed = p1.SquareDistance(p2) <= Tol2;
+      return;
+    }
+    case GeomAbs_Cone:
+    {
+      Standard_Real u1 = aGAS.FirstUParameter(), u2 = aGAS.LastUParameter();
+      Standard_Real v1 = aGAS.FirstVParameter(), v2 = aGAS.LastVParameter();
+      //find v with maximal distance from axis
+      if(!(Precision::IsInfinite(v1) || Precision::IsInfinite(v2)))
+      {
+        gp_Cone aCone = aGAS.Cone();
+        gp_Pnt anApex = aCone.Apex();
+        gp_Pnt P1 = aGAS.Value(u1, v1);
+        gp_Pnt P2 = aGAS.Value(u1, v2);
+        if(P2.SquareDistance(anApex) > P1.SquareDistance(anApex))
+        {
+          v1 = v2;
+        }
+      }
+      else
+      {
+        v1 = 0.;
+      }
+      gp_Pnt p1 = aGAS.Value(u1, v1);
+      gp_Pnt p2 = aGAS.Value(u2, v1);
+      isUClosed = p1.SquareDistance(p2) <= Tol2;
+      return;
+    }
+    case GeomAbs_Sphere:
+    {
+      Standard_Real u1 = aGAS.FirstUParameter(), u2 = aGAS.LastUParameter();
+      Standard_Real v1 = aGAS.FirstVParameter(), v2 = aGAS.LastVParameter();
+      //find v with maximal distance from axis
+      if(v1*v2 <= 0.)
+      {
+        v1 = 0.;
+      }
+      else
+      {
+        if(v1 < 0.)
+        {
+          v1 = v2;
+        }
+      }
+      gp_Pnt p1 = aGAS.Value(u1, v1);
+      gp_Pnt p2 = aGAS.Value(u2, v1);
+      isUClosed = p1.SquareDistance(p2) <= Tol2;
+      return;
+    }
+    case GeomAbs_Torus:
+    {
+      Standard_Real ures = aGAS.UResolution(Tol);
+      Standard_Real vres = aGAS.VResolution(Tol);
+      Standard_Real u1 = aGAS.FirstUParameter(), u2 = aGAS.LastUParameter();
+      Standard_Real v1 = aGAS.FirstVParameter(), v2 = aGAS.LastVParameter();
+      //
+      isUClosed = (u2 - u1) >= aGAS.UPeriod() - ures;
+      isVClosed = (v2 - v1) >= aGAS.VPeriod() - vres;
+      return;
+    }
+    case GeomAbs_BSplineSurface:
+    {
+      Standard_Real u1 = aGAS.FirstUParameter(), u2 = aGAS.LastUParameter();
+      Standard_Real v1 = aGAS.FirstVParameter(), v2 = aGAS.LastVParameter();
+      Handle(Geom_BSplineSurface) aBSpl = aGAS.BSpline();
+      isUClosed = GeomLib::IsBSplUClosed(aBSpl, u1, u2, Tol);
+      isVClosed = GeomLib::IsBSplVClosed(aBSpl, v1, v2, Tol);
+      return;
+    }
+    case GeomAbs_BezierSurface:
+    {
+      Standard_Real u1 = aGAS.FirstUParameter(), u2 = aGAS.LastUParameter();
+      Standard_Real v1 = aGAS.FirstVParameter(), v2 = aGAS.LastVParameter();
+      Handle(Geom_BezierSurface) aBz = aGAS.Bezier();
+      isUClosed = GeomLib::IsBzUClosed(aBz, u1, u2, Tol);
+      isVClosed = GeomLib::IsBzVClosed(aBz, v1, v2, Tol);
+      return;
+    }
+    case GeomAbs_SurfaceOfRevolution:
+    case GeomAbs_OffsetSurface:
+    case GeomAbs_OtherSurface:
+    {
+      Standard_Integer nbp = 23;
+      Standard_Real u1 = aGAS.FirstUParameter(), u2 = aGAS.LastUParameter();
+      Standard_Real v1 = aGAS.FirstVParameter(), v2 = aGAS.LastVParameter();
+      if(Precision::IsInfinite(v1))
+      {
+        v1 = Sign(1., v1);
+      }
+      if(Precision::IsInfinite(v2))
+      {
+        v2 = Sign(1., v2);
+      }
+      //
+      if(aSType == GeomAbs_OffsetSurface ||
+         aSType == GeomAbs_OtherSurface)
+      {
+        if(Precision::IsInfinite(u1))
+        {
+          u1 = Sign(1., u1);
+        }
+        if(Precision::IsInfinite(u2))
+        {
+          u2 = Sign(1., u2);
+        }
+      }
+      isUClosed = Standard_True;
+      Standard_Real dt = (v2 - v1) / (nbp - 1);
+      Standard_Real res = Max(aGAS.UResolution(Tol), Precision::PConfusion());
+      if(dt <= res)
+      {
+        nbp = RealToInt((v2 - v1) /(2.*res)) + 1;
+        nbp = Max(nbp, 2);
+        dt = (v2 - v1) / (nbp - 1);
+      }
+      Standard_Real t;
+      Standard_Integer i;
+      for(i = 0; i < nbp;  ++i)
+      {
+        t = (i == nbp-1 ? v2 : v1 + i * dt);
+        gp_Pnt p1 = aGAS.Value(u1, t);
+        gp_Pnt p2 = aGAS.Value(u2, t);
+        if(p1.SquareDistance(p2) > Tol2)
+        {
+          isUClosed = Standard_False;
+          break;
+        }
+      }
+      // 
+      nbp = 23;
+      isVClosed = Standard_True;
+      dt = (u2 - u1) / (nbp - 1);
+      res = Max(aGAS.VResolution(Tol), Precision::PConfusion());
+      if(dt <= res)
+      {
+        nbp = RealToInt((u2 - u1) /(2.*res)) + 1;
+        nbp = Max(nbp, 2);
+        dt = (u2 - u1) / (nbp - 1);
+      }
+      for(i = 0; i < nbp;  ++i)
+      {
+        t = (i == nbp-1 ? u2 : u1 + i * dt);
+        gp_Pnt p1 = aGAS.Value(t, v1);
+        gp_Pnt p2 = aGAS.Value(t, v2);
+        if(p1.SquareDistance(p2) > Tol2)
+        {
+          isVClosed = Standard_False;
+          break;
+        }
+      }
+      return;
+    }
+    default:
+    {
+      return;
+    }
+  }
+}
+
+//=======================================================================
+//function : IsBSplUClosed
+//purpose  : 
+//=======================================================================
+Standard_Boolean GeomLib::IsBSplUClosed (const Handle(Geom_BSplineSurface)& S, 
+                                         const Standard_Real U1,
+                                         const Standard_Real U2,
+                                         const Standard_Real Tol) 
+{   
+  Handle(Geom_Curve) aCUF = S->UIso( U1 );
+  Handle(Geom_Curve) aCUL = S->UIso( U2 );
+  if(aCUF.IsNull() || aCUL.IsNull())
+    return Standard_False;
+  Standard_Real Tol2 = 2.*Tol;
+  Handle(Geom_BSplineCurve) aBsF = Handle(Geom_BSplineCurve)::DownCast(aCUF);
+  Handle(Geom_BSplineCurve) aBsL = Handle(Geom_BSplineCurve)::DownCast(aCUL);
+  
+  TColgp_Array1OfPnt aPF(1, aBsF->NbPoles()), aPL(1, aBsL->NbPoles());
+  aBsF->Poles(aPF);
+  aBsL->Poles(aPL);
+
+  TColStd_Array1OfReal *aWF = 0, *aWL = 0;
+  if(aBsF->IsRational())
+  {
+    aWF = new TColStd_Array1OfReal(aPF.Lower(), aPF.Upper());
+    aBsF->Weights(*aWF);
+  }
+
+  if(aBsL->IsRational())
+  {
+    aWL = new TColStd_Array1OfReal(aPL.Lower(), aPL.Upper());
+    aBsL->Weights(*aWL);
+  }
+
+  const Standard_Boolean aRetVal = CompareWeightPoles(aPF, aWF, aPL, aWL, Tol2);
+  
+  if(aWF)
+    delete aWF;
+
+  if(aWL)
+    delete aWL;
+
+  return aRetVal;
+}
+
+//=======================================================================
+//function : IsBSplVClosed
+//purpose  : 
+//=======================================================================
+Standard_Boolean GeomLib::IsBSplVClosed (const Handle(Geom_BSplineSurface)& S, 
+                                         const Standard_Real V1,
+                                         const Standard_Real V2,
+                                         const Standard_Real Tol) 
+{
+  Handle(Geom_Curve) aCVF = S->VIso( V1 );
+  Handle(Geom_Curve) aCVL = S->VIso( V2 );
+  if(aCVF.IsNull() || aCVL.IsNull())
+    return Standard_False;
+  Standard_Real Tol2 = 2.*Tol;
+  Handle(Geom_BSplineCurve) aBsF = Handle(Geom_BSplineCurve)::DownCast(aCVF);
+  Handle(Geom_BSplineCurve) aBsL = Handle(Geom_BSplineCurve)::DownCast(aCVL);
+  TColgp_Array1OfPnt aPF(1, aBsF->NbPoles()), aPL(1, aBsL->NbPoles());
+  aBsF->Poles(aPF);
+  aBsL->Poles(aPL);
+
+  TColStd_Array1OfReal *aWF = 0, *aWL = 0;
+  if(aBsF->IsRational())
+  {
+    aWF = new TColStd_Array1OfReal(aPF.Lower(), aPF.Upper());
+    aBsF->Weights(*aWF);
+  }
+
+  if(aBsL->IsRational())
+  {
+    aWL = new TColStd_Array1OfReal(aPL.Lower(), aPL.Upper());
+    aBsL->Weights(*aWL);
+  }
 
+  const Standard_Boolean aRetVal = CompareWeightPoles(aPF, aWF, aPL, aWL, Tol2);
+  
+  if(aWF)
+    delete aWF;
+
+  if(aWL)
+    delete aWL;
+
+  return aRetVal;
+}
+//=======================================================================
+//function : IsBzUClosed
+//purpose  : 
+//=======================================================================
+Standard_Boolean GeomLib::IsBzUClosed (const Handle(Geom_BezierSurface)& S, 
+                                       const Standard_Real U1,
+                                       const Standard_Real U2,
+                                       const Standard_Real Tol) 
+{   
+  Handle(Geom_Curve) aCUF = S->UIso( U1 );
+  Handle(Geom_Curve) aCUL = S->UIso( U2 );
+  if(aCUF.IsNull() || aCUL.IsNull())
+    return Standard_False;
+  Standard_Real Tol2 = 2.*Tol;
+  Handle(Geom_BezierCurve) aBzF = Handle(Geom_BezierCurve)::DownCast(aCUF);
+  Handle(Geom_BezierCurve) aBzL = Handle(Geom_BezierCurve)::DownCast(aCUL);
+  TColgp_Array1OfPnt aPF(1, aBzF->NbPoles()), aPL(1, aBzL->NbPoles());
+  aBzF->Poles(aPF);
+  aBzL->Poles(aPL);
+  //
+  return CompareWeightPoles(aPF, 0, aPL, 0, Tol2);
+}
+
+//=======================================================================
+//function : IsBzVClosed
+//purpose  : 
+//=======================================================================
+Standard_Boolean GeomLib::IsBzVClosed (const Handle(Geom_BezierSurface)& S, 
+                                       const Standard_Real V1,
+                                       const Standard_Real V2,
+                                       const Standard_Real Tol) 
+{
+  Handle(Geom_Curve) aCVF = S->VIso( V1 );
+  Handle(Geom_Curve) aCVL = S->VIso( V2 );
+  if(aCVF.IsNull() || aCVL.IsNull())
+    return Standard_False;
+  Standard_Real Tol2 = 2.*Tol;
+  Handle(Geom_BezierCurve) aBzF = Handle(Geom_BezierCurve)::DownCast(aCVF);
+  Handle(Geom_BezierCurve) aBzL = Handle(Geom_BezierCurve)::DownCast(aCVL);
+  TColgp_Array1OfPnt aPF(1, aBzF->NbPoles()), aPL(1, aBzL->NbPoles());
+  aBzF->Poles(aPF);
+  aBzL->Poles(aPL);
+  //
+  return CompareWeightPoles(aPF, 0, aPL, 0, Tol2);
+}
+
+//=======================================================================
+//function : CompareWeightPoles
+//purpose  : Checks if thePoles1(i)*theW1(i) is equal to thePoles2(i)*theW2(i)
+//            with tolerance theTol.
+//           It is necessary for not rational B-splines and Bezier curves
+//            to set theW1 and theW2 adresses to zero.
+//=======================================================================
+static Standard_Boolean CompareWeightPoles(const TColgp_Array1OfPnt& thePoles1, 
+                                           const TColStd_Array1OfReal* const theW1,
+                                           const TColgp_Array1OfPnt& thePoles2,
+                                           const TColStd_Array1OfReal* const theW2,
+                                           const Standard_Real theTol)
+{
+  if(thePoles1.Length() != thePoles2.Length())
+  {
+    return Standard_False;
+  }
+  //
+  Standard_Integer i = 1;
+  for( i = 1 ; i <= thePoles1.Length(); i++ )
+  {
+    const Standard_Real aW1 = (theW1 == 0) ? 1.0 : theW1->Value(i);
+    const Standard_Real aW2 = (theW2 == 0) ? 1.0 : theW2->Value(i);
+
+    gp_XYZ aPole1 = thePoles1.Value(i).XYZ() * aW1;
+    gp_XYZ aPole2 = thePoles2.Value(i).XYZ() * aW2;
+    if(!aPole1.IsEqual(aPole2, theTol))
+      return Standard_False;
+  }
+  //
+  return Standard_True;
+}
index 1e67122a8751a68d0d16ecfc905e6d75ada750d9..d09bbdd4793efcbdc3e1ebbd2fe7f7919e377761 100755 (executable)
@@ -1,7 +1,6 @@
-#puts "TODO OCC12345 ALL: Faulty shapes in variables faulty_1 to faulty_"
-#puts "TODO OCC12345 ALL: Error : The square of result shape is"
-puts "TODO OCC12345 ALL: Error : The command is not valid"
-puts "TODO OCC12345 ALL: Error : Result shape is WRONG because it must contains"
+puts "TODO OCC25917 ALL: Faulty shapes in variables faulty_1 to faulty_"
+puts "TODO OCC25917 ALL: Error : The square of result shape"
+puts "TODO OCC25917 ALL: Error : Result shape is WRONG"
 
 puts "========================"
 puts " OCC472 "
@@ -22,6 +21,6 @@ bfuse result b1 b2
 
 set nb_v_good 5
 set nb_e_edge 7
-set square 0
+set square 229.516
 set 2dviewer 0
 
diff --git a/tests/bugs/modalg_5/bug27035 b/tests/bugs/modalg_5/bug27035
new file mode 100644 (file)
index 0000000..1f2255f
--- /dev/null
@@ -0,0 +1,27 @@
+puts "========"
+puts "OCC27035"
+puts "========"
+puts ""
+###########################################################################
+# General fuse algorithm loses face
+###########################################################################
+
+restore [locate_data_file bug27035_cmpd.brep] a
+
+explode a
+
+bclearobjects
+bcleartools
+
+baddobjects a_1 a_2
+
+bfillds
+bbuild result
+
+set nb_w_good 2
+set nb_f_good 2
+
+donly result
+fit
+
+set 2dviewer 1