diff --git a/src/Extrema/Extrema_ExtElCS.cxx b/src/Extrema/Extrema_ExtElCS.cxx index 48d8ed4a6d..6eaac112b8 100644 --- a/src/Extrema/Extrema_ExtElCS.cxx +++ b/src/Extrema/Extrema_ExtElCS.cxx @@ -72,7 +72,7 @@ Extrema_ExtElCS::Extrema_ExtElCS(const gp_Lin& C, void Extrema_ExtElCS::Perform(const gp_Lin& C, - const gp_Cylinder& S) + const gp_Cylinder& S) { myDone = Standard_False; myNbExt = 0; @@ -85,6 +85,7 @@ void Extrema_ExtElCS::Perform(const gp_Lin& C, Standard_Real radius = S.Radius(); Extrema_ExtElC Extrem(gp_Lin(Pos.Axis()), C, Precision::Angular()); if (Extrem.IsParallel()) { + // Line direction is similar to cylinder axis of rotation. mySqDist = new TColStd_HArray1OfReal(1, 1); myPoint1 = new Extrema_HArray1OfPOnCurv(1, 1); myPoint2 = new Extrema_HArray1OfPOnSurf(1, 1); @@ -117,42 +118,28 @@ void Extrema_ExtElCS::Perform(const gp_Lin& C, myIsPar = Standard_True; } else { - Standard_Integer i; - + Standard_Integer i, aStartIdx = 0; + Extrema_POnCurv myPOnC1, myPOnC2; Extrem.Points(1, myPOnC1, myPOnC2); gp_Pnt PonAxis = myPOnC1.Value(); gp_Pnt PC = myPOnC2.Value(); - // line is tangent or outside of the cylunder -- single solution - if (radius - PonAxis.Distance(PC) < Precision::PConfusion()) - { - Extrema_ExtPElS ExPS(PC, S, Precision::Confusion()); - if (ExPS.IsDone()) { - myNbExt = ExPS.NbExt(); - mySqDist = new TColStd_HArray1OfReal(1, myNbExt); - myPoint1 = new Extrema_HArray1OfPOnCurv(1, myNbExt); - myPoint2 = new Extrema_HArray1OfPOnSurf(1, myNbExt); - for (i = 1; i <= myNbExt; i++) { - myPoint1->SetValue(i, myPOnC2); - myPoint2->SetValue(i, ExPS.Point(i)); - mySqDist->SetValue(i,(myPOnC2.Value()).SquareDistance(ExPS.Point(i).Value())); - } - } - } // line intersects the cylinder - else + if (radius - PonAxis.Distance(PC) > Precision::PConfusion()) { IntAna_Quadric theQuadric(S); IntAna_IntConicQuad Inters(C, theQuadric); if (Inters.IsDone()) { myNbExt = Inters.NbPoints(); + aStartIdx = myNbExt; if (myNbExt > 0) { - mySqDist = new TColStd_HArray1OfReal(1, myNbExt); - myPoint1 = new Extrema_HArray1OfPOnCurv(1, myNbExt); - myPoint2 = new Extrema_HArray1OfPOnSurf(1, myNbExt); + // Not more than 2 additional points from perpendiculars. + mySqDist = new TColStd_HArray1OfReal(1, myNbExt + 2); + myPoint1 = new Extrema_HArray1OfPOnCurv(1, myNbExt + 2); + myPoint2 = new Extrema_HArray1OfPOnSurf(1, myNbExt + 2); Standard_Real u, v, w; for (i = 1; i <= myNbExt; i++) { @@ -168,6 +155,27 @@ void Extrema_ExtElCS::Perform(const gp_Lin& C, } } } + + // line is tangent or outside of the cylinder + Extrema_ExtPElS ExPS(PC, S, Precision::Confusion()); + if (ExPS.IsDone()) + { + if (aStartIdx == 0) + { + myNbExt = ExPS.NbExt(); + mySqDist = new TColStd_HArray1OfReal(1, myNbExt); + myPoint1 = new Extrema_HArray1OfPOnCurv(1, myNbExt); + myPoint2 = new Extrema_HArray1OfPOnSurf(1, myNbExt); + } + else + myNbExt += ExPS.NbExt(); + + for (i = aStartIdx + 1; i <= myNbExt; i++) { + myPoint1->SetValue(i, myPOnC2); + myPoint2->SetValue(i, ExPS.Point(i - aStartIdx)); + mySqDist->SetValue(i,(myPOnC2.Value()).SquareDistance(ExPS.Point(i - aStartIdx).Value())); + } + } myDone = Standard_True; } @@ -203,33 +211,75 @@ Extrema_ExtElCS::Extrema_ExtElCS(const gp_Lin& C, void Extrema_ExtElCS::Perform(const gp_Lin& C, - const gp_Sphere& S) + const gp_Sphere& S) { + // In case of intersection - return four points: + // 2 intersection points and 2 perpendicular. + // No intersection - only min and max. + myDone = Standard_False; myNbExt = 0; myIsPar = Standard_False; + Standard_Integer aStartIdx = 0; - gp_Pnt O = S.Location(); + gp_Pnt aCenter = S.Location(); - Extrema_ExtPElC Extrem(O, C, Precision::Angular(), RealFirst(), RealLast()); + Extrema_ExtPElC Extrem(aCenter, C, Precision::Angular(), RealFirst(), RealLast()); Standard_Integer i; - if (Extrem.IsDone()) { + if (Extrem.IsDone() && + Extrem.NbExt() > 0) + { Extrema_POnCurv myPOnC1 = Extrem.Point(1); + if (myPOnC1.Value().Distance(aCenter) <= S.Radius()) + { + IntAna_IntConicQuad aLinSphere(C, S); + if (aLinSphere.IsDone()) + { + myNbExt = aLinSphere.NbPoints(); + aStartIdx = myNbExt; + // Not more than 2 additional points from perpendiculars. + mySqDist = new TColStd_HArray1OfReal(1, myNbExt + 2); + myPoint1 = new Extrema_HArray1OfPOnCurv(1, myNbExt + 2); + myPoint2 = new Extrema_HArray1OfPOnSurf(1, myNbExt + 2); + + for (i = 1; i <= myNbExt; i++) + { + Extrema_POnCurv aCPnt(aLinSphere.ParamOnConic(i), aLinSphere.Point(i)); + + Standard_Real u,v; + ElSLib::Parameters(S, aLinSphere.Point(i), u, v); + Extrema_POnSurf aSPnt(u, v, aLinSphere.Point(i)); + + myPoint1->SetValue(i, aCPnt); + myPoint2->SetValue(i, aSPnt); + mySqDist->SetValue(i,(aCPnt.Value()).SquareDistance(aSPnt.Value())); + } + } + } + Extrema_ExtPElS ExPS(myPOnC1.Value(), S, Precision::Confusion()); - if (ExPS.IsDone()) { - myNbExt = ExPS.NbExt(); - mySqDist = new TColStd_HArray1OfReal(1, myNbExt); - myPoint1 = new Extrema_HArray1OfPOnCurv(1, myNbExt); - myPoint2 = new Extrema_HArray1OfPOnSurf(1, myNbExt); - for (i = 1; i <= myNbExt; i++) { - myPoint1->SetValue(i, myPOnC1); - myPoint2->SetValue(i, ExPS.Point(i)); - mySqDist->SetValue(i,(myPOnC1.Value()).SquareDistance(ExPS.Point(i).Value())); - myDone = Standard_True; + if (ExPS.IsDone()) + { + if (aStartIdx == 0) + { + myNbExt = ExPS.NbExt(); + mySqDist = new TColStd_HArray1OfReal(1, myNbExt); + myPoint1 = new Extrema_HArray1OfPOnCurv(1, myNbExt); + myPoint2 = new Extrema_HArray1OfPOnSurf(1, myNbExt); + } + else + myNbExt += ExPS.NbExt(); + + for (i = aStartIdx + 1; i <= myNbExt; i++) + { + myPoint1->SetValue(i, myPOnC1); + myPoint2->SetValue(i, ExPS.Point(i - aStartIdx)); + mySqDist->SetValue(i,(myPOnC1.Value()).SquareDistance(ExPS.Point(i - aStartIdx).Value())); } } } + myDone = Standard_True; } diff --git a/tests/bugs/modalg_5/bug25368_1 b/tests/bugs/modalg_5/bug25368_1 new file mode 100644 index 0000000000..af3e75ab75 --- /dev/null +++ b/tests/bugs/modalg_5/bug25368_1 @@ -0,0 +1,29 @@ +puts "==========" +puts "OCC25368" +puts "==========" +puts "" +################################################ +# BREPExtrma DistShapeShape gives wrong result for Sphere and Line +################################################ + +sphere s 0 0 0 5 +line l 0 0 0.2 1 1 0 +trim l l 0 10 + +set extrema_res [extrema l s] +set extrema_length [llength ${extrema_res} ] + +#Amount Check +if {${extrema_length} != 10 } { + puts "Error: Invalid extrema number in extrema output" +} +regexp {Extrema 1 is point : +([-0-9.+eE]+) +([-0-9.+eE]+) +([-0-9.+eE]+)} $extrema_res full x y z + +# Point check +set good_x 3.5327043465311383 +set good_y 3.5327043465311383 +set good_z 0.20 +checkreal "Intersection point x:" ${x} ${good_x} 0.01 0.01 +checkreal "Intersection point y:" ${y} ${good_y} 0.01 0.01 +checkreal "Intersection point z:" ${z} ${good_z} 0.01 0.01 + diff --git a/tests/bugs/modalg_5/bug25368_2 b/tests/bugs/modalg_5/bug25368_2 new file mode 100644 index 0000000000..5daf8f99dd --- /dev/null +++ b/tests/bugs/modalg_5/bug25368_2 @@ -0,0 +1,41 @@ +puts "==========" +puts "OCC25368" +puts "==========" +puts "" +################################################ +# BREPExtrma DistShapeShape gives wrong result for Sphere and Line +################################################ + +sphere s 0 0 0 4.5 +rotate s 0 0.5 1 1 1 0.5 34.9 +line l -0.79 0.88 1.22 0.579 1.765 0.576 + +set extrema_res [extrema l s] +set extrema_length [llength ${extrema_res} ] + +# Amount check +if {${extrema_length} != 18 } { + puts "Error: expected only two lines as result of extrema!" +} + +# Distance check on ext_1 +set info [dump ext_1] +regexp {Extrema 1 is point : +([-0-9.+eE]+) +([-0-9.+eE]+) +([-0-9.+eE]+)} $extrema_res full x1 y1 z1 +# Point check +set good_x1 -2.2838350838816694 +set good_y1 -3.6737459810900646 +set good_z1 -0.2660950057268425 +checkreal "Intersection point x:" ${x1} ${good_x1} 0.01 0.01 +checkreal "Intersection point y:" ${y1} ${good_y1} 0.01 0.01 +checkreal "Intersection point z:" ${z1} ${good_z1} 0.01 0.01 + + +# Distance check on ext_2 +regexp {Extrema 2 is point : +([-0-9.+eE]+) +([-0-9.+eE]+) +([-0-9.+eE]+)} $extrema_res full x2 y2 z2 +# Point check +set good_x2 0.29086178559218934 +set good_y2 4.1748550113475211 +set good_z2 2.2952614654595873 +checkreal "Intersection point x:" ${x2} ${good_x2} 0.01 0.01 +checkreal "Intersection point y:" ${y2} ${good_y2} 0.01 0.01 +checkreal "Intersection point z:" ${z2} ${good_z2} 0.01 0.01