diff --git a/src/ProjLib/ProjLib_Cone.cxx b/src/ProjLib/ProjLib_Cone.cxx index 005f2e3b80..9118233252 100644 --- a/src/ProjLib/ProjLib_Cone.cxx +++ b/src/ProjLib/ProjLib_Cone.cxx @@ -94,10 +94,19 @@ void ProjLib_Cone::Init(const gp_Cone& Co) void ProjLib_Cone::Project(const gp_Lin& L) { + gp_Pnt aPnt = L.Location(), anApex = myCone.Apex(); + + Standard_Real aDeltaV = 0.0; Standard_Real U,V; + if (aPnt.IsEqual(anApex, Precision::Confusion())) + { + //Take another point in the line L, which does not coincide with the cone apex. + aPnt.Translate(L.Direction().XYZ()); + aDeltaV = 1.0; // == ||L.Direction()|| == 1.0 + } - ElSLib::ConeParameters(myCone.Position(), myCone.RefRadius(), myCone.SemiAngle(), L.Location(), + ElSLib::ConeParameters(myCone.Position(), myCone.RefRadius(), myCone.SemiAngle(), aPnt, U, V); // gp_Pnt P; @@ -107,21 +116,19 @@ void ProjLib_Cone::Project(const gp_Lin& L) P, Vu, Vv); gp_Dir Dv(Vv); - if(Dv.IsParallel(L.Direction(), Precision::Angular())) { - + if(Dv.IsParallel(L.Direction(), Precision::Angular())) + { + // L is parallel to U-isoline of the cone. myType = GeomAbs_Line; - - gp_Pnt2d P2d(U,V); - Standard_Real Signe = L.Direction().Dot(Dv); - Signe = (Signe > 0.) ? 1. : -1.; - gp_Dir2d D2d(0., Signe); + const Standard_Real aSign = Sign(1.0, L.Direction().Dot(Dv)); + gp_Pnt2d P2d(U, V - aDeltaV*aSign); + gp_Dir2d D2d(0., aSign); myLin = gp_Lin2d( P2d, D2d); isDone = Standard_True; - } - + } } diff --git a/src/Standard/Standard_Real.cxx b/src/Standard/Standard_Real.cxx index 0c9733485a..b587af4f82 100644 --- a/src/Standard/Standard_Real.cxx +++ b/src/Standard/Standard_Real.cxx @@ -113,11 +113,9 @@ Standard_Real ATan2 (const Standard_Real Value, const Standard_Real Other) //------------------------------------------------------------------- // Sign : Returns |a| if B >= 0; -|a| if b < 0. -// from x in the direction y //------------------------------------------------------------------- Standard_Real Sign(const Standard_Real a, const Standard_Real b) { - //==== We use the function "nextafter()" fom library "math.h" ============== if (b >= 0.0) { return Abs(a); } else { diff --git a/src/Standard/Standard_Real.hxx b/src/Standard/Standard_Real.hxx index 84e84e0832..9beb501c32 100644 --- a/src/Standard/Standard_Real.hxx +++ b/src/Standard/Standard_Real.hxx @@ -37,7 +37,10 @@ __Standard_API Standard_Real ACosApprox (const Standard_Real ); __Standard_API Standard_Real ASin (const Standard_Real ); __Standard_API Standard_Real ATan2 (const Standard_Real , const Standard_Real ); __Standard_API Standard_Real NextAfter (const Standard_Real , const Standard_Real ); -__Standard_API Standard_Real Sign (const Standard_Real , const Standard_Real ); + +//! Returns |a| if b >= 0; -|a| if b < 0. +__Standard_API Standard_Real Sign(const Standard_Real a, const Standard_Real b); + __Standard_API Standard_Real ATanh (const Standard_Real ); __Standard_API Standard_Real ACosh (const Standard_Real ); __Standard_API Standard_Real Sinh (const Standard_Real ); diff --git a/tests/bugs/modalg_6/bug28054_1 b/tests/bugs/modalg_6/bug28054_1 new file mode 100644 index 0000000000..e024183e83 --- /dev/null +++ b/tests/bugs/modalg_6/bug28054_1 @@ -0,0 +1,33 @@ +puts "========" +puts "OCC28054" +puts "========" +puts "" +################################################# +# Regression: Class BRepProj_Projection gives invalid result after projection edge based on the line on the conical surface +################################################# + +set Tol 1.0e-7 + +dsetsignal 1 + +restore [locate_data_file bug28054_FaceProj.brep] f1 +restore [locate_data_file bug28054_EdgeProj.brep] e1 + +set ProjList [prj r e1 f1 0 0 1] + +if { [llength $ProjList] < 1 } { + puts "Error: no projections are found" +} + +foreach wir $ProjList { + set EdgeList [explode $wir e] + foreach ed $EdgeList { + set dist 1.0e+100 + regexp {Max Distance = +([-0-9.+eE]+)} [xdistef $ed f1] full dist + if { $dist > $Tol } { + puts "Error in projection. 3D and 2D curves of edge $ed are not same-parameter" + } else { + puts "OK: Max Distance is less than $Tol" + } + } +} \ No newline at end of file diff --git a/tests/bugs/modalg_6/bug28054_2 b/tests/bugs/modalg_6/bug28054_2 new file mode 100644 index 0000000000..89958f9bb9 --- /dev/null +++ b/tests/bugs/modalg_6/bug28054_2 @@ -0,0 +1,60 @@ +puts "========" +puts "OCC28054" +puts "========" +puts "" +################################################# +# Regression: Class BRepProj_Projection gives invalid result after +# projection edge based on the line on the conical surface +################################################# + +set Tol 1.0e-7 + +dsetsignal 1 + +cone c 0 0 0 45 0 +trimv c1 c 5 10 +trimv c2 c -10 -5 +mkface f1 c1 +mkface f2 c2 +line l1 0 0 0 1 0 1 +line l2 0 0 0 0 -1 -1 +trim l1 l1 -100 100 +trim l2 l2 -100 100 +mkedge e1 l1 +mkedge e2 l2 + +# Rotate f1 around e1 by the angle 32 degree +copy f1 f3 +rotate f3 7 0 7 1 0 1 32 + +# Rotate f2 around e2 by the angle 81 degree +copy f2 f4 +rotate f4 0 -6 -6 0 -1 -1 81 + +for { set i 1 } { $i <= 2 } { incr i } { + for { set j 1 } { $j <= 4 } { incr j } { + if { $i == 1 && $j == 4 } continue; + if { $i == 2 && $j == 3 } continue; + + puts "" + puts "Check e${i} and f${j}" + + set ProjList [prj r e${i} f${j} 0 0 1] + if { [llength $ProjList] < 1 } { + puts "Error: no projections are found" + } + + foreach wir $ProjList { + set EdgeList [explode $wir e] + foreach ed $EdgeList { + set dist 1.0e+100 + regexp {Max Distance = +([-0-9.+eE]+)} [xdistef $ed f${j}] full dist + if { $dist > $Tol } { + puts "Error in projection. 3D and 2D curves of edge $ed are not same-parameter" + } else { + puts "OK: Max Distance is less than $Tol" + } + } + } + } +}