diff --git a/src/BRepCheck/BRepCheck_Wire.cxx b/src/BRepCheck/BRepCheck_Wire.cxx index 062a49dbe1..da035c69cd 100644 --- a/src/BRepCheck/BRepCheck_Wire.cxx +++ b/src/BRepCheck/BRepCheck_Wire.cxx @@ -1395,7 +1395,7 @@ BRepCheck_Status BRepCheck_Wire::SelfIntersect(const TopoDS_Face& F, if (aCT1==GeomAbs_Line && aCT2==GeomAbs_Line) { // check for the two lines coincidence Standard_Real aPAR_T, aT11, aT12, aT21, aT22, aT1m, aT2m; - Standard_Real aD2, aTolE1, aTolE2, aTol2, aDot; + Standard_Real aD2, aTolE1, aTolE2, aTol2; gp_Lin2d aL1, aL2; gp_Pnt2d aP1m; // @@ -1423,14 +1423,10 @@ BRepCheck_Status BRepCheck_Wire::SelfIntersect(const TopoDS_Face& F, if (aT2m>aT21 && aT2maT21 && aT2m= 0.) ? 2.*(1. - aCos) : 2.*(1. + aCos); - // - if(aAng <= Precision::Angular()) { - IsParallel = Standard_True; - if(aL1.SquareDistance(aL2.Location()) <= aTol) { - IsCoincide = Standard_True; - aP11 = ElCLib::Value(aT11, aL1); - aP12 = ElCLib::Value(aT12, aL1); - } - } - else { - aP11 = ElCLib::Value(aT11, aL1); - aP12 = ElCLib::Value(aT12, aL1); - if(aL2.SquareDistance(aP11) <= aTol && aL2.SquareDistance(aP12) <= aTol) { - IsCoincide = Standard_True; - } - } - // - if (IsCoincide) { - Standard_Real t21, t22; - // - t21 = ElCLib::Parameter(aL2, aP11); - t22 = ElCLib::Parameter(aL2, aP12); - if((t21 > aT22 && t22 > aT22) || (t21 < aT21 && t22 < aT21)) { - return; - } - // - Standard_Real temp; - if(t21 > t22) { - temp = t21; - t21 = t22; - t22 = temp; - } - // - if(t21 >= aT21) { - if(t22 <= aT22) { - aCommonPrt.SetRange1(aT11, aT12); - aCommonPrt.SetAllNullFlag(Standard_True); - aCommonPrt.AppendRange2(t21, t22); - } - else { - aCommonPrt.SetRange1(aT11, aT12 - (t22 - aT22)); - aCommonPrt.AppendRange2(t21, aT22); - } - } - else { - aCommonPrt.SetRange1(aT11 + (aT21 - t21), aT12); - aCommonPrt.AppendRange2(aT21, t22); - } - aCommonPrt.SetType(TopAbs_EDGE); - myCommonParts.Append(aCommonPrt); - return; - } - // - if (IsParallel) { - return; - } - // + Standard_Real aTol = myTol * myTol; + + gp_Lin aL1 = myCurve1.Line(); + gp_Lin aL2 = myCurve2.Line(); + + gp_Dir aD1 = aL1.Direction(); + gp_Dir aD2 = aL2.Direction(); + + Standard_Real anAngle = aD1.Angle (aD2); + Standard_Boolean IsCoincide = anAngle < Precision::Angular(); + if (IsCoincide) { - TopoDS_Iterator aIt1, aIt2; - aIt1.Initialize(myEdge1); - for (; aIt1.More(); aIt1.Next()) { - const TopoDS_Shape& aV1 = aIt1.Value(); - aIt2.Initialize(myEdge2); - for (; aIt2.More(); aIt2.Next()) { - const TopoDS_Shape& aV2 = aIt2.Value(); - if (aV2.IsSame(aV1)) { + if (aL1.SquareDistance (aL2.Location()) > aTol) + return; + } + + Standard_Real aT11, aT12, aT21, aT22; + myRange1.Range (aT11, aT12); + myRange2.Range (aT21, aT22); + + gp_Pnt aP11 = ElCLib::Value (aT11, aL1); + gp_Pnt aP12 = ElCLib::Value (aT12, aL1); + + if (!IsCoincide) + { + gp_Pnt O2 (aL2.Location()); + if (!Precision::IsInfinite (aT21) && !Precision::IsInfinite (aT22)) + O2 = ElCLib::Value ((aT21 + aT22) / 2., aL2); + + gp_Vec aVec1 = gp_Vec (O2, aP11).Crossed (aD2); + gp_Vec aVec2 = gp_Vec (O2, aP12).Crossed (aD2); + + Standard_Real aSqDist1 = aVec1.SquareMagnitude(); + Standard_Real aSqDist2 = aVec2.SquareMagnitude(); + + IsCoincide = (aSqDist1 <= aTol && aSqDist2 <= aTol); + + if (!IsCoincide && aVec1.Dot (aVec2) > 0) + // the lines do not intersect + return; + } + + IntTools_CommonPrt aCommonPrt; + aCommonPrt.SetEdge1 (myEdge1); + aCommonPrt.SetEdge2 (myEdge2); + + if (IsCoincide) + { + Standard_Real t21 = ElCLib::Parameter (aL2, aP11); + Standard_Real t22 = ElCLib::Parameter (aL2, aP12); + + if ((t21 > aT22 && t22 > aT22) || (t21 < aT21 && t22 < aT21)) + // projections are out of range + return; + + if (t21 > t22) + std::swap (t21, t22); + + if (t21 >= aT21) + { + if (t22 <= aT22) + { + aCommonPrt.SetRange1 (aT11, aT12); + aCommonPrt.SetAllNullFlag (Standard_True); + aCommonPrt.AppendRange2 (t21, t22); + } + else + { + aCommonPrt.SetRange1 (aT11, aT12 - (t22 - aT22)); + aCommonPrt.AppendRange2 (t21, aT22); + } + } + else + { + aCommonPrt.SetRange1 (aT11 + (aT21 - t21), aT12); + aCommonPrt.AppendRange2 (aT21, t22); + } + aCommonPrt.SetType (TopAbs_EDGE); + myCommonParts.Append (aCommonPrt); + return; + } + + + gp_Vec O1O2 (aL1.Location(), aL2.Location()); + gp_XYZ aCross = aD1.XYZ().Crossed (aD2.XYZ()); + Standard_Real aDistLL = O1O2.Dot (gp_Vec (aCross.Normalized())); + if (Abs (aDistLL) > myTol) + return; + + { + // Fast check that no intersection needs to be added + for (TopoDS_Iterator it1 (myEdge1); it1.More(); it1.Next()) + { + for (TopoDS_Iterator it2 (myEdge2); it2.More(); it2.Next()) + { + if (it1.Value().IsSame (it2.Value())) return; - } } } } - // - aSin = 1. - aCos*aCos; - gp_Pnt O1 = aL1.Location(); - gp_Pnt O2 = aL2.Location(); - gp_Vec O1O2 (O1, O2); - // - aT2 = (aD1.XYZ()*(O1O2.Dot(aD1))-(O1O2.XYZ())).Dot(aD2.XYZ()); - aT2 /= aSin; - // - if(aT2 < aT21 || aT2 > aT22) { + + Standard_Real aSqSin = aCross.SquareModulus(); + Standard_Real aT2 = (aD1.XYZ() * (O1O2.Dot (aD1)) - (O1O2.XYZ())).Dot (aD2.XYZ()); + aT2 /= aSqSin; + + if (aT2 < aT21 || aT2 > aT22) + // out of range return; - } - // - gp_Pnt aP2(ElCLib::Value(aT2, aL2)); - aT1 = (gp_Vec(O1, aP2)).Dot(aD1); - // - if(aT1 < aT11 || aT1 > aT12) { + + gp_Pnt aP2 = ElCLib::Value (aT2, aL2); + Standard_Real aT1 = gp_Vec (aL1.Location(), aP2).Dot (aD1); + + if (aT1 < aT11 || aT1 > aT12) + // out of range return; - } - // - gp_Pnt aP1(ElCLib::Value(aT1, aL1)); - Standard_Real aDist = aP1.SquareDistance(aP2); - // - if (aDist > aTol) { + + gp_Pnt aP1 = ElCLib::Value (aT1, aL1); + Standard_Real aDist = aP1.SquareDistance (aP2); + + if (aDist > aTol) + // no intersection return; - } - // + // compute correct range on the edges - Standard_Real anAngle, aDt1, aDt2; - // - anAngle = aD1.Angle(aD2); - // - aDt1 = IntTools_Tools::ComputeIntRange(myTol1, myTol2, anAngle); - aDt2 = IntTools_Tools::ComputeIntRange(myTol2, myTol1, anAngle); - // - aCommonPrt.SetRange1(aT1 - aDt1, aT1 + aDt1); - aCommonPrt.AppendRange2(aT2 - aDt2, aT2 + aDt2); - aCommonPrt.SetType(TopAbs_VERTEX); - aCommonPrt.SetVertexParameter1(aT1); - aCommonPrt.SetVertexParameter2(aT2); - myCommonParts.Append(aCommonPrt); + Standard_Real aDt1 = IntTools_Tools::ComputeIntRange (myTol1, myTol2, anAngle); + Standard_Real aDt2 = IntTools_Tools::ComputeIntRange (myTol2, myTol1, anAngle); + + aCommonPrt.SetRange1 (aT1 - aDt1, aT1 + aDt1); + aCommonPrt.AppendRange2 (aT2 - aDt2, aT2 + aDt2); + aCommonPrt.SetType (TopAbs_VERTEX); + aCommonPrt.SetVertexParameter1 (aT1); + aCommonPrt.SetVertexParameter2 (aT2); + myCommonParts.Append (aCommonPrt); } //======================================================================= diff --git a/tests/bugs/modalg_7/bug30913_1 b/tests/bugs/modalg_7/bug30913_1 new file mode 100644 index 0000000000..a3db016438 --- /dev/null +++ b/tests/bugs/modalg_7/bug30913_1 @@ -0,0 +1,37 @@ +puts "========" +puts "0030913: Invalid result of Fusing slices" +puts "========" +puts "" + +restore [locate_data_file bug30913_case1.brep] s + +bclearobjects +bcleartools +set exp [explode s] +baddobjects s_1 +eval baddtools [lrange $exp 1 end] + +# Use gluing Shift option +bglue 1 +# Avoid History filling +setfillhistory 0 + +bfillds +bbop result 1 + +checkshape result + +unifysamedom result result + +checkshape result + +checkprops result -s 3.81335e+06 -v 1.39597e+08 +checknbshapes result -vertex 12042 -edge 18169 -wire 6223 -face 6176 -shell 1 -solid 1 -t + +if {![regexp "This shape seems to be OK" [bopcheck result]]} { + puts "Error: result is a self-intersecting shape" +} + +checkview -display result -2d -path ${imagedir}/${test_image}.png + +boptions -default \ No newline at end of file diff --git a/tests/bugs/modalg_7/bug30913_2 b/tests/bugs/modalg_7/bug30913_2 new file mode 100644 index 0000000000..8003c2fd39 --- /dev/null +++ b/tests/bugs/modalg_7/bug30913_2 @@ -0,0 +1,39 @@ +puts "========" +puts "0030913: Invalid result of Fusing slices" +puts "========" +puts "" + +restore [locate_data_file bug30913_case2.brep] s + +bclearobjects +bcleartools +set exp [explode s] +baddobjects s_1 +eval baddtools [lrange $exp 1 end] + +# Use gluing Shift option +bglue 1 +# Avoid History filling +setfillhistory 0 + +bfillds +bbop result 1 + +checkshape result + +dchrono unify restart +unifysamedom result result +dchrono unify stop counter UNIFY_SD + +checkshape result + +checkprops result -s 3.89766e+06 -v 1.40733e+08 +checknbshapes result -vertex 46597 -edge 70375 -wire 24212 -face 23995 -shell 1 -solid 1 -t + +#if {![regexp "This shape seems to be OK" [bopcheck result]]} { +# puts "Error: result is a self-intersecting shape" +#} + +checkview -display result -2d -path ${imagedir}/${test_image}.png + +boptions -default