0027282: [Regression to 6.9.1] smesh/bugs_00/A6: Cut produces an empty shape
authornbv <nbv@opencascade.com>
Wed, 24 Feb 2016 09:59:36 +0000 (12:59 +0300)
committerbugmaster <bugmaster@opencascade.com>
Tue, 29 Mar 2016 12:52:18 +0000 (15:52 +0300)
1. The reason of the regression is not-closed intersection result. This problem has been solved (in this fix) by adding joint point to the both neighbors intersection lines (lines were extended to the this intersection point). It is made in IntPatch_WLineTool::ExtendTwoWlinesToEachOther(...) method.

2. Interface of IntPatch_PointLine and inherited classes has been changed. Methods ChangeVertex(...) and RemoveVertex(...) have been added.

Test cases for this issue have been created.

Small correction in the code.

12 files changed:
src/IntPatch/IntPatch_Intersection.cxx
src/IntPatch/IntPatch_PointLine.hxx
src/IntPatch/IntPatch_RLine.hxx
src/IntPatch/IntPatch_RLine.lxx
src/IntPatch/IntPatch_WLine.hxx
src/IntPatch/IntPatch_WLine.lxx
src/IntPatch/IntPatch_WLineTool.cxx
src/IntPatch/IntPatch_WLineTool.hxx
src/IntSurf/IntSurf_PntOn2S.cxx
src/IntSurf/IntSurf_PntOn2S.hxx
tests/bugs/modalg_6/bug27282_1 [new file with mode: 0644]
tests/bugs/modalg_6/bug27282_2 [new file with mode: 0644]

