Fixed algebra used by XrPenVerticesNeeded to avoid sqrt() of negative numbers.

This commit is contained in:
Carl Worth 2003-02-06 08:06:28 +00:00
parent a4b439eb69
commit d4ba730ba2
7 changed files with 54 additions and 30 deletions

View file

@ -1,3 +1,9 @@
2003-02-06 Carl Worth <cworth@isi.edu>
* xrpen.c (_XrPenVerticesNeeded): Fixed to use determinant rather
than eigenvalues to compute maximal scaling of radius. Now avoids
embarrassing segfaults due to NaN from the eigenvalue computation.
2003-01-28 Carl Worth <cworth@isi.edu>
* xrtraps.c (_XrTrapsTessellateTriangle): Fixed to not re-order

View file

@ -764,6 +764,9 @@ _XrTransformBoundingBox(XrTransform *transform,
XrStatus
_XrTransformComputeInverse(XrTransform *transform);
void
_XrTransformComputeDeterminant(XrTransform *transform, double *det);
void
_XrTransformEigenValues(XrTransform *transform, double *lambda1, double *lambda2);

View file

@ -188,20 +188,19 @@ _XrPenAddPoints(XrPen *pen, XPointFixed *pt, int num_pts)
static int
_XrPenVerticesNeeded(double radius, double tolerance, XrTransform *matrix)
{
double e1, e2, emax, theta;
double expansion, theta;
_XrTransformEigenValues(matrix, &e1, &e2);
/* The determinant represents the area expansion factor of the
transform. In the worst case, this is entirely in one
dimension, which is what we assume here. */
if (fabs(e1) > fabs(e2))
emax = fabs(e1);
else
emax = fabs(e2);
_XrTransformComputeDeterminant(matrix, &expansion);
if (tolerance > emax*radius) {
if (tolerance > expansion*radius) {
return 4;
}
theta = acos(1 - tolerance/(emax * radius));
theta = acos(1 - tolerance/(expansion * radius));
return ceil(M_PI / theta);
}

View file

@ -244,14 +244,10 @@ XrStatus
_XrTransformComputeInverse(XrTransform *transform)
{
/* inv(A) = 1/det(A) * adj(A) */
double det;
double a, b, c, d, det;
a = transform->m[0][0]; b = transform->m[0][1];
c = transform->m[1][0]; d = transform->m[1][1];
det = a*d - b*c;
_XrTransformComputeDeterminant(transform, &det);
if (det == 0)
return XrStatusInvalidMatrix;
@ -261,6 +257,17 @@ _XrTransformComputeInverse(XrTransform *transform)
return XrStatusSuccess;
}
void
_XrTransformComputeDeterminant(XrTransform *transform, double *det)
{
double a, b, c, d;
a = transform->m[0][0]; b = transform->m[0][1];
c = transform->m[1][0]; d = transform->m[1][1];
*det = a*d - b*c;
}
void
_XrTransformEigenValues(XrTransform *transform, double *lambda1, double *lambda2)
{

View file

@ -764,6 +764,9 @@ _XrTransformBoundingBox(XrTransform *transform,
XrStatus
_XrTransformComputeInverse(XrTransform *transform);
void
_XrTransformComputeDeterminant(XrTransform *transform, double *det);
void
_XrTransformEigenValues(XrTransform *transform, double *lambda1, double *lambda2);

15
xrpen.c
View file

@ -188,20 +188,19 @@ _XrPenAddPoints(XrPen *pen, XPointFixed *pt, int num_pts)
static int
_XrPenVerticesNeeded(double radius, double tolerance, XrTransform *matrix)
{
double e1, e2, emax, theta;
double expansion, theta;
_XrTransformEigenValues(matrix, &e1, &e2);
/* The determinant represents the area expansion factor of the
transform. In the worst case, this is entirely in one
dimension, which is what we assume here. */
if (fabs(e1) > fabs(e2))
emax = fabs(e1);
else
emax = fabs(e2);
_XrTransformComputeDeterminant(matrix, &expansion);
if (tolerance > emax*radius) {
if (tolerance > expansion*radius) {
return 4;
}
theta = acos(1 - tolerance/(emax * radius));
theta = acos(1 - tolerance/(expansion * radius));
return ceil(M_PI / theta);
}

View file

@ -244,14 +244,10 @@ XrStatus
_XrTransformComputeInverse(XrTransform *transform)
{
/* inv(A) = 1/det(A) * adj(A) */
double det;
double a, b, c, d, det;
a = transform->m[0][0]; b = transform->m[0][1];
c = transform->m[1][0]; d = transform->m[1][1];
det = a*d - b*c;
_XrTransformComputeDeterminant(transform, &det);
if (det == 0)
return XrStatusInvalidMatrix;
@ -261,6 +257,17 @@ _XrTransformComputeInverse(XrTransform *transform)
return XrStatusSuccess;
}
void
_XrTransformComputeDeterminant(XrTransform *transform, double *det)
{
double a, b, c, d;
a = transform->m[0][0]; b = transform->m[0][1];
c = transform->m[1][0]; d = transform->m[1][1];
*det = a*d - b*c;
}
void
_XrTransformEigenValues(XrTransform *transform, double *lambda1, double *lambda2)
{