1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-03 17:56:21 +03:00

0025757: distmini returns wrong solution for ellipse/vertex

Analytical handling of degenerated cases added.

Test case for issue CR25757

Correction of test case for issue CR25757
This commit is contained in:
aml 2015-02-12 12:14:27 +03:00 committed by bugmaster
parent 2bfe59b69c
commit 20f319cdb8
2 changed files with 195 additions and 55 deletions

View File

@ -29,6 +29,7 @@
#include <Standard_OutOfRange.hxx>
#include <math_FunctionWithDerivative.hxx>
#include <math_NewtonFunctionRoot.hxx>
#include <Precision.hxx>
class MyTrigoFunction: public math_FunctionWithDerivative
@ -178,97 +179,207 @@ void math_TrigonometricFunctionRoots::Perform(const Standard_Real A,
if ((Abs(A) <= Eps) && (Abs(B) <= Eps)) {
if (Abs(C) <= Eps) {
if (Abs(D) <= Eps) {
if (Abs(E) <= Eps) {
InfiniteStatus = Standard_True; // infinite de solutions.
return;
}
else {
NbSol = 0;
return;
}
if (Abs(E) <= Eps) {
InfiniteStatus = Standard_True; // infinite de solutions.
return;
}
else {
NbSol = 0;
return;
}
}
else {
// Equation du type d*sin(x) + e = 0
// =================================
NbSol = 0;
AA = -E/D;
if (Abs(AA) > 1.) {
return;
}
// Equation du type d*sin(x) + e = 0
// =================================
NbSol = 0;
AA = -E/D;
if (Abs(AA) > 1.) {
return;
}
Zer(1) = ASin(AA);
Zer(2) = M_PI - Zer(1);
NZer = 2;
for (i = 1; i <= NZer; i++) {
if (Zer(i) <= -Eps) {
Zer(i) = Depi - Abs(Zer(i));
}
// On rend les solutions entre InfBound et SupBound:
// =================================================
Zer(i) += IntegerPart(Mod)*Depi;
X = Zer(i)-MyBorneInf;
if ((X > (-Epsilon(Delta))) && (X < Delta+ Epsilon(Delta))) {
NbSol++;
Sol(NbSol) = Zer(i);
}
}
Zer(1) = ASin(AA);
Zer(2) = M_PI - Zer(1);
NZer = 2;
for (i = 1; i <= NZer; i++) {
if (Zer(i) <= -Eps) {
Zer(i) = Depi - Abs(Zer(i));
}
// On rend les solutions entre InfBound et SupBound:
// =================================================
Zer(i) += IntegerPart(Mod)*Depi;
X = Zer(i)-MyBorneInf;
if ((X > (-Epsilon(Delta))) && (X < Delta+ Epsilon(Delta))) {
NbSol++;
Sol(NbSol) = Zer(i);
}
}
}
return;
}
else if (Abs(D) <= Eps) {
// Equation du premier degre de la forme c*cos(x) + e = 0
// ======================================================
// Equation du premier degre de la forme c*cos(x) + e = 0
// ======================================================
NbSol = 0;
AA = -E/C;
if (Abs(AA) >1.) {
return;
return;
}
Zer(1) = ACos(AA);
Zer(2) = -Zer(1);
NZer = 2;
for (i = 1; i <= NZer; i++) {
if (Zer(i) <= -Eps) {
Zer(i) = Depi-Abs(Zer(i));
}
// On rend les solutions entre InfBound et SupBound:
// =================================================
Zer(i) += IntegerPart(Mod)*2.*M_PI;
X = Zer(i)-MyBorneInf;
if ((X >= (-Epsilon(Delta))) && (X <= Delta+ Epsilon(Delta))) {
NbSol++;
Sol(NbSol) = Zer(i);
}
if (Zer(i) <= -Eps) {
Zer(i) = Depi - Abs(Zer(i));
}
// On rend les solutions entre InfBound et SupBound:
// =================================================
Zer(i) += IntegerPart(Mod)*2.*M_PI;
X = Zer(i)-MyBorneInf;
if ((X >= (-Epsilon(Delta))) && (X <= Delta+ Epsilon(Delta))) {
NbSol++;
Sol(NbSol) = Zer(i);
}
}
return;
}
else {
// Equation du second degre:
// =========================
// Equation du second degre:
// =========================
AA = E - C;
BB = 2.0*D;
CC = E + C;
math_DirectPolynomialRoots Resol(AA, BB, CC);
if (!Resol.IsDone()) {
Done = Standard_False;
return;
Done = Standard_False;
return;
}
else if(!Resol.InfiniteRoots()) {
NZer = Resol.NbSolutions();
for (i = 1; i <= NZer; i++) {
Zer(i) = Resol.Value(i);
}
NZer = Resol.NbSolutions();
for (i = 1; i <= NZer; i++) {
Zer(i) = Resol.Value(i);
}
}
else if (Resol.InfiniteRoots()) {
InfiniteStatus = Standard_True;
return;
InfiniteStatus = Standard_True;
return;
}
}
}
else {
// Two additional analytical cases.
if ((Abs(A) <= Eps) &&
(Abs(E) <= Eps))
{
if (Abs(C) <= Eps)
{
// 2 * B * sin * cos + D * sin = 0
NZer = 2;
Zer(1) = 0.0;
Zer(2) = M_PI;
AA = -D/(B * 2);
if (Abs(AA) <= 1.0 + Precision::PConfusion())
{
NZer = 4;
if (AA >= 1.0)
{
Zer(3)= 0.0;
Zer(4)= 0.0;
}
else if (AA <= -1.0)
{
Zer(3)= M_PI;
Zer(4)= M_PI;
}
else
{
Zer(3)= ACos(AA);
Zer(4) = Depi - Zer(3);
}
}
NbSol = 0;
for (i = 1; i <= NZer; i++)
{
if (Zer(i) <= MyBorneInf - Eps)
{
Zer(i) += Depi;
}
// On rend les solutions entre InfBound et SupBound:
// =================================================
Zer(i) += IntegerPart(Mod)*2.*M_PI;
X = Zer(i)-MyBorneInf;
if ((X >= (-Precision::PConfusion())) &&
(X <= Delta + Precision::PConfusion()))
{
if (Zer(i) < InfBound)
Zer(i) = InfBound;
if (Zer(i) > SupBound)
Zer(i) = SupBound;
NbSol++;
Sol(NbSol) = Zer(i);
}
}
return;
}
if (Abs(D) <= Eps)
{
// 2 * B * sin * cos + C * cos = 0
NZer = 2;
Zer(1) = M_PI / 2.0;
Zer(2) = M_PI * 3.0 / 2.0;
AA = -C/(B * 2);
if (Abs(AA) <= 1.0 + Precision::PConfusion())
{
NZer = 4;
if (AA >= 1.0)
{
Zer(3) = M_PI / 2.0;
Zer(4) = M_PI / 2.0;
}
else if (AA <= -1.0)
{
Zer(3) = M_PI * 3.0 / 2.0;
Zer(4) = M_PI * 3.0 / 2.0;
}
else
{
Zer(3)= ASin(AA);
Zer(4) = M_PI - Zer(3);
}
}
NbSol = 0;
for (i = 1; i <= NZer; i++)
{
if (Zer(i) <= MyBorneInf - Eps)
{
Zer(i) += Depi;
}
// On rend les solutions entre InfBound et SupBound:
// =================================================
Zer(i) += IntegerPart(Mod)*2.*M_PI;
X = Zer(i)-MyBorneInf;
if ((X >= (-Precision::PConfusion())) &&
(X <= Delta + Precision::PConfusion()))
{
if (Zer(i) < InfBound)
Zer(i) = InfBound;
if (Zer(i) > SupBound)
Zer(i) = SupBound;
NbSol++;
Sol(NbSol) = Zer(i);
}
}
return;
}
}
// Equation du 4 ieme degre
// ========================

29
tests/bugs/fclasses/bug25757 Executable file
View File

@ -0,0 +1,29 @@
puts "========"
puts "OCC25757"
puts "========"
puts ""
##############################################
# distmini returns wrong solution for ellipse/vertex
##############################################
restore [locate_data_file bug25757_ellipse.brep] ellipse
vertex vertex1 7.32050807568877 3.999999999999999 10.0
vertex vertex2 7.32050807568877 3.99999999999999 10.0
distmini dv1 vertex1 ellipse
set dist1 [dval dv1_val]
puts "vertex1 distance = ${dist1}"
distmini dv2 vertex2 ellipse
set dist2 [dval dv2_val]
puts "vertex2 distance = ${dist2}"
set tol_abs_dist 1.0e-12
set tol_rel_dist 1.0e-2
set expected_dist1 0.0
set expected_dist2 0.0
checkreal "Distance 1" ${dist1} ${expected_dist1} ${tol_abs_dist} ${tol_rel_dist}
checkreal "Distance 2" ${dist2} ${expected_dist2} ${tol_abs_dist} ${tol_rel_dist}