index 26e7312..719b406 100644 (file)
@@ -1356,73 +1356,98 @@ void IntPatch_Intersection::GeomGeomPerfom(const Handle(Adaptor3d_HSurface)& the
       if (tgte)
         oppo = interii.OppositeFaces();
 
+      Standard_Boolean isQuadSet = Standard_False;
+      IntSurf_Quadric Quad1,Quad2;
+
       for (Standard_Integer i = 1; i <= interii.NbLines(); i++)
       {
         const Handle(IntPatch_Line)& line = interii.Line(i);
         if (line->ArcType() == IntPatch_Analytic)
         {
-          const GeomAbs_SurfaceType aTyps1 = theS1->GetType();
-          const GeomAbs_SurfaceType aTyps2 = theS2->GetType();
-          IntSurf_Quadric Quad1,Quad2;
-          
-          switch(aTyps1)
+          if(!isQuadSet)
           {
-          case GeomAbs_Plane:
-            Quad1.SetValue(theS1->Plane());
-            break;
-
-          case GeomAbs_Cylinder:
-            Quad1.SetValue(theS1->Cylinder());
-            break;
-
-          case GeomAbs_Sphere:
-            Quad1.SetValue(theS1->Sphere());
-            break;
-
-          case GeomAbs_Cone:
-            Quad1.SetValue(theS1->Cone());
-            break;
-
-          case GeomAbs_Torus:
-            Quad1.SetValue(theS1->Torus());
-            break;
+            isQuadSet = Standard_True;
+            
+            const GeomAbs_SurfaceType aTyps1 = theS1->GetType();
+            const GeomAbs_SurfaceType aTyps2 = theS2->GetType();
+
+            switch(aTyps1)
+            {
+            case GeomAbs_Plane:
+              Quad1.SetValue(theS1->Plane());
+              break;
+
+            case GeomAbs_Cylinder:
+              Quad1.SetValue(theS1->Cylinder());
+              break;
+
+            case GeomAbs_Sphere:
+              Quad1.SetValue(theS1->Sphere());
+              break;
+
+            case GeomAbs_Cone:
+              Quad1.SetValue(theS1->Cone());
+              break;
+
+            case GeomAbs_Torus:
+              Quad1.SetValue(theS1->Torus());
+              break;
+
+            default:
+              isQuadSet = Standard_False;
+              break;
+            }
 
-          default:
-            break;
-          }
+            switch(aTyps2)
+            {
+            case GeomAbs_Plane:
+              Quad2.SetValue(theS2->Plane());
+              break;
+            case GeomAbs_Cylinder:
+              Quad2.SetValue(theS2->Cylinder());
+              break;
+
+            case GeomAbs_Sphere:
+              Quad2.SetValue(theS2->Sphere());
+              break;
+
+            case GeomAbs_Cone:
+              Quad2.SetValue(theS2->Cone());
+              break;
+
+            case GeomAbs_Torus:
+              Quad2.SetValue(theS2->Torus());
+              break;
+
+            default:
+              isQuadSet = Standard_False;
+              break;
+            }
 
-          switch(aTyps2)
-          {
-          case GeomAbs_Plane:
-            Quad2.SetValue(theS2->Plane());
-            break;
-          case GeomAbs_Cylinder:
-            Quad2.SetValue(theS2->Cylinder());
-            break;
-
-          case GeomAbs_Sphere:
-            Quad2.SetValue(theS2->Sphere());
-            break;
-
-          case GeomAbs_Cone:
-            Quad2.SetValue(theS2->Cone());
-            break;
-
-          case GeomAbs_Torus:
-            Quad2.SetValue(theS2->Torus());
-            break;
-
-          default:
-            break;
+            if(!isQuadSet)
+            {
+              break;
+            }
           }
 
           IntPatch_ALineToWLine AToW(Quad1,Quad2,0.01,0.05,aNbPointsInALine);
-          Handle(IntPatch_WLine) wlin=AToW.MakeWLine((*((Handle(IntPatch_ALine) *)(&line))));
+          Handle(IntPatch_WLine) wlin = 
+                      AToW.MakeWLine(Handle(IntPatch_ALine)::DownCast(line));
           wlin->EnablePurging(Standard_False);
           slin.Append(wlin);
         }
         else
-          slin.Append(interii.Line(i));
+          slin.Append(line);
+      }
+
+      if(isQuadSet)
+      {
+        IntPatch_WLineTool::
+          ExtendTwoWlinesToEachOther(slin, Quad1, Quad2, TolTang,
+                                     theS1->IsUPeriodic()? theS1->UPeriod() : 0.0,
+                                     theS2->IsUPeriodic()? theS2->UPeriod() : 0.0,
+                                     theS1->IsVPeriodic()? theS1->VPeriod() : 0.0,
+                                     theS2->IsVPeriodic()? theS2->VPeriod() : 0.0);
       }
 
       for (Standard_Integer i = 1; i <= interii.NbPnts(); i++)
index 3d5561e..71477fe 100644 (file)
@@ -60,9 +60,15 @@ public:
   //! Returns the vertex of range Index on the line.
   Standard_EXPORT virtual const IntPatch_Point& Vertex (const Standard_Integer Index) const = 0;
 
+  //! Returns the vertex of range Index on the line.
+  virtual IntPatch_Point& ChangeVertex (const Standard_Integer Index) = 0;
+
   //! Removes vertices from the line
   Standard_EXPORT virtual void ClearVertexes() = 0;
 
+  //! Removes single vertex from the line
+  Standard_EXPORT virtual void RemoveVertex (const Standard_Integer theIndex) = 0;
+
   //! Returns set of intersection points
   Standard_EXPORT virtual Handle(IntSurf_LineOn2S) Curve() const = 0;
 
index 55d75ab..f91273b 100644 (file)
@@ -122,7 +122,13 @@ public:
   
   //! Returns the vertex of range Index on the line.
   virtual const IntPatch_Point& Vertex (const Standard_Integer Index) const Standard_OVERRIDE;
+
+  //! Returns the vertex of range Index on the line.
+  virtual IntPatch_Point& ChangeVertex (const Standard_Integer Index) Standard_OVERRIDE;
   
+  //! Removes single vertex from the line
+  virtual void RemoveVertex (const Standard_Integer theIndex) Standard_OVERRIDE;
+
     Standard_Boolean HasPolygon() const;
   
   //! Returns the number of intersection points.
index 82c3e13..70debb4 100644 (file)
@@ -102,6 +102,18 @@ inline const IntPatch_Point& IntPatch_RLine::Vertex (const Standard_Integer Inde
   return svtx(Index);
 }
 
+inline IntPatch_Point& IntPatch_RLine::ChangeVertex (const Standard_Integer Index)
+{
+  return svtx(Index);
+}
+
+inline void IntPatch_RLine::RemoveVertex(const Standard_Integer theIndex)
+{
+  if((theIndex < 1) || (theIndex > NbVertex()))
+    Standard_OutOfRange::Raise("Cannot delete not existing vertex");
+  svtx.Remove(theIndex);
+}
+
 inline Standard_Boolean IntPatch_RLine::HasPolygon () const
 {
   return (!curv.IsNull());
index ba64bff..4cfeabf 100644 (file)
@@ -113,6 +113,9 @@ public:
   
   //! Returns the vertex of range Index on the line.
   virtual const IntPatch_Point& Vertex (const Standard_Integer Index) const Standard_OVERRIDE;
+
+  //! Returns the vertex of range Index on the line.
+  virtual IntPatch_Point& ChangeVertex (const Standard_Integer Index) Standard_OVERRIDE;
   
   //! Set the parameters of all the vertex on the line.
   //! if a vertex is already in the line,
@@ -154,7 +157,8 @@ public:
   //! Removes vertices from the line (i.e. cleans svtx member)
   virtual void ClearVertexes() Standard_OVERRIDE;
   
-  Standard_EXPORT void RemoveVertex (const Standard_Integer theIndex);
+  //! Removes single vertex from the line
+  virtual void RemoveVertex (const Standard_Integer theIndex) Standard_OVERRIDE;
   
   Standard_EXPORT void InsertVertexBefore (const Standard_Integer theIndex, const IntPatch_Point& thePnt);
   
index 123bd2f..6c95ee8 100644 (file)
@@ -98,6 +98,11 @@ inline const IntPatch_Point& IntPatch_WLine::Vertex (const Standard_Integer Inde
   return svtx(Index);
 }
 
+inline IntPatch_Point& IntPatch_WLine::ChangeVertex (const Standard_Integer Index)
+{
+  return svtx(Index);
+}
+
 inline void IntPatch_WLine::ClearVertexes()
 {
   svtx.Clear();
index 49d8635..9da9e9d 100644 (file)
@@ -519,12 +519,10 @@ static Standard_Integer IsSeam( const Standard_Real theU1,
 //purpose  : Returns TRUE if segment [thePtf, thePtl] intersects "seam-edge"
 //            (if it exist) or surface boundaries and both thePtf and thePtl do
 //            not match "seam-edge" or boundaries.
-//           Point thePtmid lies in this segment. If thePtmid match
-//            "seam-edge" or boundaries strictly (without any tolerance) then
-//            the function will return TRUE.
+//           Point thePtmid lies in this segment (in both 3D and 2D-space).
+//           If thePtmid match "seam-edge" or boundaries strictly 
+//            (without any tolerance) then the function will return TRUE.
 //            See comments in function body for detail information.
-//
-//           Static subfunction in JoinWLines.
 //=======================================================================
 static Standard_Boolean IsSeamOrBound(const IntSurf_PntOn2S& thePtf,
                                       const IntSurf_PntOn2S& thePtl,
@@ -651,6 +649,107 @@ static Standard_Boolean IsSeamOrBound(const IntSurf_PntOn2S& thePtf,
   return Standard_False;
 }
 
+//=======================================================================
+//function : AbjustPeriodicToPrevPoint
+//purpose  : Returns theCurrentParam in order to the distance betwen 
+//            theRefParam and theCurrentParam is less than 0.5*thePeriod.
+//=======================================================================
+static void AbjustPeriodicToPrevPoint(const Standard_Real theRefParam,
+                                      const Standard_Real thePeriod,
+                                      Standard_Real& theCurrentParam)
+{
+  if(thePeriod == 0.0)
+    return;
+
+  Standard_Real aDeltaPar = 2.0*(theRefParam - theCurrentParam);
+  const Standard_Real anIncr = Sign(thePeriod, aDeltaPar);
+  while(Abs(aDeltaPar) > thePeriod)
+  {
+    theCurrentParam += anIncr;
+    aDeltaPar = 2.0*(theRefParam-theCurrentParam);
+  }
+}
+
+//=======================================================================
+//function : IsIntersectionPoint
+//purpose  : Returns True if thePmid is intersection point
+//            between theS1 and theS2 with given tolerance.
+//           In this case, parameters of thePmid on every quadric
+//            will be recomputed and returned.
+//=======================================================================
+static Standard_Boolean IsIntersectionPoint(const gp_Pnt& thePmid,
+                                            const IntSurf_Quadric& theS1,
+                                            const IntSurf_Quadric& theS2,
+                                            const IntSurf_PntOn2S& theRefPt,
+                                            const Standard_Real theTol,
+                                            const Standard_Real theU1Period,
+                                            const Standard_Real theU2Period,
+                                            const Standard_Real theV1Period,
+                                            const Standard_Real theV2Period,
+                                            Standard_Real &theU1,
+                                            Standard_Real &theV1,
+                                            Standard_Real &theU2,
+                                            Standard_Real &theV2)
+{
+  Standard_Real aU1Ref = 0.0, aV1Ref = 0.0, aU2Ref = 0.0, aV2Ref = 0.0;
+  theRefPt.Parameters(aU1Ref, aV1Ref, aU2Ref, aV2Ref);
+  theS1.Parameters(thePmid, theU1, theV1);
+  theS2.Parameters(thePmid, theU2, theV2);
+
+  AbjustPeriodicToPrevPoint(aU1Ref, theU1Period, theU1);
+  AbjustPeriodicToPrevPoint(aV1Ref, theV1Period, theV1);
+  AbjustPeriodicToPrevPoint(aU2Ref, theU2Period, theU2);
+  AbjustPeriodicToPrevPoint(aV2Ref, theV2Period, theV2);
+
+  const gp_Pnt aP1(theS1.Value(theU1, theV1));
+  const gp_Pnt aP2(theS2.Value(theU2, theV2));
+
+  return (aP1.SquareDistance(aP2) <= theTol*theTol);
+}
+
+//=======================================================================
+//function : ExtendFirst
+//purpose  : Adds thePOn2S to the begin of theWline
+//=======================================================================
+static void ExtendFirst(const Handle(IntPatch_WLine)& theWline,
+                        const IntSurf_PntOn2S &thePOn2S)
+{
+  theWline->Curve()->InsertBefore(1, thePOn2S);
+
+  IntPatch_Point &aVert = theWline->ChangeVertex(1);
+
+  Standard_Real aU1 = 0.0, aV1 = 0.0, aU2 = 0.0, aV2 = 0.0;
+  thePOn2S.Parameters(aU1, aV1, aU2, aV2);
+
+  aVert.SetParameters(aU1, aV1, aU2, aV2);
+  aVert.SetValue(thePOn2S.Value());
+
+  for(Standard_Integer i = 2; i <= theWline->NbVertex(); i++)
+  {
+    IntPatch_Point &aV = theWline->ChangeVertex(i);
+    aV.SetParameter(aV.ParameterOnLine()+1);
+  }
+}
+
+//=======================================================================
+//function : ExtendLast
+//purpose  : Adds thePOn2S to the end of theWline
+//=======================================================================
+static void ExtendLast(const Handle(IntPatch_WLine)& theWline,
+                       const IntSurf_PntOn2S &thePOn2S)
+{
+  theWline->Curve()->Add(thePOn2S);
+
+  IntPatch_Point &aVert = theWline->ChangeVertex(theWline->NbVertex());
+
+  Standard_Real aU1 = 0.0, aV1 = 0.0, aU2 = 0.0, aV2 = 0.0;
+  thePOn2S.Parameters(aU1, aV1, aU2, aV2);
+
+  aVert.SetParameters(aU1, aV1, aU2, aV2);
+  aVert.SetValue(thePOn2S.Value());
+  aVert.SetParameter(theWline->NbPnts());
+}
+
 //=========================================================================
 // function : ComputePurgedWLine
 // purpose  :
@@ -951,4 +1050,298 @@ void IntPatch_WLineTool::JoinWLines(IntPatch_SequenceOfLine& theSlin,
     if(hasBeenRemoved)
       aNumOfLine1--;
   }
-}
\ No newline at end of file
+}
+
+//=======================================================================
+//function : ExtendTwoWlinesToEachOther
+//purpose  : 
+//=======================================================================
+void IntPatch_WLineTool::ExtendTwoWlinesToEachOther(IntPatch_SequenceOfLine& theSlin,
+                                                    const IntSurf_Quadric& theS1,
+                                                    const IntSurf_Quadric& theS2,
+                                                    const Standard_Real theToler3D,
+                                                    const Standard_Real theU1Period,
+                                                    const Standard_Real theU2Period,
+                                                    const Standard_Real theV1Period,
+                                                    const Standard_Real theV2Period)
+{
+  if(theSlin.Length() < 2)
+    return;
+
+  const Standard_Real aMaxAngle = M_PI/6; //30 degree
+  const Standard_Real aSqToler = theToler3D*theToler3D;
+  Standard_Real aU1=0.0, aV1=0.0, aU2=0.0, aV2=0.0;
+  gp_Pnt aPmid;
+  gp_Vec aVec1, aVec2, aVec3;
+
+  for(Standard_Integer aNumOfLine1 = 1; aNumOfLine1 <= theSlin.Length(); aNumOfLine1++)
+  {
+    Handle(IntPatch_WLine) aWLine1 (Handle(IntPatch_WLine)::
+                                    DownCast(theSlin.Value(aNumOfLine1)));
+
+    if(aWLine1.IsNull())
+    {//We must have failed to join not-point-lines
+      continue;
+    }
+    
+    const Standard_Integer aNbPntsWL1 = aWLine1->NbPnts();
+
+    for(Standard_Integer aNumOfLine2 = aNumOfLine1 + 1;
+        aNumOfLine2 <= theSlin.Length(); aNumOfLine2++)
+    {
+      Handle(IntPatch_WLine) aWLine2 (Handle(IntPatch_WLine)::
+                                    DownCast(theSlin.Value(aNumOfLine2)));
+
+      if(aWLine2.IsNull())
+        continue;
+
+      //Enable/Disable of some ckeck. Bit-mask is used for it.
+      //E.g. if 1st point of aWLine1 matches with
+      //1st point of aWLine2 then we do not need in check
+      //1st point of aWLine1 and last point of aWLine2 etc.
+      enum
+      {
+        IntPatchWT_EnAll = 0x00,
+        IntPatchWT_DisLastLast = 0x01,
+        IntPatchWT_DisLastFirst = 0x02,
+        IntPatchWT_DisFirstLast = 0x04,
+        IntPatchWT_DisFirstFirst = 0x08
+      };
+
+      unsigned int aCheckResult = IntPatchWT_EnAll;
+
+      const Standard_Integer aNbPntsWL2 = aWLine2->NbPnts();
+
+      const IntSurf_PntOn2S& aPntFWL1 = aWLine1->Point(1);
+      const IntSurf_PntOn2S& aPntFp1WL1 = aWLine1->Point(2);
+
+      const IntSurf_PntOn2S& aPntLWL1 = aWLine1->Point(aNbPntsWL1);
+      const IntSurf_PntOn2S& aPntLm1WL1 = aWLine1->Point(aNbPntsWL1-1);
+      
+      const IntSurf_PntOn2S& aPntFWL2 = aWLine2->Point(1);
+      const IntSurf_PntOn2S& aPntFp1WL2 = aWLine2->Point(2);
+
+      const IntSurf_PntOn2S& aPntLWL2 = aWLine2->Point(aNbPntsWL2);
+      const IntSurf_PntOn2S& aPntLm1WL2 = aWLine2->Point(aNbPntsWL2-1);
+      
+      //if(!(aCheckResult & IntPatchWT_DisFirstFirst))
+      {// First/First
+        aVec1.SetXYZ(aPntFp1WL1.Value().XYZ() - aPntFWL1.Value().XYZ());
+        aVec2.SetXYZ(aPntFWL2.Value().XYZ() - aPntFp1WL2.Value().XYZ());
+        aVec3.SetXYZ(aPntFWL1.Value().XYZ() - aPntFWL2.Value().XYZ());
+
+        if(aVec3.SquareMagnitude() > aSqToler)
+        {
+          if( (aVec1.Angle(aVec2) < aMaxAngle) &&
+              (aVec1.Angle(aVec3) < aMaxAngle) &&
+              (aVec2.Angle(aVec3) < aMaxAngle))
+          {
+            aPmid.SetXYZ(0.5*(aPntFWL1.Value().XYZ()+aPntFWL2.Value().XYZ()));
+            if(IsIntersectionPoint(aPmid, theS1, theS2, aPntFWL1, theToler3D,
+                                   theU1Period, theU2Period, theV1Period, theV2Period,
+                                   aU1, aV1, aU2, aV2))
+            {
+              IntSurf_PntOn2S aPOn2S;
+              aPOn2S.SetValue(aPmid, aU1, aV1, aU2, aV2);
+              
+              Standard_Real aU11 = 0.0, aV11 = 0.0, aU21 = 0.0, aV21 = 0.0,
+                            aU12 = 0.0, aV12 = 0.0, aU22 = 0.0, aV22 = 0.0;
+              aPntFWL1.Parameters(aU11, aV11, aU21, aV21);
+              aPntFWL2.Parameters(aU12, aV12, aU22, aV22);
+
+              if(!IsSeam(aU11, aU12, theU1Period) &&
+                 !IsSeam(aV11, aV12, theV1Period) &&
+                 !IsSeam(aU21, aU22, theU2Period) &&
+                 !IsSeam(aV21, aV22, theV2Period))
+              {
+                aCheckResult |= (IntPatchWT_DisFirstLast |
+                                 IntPatchWT_DisLastFirst);
+
+                if(!aPOn2S.IsSame(aPntFWL1, Precision::Confusion()))
+                {
+                  ExtendFirst(aWLine1, aPOn2S);
+                }
+                else
+                {
+                  aWLine1->Curve()->Value(1, aPOn2S);
+                }
+
+                if(!aPOn2S.IsSame(aPntFWL2, Precision::Confusion()))
+                {
+                  ExtendFirst(aWLine2, aPOn2S);
+                }
+                else
+                {
+                  aWLine2->Curve()->Value(1, aPOn2S);
+                }
+              }
+            }
+          }
+        }//if(aVec3.SquareMagnitude() > aSqToler) cond.
+      }//if(!(aCheckResult & 0x08)) cond.
+
+      if(!(aCheckResult & IntPatchWT_DisFirstLast))
+      {// First/Last
+        aVec1.SetXYZ(aPntFp1WL1.Value().XYZ() - aPntFWL1.Value().XYZ());
+        aVec2.SetXYZ(aPntLWL2.Value().XYZ() - aPntLm1WL2.Value().XYZ());
+        aVec3.SetXYZ(aPntFWL1.Value().XYZ() - aPntLWL2.Value().XYZ());
+
+        if(aVec3.SquareMagnitude() > aSqToler)
+        {
+          if((aVec1.Angle(aVec2) < aMaxAngle) &&
+             (aVec1.Angle(aVec3) < aMaxAngle) &&
+             (aVec2.Angle(aVec3) < aMaxAngle))
+          {
+            aPmid.SetXYZ(0.5*(aPntFWL1.Value().XYZ()+aPntLWL2.Value().XYZ()));
+            if(IsIntersectionPoint(aPmid, theS1, theS2, aPntFWL1, theToler3D,
+                                   theU1Period, theU2Period, theV1Period, theV2Period,
+                                   aU1, aV1, aU2, aV2))
+            {
+              IntSurf_PntOn2S aPOn2S;
+              aPOn2S.SetValue(aPmid, aU1, aV1, aU2, aV2);
+
+              Standard_Real aU11 = 0.0, aV11 = 0.0, aU21 = 0.0, aV21 = 0.0,
+                            aU12 = 0.0, aV12 = 0.0, aU22 = 0.0, aV22 = 0.0;
+              aPntFWL1.Parameters(aU11, aV11, aU21, aV21);
+              aPntLWL2.Parameters(aU12, aV12, aU22, aV22);
+
+              if(!IsSeam(aU11, aU12, theU1Period) &&
+                 !IsSeam(aV11, aV12, theV1Period) &&
+                 !IsSeam(aU21, aU22, theU2Period) &&
+                 !IsSeam(aV21, aV22, theV2Period))
+              {
+                aCheckResult |= IntPatchWT_DisLastLast;
+
+                if(!aPOn2S.IsSame(aPntFWL1, Precision::Confusion()))
+                {
+                  ExtendFirst(aWLine1, aPOn2S);
+                }
+                else
+                {
+                  aWLine1->Curve()->Value(1, aPOn2S);
+                }
+
+                if(!aPOn2S.IsSame(aPntLWL2, Precision::Confusion()))
+                {
+                  ExtendLast(aWLine2, aPOn2S);
+                }
+                else
+                {
+                  aWLine2->Curve()->Value(aWLine2->NbPnts(), aPOn2S);
+                }
+              }
+            }
+          }
+        }//if(aVec3.SquareMagnitude() > aSqToler) cond.
+      }//if(!(aCheckResult & 0x04)) cond.
+
+      if(!(aCheckResult & IntPatchWT_DisLastFirst))
+      {// Last/First
+        aVec1.SetXYZ(aPntLWL1.Value().XYZ() - aPntLm1WL1.Value().XYZ());
+        aVec2.SetXYZ(aPntFp1WL2.Value().XYZ() - aPntFWL2.Value().XYZ());
+        aVec3.SetXYZ(aPntFWL2.Value().XYZ() - aPntLWL1.Value().XYZ());
+
+        if(aVec3.SquareMagnitude() > aSqToler)
+        {
+          if((aVec1.Angle(aVec2) < aMaxAngle) &&
+             (aVec1.Angle(aVec3) < aMaxAngle) &&
+             (aVec2.Angle(aVec3) < aMaxAngle))
+          {
+            aPmid.SetXYZ(0.5*(aPntLWL1.Value().XYZ()+aPntFWL2.Value().XYZ()));
+            if(IsIntersectionPoint(aPmid, theS1, theS2, aPntLWL1, theToler3D,
+                                   theU1Period, theU2Period, theV1Period, theV2Period,
+                                   aU1, aV1, aU2, aV2))
+            {
+              IntSurf_PntOn2S aPOn2S;
+              aPOn2S.SetValue(aPmid, aU1, aV1, aU2, aV2);
+
+              Standard_Real aU11 = 0.0, aV11 = 0.0, aU21 = 0.0, aV21 = 0.0,
+                            aU12 = 0.0, aV12 = 0.0, aU22 = 0.0, aV22 = 0.0;
+              aPntLWL1.Parameters(aU11, aV11, aU21, aV21);
+              aPntFWL2.Parameters(aU12, aV12, aU22, aV22);
+
+              if(!IsSeam(aU11, aU12, theU1Period) &&
+                 !IsSeam(aV11, aV12, theV1Period) &&
+                 !IsSeam(aU21, aU22, theU2Period) &&
+                 !IsSeam(aV21, aV22, theV2Period))
+              {
+                aCheckResult |= IntPatchWT_DisLastLast;
+
+                if(!aPOn2S.IsSame(aPntLWL1, Precision::Confusion()))
+                {
+                  ExtendLast(aWLine1, aPOn2S);
+                }
+                else
+                {
+                  aWLine1->Curve()->Value(aWLine1->NbPnts(), aPOn2S);
+                }
+
+                if(!aPOn2S.IsSame(aPntFWL2, Precision::Confusion()))
+                {
+                  ExtendFirst(aWLine2, aPOn2S);
+                }
+                else
+                {
+                  aWLine2->Curve()->Value(1, aPOn2S);
+                }
+              }
+            }
+          }
+        }//if(aVec3.SquareMagnitude() > aSqToler) cond.
+      }//if(!(aCheckResult & 0x02)) cond.
+
+      if(!(aCheckResult & IntPatchWT_DisLastLast))
+      {// Last/Last
+        aVec1.SetXYZ(aPntLWL1.Value().XYZ() - aPntLm1WL1.Value().XYZ());
+        aVec2.SetXYZ(aPntLm1WL2.Value().XYZ() - aPntLWL2.Value().XYZ());
+        aVec3.SetXYZ(aPntLWL2.Value().XYZ() - aPntLWL1.Value().XYZ());
+
+        if(aVec3.SquareMagnitude() > aSqToler)
+        {
+          if((aVec1.Angle(aVec2) < aMaxAngle) &&
+             (aVec1.Angle(aVec3) < aMaxAngle) &&
+             (aVec2.Angle(aVec3) < aMaxAngle))
+          {
+            aPmid.SetXYZ(0.5*(aPntLWL1.Value().XYZ()+aPntLWL2.Value().XYZ()));
+            if(IsIntersectionPoint(aPmid, theS1, theS2, aPntLWL1, theToler3D,
+                                   theU1Period, theU2Period, theV1Period, theV2Period,
+                                   aU1, aV1, aU2, aV2))
+            {
+              IntSurf_PntOn2S aPOn2S;
+              aPOn2S.SetValue(aPmid, aU1, aV1, aU2, aV2);
+
+              Standard_Real aU11 = 0.0, aV11 = 0.0, aU21 = 0.0, aV21 = 0.0,
+                            aU12 = 0.0, aV12 = 0.0, aU22 = 0.0, aV22 = 0.0;
+              aPntLWL1.Parameters(aU11, aV11, aU21, aV21);
+              aPntLWL2.Parameters(aU12, aV12, aU22, aV22);
+
+              if(!IsSeam(aU11, aU12, theU1Period) &&
+                 !IsSeam(aV11, aV12, theV1Period) &&
+                 !IsSeam(aU21, aU22, theU2Period) &&
+                 !IsSeam(aV21, aV22, theV2Period))
+              {
+                if(!aPOn2S.IsSame(aPntLWL1, Precision::Confusion()))
+                {
+                  ExtendLast(aWLine1, aPOn2S);
+                }
+                else
+                {
+                  aWLine1->Curve()->Value(aWLine1->NbPnts(), aPOn2S);
+                }
+
+                if(!aPOn2S.IsSame(aPntLWL2, Precision::Confusion()))
+                {
+                  ExtendLast(aWLine2, aPOn2S);
+                }
+                else
+                {
+                  aWLine2->Curve()->Value(aWLine2->NbPnts(), aPOn2S);
+                }
+              }
+            }
+          }
+        }//if(aVec3.SquareMagnitude() > aSqToler) cond.
+      }//if(!(aCheckResult & 0x01)) cond.
+    }
+  }
+}
index 210aa89..75a8e73 100644 (file)
@@ -18,6 +18,7 @@
 #include <Standard_Macro.hxx>
 #include <IntPatch_WLine.hxx>
 #include <IntPatch_SequenceOfLine.hxx>
+#include <IntSurf_Quadric.hxx>
 class TopoDS_Face;
 class GeomAdaptor_HSurface;
 class GeomInt_LineConstructor;
@@ -76,6 +77,23 @@ public:
                                          const Standard_Real theVfSurf2,
                                          const Standard_Real theVlSurf2);
 
+
+//! Concatenates two some Walking lines from theSlin if it is possible.
+//! This method does not create single line from several. It allows every
+//! extended line to be started/finished in strictly determined point
+//! (in the place of joint of two lines). As result, some gaps between two lines
+//! will vanish.
+//! The Walking lines are supposed (algorithm will do nothing for not-Walking line)
+//! to be computed as a result of intersection of two quadrics.
+//! The quadrics definition is accepted in input parameters.
+  Standard_EXPORT static void ExtendTwoWlinesToEachOther(IntPatch_SequenceOfLine& theSlin,
+                                                         const IntSurf_Quadric& theS1,
+                                                         const IntSurf_Quadric& theS2,
+                                                         const Standard_Real theToler3D,
+                                                         const Standard_Real theU1Period,
+                                                         const Standard_Real theU2Period,
+                                                         const Standard_Real theV1Period,
+                                                         const Standard_Real theV2Period);
 };
 
 #endif
\ No newline at end of file
index 14a25d2..4397630 100644 (file)
@@ -57,7 +57,7 @@ Standard_Boolean IntSurf_PntOn2S::IsSame( const IntSurf_PntOn2S& theOterPoint,
   if(pt.SquareDistance(theOterPoint.Value()) > theTol3D*theTol3D)
     return Standard_False;
 
-  if(IsEqual(theTol2D, 0.0))
+  if(theTol2D < 0.0)
   {//We need not compare 2D-coordinates of the points
     return Standard_True;
   }
index 7dd65db..a6cc213 100644 (file)
@@ -74,8 +74,8 @@ public:
   
   //! Returns TRUE if 2D- and 3D-coordinates of theOterPoint are equal to
   //! corresponding coordinates of me (with given tolerance).
-  //! If theTol2D == 0.0 we will compare 3D-points only.
-  Standard_EXPORT Standard_Boolean IsSame (const IntSurf_PntOn2S& theOterPoint, const Standard_Real theTol3D = 0.0, const Standard_Real theTol2D = 0.0) const;
+  //! If theTol2D < 0.0 we will compare 3D-points only.
+  Standard_EXPORT Standard_Boolean IsSame (const IntSurf_PntOn2S& theOterPoint, const Standard_Real theTol3D = 0.0, const Standard_Real theTol2D = -1.0) const;
 
 
 
diff --git a/tests/bugs/modalg_6/bug27282_1 b/tests/bugs/modalg_6/bug27282_1
new file mode 100644 (file)
index 0000000..1efe3b0
--- /dev/null
@@ -0,0 +1,34 @@
+puts "TODO OCC27300 ALL: ERROR. result is not valid for BOP"
+
+puts "============"
+puts "OCC27282"
+puts "============"
+puts ""
+###############################
+## [Regression to 6.9.1] smesh/bugs_00/A6: Cut produces an empty shape
+###############################
+
+restore [locate_data_file bug27282_cmpd.brep] a
+explode a
+
+bclearobjects
+bcleartools
+baddobjects a_1
+baddtools a_2
+
+bfillds
+
+# CUT-operation
+bbop result 2
+
+set log [bopargcheck result #F]
+
+if { [string compare -nocase $log "Shape(s) seem(s) to be valid for BOP.\n"] } {
+  puts "ERROR. result is not valid for BOP"
+}
+
+checkshape result
+checknbshapes result -solid 1 -face 4
+checkprops result -v 2.96079e+007
+
+checkview -display result -2d -path ${imagedir}/${test_image}.png
diff --git a/tests/bugs/modalg_6/bug27282_2 b/tests/bugs/modalg_6/bug27282_2
new file mode 100644 (file)
index 0000000..2b48d65
--- /dev/null
@@ -0,0 +1,47 @@
+puts "TODO OCC27302 ALL: Error: Curve Number is bad!"
+
+puts "============"
+puts "OCC27282"
+puts "============"
+puts ""
+###############################
+## [Regression to 6.9.1] smesh/bugs_00/A6: Cut produces an empty shape
+###############################
+
+set MaxTol 4.8106951786435371e-006
+set GoodNbCurv 1
+
+restore [locate_data_file bug27282_cmpd.brep] a
+explode a f
+
+smallview
+don a_2 a_5
+fit
+
+set log [bopcurves a_2 a_5 -2d]
+
+regexp {Tolerance Reached=+([-0-9.+eE]+)\n+([-0-9.+eE]+)} ${log} full Toler NbCurv
+
+checkreal ToleranceReached ${Toler} ${MaxTol} 0.0 0.1
+
+checkview -screenshot -2d -path ${imagedir}/${test_image}.png
+
+if {${NbCurv} != ${GoodNbCurv}} {
+  puts "Error: Curve Number is bad!"
+  
+  for {set i 1} {$i < ${NbCurv}} {incr i} {
+    for {set j [expr $i+1]} {$j <= $NbCurv} {incr j} {
+      mkedge e1 c_$i
+      mkedge e2 c_$j
+      
+      dset dd_val 100.0*${Toler}
+      distmini dd e1 e2
+      
+      if { [dval dd_val] > ${Toler} } {
+        puts "Error: Intersection result is not closed"
+      }
+    }
+  }
+} else {
+  checklength c_1 -l 833.56846559428755
+}
\ No newline at end of file