PageRenderTime 41ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/brlcad/tags/rel-7-16-10/src/tab/tabinterp.c

https://bitbucket.org/vrrm/brl-cad-copy-for-fast-history-browsing-in-git
C | 1240 lines | 876 code | 153 blank | 211 comment | 181 complexity | 5e90570afa0a4b0b3b00cea1f636527f MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, LGPL-2.1, Apache-2.0, AGPL-3.0, LGPL-3.0, GPL-3.0, MPL-2.0-no-copyleft-exception, CC-BY-SA-3.0, 0BSD, BSD-3-Clause
  1. /* T A B I N T E R P . C
  2. * BRL-CAD
  3. *
  4. * Copyright (c) 1988-2010 United States Government as represented by
  5. * the U.S. Army Research Laboratory.
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU Lesser General Public License
  9. * version 2.1 as published by the Free Software Foundation.
  10. *
  11. * This program is distributed in the hope that it will be useful, but
  12. * WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with this file; see the file named COPYING for more
  18. * information.
  19. */
  20. /** @file tabinterp.c
  21. *
  22. * This program is the crucial middle step in the key-frame animation
  23. * software.
  24. *
  25. * First, one or more files, on different time scales, are read into
  26. * internal "channels", with FILE and RATE commands.
  27. *
  28. * Next, the TIMES command is given.
  29. *
  30. * Next, a section of those times is interpolated, and multi-channel
  31. * output is produced, on uniform time samples.
  32. *
  33. * This multi-channel output is fed to the next stage to generate
  34. * control scripts, etc.
  35. *
  36. */
  37. #include "common.h"
  38. #include <stdlib.h>
  39. #include <math.h>
  40. #include <string.h>
  41. #include "bio.h"
  42. #include "bu.h"
  43. #include "vmath.h"
  44. #include "bn.h"
  45. #include "raytrace.h"
  46. struct chan {
  47. /* INPUTS */
  48. int c_ilen; /* length of input array */
  49. char *c_itag; /* description of input source */
  50. fastf_t *c_itime; /* input time array */
  51. fastf_t *c_ival; /* input value array */
  52. /* OUTPUTS */
  53. fastf_t *c_oval; /* output value array */
  54. /* FLAGS */
  55. int c_interp; /* linear or spline? */
  56. #define INTERP_STEP 1
  57. #define INTERP_LINEAR 2
  58. #define INTERP_SPLINE 3
  59. #define INTERP_RATE 4
  60. #define INTERP_ACCEL 5
  61. #define INTERP_QUAT 6 /* first chan of 4 that define a quaternion */
  62. #define INTERP_QUAT2 7 /* an additional quaterion chan (2, 3, 4) */
  63. #define INTERP_NEXT 8 /* method to look forward/backward in time */
  64. int c_periodic; /* cyclic end conditions? */
  65. int c_sourcechan; /* index of source chan (QUAT, NEXT) */
  66. int c_offset; /* source offset (NEXT) */
  67. };
  68. extern int bu_optind;
  69. extern char *bu_optarg;
  70. int verbose = 1;
  71. int o_len; /* length of all output arrays */
  72. fastf_t *o_time; /* pointer to output time array */
  73. int fps; /* frames/sec of output */
  74. int nchans; /* number of chan[] elements in use */
  75. int max_chans; /* current size of chan[] array */
  76. struct chan *chan; /* ptr to array of chan structs */
  77. /*
  78. * Returns -
  79. * -1 on error
  80. * 0 if data loaded, and interpolator not yet set.
  81. * 1 if no data, or interpolator already set (message printed)
  82. */
  83. HIDDEN int
  84. chan_not_loaded_or_specified(int ch)
  85. {
  86. if (ch < 0 || ch >= nchans) return -1;
  87. if (chan[ch].c_ilen <= 0) {
  88. bu_log("error: attempt to set interpolation type on unallocated channel %d\n", ch);
  89. return 1;
  90. }
  91. if (chan[ch].c_interp > 0) {
  92. bu_log("error: attempt to modify channel %d which already has interpolation type set\n", ch);
  93. return 1;
  94. }
  95. return 0;
  96. }
  97. /*
  98. * C R E A T E _ C H A N
  99. */
  100. HIDDEN int
  101. create_chan(char *num, int len, char *itag)
  102. {
  103. int n;
  104. n = atoi(num);
  105. if (n < 0) return -1;
  106. if (n >= max_chans) {
  107. int prev = max_chans;
  108. if (max_chans <= 0) {
  109. max_chans = 32;
  110. chan = (struct chan *)bu_calloc(1,
  111. max_chans * sizeof(struct chan),
  112. "chan[]");
  113. } else {
  114. while (n >= max_chans)
  115. max_chans *= 2;
  116. if (verbose) bu_log("reallocating from %d to %d chans\n",
  117. prev, max_chans);
  118. chan = (struct chan *)bu_realloc((char *)chan,
  119. max_chans * sizeof(struct chan),
  120. "chan[]");
  121. memset((char *)(&chan[prev]), 0, (max_chans-prev)*sizeof(struct chan));
  122. }
  123. }
  124. /* Allocate and clear channels */
  125. while (nchans <= n) {
  126. if (chan[nchans].c_ilen > 0) {
  127. bu_log("create_chan: internal error\n");
  128. return -1;
  129. } else {
  130. memset((char *)&chan[nchans++], 0, sizeof(struct chan));
  131. }
  132. }
  133. if (verbose) bu_log("chan %d: %s\n", n, itag);
  134. chan[n].c_ilen = len;
  135. chan[n].c_itag = bu_strdup(itag);
  136. chan[n].c_ival = (fastf_t *)bu_malloc(len * sizeof(fastf_t), "c_ival");
  137. return n;
  138. }
  139. /*
  140. * C M _ F I L E
  141. */
  142. HIDDEN int
  143. cm_file(int argc, char **argv)
  144. {
  145. FILE *fp;
  146. char *file;
  147. char lbuf[512]; /* temporary label buffer */
  148. int *cnum;
  149. int i;
  150. int line;
  151. char **iwords;
  152. int nlines; /* number of lines in input file */
  153. int nwords; /* number of words on each input line */
  154. fastf_t *times;
  155. auto double d;
  156. int errors = 0;
  157. struct bu_vls buf; /* unlimited size input line buffer */
  158. file = argv[1];
  159. if ((fp = fopen(file, "r")) == NULL) {
  160. perror(file);
  161. return 0;
  162. }
  163. /* First step, count number of lines in file */
  164. nlines = 0;
  165. {
  166. int c;
  167. while ((c = fgetc(fp)) != EOF) {
  168. if (c == '\n')
  169. nlines++;
  170. }
  171. }
  172. rewind(fp);
  173. /* Intermediate dynamic memory */
  174. cnum = (int *)bu_malloc(argc * sizeof(int), "cnum[]");
  175. nwords = argc - 1;
  176. iwords = (char **)bu_malloc((nwords+1) * sizeof(char *), "iwords[]");
  177. bu_vls_init(&buf);
  178. /* Retained dynamic memory */
  179. times = (fastf_t *)bu_malloc(nlines * sizeof(fastf_t), "times");
  180. /* Now, create & allocate memory for each chan */
  181. for (i = 1; i < nwords; i++) {
  182. /* See if this column is not wanted */
  183. if (argv[i+1][0] == '-') {
  184. cnum[i] = -1;
  185. continue;
  186. }
  187. snprintf(lbuf, 512, "File '%s', Column %d", file, i);
  188. if ((cnum[i] = create_chan(argv[i+1], nlines, lbuf)) < 0) {
  189. errors = 1;
  190. goto out;
  191. }
  192. /* Share array of times */
  193. chan[cnum[i]].c_itime = times;
  194. }
  195. for (line=0; line < nlines; line++) {
  196. char *bp;
  197. bu_vls_trunc(&buf, 0);
  198. if (bu_vls_gets(&buf, fp) == -1) break;
  199. bp = bu_vls_addr(&buf);
  200. if (bp[0] == '#') {
  201. line--;
  202. nlines--;
  203. for (i = 1; i < nwords; i++) {
  204. if (cnum[i] < 0) continue;
  205. chan[cnum[i]].c_ilen--;
  206. }
  207. continue;
  208. }
  209. i = bu_argv_from_string(iwords, nwords, bp);
  210. if (i != nwords) {
  211. bu_log("File '%s', Line %d: expected %d columns, got %d\n",
  212. file, line, nwords, i);
  213. while (i < nwords) {
  214. iwords[i++] = "0.123456789";
  215. errors++;
  216. }
  217. }
  218. /* Obtain the time from the first column */
  219. sscanf(iwords[0], "%lf", &d);
  220. times[line] = d;
  221. if (line > 0 && times[line-1] > times[line]) {
  222. bu_log("File '%s', Line %d: time sequence error %g > %g\n",
  223. file, line, times[line-1], times[line]);
  224. errors++;
  225. }
  226. /* Obtain the desired values from the remaining columns, and
  227. * assign them to the channels indicated in cnum[]
  228. */
  229. for (i=1; i < nwords; i++) {
  230. if (cnum[i] < 0) continue;
  231. if (sscanf(iwords[i], "%lf", &d) != 1) {
  232. bu_log("File '%s', Line %d: scanf failure on '%s'\n",
  233. file, line, iwords[i]);
  234. d = 0.0;
  235. errors++;
  236. }
  237. chan[cnum[i]].c_ival[line] = d;
  238. }
  239. }
  240. fclose(fp);
  241. /* Free intermediate dynamic memory */
  242. out:
  243. bu_free((char *)cnum, "cnum[]");
  244. bu_free((char *)iwords, "iwords[]");
  245. bu_vls_free(&buf);
  246. if (errors)
  247. return -1; /* abort */
  248. return 0;
  249. }
  250. /*
  251. * P R _ I C H A N S
  252. *
  253. * Print input channel values.
  254. */
  255. HIDDEN void
  256. pr_ichan(int ch)
  257. {
  258. struct chan *cp;
  259. int i;
  260. if (ch < 0 || ch >= nchans) {
  261. bu_log("pr_ichan(%d) out of range\n", ch);
  262. return;
  263. }
  264. cp = &chan[ch];
  265. if (cp->c_itag == (char *)0) cp->c_itag = "_no_file_";
  266. bu_log("--- Channel %d, ilen=%d (%s):\n",
  267. ch, cp->c_ilen, cp->c_itag);
  268. for (i=0; i < cp->c_ilen; i++) {
  269. bu_log(" %g\t%g\n", cp->c_itime[i], cp->c_ival[i]);
  270. }
  271. }
  272. /*
  273. * C M _ I D U M P
  274. *
  275. * Dump the indicated input channels, or all, if none specified.
  276. */
  277. HIDDEN int
  278. cm_idump(int argc, char **argv)
  279. {
  280. int ch;
  281. int i;
  282. if (argc <= 1) {
  283. for (ch=0; ch < nchans; ch++) {
  284. pr_ichan(ch);
  285. }
  286. } else {
  287. for (i = 1; i < argc; i++) {
  288. pr_ichan(atoi(argv[i]));
  289. }
  290. }
  291. return 0;
  292. }
  293. /*
  294. * O U T P U T
  295. */
  296. HIDDEN void
  297. output()
  298. {
  299. int ch;
  300. struct chan *cp;
  301. int t;
  302. if (!o_time) {
  303. bu_log("times command not given, aborting\n");
  304. return;
  305. }
  306. for (t=0; t < o_len; t++) {
  307. printf("%g", o_time[t]);
  308. for (ch=0; ch < nchans; ch++) {
  309. cp = &chan[ch];
  310. if (cp->c_ilen <= 0) {
  311. printf("\t.");
  312. continue;
  313. }
  314. printf("\t%g", cp->c_oval[t]);
  315. }
  316. printf("\n");
  317. }
  318. }
  319. /*
  320. * C M _ T I M E S
  321. */
  322. HIDDEN int
  323. cm_times(int argc, char **argv)
  324. {
  325. double a, b;
  326. int i;
  327. if (argc < 3)
  328. bu_exit(1, "Internal error. Unexpected argument count encountered.");
  329. a = atof(argv[1]);
  330. b = atof(argv[2]);
  331. fps = atoi(argv[3]);
  332. if (a >= b) {
  333. bu_log("times: %g >= %g\n", a, b);
  334. return 0;
  335. }
  336. if (o_len > 0) {
  337. bu_log("times: already specified\n");
  338. return 0; /* ignore */
  339. }
  340. o_len = ((b-a) * fps) + 0.999;
  341. o_len++; /* one final step to reach endpoint */
  342. o_time = (fastf_t *)bu_malloc(o_len * sizeof(fastf_t), "o_time[]");
  343. /*
  344. * Don't use an incremental algorithm, to avoid acrueing error
  345. */
  346. for (i=0; i<o_len; i++)
  347. o_time[i] = a + ((double)i)/fps;
  348. return 0;
  349. }
  350. /*
  351. * C M _ I N T E R P
  352. */
  353. HIDDEN int
  354. cm_interp(int argc, char **argv)
  355. {
  356. int interp = 0;
  357. int periodic = 0;
  358. int i;
  359. int ch;
  360. struct chan *chp;
  361. if (strcmp(argv[1], "step") == 0) {
  362. interp = INTERP_STEP;
  363. periodic = 0;
  364. } else if (strcmp(argv[1], "cstep") == 0) {
  365. interp = INTERP_STEP;
  366. periodic = 1;
  367. } else if (strcmp(argv[1], "linear") == 0) {
  368. interp = INTERP_LINEAR;
  369. periodic = 0;
  370. } else if (strcmp(argv[1], "clinear") == 0) {
  371. interp = INTERP_LINEAR;
  372. periodic = 1;
  373. } else if (strcmp(argv[1], "spline") == 0) {
  374. interp = INTERP_SPLINE;
  375. periodic = 0;
  376. } else if (strcmp(argv[1], "cspline") == 0) {
  377. interp = INTERP_SPLINE;
  378. periodic = 1;
  379. } else if (strcmp(argv[1], "quat") == 0) {
  380. interp = INTERP_QUAT;
  381. periodic = 0;
  382. } else {
  383. bu_log("interpolation type '%s' unknown\n", argv[1]);
  384. interp = INTERP_LINEAR;
  385. }
  386. for (i = 2; i < argc; i++) {
  387. ch = atoi(argv[i]);
  388. chp = &chan[ch];
  389. if (chan_not_loaded_or_specified(ch)) continue;
  390. chp->c_interp = interp;
  391. chp->c_periodic = periodic;
  392. if (interp == INTERP_QUAT) {
  393. int j;
  394. for (j = 1; j < 4; j++) {
  395. chp = &chan[ch+j];
  396. if (chan_not_loaded_or_specified(ch+j)) continue;
  397. chp->c_interp = INTERP_QUAT2;
  398. chp->c_periodic = periodic;
  399. chp->c_sourcechan = ch;
  400. }
  401. }
  402. }
  403. return 0;
  404. }
  405. /*
  406. * N E X T _ I N T E R P O L A T E
  407. */
  408. HIDDEN void
  409. next_interpolate(struct chan *chp)
  410. {
  411. int t; /* output time index */
  412. int i; /* input time index */
  413. struct chan *ip;
  414. ip = &chan[chp->c_sourcechan];
  415. for (t=0; t<o_len; t++) {
  416. i = t + chp->c_offset;
  417. if (i <= 0) {
  418. chp->c_oval[t] = ip->c_oval[0];
  419. continue;
  420. }
  421. if (i >= o_len) {
  422. chp->c_oval[t] = ip->c_oval[o_len-1];
  423. continue;
  424. }
  425. chp->c_oval[t] = ip->c_oval[i];
  426. }
  427. }
  428. /*
  429. * S T E P _ I N T E R P O L A T E
  430. *
  431. * Simply select the value at the beinning of the interval. This
  432. * allows parameters to take instantaneous jumps in value at specified
  433. * times.
  434. *
  435. * This routine takes advantage of (and depends on) the fact that the
  436. * input and output is sorted in increasing time values.
  437. */
  438. HIDDEN void
  439. step_interpolate(struct chan *chp, fastf_t *times)
  440. {
  441. int t; /* output time index */
  442. int i; /* input time index */
  443. i = 0;
  444. for (t=0; t<o_len; t++) {
  445. /* Check for below initial time */
  446. if (times[t] < chp->c_itime[0]) {
  447. chp->c_oval[t] = chp->c_ival[0];
  448. continue;
  449. }
  450. /* Find time range in input data. */
  451. while (i < chp->c_ilen-1) {
  452. if (times[t] >= chp->c_itime[i] &&
  453. times[t] < chp->c_itime[i+1])
  454. break;
  455. i++;
  456. }
  457. /* Check for above final time */
  458. if (i >= chp->c_ilen-1) {
  459. chp->c_oval[t] = chp->c_ival[chp->c_ilen-1];
  460. continue;
  461. }
  462. /* Select value at beginning of interval */
  463. chp->c_oval[t] = chp->c_ival[i];
  464. }
  465. }
  466. /*
  467. * L I N E A R _ I N T E R P O L A T E
  468. *
  469. * This routine takes advantage of (and depends on) the fact that the
  470. * input and output arrays are sorted in increasing time values.
  471. */
  472. HIDDEN void
  473. linear_interpolate(struct chan *chp, fastf_t *times)
  474. {
  475. int t; /* output time index */
  476. int i; /* input time index */
  477. if (chp->c_ilen < 2) {
  478. bu_log("lienar_interpolate: need at least 2 points\n");
  479. return;
  480. }
  481. i = 0;
  482. for (t=0; t<o_len; t++) {
  483. /* Check for below initial time */
  484. if (times[t] < chp->c_itime[0]) {
  485. chp->c_oval[t] = chp->c_ival[0];
  486. continue;
  487. }
  488. /* Find time range in input data. */
  489. while (i < chp->c_ilen-1) {
  490. if (times[t] >= chp->c_itime[i] &&
  491. times[t] < chp->c_itime[i+1])
  492. break;
  493. i++;
  494. }
  495. /* Check for above final time */
  496. if (i >= chp->c_ilen-1) {
  497. chp->c_oval[t] = chp->c_ival[chp->c_ilen-1];
  498. continue;
  499. }
  500. /* Perform actual interpolation */
  501. chp->c_oval[t] = chp->c_ival[i] +
  502. (times[t] - chp->c_itime[i]) *
  503. (chp->c_ival[i+1] - chp->c_ival[i]) /
  504. (chp->c_itime[i+1] - chp->c_itime[i]);
  505. }
  506. }
  507. /*
  508. * R A T E _ I N T E R P O L A T E
  509. *
  510. * The one (and only) input value is interpreted as rate, in
  511. * unspecified units per second. This is really just a hack to allow
  512. * multiplying the time by a constant.
  513. */
  514. HIDDEN void
  515. rate_interpolate(struct chan *chp, fastf_t *times)
  516. {
  517. int t; /* output time index */
  518. double ival;
  519. double rate;
  520. times = times; /* quell warning */
  521. if (chp->c_ilen != 2) {
  522. bu_log("rate_interpolate: only 2 points (ival & rate) may be specified\n");
  523. return;
  524. }
  525. ival = chp->c_ival[0];
  526. rate = chp->c_ival[1];
  527. for (t=0; t < o_len; t++) {
  528. chp->c_oval[t] = ival + rate * t;
  529. }
  530. }
  531. /*
  532. * A C C E L _ I N T E R P O L A T E
  533. *
  534. */
  535. HIDDEN void
  536. accel_interpolate(struct chan *chp, fastf_t *times)
  537. {
  538. int t; /* output time index */
  539. double ival;
  540. double mul;
  541. double scale;
  542. times = times; /* quell warning */
  543. if (chp->c_ilen != 2) {
  544. bu_log("accel_interpolate: only 2 points (ival & mul) may be specified\n");
  545. return;
  546. }
  547. ival = chp->c_ival[0];
  548. mul = chp->c_ival[1];
  549. /* scale ^ fps = mul */
  550. scale = exp(log(mul) / fps);
  551. chp->c_oval[0] = ival;
  552. for (t=1; t < o_len; t++) {
  553. chp->c_oval[t] = chp->c_oval[t-1] * scale;
  554. }
  555. }
  556. /*
  557. * Q U A T _ I N T E R P O L A T E
  558. *
  559. * Do linear interpolation for first and last span. Use Bezier
  560. * interpolation for all the rest.
  561. *
  562. * This routine depends on the four input channels having identical
  563. * time stamps, because only the "x" input times are used.
  564. */
  565. HIDDEN void
  566. quat_interpolate(struct chan *x, struct chan *y, struct chan *z, struct chan *w, fastf_t *times)
  567. {
  568. int t; /* output time index */
  569. int i; /* input time index */
  570. #define QIGET(_q, _it) QSET((_q), x->c_ival[(_it)], y->c_ival[(_it)], z->c_ival[(_it)], w->c_ival[(_it)]);
  571. #define QPUT(_q) { x->c_oval[t] = (_q)[X]; y->c_oval[t] = (_q)[Y]; \
  572. z->c_oval[t] = (_q)[Z]; w->c_oval[t] = (_q)[W]; }
  573. i = 0;
  574. for (t=0; t<o_len; t++) {
  575. fastf_t now = times[t];
  576. /* Check for below initial time */
  577. if (now <= x->c_itime[0]) {
  578. quat_t q1;
  579. QIGET(q1, 0);
  580. QUNITIZE(q1);
  581. QPUT(q1);
  582. continue;
  583. }
  584. /* Find time range in input data. */
  585. while (i < x->c_ilen-1) {
  586. if (now >= x->c_itime[i] &&
  587. now < x->c_itime[i+1])
  588. break;
  589. i++;
  590. }
  591. /* Check for above final time */
  592. if (i >= x->c_ilen-1) {
  593. quat_t q1;
  594. i = x->c_ilen-1;
  595. QIGET(q1, i);
  596. QUNITIZE(q1);
  597. QPUT(q1);
  598. continue;
  599. }
  600. /* Check for being in first or last time span */
  601. if (i == 0 || i >= x->c_ilen-2)
  602. {
  603. fastf_t f;
  604. quat_t qout, q1, q2, q3, qtemp1, qtemp2, qtemp3;
  605. f = (now - x->c_itime[i]) /
  606. (x->c_itime[i+1] - x->c_itime[i]);
  607. if (i==0)
  608. {
  609. QIGET(q1, i);
  610. QIGET(q2, i+1);
  611. QIGET(q3, i+2);
  612. QUNITIZE(q1);
  613. QUNITIZE(q2);
  614. QUNITIZE(q3);
  615. quat_make_nearest(q2, q1);
  616. quat_make_nearest(q3, q2);
  617. }
  618. else
  619. {
  620. QIGET(q1, i+1);
  621. QIGET(q2, i);
  622. QIGET(q3, i-1);
  623. f = 1.0 - f;
  624. QUNITIZE(q1);
  625. QUNITIZE(q2);
  626. QUNITIZE(q3);
  627. quat_make_nearest(q2, q3);
  628. quat_make_nearest(q1, q2);
  629. }
  630. /* find middle control point */
  631. quat_slerp(qtemp1, q3, q2, 2.0);
  632. quat_slerp(qtemp2, qtemp1, q1, 0.5);
  633. quat_slerp(qtemp3, q2, qtemp2, 0.33333);
  634. /* do 3-point bezier interpolation */
  635. quat_slerp(qtemp1, q1, qtemp3, f);
  636. quat_slerp(qtemp2, qtemp3, q2, f);
  637. quat_slerp(qout, qtemp1, qtemp2, f);
  638. QPUT(qout);
  639. continue;
  640. }
  641. /* In an intermediate time span */
  642. {
  643. fastf_t f;
  644. quat_t qout, q1, q2, q3, q4, qa, qb, qtemp1, qtemp2;
  645. f = (now - x->c_itime[i]) /
  646. (x->c_itime[i+1] - x->c_itime[i]);
  647. QIGET(q1, i-1);
  648. QIGET(q2, i);
  649. QIGET(q3, i+1);
  650. QIGET(q4, i+2);
  651. QUNITIZE(q1);
  652. QUNITIZE(q2);
  653. QUNITIZE(q3);
  654. QUNITIZE(q4);
  655. quat_make_nearest(q2, q1);
  656. quat_make_nearest(q3, q2);
  657. quat_make_nearest(q4, q3);
  658. /* find two middle control points */
  659. quat_slerp(qtemp1, q1, q2, 2.0);
  660. quat_slerp(qtemp2, qtemp1, q3, 0.5);
  661. quat_slerp(qa, q2, qtemp2, 0.333333);
  662. quat_slerp(qtemp1, q4, q3, 2.0);
  663. quat_slerp(qtemp2, qtemp1, q2, 0.5);
  664. quat_slerp(qb, q3, qtemp2, 0.333333);
  665. quat_sberp(qout, q2, qa, qb, q3, f);
  666. QPUT(qout);
  667. }
  668. }
  669. }
  670. /*
  671. * S P L I N E
  672. *
  673. * Fit an interpolating spline to the data points given. Time in the
  674. * independent (x) variable, and the single channel of data values is
  675. * the dependent (y) variable.
  676. *
  677. * Returns -
  678. * 0 bad
  679. * 1 OK
  680. */
  681. HIDDEN int
  682. spline(struct chan *chp, fastf_t *times)
  683. {
  684. double d, s;
  685. double u = 0;
  686. double v = 0;
  687. double hi; /* horiz interval i-1 to i */
  688. double hi1; /* horiz interval i to i+1 */
  689. double D2yi; /* D2 of y[i] */
  690. double D2yi1; /* D2 of y[i+1] */
  691. double D2yn1; /* D2 of y[n-1] (last point) */
  692. double a;
  693. int end;
  694. double corr;
  695. double konst = 0.0; /* derriv. at endpts, non-periodic */
  696. double *diag = (double *)0;
  697. double *rrr = (double *)0;
  698. int i;
  699. int t;
  700. if (chp->c_ilen<3) {
  701. bu_log("spline(%s): need at least 3 points\n", chp->c_itag);
  702. goto bad;
  703. }
  704. /* First, as a quick hack, do linear interpolation to fill in
  705. * values off the endpoints, in non-periodic case
  706. */
  707. if (chp->c_periodic == 0)
  708. linear_interpolate(chp, times);
  709. if (chp->c_periodic
  710. && !NEAR_ZERO(chp->c_ival[0] - chp->c_ival[chp->c_ilen-1], SMALL_FASTF))
  711. {
  712. bu_log("spline(%s): endpoints don't match, replacing final data value\n", chp->c_itag);
  713. chp->c_ival[chp->c_ilen-1] = chp->c_ival[0];
  714. }
  715. i = (chp->c_ilen+1)*sizeof(double);
  716. diag = (double *)bu_malloc((unsigned)i, "diag");
  717. rrr = (double *)bu_malloc((unsigned)i, "rrr");
  718. if (!rrr || !diag) {
  719. bu_log("spline: malloc failure\n");
  720. goto bad;
  721. }
  722. if (chp->c_periodic) konst = 0;
  723. d = 1;
  724. rrr[0] = 0;
  725. s = chp->c_periodic?-1:0;
  726. /* triangularize */
  727. for (i=0; ++i < chp->c_ilen - !chp->c_periodic;) {
  728. double rhs;
  729. hi = chp->c_itime[i]-chp->c_itime[i-1];
  730. hi1 = (i==chp->c_ilen-1) ?
  731. chp->c_itime[1] - chp->c_itime[0] :
  732. chp->c_itime[i+1] - chp->c_itime[i];
  733. if (hi1*hi<=0) {
  734. bu_log(
  735. "spline: Horiz. interval changed sign at i=%d, time=%g\n",
  736. i, chp->c_itime[i]);
  737. goto bad;
  738. }
  739. if (i <= 1) {
  740. u = v = 0.0; /* First time through */
  741. } else {
  742. u = u - s * s / d;
  743. v = v - s * rrr[i-1] / d;
  744. }
  745. rhs = (i==chp->c_ilen-1) ?
  746. (chp->c_ival[1] - chp->c_ival[0]) /
  747. (chp->c_itime[1] - chp->c_itime[0]) :
  748. (chp->c_ival[i+1] - chp->c_ival[i]) /
  749. (chp->c_itime[i+1] - chp->c_itime[i]);
  750. rhs = 6 * (rhs -
  751. ((chp->c_ival[i] - chp->c_ival[i-1]) /
  752. (chp->c_itime[i] - chp->c_itime[i-1])));
  753. rrr[i] = rhs - hi * rrr[i-1] / d;
  754. s = -hi*s/d;
  755. a = 2*(hi+hi1);
  756. if (i==1) a += konst*hi;
  757. if (i==chp->c_ilen-2) a += konst*hi1;
  758. diag[i] = d = i==1? a:
  759. a - hi*hi/d;
  760. }
  761. D2yi = D2yn1 = 0;
  762. /* back substitute */
  763. for (i = chp->c_ilen - !chp->c_periodic; --i >= 0;) {
  764. end = i==chp->c_ilen-1;
  765. /* hi1 is range of time covered in this interval */
  766. hi1 = end ? chp->c_itime[1] - chp->c_itime[0]:
  767. chp->c_itime[i+1] - chp->c_itime[i];
  768. D2yi1 = D2yi;
  769. if (i>0) {
  770. hi = chp->c_itime[i]-chp->c_itime[i-1];
  771. corr = end ? 2*s+u : 0.0;
  772. D2yi = (end*v+rrr[i]-hi1*D2yi1-s*D2yn1)/
  773. (diag[i]+corr);
  774. if (end) D2yn1 = D2yi;
  775. if (i>1) {
  776. a = 2*(hi+hi1);
  777. if (i==1) a += konst*hi;
  778. if (i==chp->c_ilen-2) a += konst*hi1;
  779. d = diag[i-1];
  780. s = -s*d/hi;
  781. }
  782. }
  783. else D2yi = D2yn1;
  784. if (!chp->c_periodic) {
  785. if (i==0) D2yi = konst*D2yi1;
  786. if (i==chp->c_ilen-2) D2yi1 = konst*D2yi;
  787. }
  788. if (end) continue;
  789. /* Sweep downward in times[], looking for times in this span */
  790. for (t=o_len-1; t>=0; t--) {
  791. double x0; /* fraction from [i+0] */
  792. double x1; /* fraction from [i+1] */
  793. double yy;
  794. double cur_t;
  795. cur_t = times[t];
  796. if (cur_t > chp->c_itime[i+1])
  797. continue;
  798. if (cur_t < chp->c_itime[i])
  799. continue;
  800. x1 = (cur_t - chp->c_itime[i]) /
  801. (chp->c_itime[i+1] - chp->c_itime[i]);
  802. x0 = 1 - x1;
  803. /* Linear interpolation, with correction */
  804. yy = D2yi * (x0 - x0*x0*x0) + D2yi1 * (x1 - x1*x1*x1);
  805. yy = chp->c_ival[i] * x0 + chp->c_ival[i+1] * x1 -
  806. hi1 * hi1 * yy / 6;
  807. chp->c_oval[t] = yy;
  808. }
  809. }
  810. bu_free((char *)diag, "diag");
  811. bu_free((char *)rrr, "rrr");
  812. return 1;
  813. bad:
  814. if (diag) bu_free((char *)diag, "diag");
  815. if (rrr) bu_free((char *)rrr, "rrr");
  816. return 0;
  817. }
  818. /*
  819. * G O
  820. *
  821. * Perform the requested interpolation on each channel
  822. */
  823. HIDDEN void
  824. go()
  825. {
  826. int ch;
  827. struct chan *chp;
  828. fastf_t *times;
  829. int t;
  830. if (!o_time) {
  831. bu_log("times command not given\n");
  832. return;
  833. }
  834. times = (fastf_t *)bu_malloc(o_len*sizeof(fastf_t), "periodic times");
  835. /* First, get memory for all output channels */
  836. for (ch=0; ch < nchans; ch++) {
  837. chp = &chan[ch];
  838. if (chp->c_ilen <= 0)
  839. continue;
  840. /* Allocate memory for all the output values */
  841. chan[ch].c_oval = (fastf_t *)bu_malloc(
  842. o_len * sizeof(fastf_t), "c_oval[]");
  843. }
  844. /* Interpolate values for all "interp" channels */
  845. for (ch=0; ch < nchans; ch++) {
  846. chp = &chan[ch];
  847. if (chp->c_ilen <= 0)
  848. continue;
  849. if (chp->c_interp == INTERP_NEXT) continue;
  850. /* As a service to interpolators, if this is a periodic
  851. * interpolation, build the mapped time array.
  852. */
  853. if (chp->c_periodic) {
  854. for (t=0; t < o_len; t++) {
  855. double cur_t;
  856. cur_t = o_time[t];
  857. while (cur_t > chp->c_itime[chp->c_ilen-1]) {
  858. cur_t -= (chp->c_itime[chp->c_ilen-1] -
  859. chp->c_itime[0]);
  860. }
  861. while (cur_t < chp->c_itime[0]) {
  862. cur_t += (chp->c_itime[chp->c_ilen-1] -
  863. chp->c_itime[0]);
  864. }
  865. times[t] = cur_t;
  866. }
  867. } else {
  868. for (t=0; t < o_len; t++) {
  869. times[t] = o_time[t];
  870. }
  871. }
  872. again:
  873. switch (chp->c_interp) {
  874. default:
  875. bu_log("channel %d: unknown interpolation type %d\n", ch, chp->c_interp);
  876. break;
  877. case INTERP_LINEAR:
  878. linear_interpolate(chp, times);
  879. break;
  880. case INTERP_STEP:
  881. step_interpolate(chp, times);
  882. break;
  883. case INTERP_SPLINE:
  884. if (spline(chp, times) <= 0) {
  885. bu_log("spline failure, switching to linear\n");
  886. chp->c_interp = INTERP_LINEAR;
  887. goto again;
  888. }
  889. break;
  890. case INTERP_RATE:
  891. rate_interpolate(chp, times);
  892. break;
  893. case INTERP_ACCEL:
  894. accel_interpolate(chp, times);
  895. break;
  896. case INTERP_QUAT:
  897. quat_interpolate(chp, &chan[ch+1], &chan[ch+2], &chan[ch+3], times);
  898. break;
  899. case INTERP_QUAT2:
  900. /* Don't touch these here, handled above */
  901. continue;
  902. }
  903. }
  904. /* Copy out values for all "next" channels */
  905. for (ch=0; ch < nchans; ch++) {
  906. chp = &chan[ch];
  907. if (chp->c_ilen <= 0)
  908. continue;
  909. if (chp->c_interp != INTERP_NEXT) continue;
  910. next_interpolate(chp);
  911. }
  912. bu_free((char *)times, "loc times");
  913. }
  914. /*
  915. * C M _ R A T E
  916. *
  917. * Just to communiate with the "interpolator", use two input values.
  918. * First is initial value, second is change PER SECOND. Input time
  919. * values are meaningless.
  920. */
  921. HIDDEN int
  922. cm_rate(int argc, char **argv)
  923. {
  924. struct chan *chp;
  925. int ch;
  926. int nvals = 2;
  927. ch = create_chan(argv[1], nvals, argc>4?argv[4]:"rate chan");
  928. chp = &chan[ch];
  929. chp->c_interp = INTERP_RATE;
  930. chp->c_periodic = 0;
  931. chp->c_itime = (fastf_t *)bu_malloc(nvals * sizeof(fastf_t), "rate times");
  932. chp->c_itime[0] = chp->c_itime[1] = 0;
  933. chp->c_ival[0] = atof(argv[2]);
  934. chp->c_ival[1] = atof(argv[3]);
  935. return 0;
  936. }
  937. /*
  938. * C M _ A C C E L
  939. *
  940. * Just to communiate with the "interpolator", use two input values.
  941. * First is initial value, second is change PER SECOND. Input time
  942. * values are meaningless.
  943. */
  944. HIDDEN int
  945. cm_accel(int argc, char **argv)
  946. {
  947. struct chan *chp;
  948. int ch;
  949. int nvals = 2;
  950. ch = create_chan(argv[1], nvals, argc>4?argv[4]:"accel chan");
  951. chp = &chan[ch];
  952. chp->c_interp = INTERP_ACCEL;
  953. chp->c_periodic = 0;
  954. chp->c_itime = (fastf_t *)bu_malloc(nvals * sizeof(fastf_t), "accel times");
  955. chp->c_itime[0] = chp->c_itime[1] = 0;
  956. chp->c_ival[0] = atof(argv[2]);
  957. chp->c_ival[1] = atof(argv[3]);
  958. return 0;
  959. }
  960. HIDDEN int
  961. cm_next(int argc, char **argv)
  962. {
  963. int ochan, ichan;
  964. int offset = 1;
  965. char buf[128];
  966. ochan = atoi(argv[1]);
  967. ichan = atoi(argv[2]);
  968. if (argc > 3) offset = atoi(argv[3]);
  969. /* If input channel not loaded, or not interpolated, error */
  970. if (chan[ichan].c_ilen <= 0 || chan[ichan].c_interp <= 0) {
  971. bu_log("ERROR next: ichan %d not loaded yet\n", ichan);
  972. return 0;
  973. }
  974. /* If output channel is loaded, error */
  975. if (chan[ochan].c_ilen > 0) {
  976. bu_log("ERROR next: ochan %d previous loaded\n", ochan);
  977. return 0;
  978. }
  979. sprintf(buf, "next: value of chan %d [%d]", ichan, offset);
  980. if (create_chan(argv[1], chan[ichan].c_ilen, buf) < 0) {
  981. bu_log("ERROR next: uanble to create output channel\n");
  982. return 0;
  983. }
  984. /* c_ilen, c_itag, c_ival are now initialized */
  985. chan[ochan].c_interp = INTERP_NEXT;
  986. chan[ochan].c_sourcechan = ichan;
  987. chan[ochan].c_offset = offset;
  988. chan[ochan].c_periodic = 0;
  989. chan[ochan].c_itime = chan[ichan].c_itime; /* share time array */
  990. /* c_ival[] will not be loaded with anything */
  991. return 0;
  992. }
  993. #define OPT_STR "q"
  994. HIDDEN int
  995. get_args(int argc, char **argv)
  996. {
  997. int c;
  998. while ((c=bu_getopt(argc, argv, OPT_STR)) != EOF) {
  999. switch (c) {
  1000. case 'q':
  1001. verbose = 0;
  1002. break;
  1003. default:
  1004. fprintf(stderr, "Unknown option: -%c\n", c);
  1005. return 0;
  1006. }
  1007. }
  1008. return 1;
  1009. }
  1010. HIDDEN int cm_help(int argc, char **argv);
  1011. struct command_tab cmdtab[] = {
  1012. {"file", "filename chan_num(s)", "load channels from file",
  1013. cm_file, 3, 999},
  1014. {"times", "start stop fps", "specify time range and fps rate",
  1015. cm_times, 4, 4},
  1016. {"interp", "{step|linear|spline|cspline|quat} chan_num(s)", "set interpolation type",
  1017. cm_interp, 3, 999},
  1018. {"next", "dest_chan src_chan [+/- #nsamp]", "lookahead in time",
  1019. cm_next, 3, 4},
  1020. {"idump", "[chan_num(s)]", "dump input channel values",
  1021. cm_idump, 1, 999},
  1022. {"rate", "chan_num init_value incr_per_sec [comment]", "create rate based channel",
  1023. cm_rate, 4, 5},
  1024. {"accel", "chan_num init_value mult_per_sec [comment]", "create acceleration based channel",
  1025. cm_accel, 4, 5},
  1026. {"help", "", "print help message",
  1027. cm_help, 1, 999},
  1028. {(char *)0, (char *)0, (char *)0,
  1029. 0, 0, 0} /* END */
  1030. };
  1031. /*
  1032. * XXX this really should go in librt/cmd.c as rt_help_cmd().
  1033. */
  1034. HIDDEN int
  1035. cm_help(int argc, char **argv)
  1036. {
  1037. struct command_tab *ctp;
  1038. if (argc <= 1) {
  1039. bu_log("The following commands are available:\n\n");
  1040. for (ctp = cmdtab; ctp->ct_cmd != (char *)0; ctp++) {
  1041. bu_log("%s %s\n\t%s\n",
  1042. ctp->ct_cmd, ctp->ct_parms,
  1043. ctp->ct_comment);
  1044. }
  1045. return 0;
  1046. }
  1047. bu_log("%s: Detailed help is not yet available.\n", argv[0]);
  1048. return -1;
  1049. }
  1050. /*
  1051. * M A I N
  1052. */
  1053. int
  1054. main(int argc, char *argv[])
  1055. {
  1056. char *buf;
  1057. int ret;
  1058. get_args(argc, argv);
  1059. /*
  1060. * All the work happens in the functions called by rt_do_cmd().
  1061. * NOTE that the value of MAXWORDS in rt_do_cmd() limits the
  1062. * maximum number of columns that a 'file' command can list.
  1063. */
  1064. while ((buf = rt_read_cmd(stdin)) != (char *)0) {
  1065. if (verbose) bu_log("cmd: %s\n", buf);
  1066. ret = rt_do_cmd(0, buf, cmdtab);
  1067. bu_free(buf, "cmd buf");
  1068. if (ret < 0) {
  1069. if (verbose) bu_log("aborting\n");
  1070. bu_exit(1, NULL);
  1071. }
  1072. }
  1073. if (verbose) bu_log("performing interpolations\n");
  1074. go();
  1075. if (verbose) bu_log("writing output\n");
  1076. output();
  1077. bu_exit(0, NULL);
  1078. }
  1079. /*
  1080. * Local Variables:
  1081. * mode: C
  1082. * tab-width: 8
  1083. * indent-tabs-mode: t
  1084. * c-file-style: "stroustrup"
  1085. * End:
  1086. * ex: shiftwidth=4 tabstop=8
  1087. */