]> OCCT Git - occt-copy.git/commitdiff
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 26e73129f9d507f1c4e1748d99e102ee75a708c2..719b406bad1e1a4bf0048a5d54b4dec8d8ee05f0 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 3d5561ec786205cdd28b0b926a8187629e1751af..71477fe3780c00347fc96fa424b704af87056b66 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 55d75ab4591ed9dbd9760f2348e01c047f44f8d4..f91273b128d9abcee573d478a3e466aa6ad9e78d 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 82c3e13b356fd52ae56005c9adda6cb1a1fbd70a..70debb43232dedd223fc3e72158ba83a90366f97 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 ba64bff7d0fa19fcf09159d766b4541435afbb55..4cfeabf081e74828a957aaf841cb55b6fb8d9fb9 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 123bd2f1f87a08163f4dd23736e509b95569b0af..6c95ee842ff93394609bf3bd796f0c335561deb1 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 49d8635eae44c739e80905f51ab3ba0c6893487e..9da9e9dd36c74ad4b9adcc636faa22df4a3db574 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 210aa893661cda98d76145953b38f4516908f983..75a8e739bf6e9f98f0a762ba698e006b008a6b3d 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 14a25d22ff3db54dda26c014dbd554cbccb118fc..4397630da9e4abccb13815165ffa4e8dc5bcc92c 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 7dd65db9a1bc159e0db4aba110083c16a3c09324..a6cc213d489895200bb3ad704e3db1b9cf50553a 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