From b070046674428fad3a4c2e9b19c64d48fe8ce2b6 Mon Sep 17 00:00:00 2001 From: nbv Date: Mon, 7 Nov 2016 18:48:37 +0300 Subject: [PATCH] 0028054: Regression: Class BRepProj_Projection gives invalid result after projection edge based on the line on the conical surface Problem of projection of line on the cone in the special case when starting point of the line coincides with the cone apex is fixed (by shifting this point along the source line). --- src/ProjLib/ProjLib_Cone.cxx | 27 +++++++++------ src/Standard/Standard_Real.cxx | 2 -- src/Standard/Standard_Real.hxx | 5 ++- tests/bugs/modalg_6/bug28054_1 | 33 +++++++++++++++++++ tests/bugs/modalg_6/bug28054_2 | 60 ++++++++++++++++++++++++++++++++++ 5 files changed, 114 insertions(+), 13 deletions(-) create mode 100644 tests/bugs/modalg_6/bug28054_1 create mode 100644 tests/bugs/modalg_6/bug28054_2 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" + } + } + } + } +}