cornu.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615
  1. /*
  2. ppedit - A pattern plate editor for Spiro splines.
  3. Copyright (C) 2007 Raph Levien
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  15. 02110-1301, USA.
  16. */
  17. #include <math.h>
  18. #include <stdlib.h>
  19. #include <stdio.h>
  20. #include "bezctx_intf.h"
  21. /* The computation of fresnel integrals is adapted from: */
  22. /*
  23. Cephes Math Library Release 2.1: December, 1988
  24. Copyright 1984, 1987, 1988 by Stephen L. Moshier
  25. Direct inquiries to 30 Frost Street, Cambridge, MA 02140
  26. */
  27. double polevl( double x, double coef[], int N )
  28. {
  29. double ans;
  30. int i;
  31. double *p;
  32. p = coef;
  33. ans = *p++;
  34. i = N;
  35. do
  36. ans = ans * x + *p++;
  37. while( --i );
  38. return( ans );
  39. }
  40. /* p1evl() */
  41. /* N
  42. * Evaluate polynomial when coefficient of x is 1.0.
  43. * Otherwise same as polevl.
  44. */
  45. double p1evl( double x, double coef[], int N )
  46. {
  47. double ans;
  48. double *p;
  49. int i;
  50. p = coef;
  51. ans = x + *p++;
  52. i = N-1;
  53. do
  54. ans = ans * x + *p++;
  55. while( --i );
  56. return( ans );
  57. }
  58. static double sn[6] = {
  59. -2.99181919401019853726E3,
  60. 7.08840045257738576863E5,
  61. -6.29741486205862506537E7,
  62. 2.54890880573376359104E9,
  63. -4.42979518059697779103E10,
  64. 3.18016297876567817986E11,
  65. };
  66. static double sd[6] = {
  67. /* 1.00000000000000000000E0,*/
  68. 2.81376268889994315696E2,
  69. 4.55847810806532581675E4,
  70. 5.17343888770096400730E6,
  71. 4.19320245898111231129E8,
  72. 2.24411795645340920940E10,
  73. 6.07366389490084639049E11,
  74. };
  75. static double cn[6] = {
  76. -4.98843114573573548651E-8,
  77. 9.50428062829859605134E-6,
  78. -6.45191435683965050962E-4,
  79. 1.88843319396703850064E-2,
  80. -2.05525900955013891793E-1,
  81. 9.99999999999999998822E-1,
  82. };
  83. static double cd[7] = {
  84. 3.99982968972495980367E-12,
  85. 9.15439215774657478799E-10,
  86. 1.25001862479598821474E-7,
  87. 1.22262789024179030997E-5,
  88. 8.68029542941784300606E-4,
  89. 4.12142090722199792936E-2,
  90. 1.00000000000000000118E0,
  91. };
  92. static double fn[10] = {
  93. 4.21543555043677546506E-1,
  94. 1.43407919780758885261E-1,
  95. 1.15220955073585758835E-2,
  96. 3.45017939782574027900E-4,
  97. 4.63613749287867322088E-6,
  98. 3.05568983790257605827E-8,
  99. 1.02304514164907233465E-10,
  100. 1.72010743268161828879E-13,
  101. 1.34283276233062758925E-16,
  102. 3.76329711269987889006E-20,
  103. };
  104. static double fd[10] = {
  105. /* 1.00000000000000000000E0,*/
  106. 7.51586398353378947175E-1,
  107. 1.16888925859191382142E-1,
  108. 6.44051526508858611005E-3,
  109. 1.55934409164153020873E-4,
  110. 1.84627567348930545870E-6,
  111. 1.12699224763999035261E-8,
  112. 3.60140029589371370404E-11,
  113. 5.88754533621578410010E-14,
  114. 4.52001434074129701496E-17,
  115. 1.25443237090011264384E-20,
  116. };
  117. static double gn[11] = {
  118. 5.04442073643383265887E-1,
  119. 1.97102833525523411709E-1,
  120. 1.87648584092575249293E-2,
  121. 6.84079380915393090172E-4,
  122. 1.15138826111884280931E-5,
  123. 9.82852443688422223854E-8,
  124. 4.45344415861750144738E-10,
  125. 1.08268041139020870318E-12,
  126. 1.37555460633261799868E-15,
  127. 8.36354435630677421531E-19,
  128. 1.86958710162783235106E-22,
  129. };
  130. static double gd[11] = {
  131. /* 1.00000000000000000000E0,*/
  132. 1.47495759925128324529E0,
  133. 3.37748989120019970451E-1,
  134. 2.53603741420338795122E-2,
  135. 8.14679107184306179049E-4,
  136. 1.27545075667729118702E-5,
  137. 1.04314589657571990585E-7,
  138. 4.60680728146520428211E-10,
  139. 1.10273215066240270757E-12,
  140. 1.38796531259578871258E-15,
  141. 8.39158816283118707363E-19,
  142. 1.86958710162783236342E-22,
  143. };
  144. #ifndef M_PI
  145. #define M_PI 3.14159265358979323846 /* pi */
  146. #endif
  147. #ifndef M_PI_2
  148. #define M_PI_2 1.57079632679489661923 /* pi/2 */
  149. #endif
  150. int fresnl( xxa, ssa, cca )
  151. double xxa, *ssa, *cca;
  152. {
  153. double f, g, cc, ss, c, s, t, u;
  154. double x, x2;
  155. x = fabs(xxa);
  156. x2 = x * x;
  157. if( x2 < 2.5625 )
  158. {
  159. t = x2 * x2;
  160. ss = x * x2 * polevl( t, sn, 5)/p1evl( t, sd, 6 );
  161. cc = x * polevl( t, cn, 5)/polevl(t, cd, 6 );
  162. goto done;
  163. }
  164. #if 0
  165. /* Note by RLL: the cutoff here seems low to me; perhaps it should be
  166. eliminated altogether. */
  167. if( x > 36974.0 )
  168. {
  169. cc = 0.5;
  170. ss = 0.5;
  171. goto done;
  172. }
  173. #endif
  174. /* Asymptotic power series auxiliary functions
  175. * for large argument
  176. */
  177. x2 = x * x;
  178. t = M_PI * x2;
  179. u = 1.0/(t * t);
  180. t = 1.0/t;
  181. f = 1.0 - u * polevl( u, fn, 9)/p1evl(u, fd, 10);
  182. g = t * polevl( u, gn, 10)/p1evl(u, gd, 11);
  183. t = M_PI_2 * x2;
  184. c = cos(t);
  185. s = sin(t);
  186. t = M_PI * x;
  187. cc = 0.5 + (f * s - g * c)/t;
  188. ss = 0.5 - (f * c + g * s)/t;
  189. done:
  190. if( xxa < 0.0 )
  191. {
  192. cc = -cc;
  193. ss = -ss;
  194. }
  195. *cca = cc;
  196. *ssa = ss;
  197. return(0);
  198. }
  199. /*
  200. End section adapted from Cephes math library. The following code is
  201. by Raph Levien.
  202. */
  203. void eval_cornu(double t, double *ps, double *pc)
  204. {
  205. double s, c;
  206. double rspio2 = 0.7978845608028653; /* 1 / sqrt(pi/2) */
  207. double spio2 = 1.2533141373155; /* sqrt(pi/2) */
  208. fresnl(t * rspio2, &s, &c);
  209. *ps = s * spio2;
  210. *pc = c * spio2;
  211. }
  212. double mod_2pi(double th) {
  213. double u = th * (1 / (2 * M_PI));
  214. return 2 * M_PI * (u - floor(u + 0.5));
  215. }
  216. void fit_cornu_half(double th0, double th1,
  217. double *pt0, double *pt1,
  218. double *pk0, double *pk1)
  219. {
  220. int i;
  221. const int max_iter = 21;
  222. double t0, t1, t_m;
  223. double tl, tr, t_est;
  224. double s0, c0, s1, c1;
  225. /* This implementation uses bisection, which is simple but almost
  226. certainly not the fastest converging. If time is of the essence,
  227. use something like Newton-Raphson. */
  228. if (fabs(th0 + th1) < 1e-6) {
  229. th0 += 1e-6;
  230. th1 += 1e-6;
  231. }
  232. t_est = 0.29112 * (th1 + th0) / sqrt(th1 - th0);
  233. tl = t_est * .9;
  234. tr = t_est * 2;
  235. for (i = 0; i < max_iter; i++) {
  236. double dt;
  237. double chord_th;
  238. t_m = .5 * (tl + tr);
  239. dt = (th0 + th1) / (4 * t_m);
  240. t0 = t_m - dt;
  241. t1 = t_m + dt;
  242. eval_cornu(t0, &s0, &c0);
  243. eval_cornu(t1, &s1, &c1);
  244. chord_th = atan2(s1 - s0, c1 - c0);
  245. if (mod_2pi(chord_th - t0 * t0 - th0) < 0)
  246. tl = t_m;
  247. else
  248. tr = t_m;
  249. }
  250. *pt0 = t0;
  251. *pt1 = t1;
  252. if (pk0 || pk1) {
  253. double chordlen = hypot(s1 - s0, c1 - c0);
  254. if (pk0) *pk0 = t0 * chordlen;
  255. if (pk1) *pk1 = t1 * chordlen;
  256. }
  257. }
  258. /* Most of the time, this should give a fairly tight, yet conservative,
  259. (meaning it won't underestimate) approximation of the maximum error
  260. between a Cornu spiral segment and its quadratic Bezier fit.
  261. */
  262. double
  263. est_cornu_error(double t0, double t1)
  264. {
  265. double t, u, est;
  266. if (t0 < 0 || t1 < 0) {
  267. t0 = -t0;
  268. t1 = -t1;
  269. }
  270. if (t1 < 0) {
  271. fprintf(stderr, "unexpected t1 sign\n");
  272. }
  273. if (t1 < t0) {
  274. double tmp = t0;
  275. t0 = t1;
  276. t1 = tmp;
  277. }
  278. if (fabs(t0) < 1e-9) {
  279. est = t1 * t1 * t1;
  280. est *= .017256 - .0059 - est * t1;
  281. } else {
  282. t = t1 - t0;
  283. t *= t;
  284. t *= t;
  285. est = t * fabs(t0 + t1 - 1.22084) / (t0 + t1);
  286. u = t0 + t1 + .6;
  287. u = u * u * u;
  288. est *= .014 * (.6 * u + 1);
  289. est += t * (t1 - t0) * .004;
  290. }
  291. return est;
  292. }
  293. void
  294. affine_pt(const double aff[6], double x, double y, double *px, double *py) {
  295. *px = x * aff[0] + y * aff[2] + aff[4];
  296. *py = x * aff[1] + y * aff[3] + aff[5];
  297. }
  298. void
  299. affine_multiply(double dst[6], const double src1[6], const double src2[6])
  300. {
  301. double d0, d1, d2, d3, d4, d5;
  302. d0 = src1[0] * src2[0] + src1[1] * src2[2];
  303. d1 = src1[0] * src2[1] + src1[1] * src2[3];
  304. d2 = src1[2] * src2[0] + src1[3] * src2[2];
  305. d3 = src1[2] * src2[1] + src1[3] * src2[3];
  306. d4 = src1[4] * src2[0] + src1[5] * src2[2] + src2[4];
  307. d5 = src1[4] * src2[1] + src1[5] * src2[3] + src2[5];
  308. dst[0] = d0;
  309. dst[1] = d1;
  310. dst[2] = d2;
  311. dst[3] = d3;
  312. dst[4] = d4;
  313. dst[5] = d5;
  314. }
  315. void
  316. fit_quadratic(double x0, double y0, double th0,
  317. double x1, double y1, double th1,
  318. double quad[6]) {
  319. double th;
  320. double s0, c0, s1, c1;
  321. double det, s, c;
  322. th = atan2(y1 - y0, x1 - x0);
  323. s0 = sin(th0 - th);
  324. c0 = cos(th0 - th);
  325. s1 = sin(th - th1);
  326. c1 = cos(th - th1);
  327. det = 1 / (s0 * c1 + s1 * c0);
  328. s = s0 * s1 * det;
  329. c = c0 * s1 * det;
  330. quad[0] = x0;
  331. quad[1] = y0;
  332. quad[2] = x0 + (x1 - x0) * c - (y1 - y0) * s;
  333. quad[3] = y0 + (y1 - y0) * c + (x1 - x0) * s;
  334. quad[4] = x1;
  335. quad[5] = y1;
  336. }
  337. void
  338. cornu_seg_to_quad(double t0, double t1, const double aff[6], bezctx *bc)
  339. {
  340. double x0, y0;
  341. double x1, y1;
  342. double th0 = t0 * t0;
  343. double th1 = t1 * t1;
  344. double quad[6];
  345. double qx1, qy1, qx2, qy2;
  346. eval_cornu(t0, &y0, &x0);
  347. eval_cornu(t1, &y1, &x1);
  348. fit_quadratic(x0, y0, th0, x1, y1, th1, quad);
  349. affine_pt(aff, quad[2], quad[3], &qx1, &qy1);
  350. affine_pt(aff, quad[4], quad[5], &qx2, &qy2);
  351. bezctx_quadto(bc, qx1, qy1, qx2, qy2);
  352. }
  353. void
  354. cornu_seg_to_bpath(double t0, double t1, const double aff[6],
  355. bezctx *bc, double tol)
  356. {
  357. double tm;
  358. if ((t0 < 0 && t1 > 0) || (t1 < 0 && t0 > 0))
  359. tm = 0;
  360. else {
  361. if (fabs(t0 * t0 - t1 * t1) < 1.5 &&
  362. est_cornu_error(t0, t1) < tol) {
  363. cornu_seg_to_quad(t0, t1, aff, bc);
  364. return;
  365. }
  366. #if 0
  367. if (fabs(t0 - t1) < 1e-6) {
  368. printf("DIVERGENCE!\007\n");
  369. return;
  370. }
  371. #endif
  372. tm = (t0 + t1) * .5;
  373. }
  374. cornu_seg_to_bpath(t0, tm, aff, bc, tol);
  375. cornu_seg_to_bpath(tm, t1, aff, bc, tol);
  376. }
  377. void
  378. cornu_to_bpath(const double xs[], const double ys[], const double ths[], int n,
  379. bezctx *bc, double tol, int closed, int kt0, int n_kt)
  380. {
  381. int i;
  382. for (i = 0; i < n - 1 + closed; i++) {
  383. double x0 = xs[i], y0 = ys[i];
  384. int ip1 = (i + 1) % n;
  385. double x1 = xs[ip1], y1 = ys[ip1];
  386. double th = atan2(y1 - y0, x1 - x0);
  387. double th0 = mod_2pi(ths[i] - th);
  388. double th1 = mod_2pi(th - ths[ip1]);
  389. double t0, t1;
  390. double s0, c0, s1, c1;
  391. double chord_th, chordlen, rot, scale;
  392. double aff[6], aff2[6];
  393. double flip = -1;
  394. th1 += 1e-6;
  395. if (th1 < th0) {
  396. double tmp = th0;
  397. th0 = th1;
  398. th1 = tmp;
  399. flip = 1;
  400. }
  401. fit_cornu_half(th0, th1, &t0, &t1, NULL, NULL);
  402. if (flip == 1) {
  403. double tmp = t0;
  404. t0 = t1;
  405. t1 = tmp;
  406. }
  407. eval_cornu(t0, &s0, &c0);
  408. s0 *= flip;
  409. eval_cornu(t1, &s1, &c1);
  410. s1 *= flip;
  411. chord_th = atan2(s1 - s0, c1 - c0);
  412. chordlen = hypot(s1 - s0, c1 - c0);
  413. rot = th - chord_th;
  414. scale = hypot(y1 - y0, x1 - x0) / chordlen;
  415. aff[0] = 1;
  416. aff[1] = 0;
  417. aff[2] = 0;
  418. aff[3] = flip;
  419. aff[4] = -c0;
  420. aff[5] = -s0;
  421. aff2[0] = scale * cos(rot);
  422. aff2[1] = scale * sin(rot);
  423. aff2[2] = -aff2[1];
  424. aff2[3] = aff2[0];
  425. aff2[4] = x0;
  426. aff2[5] = y0;
  427. affine_multiply(aff, aff, aff2);
  428. bezctx_mark_knot(bc, (kt0 + i) % n_kt);
  429. cornu_seg_to_bpath(t0, t1, aff, bc, tol / scale);
  430. }
  431. }
  432. /* fit arc to pts (0, 0), (x, y), and (1, 0), return th tangent to
  433. arc at (x, y) */
  434. double fit_arc(double x, double y) {
  435. return atan2(y - 2 * x * y, y * y + x - x * x);
  436. }
  437. void
  438. local_ths(const double xs[], const double ys[], double ths[], int n,
  439. int closed)
  440. {
  441. int i;
  442. for (i = 1 - closed; i < n - 1 + closed; i++) {
  443. int im1 = (i + n - 1) % n;
  444. double x0 = xs[im1];
  445. double y0 = ys[im1];
  446. double x1 = xs[i];
  447. double y1 = ys[i];
  448. int ip1 = (i + 1) % n;
  449. double x2 = xs[ip1];
  450. double y2 = ys[ip1];
  451. double dx = x2 - x0;
  452. double dy = y2 - y0;
  453. double ir2 = dx * dx + dy * dy;
  454. double x = ((x1 - x0) * dx + (y1 - y0) * dy) / ir2;
  455. double y = ((y1 - y0) * dx - (x1 - x0) * dy) / ir2;
  456. if (dx == 0.0 && dy == 0.0)
  457. ths[i] = 0.0;
  458. else
  459. ths[i] = fit_arc(x, y) + atan2(dy, dx);
  460. }
  461. }
  462. void
  463. endpoint_ths(const double xs[], const double ys[], double ths[], int n)
  464. {
  465. ths[0] = 2 * atan2(ys[1] - ys[0], xs[1] - xs[0]) - ths[1];
  466. ths[n - 1] = 2 * atan2(ys[n - 1] - ys[n - 2], xs[n - 1] - xs[n-2]) - ths[n - 2];
  467. }
  468. void
  469. tweak_ths(const double xs[], const double ys[], double ths[], int n,
  470. double delt, int closed)
  471. {
  472. double *dks = (double *)malloc(sizeof(double) * n);
  473. int i;
  474. double first_k0, last_k1;
  475. for (i = 0; i < n - 1 + closed; i++) {
  476. double x0 = xs[i];
  477. double y0 = ys[i];
  478. int ip1 = (i + 1) % n;
  479. double x1 = xs[ip1];
  480. double y1 = ys[ip1];
  481. double th, th0, th1;
  482. double t0, t1, k0, k1;
  483. double s0, c0, s1, c1;
  484. double scale;
  485. double flip = -1;
  486. if (x0 == x1 && y0 == y1) {
  487. #ifdef VERBOSE
  488. printf("Overlapping points (i=%d)\n", i);
  489. #endif
  490. /* Very naughty, casting off the constness like this. */
  491. ((double*) xs)[i] = x1 = x1 + 1e-6;
  492. }
  493. th = atan2(y1 - y0, x1 - x0);
  494. th0 = mod_2pi(ths[i] - th);
  495. th1 = mod_2pi(th - ths[ip1]);
  496. th1 += 1e-6;
  497. if (th1 < th0) {
  498. double tmp = th0;
  499. th0 = th1;
  500. th1 = tmp;
  501. flip = 1;
  502. }
  503. fit_cornu_half(th0, th1, &t0, &t1, &k0, &k1);
  504. if (flip == 1) {
  505. double tmp = t0;
  506. t0 = t1;
  507. t1 = tmp;
  508. tmp = k0;
  509. k0 = k1;
  510. k1 = tmp;
  511. }
  512. eval_cornu(t0, &s0, &c0);
  513. eval_cornu(t1, &s1, &c1);
  514. scale = 1 / hypot(y1 - y0, x1 - x0);
  515. k0 *= scale;
  516. k1 *= scale;
  517. if (i > 0) dks[i] = k0 - last_k1;
  518. else first_k0 = k0;
  519. last_k1 = k1;
  520. }
  521. if (closed)
  522. dks[0] = first_k0 - last_k1;
  523. for (i = 1 - closed; i < n - 1 + closed; i++) {
  524. int im1 = (i + n - 1) % n;
  525. double x0 = xs[im1];
  526. double y0 = ys[im1];
  527. double x1 = xs[i];
  528. double y1 = ys[i];
  529. int ip1 = (i + 1) % n;
  530. double x2 = xs[ip1];
  531. double y2 = ys[ip1];
  532. double chord1 = hypot(x1 - x0, y1 - y0);
  533. double chord2 = hypot(x2 - x1, y2 - y1);
  534. ths[i] -= delt * dks[i] * chord1 * chord2 / (chord1 + chord2);
  535. }
  536. free(dks);
  537. }
  538. void test_cornu(void)
  539. {
  540. #if 0
  541. int i;
  542. for (i = -10; i < 100; i++) {
  543. double t = 36974 * 1.2533141373155 + i * .1;
  544. double s, c;
  545. eval_cornu(t, &s, &c);
  546. printf("%g %g %g\n", t, s, c);
  547. }
  548. #else
  549. double t0, t1;
  550. fit_cornu_half(0, 1, &t0, &t1, 0, 0);
  551. printf("%g %g\n", t0, t1);
  552. #endif
  553. }