GRASS Programmer's Manual  6.4.2(2012)
gk.c
Go to the documentation of this file.
00001 
00019 #include <stdlib.h>
00020 #include <math.h>
00021 
00022 #include <grass/gis.h>
00023 #include <grass/glocale.h>
00024 #include <grass/gstypes.h>
00025 #include <grass/keyframe.h>
00026 #include <grass/kftypes.h>
00027 
00028 static float spl3(float, double, double, double, double, double, double,
00029                   double);
00030 
00031 static float spl3(float tension, double data0, double data1, double x,
00032                   double x2, double x3, double lderiv, double rderiv)
00033 {
00034     return ((float)
00035             (data0 * (2 * x3 - 3 * x2 + 1) + data1 * (-2 * x3 + 3 * x2) +
00036              (double)tension * lderiv * (x3 - 2 * x2 + x) +
00037              (double)tension * rderiv * (x3 - x2)));
00038 }
00039 
00047 Keylist *gk_copy_key(Keylist * k)
00048 {
00049     Keylist *newk;
00050     int i;
00051 
00052     newk = (Keylist *) G_malloc(sizeof(Keylist));       /* G_fatal_error */
00053     if (!newk) {
00054         return (NULL);
00055     }
00056 
00057     for (i = 0; i < KF_NUMFIELDS; i++) {
00058         newk->fields[i] = k->fields[i];
00059     }
00060 
00061     newk->pos = k->pos;
00062     newk->look_ahead = k->look_ahead;
00063     newk->fieldmask = k->fieldmask;
00064     newk->next = newk->prior = NULL;
00065 
00066     return (newk);
00067 }
00068 
00081 unsigned long gk_get_mask_sofar(float time, Keylist * keys)
00082 {
00083     Keylist *k;
00084     float startpos, endpos, curpos;
00085     unsigned long mask = 0xFFFFFFFF;
00086 
00087     if (keys) {
00088         /* find end key */
00089         for (k = keys; k->next; k = k->next) ;
00090 
00091         startpos = keys->pos;
00092         endpos = k->pos;
00093         curpos = startpos + time * (endpos - startpos);
00094 
00095         for (k = keys; k->next; k = k->next) {
00096             if (k->pos <= curpos) {
00097                 mask &= k->fieldmask;   /* (else break) */
00098             }
00099         }
00100     }
00101 
00102     return (mask);
00103 }
00104 
00114 int gk_viable_keys_for_mask(unsigned long mask, Keylist * keys,
00115                             Keylist ** keyret)
00116 {
00117     Keylist *k;
00118     int cnt = 0;
00119 
00120     for (k = keys; k; k = k->next) {
00121         if ((mask & k->fieldmask) == mask) {
00122             keyret[cnt++] = k;
00123         }
00124     }
00125 
00126     return (cnt);
00127 }
00128 
00143 void gk_follow_frames(Viewnode * view, int numsteps, Keylist * keys, int step,
00144                       int onestep, int render, unsigned long mode)
00145 {
00146     Viewnode *v;
00147     int frame;                  /* frame is index into viewnode array */
00148     float tmp[3];
00149     float x, y, z;
00150     int num, w;
00151     unsigned long mask;
00152 
00153     for (frame = step - 1; frame < numsteps; frame++) {
00154 
00155         v = &view[frame];
00156         mask = gk_get_mask_sofar((float)frame / numsteps, keys);
00157 
00158         /* TODO?: set view field to current settings if not set,
00159            thereby keeping view structure up to date for easier saving of
00160            animation? */
00161 
00162         GS_get_from(tmp);
00163         if ((mask & KF_FROMX_MASK)) {
00164             tmp[X] = v->fields[KF_FROMX];
00165         }
00166         if ((mask & KF_FROMY_MASK)) {
00167             tmp[Y] = v->fields[KF_FROMY];
00168         }
00169         if ((mask & KF_FROMZ_MASK)) {
00170             tmp[Z] = v->fields[KF_FROMZ];
00171         }
00172 
00173         GS_moveto(tmp);
00174 
00175         GS_get_from(tmp);
00176         G_debug(3, "gk_follow_frames():");
00177         G_debug(3, "  MASK: %lx", mask);
00178         G_debug(3, "  FROM: %f %f %f", tmp[X], tmp[Y], tmp[Z]);
00179 
00180         /* ACS 1 line: was      GS_get_focus(tmp);
00181            with this kanimator works also for flythrough navigation
00182            also changed in GK2.c
00183          */
00184         GS_get_viewdir(tmp);
00185         if ((mask & KF_DIRX_MASK)) {
00186             tmp[X] = v->fields[KF_DIRX];
00187         }
00188         if ((mask & KF_DIRY_MASK)) {
00189             tmp[Y] = v->fields[KF_DIRY];
00190         }
00191         if ((mask & KF_DIRZ_MASK)) {
00192             tmp[Z] = v->fields[KF_DIRZ];
00193         }
00194         /* ACS 1 line: was      GS_set_focus(tmp);
00195            with this kanimator works also for flythrough navigation
00196            also changed in GK2.c
00197          */
00198         GS_set_viewdir(tmp);
00199 
00200         G_debug(3, "gk_follow_frames():");
00201         GS_get_viewdir(tmp);
00202         G_debug(3, "  DIR: %f %f %f\n", tmp[X], tmp[Y], tmp[Z]);
00203 
00204         if ((mask & KF_TWIST_MASK)) {
00205             GS_set_twist((int)v->fields[KF_TWIST]);
00206         }
00207 
00208         if ((mask & KF_FOV_MASK)) {
00209             GS_set_fov((int)v->fields[KF_FOV]);
00210         }
00211 
00212         /* Initilaize lights before drawing */
00213         num = 1;
00214         GS_getlight_position(num, &x, &y, &z, &w);
00215         GS_setlight_position(num, x, y, z, w);
00216         num = 2;                /* Top light */
00217         GS_setlight_position(num, 0., 0., 1., 0);
00218 
00219         if (render) {
00220             GS_set_draw(GSD_FRONT);
00221         }
00222         else {
00223             GS_set_draw(GSD_BACK);
00224         }
00225 
00226         GS_ready_draw();
00227         GS_clear(GS_background_color());
00228 
00229         if (render) {
00230             GS_alldraw_surf();
00231         }
00232         else {
00233             GS_alldraw_wire();
00234         }
00235 
00236         GS_alldraw_cplane_fences();
00237 
00238         if (mode & FM_PATH) {
00239             gk_draw_path(view, numsteps, keys);
00240         }
00241 
00242         if (mode & FM_VECT) {
00243             GV_alldraw_vect();
00244         }
00245 
00246         if (mode & FM_SITE) {
00247             GP_alldraw_site();
00248         }
00249 
00250         if (mode & FM_VOL) {
00251             GVL_alldraw_vol();
00252         }
00253 
00254         GS_done_draw();
00255 
00256         if (mode & FM_LABEL) {
00257             GS_draw_all_list(); /* draw labels and legend */
00258         }
00259 
00260         if (onestep) {
00261             return;
00262         }
00263     }
00264 
00265     return;
00266 }
00267 
00273 void gk_free_key(Keylist * ok)
00274 {
00275     Keylist *k, *prev;
00276 
00277     if (ok) {
00278         k = ok;
00279         while (k) {
00280             prev = k;
00281             k = k->next;
00282             G_free(prev);
00283         }
00284     }
00285 
00286     return;
00287 }
00288 
00303 Viewnode *gk_make_framesfromkeys(Keylist * keys, int keysteps, int newsteps,
00304                                  int loop, float t)
00305 {
00306     int i;
00307     Viewnode *v, *newview;
00308     Keylist *k, *kp1, *kp2, *km1, **tkeys;
00309     float startpos, endpos;
00310     double dt1, dt2, x, x2, x3, range, time, time_step, len, rderiv, lderiv;
00311 
00312     /* allocate tmp keys to hold valid keys for fields */
00313     tkeys = (Keylist **) G_malloc(keysteps * sizeof(Keylist *));        /* G_fatal_error */
00314     if (!tkeys) {
00315         return (NULL);
00316     }
00317 
00318     correct_twist(keys);
00319 
00320     if (keys && keysteps) {
00321         if (keysteps < 3) {
00322             G_warning(_("Need at least 3 keyframes for spline"));
00323             G_free(tkeys);
00324             return (NULL);
00325         }
00326 
00327         /* find end key */
00328         for (k = keys; k->next; k = k->next) ;
00329 
00330         startpos = keys->pos;
00331         endpos = k->pos;
00332         range = endpos - startpos;
00333         time_step = range / (newsteps - 1);
00334 
00335         newview = (Viewnode *) G_malloc(newsteps * sizeof(Viewnode));   /* G_fatal_error */
00336         if (!newview) {         /* not used */
00337             G_free(tkeys);
00338             return (NULL);
00339         }
00340 
00341         for (i = 0; i < newsteps; i++) {
00342             int field = 0;
00343 
00344             v = &newview[i];
00345 
00346             time = startpos + i * time_step;
00347 
00348             if (i == newsteps - 1) {
00349                 time = endpos;  /*to ensure no roundoff errors */
00350             }
00351 
00352             for (field = 0; field < KF_NUMFIELDS; field++) {
00353                 int nvk = 0;    /* number of viable keyframes for this field */
00354 
00355                 /* now need to do for each field to look at mask */
00356                 k = kp1 = kp2 = km1 = NULL;
00357                 nvk = gk_viable_keys_for_mask((unsigned long)(1 << field),
00358                                               keys, tkeys);
00359                 if (nvk) {
00360                     len = get_key_neighbors(nvk, time, range,
00361                                             loop, tkeys, &k, &kp1, &kp2, &km1,
00362                                             &dt1, &dt2);
00363                 }
00364 
00365                 /* ACS 1 line: was      if (len == 0.0) {
00366                    when disabling a channel no calculation must be made at all (otherwise core dump)
00367                  */
00368                 if (len == 0.0 || nvk == 0) {
00369                     if (!k) {
00370                         /* none valid - use first.
00371                            (when showing , will be ignored anyway) */
00372                         v->fields[field] = keys->fields[field];
00373                     }
00374                     else if (!kp1) {
00375                         /* none on right - use left */
00376                         v->fields[field] = k->fields[field];
00377                     }
00378 
00379                     continue;
00380                 }
00381                 else if (!km1 && !kp2) {
00382                     /* only two valid - use linear */
00383                     v->fields[field] = lin_interp((time - k->pos) / len,
00384                                                   k->fields[field],
00385                                                   kp1->fields[field]);
00386                     continue;
00387                 }
00388 
00389                 x = (time - k->pos) / len;
00390                 x2 = x * x;
00391                 x3 = x2 * x;
00392 
00393                 if (!km1) {
00394                     /* leftmost interval */
00395                     rderiv = (kp2->fields[field] - k->fields[field]) / dt2;
00396                     lderiv = (3 * (kp1->fields[field] -
00397                                    k->fields[field]) / dt1 - rderiv) / 2.0;
00398                     v->fields[field] = spl3(t, k->fields[field],
00399                                             kp1->fields[field], x, x2, x3,
00400                                             lderiv, rderiv);
00401                 }
00402                 else if (!kp2) {
00403                     /* rightmost interval */
00404                     lderiv = (kp1->fields[field] - km1->fields[field]) / dt1;
00405                     rderiv = (3 * (kp1->fields[field] -
00406                                    k->fields[field]) / dt2 - lderiv) / 2.0;
00407                     v->fields[field] = spl3(t, k->fields[field],
00408                                             kp1->fields[field], x, x2, x3,
00409                                             lderiv, rderiv);
00410                 }
00411                 else {
00412                     /* not on ends */
00413                     lderiv = (kp1->fields[field] - km1->fields[field]) / dt1;
00414                     rderiv = (kp2->fields[field] - k->fields[field]) / dt2;
00415                     v->fields[field] = spl3(t, k->fields[field],
00416                                             kp1->fields[field], x, x2, x3,
00417                                             lderiv, rderiv);
00418                 }
00419             }
00420         }
00421 
00422         G_free(tkeys);
00423         return (newview);
00424     }
00425     else {
00426         G_free(tkeys);
00427         return (NULL);
00428     }
00429 }
00430 
00457 double get_key_neighbors(int nvk, double time, double range, int loop,
00458                          Keylist * karray[], Keylist ** km1, Keylist ** kp1,
00459                          Keylist ** kp2, Keylist ** km2, double *dt1,
00460                          double *dt2)
00461 {
00462     int i;
00463     double len;
00464 
00465     *km1 = *kp1 = *kp2 = *km2 = NULL;
00466     *dt1 = *dt2 = 0.0;
00467 
00468     for (i = 0; i < nvk; i++) {
00469         if (time < karray[i]->pos) {
00470             break;
00471         }
00472     }
00473 
00474     if (!i) {
00475         return (0.0);           /* before first keyframe or nvk == 0 */
00476     }
00477 
00478     if (i == nvk) {
00479         /* past or == last keyframe! */
00480         *km1 = karray[nvk - 1];
00481         return (0.0);
00482     }
00483 
00484     /* there's at least 2 */
00485     *km1 = karray[i - 1];
00486     *kp1 = karray[i];
00487     len = karray[i]->pos - karray[i - 1]->pos;
00488 
00489     if (i == 1) {
00490         /* first interval */
00491         if (loop) {
00492             *km2 = karray[nvk - 2];
00493             *kp2 = karray[(i + 1) % nvk];
00494         }
00495         else {
00496             if (nvk > 2) {
00497                 *kp2 = karray[i + 1];
00498             }
00499         }
00500     }
00501     else if (i == nvk - 1) {
00502         /* last interval */
00503         if (loop) {
00504             *km2 = nvk > 2 ? karray[i - 2] : karray[1];
00505             *kp2 = karray[1];
00506         }
00507         else {
00508             if (nvk > 2) {
00509                 *km2 = karray[i - 2];
00510             }
00511         }
00512     }
00513     else {
00514         *km2 = karray[i - 2];
00515         *kp2 = karray[i + 1];
00516     }
00517 
00518     *dt1 = (*km2) ? (*kp1)->pos - (*km2)->pos : len;
00519     *dt2 = (*kp2) ? (*kp2)->pos - (*km1)->pos : len;
00520 
00521     if (i == 1 && loop) {
00522         *dt1 += range;
00523     }
00524 
00525     if (i == nvk - 1 && loop) {
00526         *dt2 += range;
00527     }
00528 
00529     return (len);
00530 }
00531 
00541 double lin_interp(float dt, float val1, float val2)
00542 {
00543     return ((double)(val1 + dt * (val2 - val1)));
00544 }
00545 
00560 double get_2key_neighbors(int nvk, float time, float range, int loop,
00561                           Keylist * karray[], Keylist ** km1, Keylist ** kp1)
00562 {
00563     int i;
00564     double len;
00565 
00566     *km1 = *kp1 = NULL;
00567 
00568     for (i = 0; i < nvk; i++) {
00569         if (time < karray[i]->pos) {
00570             break;
00571         }
00572     }
00573 
00574     if (!i) {
00575         return (0.0);           /* before first keyframe or nvk == 0 */
00576     }
00577 
00578     if (i == nvk) {
00579         /* past or == last keyframe! */
00580         *km1 = karray[nvk - 1];
00581         return (0.0);
00582     }
00583 
00584     /* there's at least 2 */
00585     *km1 = karray[i - 1];
00586     *kp1 = karray[i];
00587     len = karray[i]->pos - karray[i - 1]->pos;
00588 
00589     return (len);
00590 }
00591 
00606 Viewnode *gk_make_linear_framesfromkeys(Keylist * keys, int keysteps,
00607                                         int newsteps, int loop)
00608 {
00609     int i, nvk;
00610     Viewnode *v, *newview;
00611     Keylist *k, *k1, *k2, **tkeys;
00612     float startpos, endpos, dt, range, time, time_step, len;
00613 
00614     /* allocate tmp keys to hold valid keys for fields */
00615     tkeys = (Keylist **) G_malloc(keysteps * sizeof(Keylist *));        /* G_fatal_error */
00616     if (!tkeys) {
00617         return (NULL);
00618     }
00619 
00620     correct_twist(keys);
00621 
00622     if (keys && keysteps) {
00623         if (keysteps < 2) {
00624             G_warning(_("Need at least 2 keyframes for interpolation"));
00625             G_free(tkeys);
00626             return (NULL);
00627         }
00628 
00629         /* find end key */
00630         for (k = keys; k->next; k = k->next) ;
00631 
00632         startpos = keys->pos;
00633         endpos = k->pos;
00634         range = endpos - startpos;
00635         time_step = range / (newsteps - 1);
00636 
00637         newview = (Viewnode *) G_malloc(newsteps * sizeof(Viewnode));   /* G_fatal_error */
00638         if (!newview) {         /* not used */
00639             G_free(tkeys);
00640             return (NULL);
00641         }
00642 
00643         for (i = 0; i < newsteps; i++) {
00644             int field = 0;
00645 
00646             v = &newview[i];
00647 
00648             time = startpos + i * time_step;
00649             if (i == newsteps - 1) {
00650                 time = endpos;  /*to ensure no roundoff errors */
00651             }
00652 
00653             for (field = 0; field < KF_NUMFIELDS; field++) {
00654 
00655                 nvk = gk_viable_keys_for_mask((unsigned long)(1 << field),
00656                                               keys, tkeys);
00657                 if (!nvk) {
00658                     v->fields[field] = keys->fields[field];     /*default-not used */
00659                 }
00660                 else {
00661                     len = get_2key_neighbors(nvk, time, range, loop,
00662                                              tkeys, &k1, &k2);
00663                 }
00664 
00665                 /* ACS 1 line: was      if (len == 0.0) {
00666                    when disabling a channel no calculation must be made at all (otherwise core dump)
00667                  */
00668                 if (len == 0.0 || nvk == 0) {
00669                     if (!k1) {
00670                         /* none valid - use first.
00671                            (when showing , will be ignored anyway) */
00672                         v->fields[field] = keys->fields[field];
00673                     }
00674                     else if (!k2) {
00675                         /* none on right - use left */
00676                         v->fields[field] = k1->fields[field];
00677                     }
00678                 }
00679                 else {
00680                     dt = (time - k1->pos) / len;
00681                     v->fields[field] = lin_interp(dt,
00682                                                   k1->fields[field],
00683                                                   k2->fields[field]);
00684                 }
00685             }
00686         }
00687 
00688         G_free(tkeys);
00689         return (newview);
00690     }
00691     else {
00692         G_free(tkeys);
00693         return (NULL);
00694     }
00695 }
00696 
00702 void correct_twist(Keylist * k)
00703 {
00704     Keylist *c, *p, *t;
00705     int cnt, j;
00706 
00707     p = NULL;
00708     cnt = 0;
00709     for (c = k; c; c = c->next) {
00710         if (p) {
00711             if ((c->fields[KF_TWIST] - p->fields[KF_TWIST]) > 1800.) {
00712                 for (t = c; t; t = t->next) {
00713                     t->fields[KF_TWIST] -= 3600.;
00714                 }
00715             }
00716             else if ((p->fields[KF_TWIST] - c->fields[KF_TWIST]) > 1800.) {
00717                 for (t = k, j = 0; j < cnt; j++, t = t->next) {
00718                     t->fields[KF_TWIST] -= 3600.;
00719                 }
00720             }
00721         }
00722 
00723         p = c;
00724         ++cnt;
00725     }
00726 
00727     return;
00728 }
00729 
00740 int gk_draw_path(Viewnode * views, int steps, Keylist * keys)
00741 {
00742     Viewnode *v;
00743     Keylist *k;
00744     int frame;
00745     float siz, from[3];
00746 
00747     if (!views || !keys) {
00748         return (0);
00749     }
00750 
00751     GS_get_longdim(&siz);
00752     siz /= 200.;
00753 
00754     gsd_colormode(CM_COLOR);
00755     gsd_linewidth(2);
00756     gsd_color_func(GS_default_draw_color());
00757     gsd_zwritemask(0);
00758 
00759     gsd_bgnline();
00760 
00761     for (frame = 0; frame < steps; frame++) {
00762         v = &views[frame];
00763         gsd_vert_func(&(v->fields[KF_FROMX]));
00764     }
00765 
00766     gsd_endline();
00767 
00768     gsd_linewidth(1);
00769 
00770 
00771     for (k = keys; k; k = k->next) {
00772         gsd_x(NULL, &(k->fields[KF_FROMX]),
00773               ~(GS_background_color() | 0xFF0000), siz);
00774     }
00775 
00776     /* draw viewer position for inset images */
00777     GS_get_from(from);
00778     gsd_x(NULL, from, ~(GS_default_draw_color() | 0xFFFF00), 3.0 * siz);
00779 
00780     gsd_zwritemask(0xffffffff);
00781 
00782     return (1);
00783 }
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines