GRASS GIS 7 Programmer's Manual  7.0.3(2016)-r00000
gk.c
Go to the documentation of this file.
1 
19 #include <stdlib.h>
20 #include <math.h>
21 
22 #include <grass/gis.h>
23 #include <grass/glocale.h>
24 #include <grass/ogsf.h>
25 
26 static float spl3(float, double, double, double, double, double, double,
27  double);
28 
29 static float spl3(float tension, double data0, double data1, double x,
30  double x2, double x3, double lderiv, double rderiv)
31 {
32  return ((float)
33  (data0 * (2 * x3 - 3 * x2 + 1) + data1 * (-2 * x3 + 3 * x2) +
34  (double)tension * lderiv * (x3 - 2 * x2 + x) +
35  (double)tension * rderiv * (x3 - x2)));
36 }
37 
45 Keylist *gk_copy_key(Keylist * k)
46 {
47  Keylist *newk;
48  int i;
49 
50  newk = (Keylist *) G_malloc(sizeof(Keylist)); /* G_fatal_error */
51  if (!newk) {
52  return (NULL);
53  }
54 
55  for (i = 0; i < KF_NUMFIELDS; i++) {
56  newk->fields[i] = k->fields[i];
57  }
58 
59  newk->pos = k->pos;
60  newk->look_ahead = k->look_ahead;
61  newk->fieldmask = k->fieldmask;
62  newk->next = newk->prior = NULL;
63 
64  return (newk);
65 }
66 
79 unsigned long gk_get_mask_sofar(float time, Keylist * keys)
80 {
81  Keylist *k;
82  float startpos, endpos, curpos;
83  unsigned long mask = 0xFFFFFFFF;
84 
85  if (keys) {
86  /* find end key */
87  for (k = keys; k->next; k = k->next) ;
88 
89  startpos = keys->pos;
90  endpos = k->pos;
91  curpos = startpos + time * (endpos - startpos);
92 
93  for (k = keys; k->next; k = k->next) {
94  if (k->pos <= curpos) {
95  mask &= k->fieldmask; /* (else break) */
96  }
97  }
98  }
99 
100  return (mask);
101 }
102 
112 int gk_viable_keys_for_mask(unsigned long mask, Keylist * keys,
113  Keylist ** keyret)
114 {
115  Keylist *k;
116  int cnt = 0;
117 
118  for (k = keys; k; k = k->next) {
119  if ((mask & k->fieldmask) == mask) {
120  keyret[cnt++] = k;
121  }
122  }
123 
124  return (cnt);
125 }
126 
141 void gk_follow_frames(Viewnode * view, int numsteps, Keylist * keys, int step,
142  int onestep, int render, unsigned long mode)
143 {
144  Viewnode *v;
145  int frame; /* frame is index into viewnode array */
146  float tmp[3];
147  float x, y, z;
148  int num, w;
149  unsigned long mask;
150 
151  for (frame = step - 1; frame < numsteps; frame++) {
152 
153  v = &view[frame];
154  mask = gk_get_mask_sofar((float)frame / numsteps, keys);
155 
156  /* TODO?: set view field to current settings if not set,
157  thereby keeping view structure up to date for easier saving of
158  animation? */
159 
160  GS_get_from(tmp);
161  if ((mask & KF_FROMX_MASK)) {
162  tmp[X] = v->fields[KF_FROMX];
163  }
164  if ((mask & KF_FROMY_MASK)) {
165  tmp[Y] = v->fields[KF_FROMY];
166  }
167  if ((mask & KF_FROMZ_MASK)) {
168  tmp[Z] = v->fields[KF_FROMZ];
169  }
170 
171  GS_moveto(tmp);
172 
173  GS_get_from(tmp);
174  G_debug(3, "gk_follow_frames():");
175  G_debug(3, " MASK: %lx", mask);
176  G_debug(3, " FROM: %f %f %f", tmp[X], tmp[Y], tmp[Z]);
177 
178  /* ACS 1 line: was GS_get_focus(tmp);
179  with this kanimator works also for flythrough navigation
180  also changed in GK2.c
181  */
182  GS_get_viewdir(tmp);
183  if ((mask & KF_DIRX_MASK)) {
184  tmp[X] = v->fields[KF_DIRX];
185  }
186  if ((mask & KF_DIRY_MASK)) {
187  tmp[Y] = v->fields[KF_DIRY];
188  }
189  if ((mask & KF_DIRZ_MASK)) {
190  tmp[Z] = v->fields[KF_DIRZ];
191  }
192  /* ACS 1 line: was GS_set_focus(tmp);
193  with this kanimator works also for flythrough navigation
194  also changed in GK2.c
195  */
196  GS_set_viewdir(tmp);
197 
198  G_debug(3, "gk_follow_frames():");
199  GS_get_viewdir(tmp);
200  G_debug(3, " DIR: %f %f %f\n", tmp[X], tmp[Y], tmp[Z]);
201 
202  if ((mask & KF_TWIST_MASK)) {
203  GS_set_twist((int)v->fields[KF_TWIST]);
204  }
205 
206  if ((mask & KF_FOV_MASK)) {
207  GS_set_fov((int)v->fields[KF_FOV]);
208  }
209 
210  /* Initilaize lights before drawing */
211  num = 1;
212  GS_getlight_position(num, &x, &y, &z, &w);
213  GS_setlight_position(num, x, y, z, w);
214  num = 2; /* Top light */
215  GS_setlight_position(num, 0., 0., 1., 0);
216 
217  if (render) {
218  GS_set_draw(GSD_FRONT);
219  }
220  else {
221  GS_set_draw(GSD_BACK);
222  }
223 
224  GS_ready_draw();
226 
227  if (render) {
228  GS_alldraw_surf();
229  }
230  else {
231  GS_alldraw_wire();
232  }
233 
235 
236  if (mode & FM_PATH) {
237  gk_draw_path(view, numsteps, keys);
238  }
239 
240  if (mode & FM_VECT) {
241  GV_alldraw_vect();
242  }
243 
244  if (mode & FM_SITE) {
245  GP_alldraw_site();
246  }
247 
248  if (mode & FM_VOL) {
249  GVL_alldraw_vol();
250  }
251 
252  GS_done_draw();
253 
254  if (mode & FM_LABEL) {
255  GS_draw_all_list(); /* draw labels and legend */
256  }
257 
258  if (onestep) {
259  return;
260  }
261  }
262 
263  return;
264 }
265 
271 void gk_free_key(Keylist * ok)
272 {
273  Keylist *k, *prev;
274 
275  if (ok) {
276  k = ok;
277  while (k) {
278  prev = k;
279  k = k->next;
280  G_free(prev);
281  }
282  }
283 
284  return;
285 }
286 
301 Viewnode *gk_make_framesfromkeys(Keylist * keys, int keysteps, int newsteps,
302  int loop, float t)
303 {
304  int i;
305  Viewnode *v, *newview;
306  Keylist *k, *kp1, *kp2, *km1, **tkeys;
307  float startpos, endpos;
308  double dt1, dt2, x, x2, x3, range, time, time_step, len, rderiv, lderiv;
309 
310  /* allocate tmp keys to hold valid keys for fields */
311  tkeys = (Keylist **) G_malloc(keysteps * sizeof(Keylist *)); /* G_fatal_error */
312  if (!tkeys) {
313  return (NULL);
314  }
315 
316  correct_twist(keys);
317 
318  if (keys && keysteps) {
319  if (keysteps < 3) {
320  G_warning(_("Need at least 3 keyframes for spline"));
321  G_free(tkeys);
322  return (NULL);
323  }
324 
325  /* find end key */
326  for (k = keys; k->next; k = k->next) ;
327 
328  startpos = keys->pos;
329  endpos = k->pos;
330  range = endpos - startpos;
331  time_step = range / (newsteps - 1);
332 
333  newview = (Viewnode *) G_malloc(newsteps * sizeof(Viewnode)); /* G_fatal_error */
334  if (!newview) { /* not used */
335  G_free(tkeys);
336  return (NULL);
337  }
338 
339  for (i = 0; i < newsteps; i++) {
340  int field = 0;
341 
342  v = &newview[i];
343 
344  time = startpos + i * time_step;
345 
346  if (i == newsteps - 1) {
347  time = endpos; /*to ensure no roundoff errors */
348  }
349 
350  for (field = 0; field < KF_NUMFIELDS; field++) {
351  int nvk = 0; /* number of viable keyframes for this field */
352 
353  /* now need to do for each field to look at mask */
354  k = kp1 = kp2 = km1 = NULL;
355  nvk = gk_viable_keys_for_mask((unsigned long)(1 << field),
356  keys, tkeys);
357  if (nvk) {
358  len = get_key_neighbors(nvk, time, range,
359  loop, tkeys, &k, &kp1, &kp2, &km1,
360  &dt1, &dt2);
361  }
362 
363  /* ACS 1 line: was if (len == 0.0) {
364  when disabling a channel no calculation must be made at all (otherwise core dump)
365  */
366  if (len == 0.0 || nvk == 0) {
367  if (!k) {
368  /* none valid - use first.
369  (when showing , will be ignored anyway) */
370  v->fields[field] = keys->fields[field];
371  }
372  else if (!kp1) {
373  /* none on right - use left */
374  v->fields[field] = k->fields[field];
375  }
376 
377  continue;
378  }
379  else if (!km1 && !kp2) {
380  /* only two valid - use linear */
381  v->fields[field] = lin_interp((time - k->pos) / len,
382  k->fields[field],
383  kp1->fields[field]);
384  continue;
385  }
386 
387  x = (time - k->pos) / len;
388  x2 = x * x;
389  x3 = x2 * x;
390 
391  if (!km1) {
392  /* leftmost interval */
393  rderiv = (kp2->fields[field] - k->fields[field]) / dt2;
394  lderiv = (3 * (kp1->fields[field] -
395  k->fields[field]) / dt1 - rderiv) / 2.0;
396  v->fields[field] = spl3(t, k->fields[field],
397  kp1->fields[field], x, x2, x3,
398  lderiv, rderiv);
399  }
400  else if (!kp2) {
401  /* rightmost interval */
402  lderiv = (kp1->fields[field] - km1->fields[field]) / dt1;
403  rderiv = (3 * (kp1->fields[field] -
404  k->fields[field]) / dt2 - lderiv) / 2.0;
405  v->fields[field] = spl3(t, k->fields[field],
406  kp1->fields[field], x, x2, x3,
407  lderiv, rderiv);
408  }
409  else {
410  /* not on ends */
411  lderiv = (kp1->fields[field] - km1->fields[field]) / dt1;
412  rderiv = (kp2->fields[field] - k->fields[field]) / dt2;
413  v->fields[field] = spl3(t, k->fields[field],
414  kp1->fields[field], x, x2, x3,
415  lderiv, rderiv);
416  }
417  }
418  }
419 
420  G_free(tkeys);
421  return (newview);
422  }
423  else {
424  G_free(tkeys);
425  return (NULL);
426  }
427 }
428 
455 double get_key_neighbors(int nvk, double time, double range, int loop,
456  Keylist * karray[], Keylist ** km1, Keylist ** kp1,
457  Keylist ** kp2, Keylist ** km2, double *dt1,
458  double *dt2)
459 {
460  int i;
461  double len;
462 
463  *km1 = *kp1 = *kp2 = *km2 = NULL;
464  *dt1 = *dt2 = 0.0;
465 
466  for (i = 0; i < nvk; i++) {
467  if (time < karray[i]->pos) {
468  break;
469  }
470  }
471 
472  if (!i) {
473  return (0.0); /* before first keyframe or nvk == 0 */
474  }
475 
476  if (i == nvk) {
477  /* past or == last keyframe! */
478  *km1 = karray[nvk - 1];
479  return (0.0);
480  }
481 
482  /* there's at least 2 */
483  *km1 = karray[i - 1];
484  *kp1 = karray[i];
485  len = karray[i]->pos - karray[i - 1]->pos;
486 
487  if (i == 1) {
488  /* first interval */
489  if (loop) {
490  *km2 = karray[nvk - 2];
491  *kp2 = karray[(i + 1) % nvk];
492  }
493  else {
494  if (nvk > 2) {
495  *kp2 = karray[i + 1];
496  }
497  }
498  }
499  else if (i == nvk - 1) {
500  /* last interval */
501  if (loop) {
502  *km2 = nvk > 2 ? karray[i - 2] : karray[1];
503  *kp2 = karray[1];
504  }
505  else {
506  if (nvk > 2) {
507  *km2 = karray[i - 2];
508  }
509  }
510  }
511  else {
512  *km2 = karray[i - 2];
513  *kp2 = karray[i + 1];
514  }
515 
516  *dt1 = (*km2) ? (*kp1)->pos - (*km2)->pos : len;
517  *dt2 = (*kp2) ? (*kp2)->pos - (*km1)->pos : len;
518 
519  if (i == 1 && loop) {
520  *dt1 += range;
521  }
522 
523  if (i == nvk - 1 && loop) {
524  *dt2 += range;
525  }
526 
527  return (len);
528 }
529 
539 double lin_interp(float dt, float val1, float val2)
540 {
541  return ((double)(val1 + dt * (val2 - val1)));
542 }
543 
558 double get_2key_neighbors(int nvk, float time, float range, int loop,
559  Keylist * karray[], Keylist ** km1, Keylist ** kp1)
560 {
561  int i;
562  double len;
563 
564  *km1 = *kp1 = NULL;
565 
566  for (i = 0; i < nvk; i++) {
567  if (time < karray[i]->pos) {
568  break;
569  }
570  }
571 
572  if (!i) {
573  return (0.0); /* before first keyframe or nvk == 0 */
574  }
575 
576  if (i == nvk) {
577  /* past or == last keyframe! */
578  *km1 = karray[nvk - 1];
579  return (0.0);
580  }
581 
582  /* there's at least 2 */
583  *km1 = karray[i - 1];
584  *kp1 = karray[i];
585  len = karray[i]->pos - karray[i - 1]->pos;
586 
587  return (len);
588 }
589 
604 Viewnode *gk_make_linear_framesfromkeys(Keylist * keys, int keysteps,
605  int newsteps, int loop)
606 {
607  int i, nvk;
608  Viewnode *v, *newview;
609  Keylist *k, *k1, *k2, **tkeys;
610  float startpos, endpos, dt, range, time, time_step, len;
611 
612  /* allocate tmp keys to hold valid keys for fields */
613  tkeys = (Keylist **) G_malloc(keysteps * sizeof(Keylist *)); /* G_fatal_error */
614  if (!tkeys) {
615  return (NULL);
616  }
617 
618  correct_twist(keys);
619 
620  if (keys && keysteps) {
621  if (keysteps < 2) {
622  G_warning(_("Need at least 2 keyframes for interpolation"));
623  G_free(tkeys);
624  return (NULL);
625  }
626 
627  /* find end key */
628  for (k = keys; k->next; k = k->next) ;
629 
630  startpos = keys->pos;
631  endpos = k->pos;
632  range = endpos - startpos;
633  time_step = range / (newsteps - 1);
634 
635  newview = (Viewnode *) G_malloc(newsteps * sizeof(Viewnode)); /* G_fatal_error */
636  if (!newview) { /* not used */
637  G_free(tkeys);
638  return (NULL);
639  }
640 
641  for (i = 0; i < newsteps; i++) {
642  int field = 0;
643 
644  v = &newview[i];
645 
646  time = startpos + i * time_step;
647  if (i == newsteps - 1) {
648  time = endpos; /*to ensure no roundoff errors */
649  }
650 
651  for (field = 0; field < KF_NUMFIELDS; field++) {
652 
653  nvk = gk_viable_keys_for_mask((unsigned long)(1 << field),
654  keys, tkeys);
655  if (!nvk) {
656  v->fields[field] = keys->fields[field]; /*default-not used */
657  }
658  else {
659  len = get_2key_neighbors(nvk, time, range, loop,
660  tkeys, &k1, &k2);
661  }
662 
663  /* ACS 1 line: was if (len == 0.0) {
664  when disabling a channel no calculation must be made at all (otherwise core dump)
665  */
666  if (len == 0.0 || nvk == 0) {
667  if (!k1) {
668  /* none valid - use first.
669  (when showing , will be ignored anyway) */
670  v->fields[field] = keys->fields[field];
671  }
672  else if (!k2) {
673  /* none on right - use left */
674  v->fields[field] = k1->fields[field];
675  }
676  }
677  else {
678  dt = (time - k1->pos) / len;
679  v->fields[field] = lin_interp(dt,
680  k1->fields[field],
681  k2->fields[field]);
682  }
683  }
684  }
685 
686  G_free(tkeys);
687  return (newview);
688  }
689  else {
690  G_free(tkeys);
691  return (NULL);
692  }
693 }
694 
700 void correct_twist(Keylist * k)
701 {
702  Keylist *c, *p, *t;
703  int cnt, j;
704 
705  p = NULL;
706  cnt = 0;
707  for (c = k; c; c = c->next) {
708  if (p) {
709  if ((c->fields[KF_TWIST] - p->fields[KF_TWIST]) > 1800.) {
710  for (t = c; t; t = t->next) {
711  t->fields[KF_TWIST] -= 3600.;
712  }
713  }
714  else if ((p->fields[KF_TWIST] - c->fields[KF_TWIST]) > 1800.) {
715  for (t = k, j = 0; j < cnt; j++, t = t->next) {
716  t->fields[KF_TWIST] -= 3600.;
717  }
718  }
719  }
720 
721  p = c;
722  ++cnt;
723  }
724 
725  return;
726 }
727 
738 int gk_draw_path(Viewnode * views, int steps, Keylist * keys)
739 {
740  Viewnode *v;
741  Keylist *k;
742  int frame;
743  float siz, from[3];
744 
745  if (!views || !keys) {
746  return (0);
747  }
748 
749  GS_get_longdim(&siz);
750  siz /= 200.;
751 
752  gsd_colormode(CM_COLOR);
753  gsd_linewidth(2);
755  gsd_zwritemask(0);
756 
757  gsd_bgnline();
758 
759  for (frame = 0; frame < steps; frame++) {
760  v = &views[frame];
761  gsd_vert_func(&(v->fields[KF_FROMX]));
762  }
763 
764  gsd_endline();
765 
766  gsd_linewidth(1);
767 
768 
769  for (k = keys; k; k = k->next) {
770  gsd_x(NULL, &(k->fields[KF_FROMX]),
771  ~(GS_background_color() | 0xFF0000), siz);
772  }
773 
774  /* draw viewer position for inset images */
775  GS_get_from(from);
776  gsd_x(NULL, from, ~(GS_default_draw_color() | 0xFFFF00), 3.0 * siz);
777 
778  gsd_zwritemask(0xffffffff);
779 
780  return (1);
781 }
void gsd_zwritemask(unsigned long n)
Write out z-mask.
Definition: gsd_prim.c:231
void GS_ready_draw(void)
Definition: gs2.c:2489
void gk_free_key(Keylist *ok)
Free keyframe list.
Definition: gk.c:271
unsigned long gk_get_mask_sofar(float time, Keylist *keys)
Get mask value.
Definition: gk.c:79
double lin_interp(float dt, float val1, float val2)
Linear interpolation.
Definition: gk.c:539
void GS_get_from(float *fr)
Get viewpoint &#39;from&#39; position.
Definition: gs2.c:2726
void GS_alldraw_cplane_fences(void)
Draw all cplace fences ?
Definition: gs2.c:3196
unsigned int GS_default_draw_color(void)
Get default draw color.
Definition: gs2.c:2440
void GS_setlight_position(int num, float xpos, float ypos, float zpos, int local)
Set light position.
Definition: gs2.c:310
void GS_draw_all_list(void)
Draw all glLists.
Definition: gs2.c:880
Viewnode * gk_make_framesfromkeys(Keylist *keys, int keysteps, int newsteps, int loop, float t)
Generate viewnode from keyframes.
Definition: gk.c:301
void GV_alldraw_vect(void)
Draw all loaded vector sets.
Definition: gv2.c:506
void gsd_colormode(int cm)
Set color mode.
Definition: gsd_prim.c:88
void GS_getlight_position(int num, float *xpos, float *ypos, float *zpos, int *local)
Get light position.
Definition: gs2.c:336
void GS_set_viewdir(float *dir)
Set viewdir.
Definition: gs2.c:2824
void correct_twist(Keylist *k)
Correct twist value.
Definition: gk.c:700
void gsd_color_func(unsigned int col)
Set current color.
Definition: gsd_prim.c:689
#define NULL
Definition: ccmath.h:32
void GS_moveto(float *pt)
Move viewpoint.
Definition: gs2.c:2618
#define Y(n)
Definition: plot.c:141
void gsd_x(geosurf *gs, float *center, int colr, float siz)
Draw X symbol.
Definition: gsd_objs.c:278
int gk_draw_path(Viewnode *views, int steps, Keylist *keys)
Draw path.
Definition: gk.c:738
Viewnode * gk_make_linear_framesfromkeys(Keylist *keys, int keysteps, int newsteps, int loop)
Generate viewnode from keyframe list (linear interpolation)
Definition: gk.c:604
double get_key_neighbors(int nvk, double time, double range, int loop, Keylist *karray[], Keylist **km1, Keylist **kp1, Keylist **kp2, Keylist **km2, double *dt1, double *dt2)
Find interval containing time.
Definition: gk.c:455
void GS_set_twist(int t)
Set viewpoint twist value.
Definition: gs2.c:2878
void gsd_endline(void)
End line.
Definition: gsd_prim.c:397
int gk_viable_keys_for_mask(unsigned long mask, Keylist *keys, Keylist **keyret)
ADD.
Definition: gk.c:112
int G_debug(int level, const char *msg,...)
Print debugging message.
Definition: debug.c:65
double t
void gk_follow_frames(Viewnode *view, int numsteps, Keylist *keys, int step, int onestep, int render, unsigned long mode)
Checks key masks.
Definition: gk.c:141
void GS_clear(int col)
Clear view.
Definition: gs2.c:3419
void GP_alldraw_site(void)
Draw all available point sets.
Definition: gp2.c:607
int GS_get_longdim(float *dim)
Get largest dimension.
Definition: gs2.c:141
unsigned int GS_background_color(void)
Get background color.
Definition: gs2.c:2453
void GS_get_viewdir(float *dir)
Get viewdir.
Definition: gs2.c:2810
void gsd_vert_func(float *pt)
ADD.
Definition: gsd_prim.c:677
void GVL_alldraw_vol(void)
Draw all volume sets.
Definition: gvl2.c:441
void GS_set_draw(int where)
Sets which buffer to draw to.
Definition: gs2.c:2463
void GS_alldraw_surf(void)
Draw all surfaces.
Definition: gs2.c:1937
void gsd_linewidth(short n)
Set width of rasterized lines.
Definition: gsd_prim.c:257
void GS_alldraw_wire(void)
Draw all wires.
Definition: gs2.c:1920
void GS_set_fov(int fov)
Set field of view.
Definition: gs2.c:2844
#define X(e)
Definition: plot.c:140
double get_2key_neighbors(int nvk, float time, float range, int loop, Keylist *karray[], Keylist **km1, Keylist **kp1)
Finds interval containing time, putting left (or equal) key at km1, right at kp1. ...
Definition: gk.c:558
void G_free(void *buf)
Free allocated memory.
Definition: alloc.c:149
void gsd_bgnline(void)
Begin line.
Definition: gsd_prim.c:387
void G_warning(const char *msg,...)
Print a warning message to stderr.
Definition: gis/error.c:203
Keylist * gk_copy_key(Keylist *k)
Copy keyframes.
Definition: gk.c:45
void GS_done_draw(void)
Draw done, swap buffers.
Definition: gs2.c:2502