58 #define MAX(a,b) ((a)>(b)?(a):(b))
59 #define MIN(a,b) ((a)<(b)?(a):(b))
61 #define NEW(t) ((t*)calloc(1,sizeof(t)))
62 #define N_NEW(n,t) ((t*)calloc(n,sizeof(t)))
64 #define PI 3.14159265358979323846
84 #define TWOPI (2*M_PI)
91 double theta, cosTheta, sinTheta;
97 double x1, y1, x2,
y2;
100 double xF1, yF1, xF2,
yF2;
116 double d = sqrt(ep->
a * ep->
a - ep->
b * ep->
b);
120 ep->
xF1 = ep->
cx - dx;
121 ep->
yF1 = ep->
cy - dy;
122 ep->
xF2 = ep->
cx + dx;
123 ep->
yF2 = ep->
cy + dy;
127 static void computeEndPoints(
ellipse_t * ep)
129 double aCosEta1 = ep->
a * cos(ep->
eta1);
130 double bSinEta1 = ep->
b * sin(ep->
eta1);
131 double aCosEta2 = ep->
a * cos(ep->
eta2);
132 double bSinEta2 = ep->
b * sin(ep->
eta2);
144 static void computeBounds(
ellipse_t * ep)
146 double bOnA = ep->
b / ep->
a;
147 double etaXMin, etaXMax, etaYMin, etaYMax;
152 etaXMin = -atan(tanTheta * bOnA);
153 etaXMax = etaXMin +
M_PI;
154 etaYMin = 0.5 * M_PI - atan(tanTheta / bOnA);
155 etaYMax = etaYMin +
M_PI;
157 etaXMax = -atan(tanTheta * bOnA);
158 etaXMin = etaXMax -
M_PI;
159 etaYMax = 0.5 * M_PI - atan(tanTheta / bOnA);
160 etaYMin = etaYMax -
M_PI;
165 etaXMax = 0.5 *
M_PI + atan(invTanTheta / bOnA);
166 etaXMin = etaXMax -
M_PI;
167 etaYMin = atan(invTanTheta * bOnA);
168 etaYMax = etaYMin +
M_PI;
170 etaXMin = 0.5 *
M_PI + atan(invTanTheta / bOnA);
171 etaXMax = etaXMin +
M_PI;
172 etaYMax = atan(invTanTheta * bOnA);
173 etaYMin = etaYMax -
M_PI;
186 ep->
yUp = (etaYMin <= ep->
eta2)
194 ep->
height = ((etaYMax <= ep->eta2)
202 initEllipse(
ellipse_t * ep,
double cx,
double cy,
double a,
double b,
203 double theta,
double lambda1,
double lambda2)
211 ep->
eta1 = atan2(sin(lambda1) / b, cos(lambda1) / a);
212 ep->
eta2 = atan2(sin(lambda2) / b, cos(lambda2) / a);
226 computeEndPoints(ep);
230 ep->
f = (ep->
a - ep->
b) / ep->
a;
231 ep->
e2 = ep->
f * (2.0 - ep->
f);
233 ep->
g2 = ep->
g * ep->
g;
241 static erray_t coeffs2Low = {
243 {3.92478, -13.5822, -0.233377, 0.0128206},
244 {-1.08814, 0.859987, 0.000362265, 0.000229036},
245 {-0.942512, 0.390456, 0.0080909, 0.00723895},
246 {-0.736228, 0.20998, 0.0129867, 0.0103456}
249 {-0.395018, 6.82464, 0.0995293, 0.0122198},
250 {-0.545608, 0.0774863, 0.0267327, 0.0132482},
251 {0.0534754, -0.0884167, 0.012595, 0.0343396},
252 {0.209052, -0.0599987, -0.00723897, 0.00789976}
259 static erray_t coeffs2High = {
261 {0.0863805, -11.5595, -2.68765, 0.181224},
262 {0.242856, -1.81073, 1.56876, 1.68544},
263 {0.233337, -0.455621, 0.222856, 0.403469},
264 {0.0612978, -0.104879, 0.0446799, 0.00867312}
267 {0.028973, 6.68407, 0.171472, 0.0211706},
268 {0.0307674, -0.0517815, 0.0216803, -0.0749348},
269 {-0.0471179, 0.1288, -0.0781702, 2.0},
270 {-0.0309683, 0.0531557, -0.0227191, 0.0434511}
276 static double safety2[] = {
277 0.02, 2.83, 0.125, 0.01
283 static erray_t coeffs3Low = {
285 {3.85268, -21.229, -0.330434, 0.0127842},
286 {-1.61486, 0.706564, 0.225945, 0.263682},
287 {-0.910164, 0.388383, 0.00551445, 0.00671814},
288 {-0.630184, 0.192402, 0.0098871, 0.0102527}
291 {-0.162211, 9.94329, 0.13723, 0.0124084},
292 {-0.253135, 0.00187735, 0.0230286, 0.01264},
293 {-0.0695069, -0.0437594, 0.0120636, 0.0163087},
294 {-0.0328856, -0.00926032, -0.00173573, 0.00527385}
301 static erray_t coeffs3High = {
303 {0.0899116, -19.2349, -4.11711, 0.183362},
304 {0.138148, -1.45804, 1.32044, 1.38474},
305 {0.230903, -0.450262, 0.219963, 0.414038},
306 {0.0590565, -0.101062, 0.0430592, 0.0204699}
309 {0.0164649, 9.89394, 0.0919496, 0.00760802},
310 {0.0191603, -0.0322058, 0.0134667, -0.0825018},
311 {0.0156192, -0.017535, 0.00326508, -0.228157},
312 {-0.0236752, 0.0405821, -0.0173086, 0.176187}
318 static double safety3[] = {
319 0.001, 4.98, 0.207, 0.0067
326 #define RationalFunction(x,c) ((x * (x * c[0] + c[1]) + c[2]) / (x + c[3]))
335 estimateError(
ellipse_t * ep,
int degree,
double etaA,
double etaB)
337 double c0, c1, eta = 0.5 * (etaA + etaB);
342 double aCosEtaA = ep->
a * cos(etaA);
343 double bSinEtaA = ep->
b * sin(etaA);
350 double aCosEtaB = ep->
a * cos(etaB);
351 double bSinEtaB = ep->
b * sin(etaB);
358 double aCosEta = ep->
a * cos(eta);
359 double bSinEta = ep->
b * sin(eta);
368 return fabs(x * dy - y * dx + xB * yA - xA * yB)
369 / sqrt(dx * dx + dy * dy);
373 double x = ep->
b / ep->
a;
374 double dEta = etaB - etaA;
375 double cos2 = cos(2 * eta);
376 double cos4 = cos(4 * eta);
377 double cos6 = cos(6 * eta);
380 double (*coeffs)[4][4];
383 coeffs = (x < 0.25) ? coeffs2Low : coeffs2High;
386 coeffs = (x < 0.25) ? coeffs3Low : coeffs3High;
421 double x2,
double y2,
double x3,
double y3)
423 if (path->
pn + 3 >= bufsize) {
425 path->
ps = realloc(path->
ps, bufsize *
sizeof(
pointf));
427 path->
ps[path->
pn].
x = x1;
428 path->
ps[path->
pn++].
y = y1;
429 path->
ps[path->
pn].
x = x2;
430 path->
ps[path->
pn++].
y = y2;
431 path->
ps[path->
pn].
x = x3;
432 path->
ps[path->
pn++].
y = y3;
435 static void lineTo(
Ppolyline_t * path,
double x,
double y)
438 curveTo(path, curp.
x, curp.
y, x, y, x, y);
441 static void endPath(
Ppolyline_t * path,
boolean close)
445 lineTo(path, p0.
x, p0.
y);
448 path->
ps = realloc(path->
ps, path->
pn *
sizeof(
pointf));
460 double threshold,
boolean isSlice)
479 boolean found =
FALSE;
481 while ((!found) && (n < 1024)) {
482 double dEta = (ep->
eta2 - ep->
eta1) / n;
483 if (dEta <= 0.5 *
M_PI) {
484 double etaB = ep->
eta1;
486 for (i = 0; found && (i < n); ++i) {
490 (estimateError(ep, degree, etaA, etaB) <= threshold);
501 aCosEtaB = ep->
a * cosEtaB;
502 bSinEtaB = ep->
b * sinEtaB;
503 aSinEtaB = ep->
a * sinEtaB;
504 bCosEtaB = ep->
b * cosEtaB;
511 moveTo(path, ep->
cx, ep->
cy);
512 lineTo(path, xB, yB);
514 moveTo(path, xB, yB);
518 alpha = sin(dEta) * (sqrt(4 + 3 * t * t) - 1) / 3;
520 for (i = 0; i < n; ++i) {
524 double xADot = xBDot;
525 double yADot = yBDot;
530 aCosEtaB = ep->
a * cosEtaB;
531 bSinEtaB = ep->
b * sinEtaB;
532 aSinEtaB = ep->
a * sinEtaB;
533 bCosEtaB = ep->
b * cosEtaB;
540 lineTo(path, xB, yB);
542 }
else if (degree == 2) {
543 double k = (yBDot * (xB - xA) - xBDot * (yB - yA))
544 / (xADot * yBDot - yADot * xBDot);
545 quadTo(path, (xA + k * xADot), (yA + k * yADot), xB, yB);
548 curveTo(path, (xA + alpha * xADot), (yA + alpha * yADot),
549 (xB - alpha * xBDot), (yB - alpha * yBDot), xB, yB);
554 endPath(path, isSlice);
566 double angle0,
double angle1)
571 initEllipse(&ell, ctr.
x, ctr.
y, xsemi, ysemi, 0, angle0, angle1);
572 pp = genEllipticPath(&ell, 3, 0.00001, 1);
583 initEllipse(&ell, 200, 200, 100, 50, 0,
M_PI / 4, 3 *
M_PI / 2);
584 pp = genEllipticPath(&ell, 3, 0.00001, 1);
586 printf(
"newpath %.02lf %.02lf moveto\n", pp->
ps[0].
x, pp->
ps[0].
y);
587 for (i = 1; i < pp->
pn; i += 3) {
588 printf(
"%.02lf %.02lf %.02lf %.02lf %.02lf %.02lf curveto\n",
590 pp->
ps[i + 1].
x, pp->
ps[i + 1].
y,
591 pp->
ps[i + 2].
x, pp->
ps[i + 2].
y);
593 printf(
"stroke showpage\n");
Ppolyline_t * ellipticWedge(pointf ctr, double xsemi, double ysemi, double angle0, double angle1)
int main(int argc, char **argv)
#define RationalFunction(x, c)