Corrected XrPenVerticesNeeded for handling transformed pens

This commit is contained in:
Carl Worth 2002-09-05 10:06:44 +00:00
parent 34ab06281f
commit bc362fc2e4
6 changed files with 102 additions and 20 deletions

View file

@ -564,6 +564,9 @@ XrTransformPointWithoutTranslate(XrTransform *transform, XPointDouble *pt);
void
XrTransformPoint(XrTransform *transform, XPointDouble *pt);
void
XrTransformEigenValues(XrTransform *transform, double *lambda1, double *lambda2);
/* xrtraps.c */
void
XrTrapsInit(XrTraps *traps);

View file

@ -26,7 +26,7 @@
#include "xrint.h"
static int
_XrPenVerticesNeeded(double radius, double tolerance);
_XrPenVerticesNeeded(double radius, double tolerance, XrTransform *matrix);
static void
_XrPenComputeSlopes(XrPen *pen);
@ -77,7 +77,7 @@ XrPenInit(XrPen *pen, double radius, XrGState *gstate)
pen->radius = radius;
pen->tolerance = gstate->tolerance;
pen->num_vertices = _XrPenVerticesNeeded(radius, gstate->tolerance);
pen->num_vertices = _XrPenVerticesNeeded(radius, gstate->tolerance, &gstate->ctm);
pen->vertex = malloc(pen->num_vertices * sizeof(XrPenVertex));
if (pen->vertex == NULL) {
@ -199,17 +199,23 @@ XrPenAddPoints(XrPen *pen, XrPenTaggedPoint *pt, int num_pts)
}
static int
_XrPenVerticesNeeded(double radius, double tolerance)
_XrPenVerticesNeeded(double radius, double tolerance, XrTransform *matrix)
{
/* XXX: BUG: This calculation needs to be corrected to account for
the fact that the radius is specified in user space, while the
tolerance is specified in device space. */
double e1, e2, emax, theta;
if (tolerance > radius) {
return 4;
} else {
double theta = acos(1 - tolerance/radius);
return ceil(M_PI / theta);
}
}
XrTransformEigenValues(matrix, &e1, &e2);
if (fabs(e1) > fabs(e2))
emax = fabs(e1);
else
emax = fabs(e2);
theta = acos(1 - tolerance/(emax * radius));
return ceil(M_PI / theta);
}
static void

View file

@ -151,3 +151,35 @@ XrTransformPoint(XrTransform *transform, XPointDouble *pt)
pt->x += transform->m[2][0];
pt->y += transform->m[2][1];
}
void
XrTransformEigenValues(XrTransform *transform, double *lambda1, double *lambda2)
{
/* The eigenvalues of an NxN matrix M are found by solving the polynomial:
det(M - lI) = 0
which for our 2x2 matrix:
M = a b
c d
gives:
l^2 - (a+d)l + (ad - bc) = 0
l = (a+d +/- sqrt(a^2 + 2ad + d^2 - 4(ad-bc))) / 2;
*/
double a, b, c, d, rad;
a = transform->m[0][0];
b = transform->m[0][1];
c = transform->m[1][0];
d = transform->m[1][1];
rad = sqrt(a*a + 2*a*d + d*d - 4*(a*d - b*c));
*lambda1 = (a + d + rad) / 2.0;
*lambda2 = (a + d - rad) / 2.0;
}

View file

@ -564,6 +564,9 @@ XrTransformPointWithoutTranslate(XrTransform *transform, XPointDouble *pt);
void
XrTransformPoint(XrTransform *transform, XPointDouble *pt);
void
XrTransformEigenValues(XrTransform *transform, double *lambda1, double *lambda2);
/* xrtraps.c */
void
XrTrapsInit(XrTraps *traps);

26
xrpen.c
View file

@ -26,7 +26,7 @@
#include "xrint.h"
static int
_XrPenVerticesNeeded(double radius, double tolerance);
_XrPenVerticesNeeded(double radius, double tolerance, XrTransform *matrix);
static void
_XrPenComputeSlopes(XrPen *pen);
@ -77,7 +77,7 @@ XrPenInit(XrPen *pen, double radius, XrGState *gstate)
pen->radius = radius;
pen->tolerance = gstate->tolerance;
pen->num_vertices = _XrPenVerticesNeeded(radius, gstate->tolerance);
pen->num_vertices = _XrPenVerticesNeeded(radius, gstate->tolerance, &gstate->ctm);
pen->vertex = malloc(pen->num_vertices * sizeof(XrPenVertex));
if (pen->vertex == NULL) {
@ -199,17 +199,23 @@ XrPenAddPoints(XrPen *pen, XrPenTaggedPoint *pt, int num_pts)
}
static int
_XrPenVerticesNeeded(double radius, double tolerance)
_XrPenVerticesNeeded(double radius, double tolerance, XrTransform *matrix)
{
/* XXX: BUG: This calculation needs to be corrected to account for
the fact that the radius is specified in user space, while the
tolerance is specified in device space. */
double e1, e2, emax, theta;
if (tolerance > radius) {
return 4;
} else {
double theta = acos(1 - tolerance/radius);
return ceil(M_PI / theta);
}
}
XrTransformEigenValues(matrix, &e1, &e2);
if (fabs(e1) > fabs(e2))
emax = fabs(e1);
else
emax = fabs(e2);
theta = acos(1 - tolerance/(emax * radius));
return ceil(M_PI / theta);
}
static void

View file

@ -151,3 +151,35 @@ XrTransformPoint(XrTransform *transform, XPointDouble *pt)
pt->x += transform->m[2][0];
pt->y += transform->m[2][1];
}
void
XrTransformEigenValues(XrTransform *transform, double *lambda1, double *lambda2)
{
/* The eigenvalues of an NxN matrix M are found by solving the polynomial:
det(M - lI) = 0
which for our 2x2 matrix:
M = a b
c d
gives:
l^2 - (a+d)l + (ad - bc) = 0
l = (a+d +/- sqrt(a^2 + 2ad + d^2 - 4(ad-bc))) / 2;
*/
double a, b, c, d, rad;
a = transform->m[0][0];
b = transform->m[0][1];
c = transform->m[1][0];
d = transform->m[1][1];
rad = sqrt(a*a + 2*a*d + d*d - 4*(a*d - b*c));
*lambda1 = (a + d + rad) / 2.0;
*lambda2 = (a + d - rad) / 2.0;
}