From eee615ad2a98d1f55ac157fbee151ffe691ad56e Mon Sep 17 00:00:00 2001 From: nbv Date: Wed, 24 Feb 2016 12:59:36 +0300 Subject: [PATCH] 0027282: [Regression to 6.9.1] smesh/bugs_00/A6: Cut produces an empty shape 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. --- src/IntPatch/IntPatch_Intersection.cxx | 113 ++++--- src/IntPatch/IntPatch_PointLine.hxx | 6 + src/IntPatch/IntPatch_RLine.hxx | 6 + src/IntPatch/IntPatch_RLine.lxx | 12 + src/IntPatch/IntPatch_WLine.hxx | 6 +- src/IntPatch/IntPatch_WLine.lxx | 5 + src/IntPatch/IntPatch_WLineTool.cxx | 405 ++++++++++++++++++++++++- src/IntPatch/IntPatch_WLineTool.hxx | 18 ++ src/IntSurf/IntSurf_PntOn2S.cxx | 2 +- src/IntSurf/IntSurf_PntOn2S.hxx | 4 +- tests/bugs/modalg_6/bug27282_1 | 34 +++ tests/bugs/modalg_6/bug27282_2 | 47 +++ 12 files changed, 604 insertions(+), 54 deletions(-) create mode 100644 tests/bugs/modalg_6/bug27282_1 create mode 100644 tests/bugs/modalg_6/bug27282_2 diff --git a/src/IntPatch/IntPatch_Intersection.cxx b/src/IntPatch/IntPatch_Intersection.cxx index 26e73129f9..719b406bad 100644 --- a/src/IntPatch/IntPatch_Intersection.cxx +++ b/src/IntPatch/IntPatch_Intersection.cxx @@ -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; + isQuadSet = Standard_True; + + const GeomAbs_SurfaceType aTyps1 = theS1->GetType(); + const GeomAbs_SurfaceType aTyps2 = theS2->GetType(); - case GeomAbs_Cylinder: - Quad1.SetValue(theS1->Cylinder()); - break; + switch(aTyps1) + { + case GeomAbs_Plane: + Quad1.SetValue(theS1->Plane()); + break; - case GeomAbs_Sphere: - Quad1.SetValue(theS1->Sphere()); - break; + case GeomAbs_Cylinder: + Quad1.SetValue(theS1->Cylinder()); + break; - case GeomAbs_Cone: - Quad1.SetValue(theS1->Cone()); - break; + case GeomAbs_Sphere: + Quad1.SetValue(theS1->Sphere()); + break; - case GeomAbs_Torus: - Quad1.SetValue(theS1->Torus()); - break; + case GeomAbs_Cone: + Quad1.SetValue(theS1->Cone()); + break; - default: - break; - } + case GeomAbs_Torus: + Quad1.SetValue(theS1->Torus()); + break; - switch(aTyps2) - { - case GeomAbs_Plane: - Quad2.SetValue(theS2->Plane()); - break; - case GeomAbs_Cylinder: - Quad2.SetValue(theS2->Cylinder()); - break; + default: + isQuadSet = Standard_False; + break; + } - case GeomAbs_Sphere: - Quad2.SetValue(theS2->Sphere()); - break; + switch(aTyps2) + { + case GeomAbs_Plane: + Quad2.SetValue(theS2->Plane()); + break; + case GeomAbs_Cylinder: + Quad2.SetValue(theS2->Cylinder()); + break; - case GeomAbs_Cone: - Quad2.SetValue(theS2->Cone()); - break; + case GeomAbs_Sphere: + Quad2.SetValue(theS2->Sphere()); + break; - case GeomAbs_Torus: - Quad2.SetValue(theS2->Torus()); - break; + case GeomAbs_Cone: + Quad2.SetValue(theS2->Cone()); + break; - default: - break; + case GeomAbs_Torus: + Quad2.SetValue(theS2->Torus()); + break; + + default: + isQuadSet = Standard_False; + 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++) diff --git a/src/IntPatch/IntPatch_PointLine.hxx b/src/IntPatch/IntPatch_PointLine.hxx index 3d5561ec78..71477fe378 100644 --- a/src/IntPatch/IntPatch_PointLine.hxx +++ b/src/IntPatch/IntPatch_PointLine.hxx @@ -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; diff --git a/src/IntPatch/IntPatch_RLine.hxx b/src/IntPatch/IntPatch_RLine.hxx index 55d75ab459..f91273b128 100644 --- a/src/IntPatch/IntPatch_RLine.hxx +++ b/src/IntPatch/IntPatch_RLine.hxx @@ -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. diff --git a/src/IntPatch/IntPatch_RLine.lxx b/src/IntPatch/IntPatch_RLine.lxx index 82c3e13b35..70debb4323 100644 --- a/src/IntPatch/IntPatch_RLine.lxx +++ b/src/IntPatch/IntPatch_RLine.lxx @@ -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()); diff --git a/src/IntPatch/IntPatch_WLine.hxx b/src/IntPatch/IntPatch_WLine.hxx index ba64bff7d0..4cfeabf081 100644 --- a/src/IntPatch/IntPatch_WLine.hxx +++ b/src/IntPatch/IntPatch_WLine.hxx @@ -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); diff --git a/src/IntPatch/IntPatch_WLine.lxx b/src/IntPatch/IntPatch_WLine.lxx index 123bd2f1f8..6c95ee842f 100644 --- a/src/IntPatch/IntPatch_WLine.lxx +++ b/src/IntPatch/IntPatch_WLine.lxx @@ -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(); diff --git a/src/IntPatch/IntPatch_WLineTool.cxx b/src/IntPatch/IntPatch_WLineTool.cxx index 49d8635eae..9da9e9dd36 100644 --- a/src/IntPatch/IntPatch_WLineTool.cxx +++ b/src/IntPatch/IntPatch_WLineTool.cxx @@ -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. + } + } +} diff --git a/src/IntPatch/IntPatch_WLineTool.hxx b/src/IntPatch/IntPatch_WLineTool.hxx index 210aa89366..75a8e739bf 100644 --- a/src/IntPatch/IntPatch_WLineTool.hxx +++ b/src/IntPatch/IntPatch_WLineTool.hxx @@ -18,6 +18,7 @@ #include #include #include +#include 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 diff --git a/src/IntSurf/IntSurf_PntOn2S.cxx b/src/IntSurf/IntSurf_PntOn2S.cxx index 14a25d22ff..4397630da9 100644 --- a/src/IntSurf/IntSurf_PntOn2S.cxx +++ b/src/IntSurf/IntSurf_PntOn2S.cxx @@ -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; } diff --git a/src/IntSurf/IntSurf_PntOn2S.hxx b/src/IntSurf/IntSurf_PntOn2S.hxx index 7dd65db9a1..a6cc213d48 100644 --- a/src/IntSurf/IntSurf_PntOn2S.hxx +++ b/src/IntSurf/IntSurf_PntOn2S.hxx @@ -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 index 0000000000..1efe3b05a8 --- /dev/null +++ b/tests/bugs/modalg_6/bug27282_1 @@ -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 index 0000000000..2b48d65028 --- /dev/null +++ b/tests/bugs/modalg_6/bug27282_2 @@ -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