Hogwarts Wand Docs: ../server/wg.c

Wand Sourcecode: ../server/wg.c

//
// wg.c - graph wpic*.txt spell files
//
// Copyright (C) 2006  Nathan (Acorn) Pooley
// 
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// version 2 as published by the Free Software Foundation.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License (gpl.txt) for more details. 
// 
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
// 
// You can contact the author, Nathan (Acorn) Pooley, by writing
// to Nathan (Acorn) Pooley, 949 Buckeye Drive, Sunnyvale, CA  94086, USA
// or through the form at http://www.rawbw.com/~acorn/wand/feedback.html
//

//
//
//#@DOC@ visually graph wpic*.txt spell files


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <math.h>
#include "graph.h"

#include "spells.h"

#define WIN_WIDTH       1200
//#define WIN_HEIGHT    900
#define WIN_HEIGHT      500

#define AVERAGE_X       87.2
#define AVERAGE_Y       81.2
#define TAP_THRESHHOLD_MAG  60.5
#define TAP_THRESHHOLD_TIME 
#define TAP_PRE_TIME        0.2
#define TAP_POST_TIME       0.2

#define DRAW_EXTRA_CRAP 0

// Tap
//
//     pre time      post time
//  long    short   short           long    time>60.5
//  0.108   0.018   0.0127          0.267   0.002       tapb
//  0.110   0.002   0.0093  0.038   0.148   0.003       tapa
//  0.145   0.012   0.0173  0.109   0.292   0.014       ltap_cusion
//  0.104   0.001   0.0053  0.015   0.079   0.002       2tap (first)
//  0.04??  0.001   0.0063  0.015   0.182   0.002       2tap (second)
//  ?       0.001   0.0088  0.042   0.144   0.002       tap (pic1)
//  ?       0.002   0.0032  0.013   ?       0.003       righttap (pic1)
//  
//
// tap-to-tap time
//  0.338
//
//

const char *g_filename="";
float g_mag_max = 0;

float OPT_avgx = -1.0;
float OPT_avgy = -1.0;
int   OPT_oldmode = 0;
int   OPT_astate = 1;
int   OPT_fmtb=1;
int   OPT_skip = 0;
int   OPT_calc_exit = 0;
int   OPT_raw = 0;
int   OPT_separate = 1;

float  scale_time = 1.0/(16.0 * 256);
//float  scale_time = 1.0;
float angle_offset =  3.5;

//===========================================================================
// getline2()
//===========================================================================
int getline2(FILE *fp, char *line, char *end)
{
    int c = getc(fp);
    if (c==EOF) return 0;

    end--;
    while(c!='\n' && c!=EOF && line != end) {
        *(line++) = c;
        c = getc(fp);
    }
    *line = 0;
    return 1;
}

//===========================================================================
// getline()
//===========================================================================
int getline(FILE *fp, float *t, float *x, float *y, float *z, float *w)
{
    float *list[6];
    float **lp = list;
    char line[1000];
    char *s, *e;
    list[0] = t;
    list[1] = x;
    list[2] = y;
    list[3] = z;
    list[4] = w;
    list[5] = 0;

    while(1) {
        if (!getline2(fp,line,line+sizeof(line))) {
            return 0;
        }
        s = line;

        while(1) {
            while(isspace(*s)) s++;

            if (*s == '#' || *s == 0) {
                break;
            }

            **lp = strtod(s,&e);
            if (!e || e==s) {
                fprintf(stderr,"Error parsing line:\n    %s\n",line);
                break;
            }
            s = e;
            lp++;
            if (*lp == 0) break;
        }

        if (lp != list) {
            while(*lp) {
                **(lp++) = 0.0;
            }
            return 1;
        }
    }
}

//===========================================================================
// func_filter()
//===========================================================================
void func_filter(GWinLineFuncInfo *info)
{
    int cnt = info->vertCntMin;
    float *vdst = gwinLineFuncVerts(info,cnt);
    float deltat = info->args[0]->v.val;
    float *vsrc = info->args[1]->l.verts;
    int i;

    for (i=0; i<cnt; i++) {
        float x = vsrc[i*2+0];
        float y = vsrc[i*2+1];
        float x0 = x;
        int ip = i-1;
        int in = i+1;

        while(1) {
            float xp,yp,xn,yn;
            if (ip < 0) break;
            if (in >= cnt) break;

            xp = vsrc[ip*2+0];
            yp = vsrc[ip*2+1];
            xn = vsrc[in*2+0];
            yn = vsrc[in*2+1];

            if (xn - xp > deltat) break;
            if ((yp > y && yn > y) || (yp < y && yn < y)) {
                x = 0.5 * (xn + xp);
                y = 0.5 * (yn + yp);
            }

            if (ip == 0) {
                in++;
            } else if (in == cnt-1) {
                ip--;
            } else if (vsrc[in*2+2]-x0 > x0-vsrc[ip*2-2]) {
                ip--;
            } else {
                in++;
            }
        }

        
        vdst[i*2+0] = x;
        vdst[i*2+1] = y;
    }
}

//===========================================================================
// func_mag()
//===========================================================================
void func_mag(GWinLineFuncInfo *info)
{
    int cnt = info->vertCntMin;
    float *vdst = gwinLineFuncVerts(info,cnt);
    float *vsrcx = info->args[0]->l.verts;
    float *vsrcy = info->args[1]->l.verts;
    int i;

    for (i=0; i<cnt; i++) {
        float xa = vsrcx[i*2+0];
        float ya = vsrcx[i*2+1];
        float yb = vsrcy[i*2+1];
        float x = xa;
        float y;

        ya -= OPT_avgx;
        yb -= OPT_avgy;

        y = sqrtf(ya*ya + yb*yb);

        g_mag_max = g_mag_max > y ? g_mag_max : y;

        vdst[i*2+0] = x;
        vdst[i*2+1] = y;
    }
}

//===========================================================================
// func_angle()
//===========================================================================
void func_angle(GWinLineFuncInfo *info)
{
    int cnt = info->vertCntMin;
    float *vdst = gwinLineFuncVerts(info,cnt);
    float *vsrcx = info->args[0]->l.verts;
    float *vsrcy = info->args[1]->l.verts;
    int i;

    for (i=0; i<cnt; i++) {
        float xa = vsrcx[i*2+0];
        float ya = vsrcx[i*2+1];
        float yb = vsrcy[i*2+1];
        float x = xa;
        float y;

        ya -= OPT_avgx;
        yb -= OPT_avgy;

        y = atan2f(ya, yb);

        vdst[i*2+0] = x;
        vdst[i*2+1] = y;
    }
}

//===========================================================================
// func_tapmag()
//===========================================================================
void func_tapmag(GWinLineFuncInfo *info)
{
    int cnt = info->vertCntMin;
    float *vdst = gwinLineFuncVerts(info,cnt);
    float *vsrcx = info->args[0]->l.verts;
    float *vsrcy = info->args[1]->l.verts;
    int i;

    for (i=0; i<cnt; i++) {
        float xa = vsrcx[i*2+0];
        float ya = vsrcx[i*2+1];
        float yb = vsrcy[i*2+1];
        float x = xa;
        float y;
        float m2;

        ya -= OPT_avgx;
        yb -= OPT_avgy;

        m2 = ya*ya + yb*yb;

        y = 0.5;
        if (m2 > TAP_THRESHHOLD_MAG * TAP_THRESHHOLD_MAG) {
            y = 1.0;
        }

        vdst[i*2+0] = x;
        vdst[i*2+1] = y;
    }
}

//===========================================================================
// func_tapmask()
//===========================================================================
void func_tapmask(GWinLineFuncInfo *info)
{
    int srccnt = info->vertCntMin;
    int dstcnt = 200;
    float *vdst = gwinLineFuncVerts(info,dstcnt);
    float *vsrctap = info->args[0]->l.verts;
    float lastt = vsrctap[0];
    int j=1;
    int i;

    vdst[0] = vsrctap[0];
    vdst[1] = 1.5;

    for (i=0; i<srccnt; i++) {
        lastt = lastt > vsrctap[i*2+0] ? lastt : vsrctap[i*2+0];
        if (vsrctap[i*2+1] > 0.5) {
            float t = vsrctap[i*2+0];
            float t0 = t - TAP_PRE_TIME;
            float t1 = t + TAP_POST_TIME;
            lastt = t1;
            if (t0 < vdst[j*2+0]) {
                t0 = vdst[j*2+0];
            }
            j++;
            if (j>=dstcnt) break;
            vdst[j*2+0] = t0;
            vdst[j*2+1] = 1.5;
            j++;
            if (j>=dstcnt) break;
            vdst[j*2+0] = t0;
            vdst[j*2+1] = 2.0;
            j++;
            if (j>=dstcnt) break;
            vdst[j*2+0] = t1;
            vdst[j*2+1] = 2.0;
            j++;
            if (j>=dstcnt) break;
            vdst[j*2+0] = t1;
            vdst[j*2+1] = 1.5;
            while(i<srccnt && vsrctap[i*2+1] > 0.5) {
                lastt = lastt > vsrctap[i*2+0] ? lastt : vsrctap[i*2+0];
                i++;
            }
        }
    }

    j++;
    if (j<dstcnt) {
        vdst[j*2+0] = lastt;
        vdst[j*2+1] = 1.5;
    }

    gwinLineFuncVerts(info,j+1);
}

//===========================================================================
// usage()
//===========================================================================
void usage(void)
{
    printf(
        "Usage: wg [OPTIONS] <filename>\n"
        "Usage: wg [OPTIONS] <filename> <filename2>\n"
        "  Display file as a graph.  File should contain lines with 3 space\n"
        "  separated numbers per line.  # marks comment lines.\n"
        "  If supplied, filename 2 is a wgtok file from fmtb_parse."
        "OPTIONS:\n"
        "  -s<n>   skip first <n> points\n"
        "  -x<v>   use <v> as average x value (for theta/mag calc)\n"
        "  -y<v>   use <v> as average y value (for theta/mag calc)\n"
        "  -o      original file mode (old default)\n"
        "  -a      astate mode\n"
        "  -b      fmtb mode (new default)\n"
        "  -r      raw mode\n"
        "  -q      exit as soon as calculations are done\n"
    );
    exit(1);
}

//===========================================================================
// runLook()
//===========================================================================
static void runLook(GWindow *gw, void *data)
{
    char buf[1000];
    snprintf(buf,sizeof(buf),"./look < %s",g_filename);
    system(buf);
}

//===========================================================================
// drawTick()
//===========================================================================
static void drawTick(GWindow *gw,float t, int val)
{
    int line = gwinLineCreate(gw);
    gwinLineName(gw,line,0);
    gwinLineColor(gw,line, (val>-2&&val<2)?0x00c000 : 0x00ff00);
    gwinLineScaleOffset(gw,line, 1.0, 1.0, 0.0, 0.0);
    gwinLineStep(gw,line, 0);

    gwinLinePoint( gw, line,
                    (scale_time*(t)),
                     3.5 + angle_offset);
    gwinLinePoint( gw, line,
                    (scale_time*(t)),
                     0.5*val + 3.5 + angle_offset);
}

//===========================================================================
// drawConnectToken()
//===========================================================================
static void drawConnectToken(GWindow *gw,float ta, float tb, int n)
{
    int line = gwinLineCreate(gw);
    gwinLineName(gw,line,0);
    gwinLineColor(gw,line,
        ((n % 10)==0) ? 0xffffff :
        ((n %  5)==0) ? 0x7f7f7f :0x000000);
    gwinLineScaleOffset(gw,line, 1.0, 1.0, 0.0, 0.0);
    gwinLineStep(gw,line, 0);

    gwinLinePoint( gw, line,
                    (scale_time*(ta)),
                    -11.0);
    gwinLinePoint( gw, line,
                    (scale_time*(tb)),
                    -17.0);

    drawTick(gw,ta,
        ((n % 10)==0) ? -2 : -1);
}

//===========================================================================
// drawSpellToken()
//===========================================================================
static void drawSpellToken(GWindow *gw,float time, int tok,int b,int repeat)
{
    float xscale = 2.0/200.0;
    float yscale = 2.0/3.0;
    float cy;
    float ma = 1.0, mb = 0.0;
    float mc = 0.0, md = 1.0;
    float a = 0;
    float rev = 1.0;

    #define TX(x,y) (rev*(x)*ma+(y)*mc)
    #define TY(x,y) (rev*(x)*mb+(y)*md)
    #define PT(x,y) \
            gwinLinePoint( \
                    gw, \
                    line, \
                    TX(x,y)*xscale + (scale_time*(time)), \
                    TY(x,y)*yscale + cy)
        
    int line = gwinLineCreate(gw);
    gwinLineName(gw,line,0);
    gwinLineColor(gw,line,0xc0c000);
    gwinLineScaleOffset(gw,line, 1.0, 1.0, 0.0, 0.0);
    gwinLineStep(gw,line, 0);


    cy = TOKEN_ANGLE(tok);
    a = cy * M_PI * 2.0 / 32.0;
    cy += angle_offset;
    while(cy<0) cy+=32;
    while(cy>32) cy-=32;

    if (b) {
        xscale /= 3;
        cy = (b==1) ? -4 : -20;
    }
    if (b==1 && repeat) {
        cy += (float) repeat * 1.5;
    }

    if (tok < 0 ) {
        if (b) {
            cy = (b==1) ? -2 : -18;
            PT(0,1);
            PT(0,-1);
        }
        return;
    }

    ma = md = cos(a);
    mb = sin(a);
    mc = -mb;
    rev = TOKEN_DIR(tok);

    if (b==0) {
        static int line_sp = -1;
        static float last_t = -1.0;
        static float last_cy = -1.0;
        int restart=0;

        if (line_sp && cy-last_cy>16.0) {
            gwinLinePoint(
                        gw,
                        line_sp,
                        scale_time*(last_t+time)*0.5,
                        0.0);
            restart = 1;
            line_sp = -1;
        }
        if (line_sp && cy-last_cy<-16.0) {
            gwinLinePoint(
                        gw,
                        line_sp,
                        scale_time*(last_t+time)*0.5,
                        32.0);
            restart = -1;
            line_sp = -1;
        }
        if (line_sp == -1) {
            line_sp = gwinLineCreate(gw);
            gwinLineName(gw,line_sp,"Spell");
            gwinLineColor(gw,line_sp,0xffff00);
            gwinLineScaleOffset(gw,line_sp,
                                1.0, 1.0, 0.0, 0.0);
            gwinLineStep(gw,line_sp, 0);
        }
        if (restart>0) {
            gwinLinePoint(
                        gw,
                        line_sp,
                        scale_time*(last_t+time)*0.5,
                        32.0);
        }
        if (restart<0) {
            gwinLinePoint(
                        gw,
                        line_sp,
                        scale_time*(last_t+time)*0.5,
                        0.0);
        }
        gwinLinePoint(
                    gw,
                    line_sp,
                    scale_time*time,
                    cy);
        last_t  = time;
        last_cy = cy;
    }

    switch(TOKEN_SHAPE(tok)) {
        case SSHP_PAUSE:
            ma = md = 1.0;
            mb = mc = 0.0;
            rev = 0;
            PT(-1,-1);
            PT( 1, 1);
            PT( 0, 0);
            PT(-1, 1);
            PT( 1,-1);
            break;
            
        case SSHP_CIRCLE:
            gwinLineColor(gw,line,0xffff7f);
        case SSHP_OCIRCLE:
            PT( 0.4,-0.9);
            PT( 0.9,-0.4);
            PT( 0.9, 0.4);
            PT( 0.4, 0.9);
            PT(-0.4, 0.9);
            PT(-0.9, 0.4);
            PT(-0.9,-0.4);
            PT(-0.4,-0.9);
            PT(-0.8,-0.8);
            PT(-0.4,-0.9);
            PT(-0.5,-0.5);
            PT(-0.4,-0.9);
            break;


        case SSHP_PULSE:
            gwinLineColor(gw,line,0xffff7f);
        case SSHP_OPULSE:
            PT(0,1);
            PT(0,-1);
            PT(0.25,0);
            PT(0,-1);
            PT(-0.25,0);
            PT(0,-1);
            break;

        default: break;

    }

    #undef PT
    #undef TX
    #undef TY
}

//===========================================================================
// drawMotionToken()
//===========================================================================
static void drawMotionToken(GWindow *gw,float time,int tok, int b, int repeat)
{
    float xscale = 2.0/200.0;
    float yscale = 2.0/3.0;
    float cy;
    float ma = 1.0, mb = 0.0;
    float mc = 0.0, md = 1.0;
    float a = 0;
    float rev = 1.0;

    int line = gwinLineCreate(gw);
    gwinLineName(gw,line,0);
    gwinLineColor(gw,line,0x00c0c0);
    gwinLineScaleOffset(gw,line, 1.0, 1.0, 0.0, 0.0);
    gwinLineStep(gw,line, 0);

    #define TX(x,y) (rev*(x)*ma+(y)*mc)
    #define TY(x,y) (rev*(x)*mb+(y)*md)
    #define PT(x,y) \
            gwinLinePoint( \
                    gw, \
                    line, \
                    TX(x,y)*xscale + (scale_time*(time)), \
                    TY(x,y)*yscale + cy)
        
    cy = TOKEN_ANGLE(tok);
    a = cy * M_PI * 2.0 / 32.0;
    cy += angle_offset;
    while(cy<0) cy+=32;
    while(cy>32) cy-=32;

    if (b) {
        xscale /= 3;
        cy = (b==1) ? -6 : -22;
    }

    if (tok < 0 ) {
        if (b) {
            cy = (b==1) ? -8 : -24;
            PT(0,1);
            PT(0,-1);
        }

        return;
    }

    ma = md = cos(a);
    mb = sin(a);
    mc = -mb;
    rev = TOKEN_DIR(tok);


    switch(TOKEN_SHAPE(tok)) {
        case MSHP_PAUSE:
            ma = md = 1.0;
            mb = mc = 0.0;
            rev = 0;
            PT(-1,-1);
            PT( 1, 1);
            PT( 0, 0);
            PT(-1, 1);
            PT( 1,-1);
            break;
            
        case MSHP_CLEAN_CIRCLE_PLUS:
            gwinLineColor(gw,line,0x7fffff);
        case MSHP_CIRCLE_GAP:
            if (TOKEN_SHAPE(tok) == MSHP_CIRCLE_GAP) {
                gwinLineColor(gw,line,0x00ff00);
            }
        case MSHP_CLEAN_CIRCLE:
            PT( 0.4,-0.9);
            PT( 0.9,-0.4);
            PT( 0.9, 0.4);
            PT( 0.4, 0.9);
            PT(-0.4, 0.9);
            PT(-0.9, 0.4);
            PT(-0.9,-0.4);
            PT(-0.4,-0.9);
            PT(-0.8,-0.8);
            PT(-0.4,-0.9);
            PT(-0.5,-0.5);
            PT(-0.4,-0.9);
            break;

        case MSHP_DIRTY_CIRCLE_PLUS:
            gwinLineColor(gw,line,0x7fffff);
        case MSHP_DIRTY_CIRCLE:
            PT( 0.9, 0.4);
            PT( 0.4, 0.9);
            PT(-0.4, 0.9);
            PT(-0.9, 0.4);
            PT(-0.5, 0.5);
            PT(-0.9, 0.4);
            PT(-0.8, 0.8);
            PT(-0.9, 0.4);

            break;

        case MSHP_PULSE_PLUS:
            gwinLineColor(gw,line,0x7fffff);
        case MSHP_PULSE:
            PT(0,1);
            PT(0,-1);
            PT(0.25,0);
            PT(0,-1);
            PT(-0.25,0);
            PT(0,-1);
            break;

        default: break;

    }


    #undef PT
    #undef TX
    #undef TY
}

//===========================================================================
// drawDelta()
//===========================================================================
static void drawDelta(GWindow *gw,float time,int delta, int b)
{
    float xscale = 2.0/200.0;
    float yscale = 2.0/3.0;
    float cy;
    float ma = 1.0, mb = 0.0;
    float mc = 0.0, md = 1.0;
    float rev = 1.0;

    int line = gwinLineCreate(gw);
    gwinLineName(gw,line,0);
    if (delta<0) delta = -delta;
    gwinLineColor(gw,line,
            (delta)>=10 ? 0xff0000 :
            (delta)>=4  ? 0xffff00 :
            (delta)>=1  ? 0x0000ff : 0x00ff00);
    gwinLineScaleOffset(gw,line, 1.0, 1.0, 0.0, 0.0);
    gwinLineStep(gw,line, 0);

    #define TX(x,y) (rev*(x)*ma+(y)*mc)
    #define TY(x,y) (rev*(x)*mb+(y)*md)
    #define PT(x,y) \
            gwinLinePoint( \
                    gw, \
                    line, \
                    TX(x,y)*xscale + (scale_time*(time)), \
                    TY(x,y)*yscale + cy)
        
    cy = (b==1) ? -10 : -26;
    xscale /= 3;

    PT(-1,-1);
    PT(-1, 1);
    PT( 1, 1);
    PT( 1,-1);
    PT(-1,-1);

    #undef PT
    #undef TX
    #undef TY
}

//===========================================================================
// main()
//===========================================================================
int main(int argc, char *argv[])
{
    char title[1000];
    char *titlep = title;
    const char *filename = 0;
    const char *filename2 = 0;
    GWindow *gw;
    FILE *fp;
    int i;
    int line_x;
    int line_y;
    int line_z;
    int line_w;
    int line_f;
#if DRAW_EXTRA_CRAP
    int line_cmag;
    int line_cx;
    int line_cy;
    int line_cx2;
    int line_cy2;
#endif
    int line_xf;
    int line_yf;
    int line_theta;
    int line_mag;
    int line_tapmag;
    int line_tapmask;
    int line_axis;
    float  timeAdd = 0;
    float  time0,ltime;
    float  mintime, maxtime;
    float  time,x,y, z, w, f;
    float  Ntime,Nx,Ny, Nz, Nw;
    float  minx, maxx, miny, maxy;
    float  minz, maxz, minw, maxw;
    float  minf, maxf;
    float  min, max;
    double avgx,avgy,sum;
    float  scale_mag;
    float  scale_theta;
    float  offset_mag;
    float  offset_theta;
    float  last_x, last_y;

    *titlep=0;

    for (i=1; i<argc; i++) {
        titlep += sprintf(titlep, "%s ", argv[i]);
        if (argv[i][0] == '-') {
            switch(argv[i][1]) {
                case 'o':
                    OPT_oldmode = 1;
                    OPT_astate  = 0;
                    OPT_fmtb    = 0;
                    break;
                case 'b':
                    OPT_oldmode = 0;
                    OPT_astate  = 1;
                    OPT_fmtb    = 1;
                    break;
                case 'a':
                    OPT_oldmode = 0;
                    OPT_astate  = 1;
                    OPT_fmtb    = 0;
                    break;
                case 'r':
                    OPT_raw = 1;
                    break;
                case 's':
                    OPT_skip = strtol(argv[i]+2,0,10);
                    break;
                case 'x':
                    OPT_avgx = strtod(argv[i]+2,0);
                    break;
                case 'y':
                    OPT_avgy = strtod(argv[i]+2,0);
                    break;
                case 'q':
                    OPT_calc_exit = 1;
                    break;
                default:
                    printf("Unknown option: '%s'\n",argv[i]);
                    usage();
            }
        } else if (!filename) {
            filename = argv[i];
        } else if (!filename2) {
            filename2 = argv[i];
        } else {
            printf("Too many arguments: '%s'\n",argv[i]);
            usage();
        }
    }
    *titlep=0;

    if (!filename) {
        printf("Please suppy filename\n");
        usage();
    }

    if (OPT_skip < 0) {
        printf("Bad OPT_skip = %d < 0\n",OPT_skip);
        usage();
    }

    gw = gwinCreate();
    gwinSetArgs(gw, argc,argv);
    gwinSetName(gw, title);
    gwinSetISize(gw, WIN_WIDTH, WIN_HEIGHT);
    gwinOpen(gw);

    gwinSetCallback(gw,runLook,0);

    printf("red     = x\n");
    printf("blue    = y\n");
    printf("magenta = theta\n");
    printf("yellow  = mag\n");

    g_filename = filename;
    fp = fopen(filename,"r");
    getline(fp,&Ntime,&Nx,&Ny,&Nz,&Nw);
    for(i=0; ; i++) {
        float lltime;

        time = Ntime;
        x = Nx;
        y = Ny;
        z = Nz;
        w = Nw;
        if (!getline(fp,&Ntime,&Nx,&Ny,&Nz,&Nw)) break;

        if (i<=OPT_skip) {
            avgx = avgy = 0;
            minx = maxx = x;
            miny = maxy = y;
            minz = maxz = z;
            minw = maxw = w;
            maxf = 0;
            minf = 1000;
            if (0) {
                miny = 0.0;
                minz = 0.0;
                minw = 0.0;
                maxy = 255.0;
                maxz = 255.0;
                maxw = 255.0;
            }
            mintime = maxtime = 0;
            time0 = time;
            ltime = 0;
            if (i != OPT_skip) continue;
        }
        while(time-time0+timeAdd < ltime) {
            time0 -= 65536;
        }
        lltime = ltime;
        ltime = time - time0 + timeAdd;
        if (maxtime < ltime) {
            maxtime = ltime;
        }
        f = 0;
        if (OPT_fmtb) {
            if (Ntime > time) {
                f = y/(Ntime-time);
            }
        }
        if (minx > x)
            minx = x;
        if (miny > y)
            miny = y;
        if (minz > z)
            minz = z;
        if (minw > w)
            minw = w;
        if (minf > f)
            minf = f;
        if (maxx < x)
            maxx = x;
        if (maxy < y)
            maxy = y;
        if (maxz < z)
            maxz = z;
        if (maxw < w)
            maxw = w;
        if (maxf < f)
            maxf = f;

        if (i!=OPT_skip) {
            double dt = lltime - ltime;
            avgx += last_x * dt;
            avgy += last_y * dt;
            sum  += dt;
        }

#if 0
        if (OPT_astate && y >250) {
            timeAdd += 500.0;
        }
#endif

        last_x = x;
        last_y = y;
    }
    fclose(fp);

    timeAdd=0;

    if (i<=OPT_skip) {
        printf("Only %d points found\n",i);
    }

    max = maxx > maxy ? maxx : maxy;
    min = minx < miny ? minx : miny;

    x = 0.5 * (maxx - minx);
    y = 0.5 * (maxy - miny);
    scale_mag = (max - min) / 127.0;
    offset_mag = max + 0.1 * (max-min);

    scale_theta = 0.5 * (max-min) / M_PI;
    offset_theta = max + 0.6 * (max-min);

    avgx *= 1.0/sum;
    avgy *= 1.0/sum;
    if (OPT_avgx < 0) OPT_avgx = avgx;
    if (OPT_avgy < 0) OPT_avgy = avgy;

    if (OPT_raw) {

        line_x = gwinLineCreate(gw);
        gwinLineName(gw,line_x,"X");
        gwinLineColor(gw,line_x,0xff0000);

        line_y = gwinLineCreate(gw);
        gwinLineName(gw,line_y,"Y");
        gwinLineColor(gw,line_y,0x0000ff);

    } else if (OPT_astate) {

#if 0
        line_axis = gwinLineCreate(gw);
        gwinLineName(gw,line_axis,0);
        gwinLineColor(gw,line_axis,0xffff00);
        gwinLinePoint(
                    gw,
                    line_axis,
                    scale_time*(mintime-1),
                    1.5);
        gwinLinePoint(
                    gw,
                    line_axis,
                    scale_time*(maxtime+1),
                    1.5);

        line_axis = gwinLineCreate(gw);
        gwinLineName(gw,line_axis,0);
        gwinLineColor(gw,line_axis,0xffff00);
        gwinLinePoint(
                    gw,
                    line_axis,
                    scale_time*(mintime-1),
                    5.5);
        gwinLinePoint(
                    gw,
                    line_axis,
                    scale_time*(maxtime+1),
                    5.5);

        line_axis = gwinLineCreate(gw);
        gwinLineName(gw,line_axis,0);
        gwinLineColor(gw,line_axis,0xffff00);
        gwinLinePoint(
                    gw,
                    line_axis,
                    scale_time*(mintime-1),
                    9.5);
        gwinLinePoint(
                    gw,
                    line_axis,
                    scale_time*(maxtime+1),
                    9.5);

        line_axis = gwinLineCreate(gw);
        gwinLineName(gw,line_axis,0);
        gwinLineColor(gw,line_axis,0xffff00);
        gwinLinePoint(
                    gw,
                    line_axis,
                    scale_time*(mintime-1),
                    13.5);
        gwinLinePoint(
                    gw,
                    line_axis,
                    scale_time*(maxtime+1),
                    13.5);

        line_axis = gwinLineCreate(gw);
        gwinLineName(gw,line_axis,0);
        gwinLineColor(gw,line_axis,0xffff00);
        gwinLinePoint(
                    gw,
                    line_axis,
                    scale_time*(mintime-1),
                    17.5);
        gwinLinePoint(
                    gw,
                    line_axis,
                    scale_time*(maxtime+1),
                    17.5);

        line_axis = gwinLineCreate(gw);
        gwinLineName(gw,line_axis,0);
        gwinLineColor(gw,line_axis,0xffff00);
        gwinLinePoint(
                    gw,
                    line_axis,
                    scale_time*(mintime-1),
                    21.5);
        gwinLinePoint(
                    gw,
                    line_axis,
                    scale_time*(maxtime+1),
                    21.5);

        line_axis = gwinLineCreate(gw);
        gwinLineName(gw,line_axis,0);
        gwinLineColor(gw,line_axis,0xffff00);
        gwinLinePoint(
                    gw,
                    line_axis,
                    scale_time*(mintime-1),
                    25.5);
        gwinLinePoint(
                    gw,
                    line_axis,
                    scale_time*(maxtime+1),
                    25.5);

        line_axis = gwinLineCreate(gw);
        gwinLineName(gw,line_axis,0);
        gwinLineColor(gw,line_axis,0xffff00);
        gwinLinePoint(
                    gw,
                    line_axis,
                    scale_time*(mintime-1),
                    29.5);
        gwinLinePoint(
                    gw,
                    line_axis,
                    scale_time*(maxtime+1),
                    29.5);
#endif

        line_axis = gwinLineCreate(gw);
        gwinLineName(gw,line_axis,0);
        gwinLineColor(gw,line_axis,0x00ff00);
        gwinLinePoint(
                    gw,
                    line_axis,
                    scale_time*(mintime-1),
                     3.5 + angle_offset);
        gwinLinePoint(
                    gw,
                    line_axis,
                    scale_time*(maxtime+1),
                     3.5 + angle_offset);

        line_axis = gwinLineCreate(gw);
        gwinLineName(gw,line_axis,0);
        gwinLineColor(gw,line_axis,0x00ff00);
        gwinLinePoint(
                    gw,
                    line_axis,
                    scale_time*(mintime-1),
                    11.5 + angle_offset);
        gwinLinePoint(
                    gw,
                    line_axis,
                    scale_time*(maxtime+1),
                    11.5 + angle_offset);

        line_axis = gwinLineCreate(gw);
        gwinLineName(gw,line_axis,0);
        gwinLineColor(gw,line_axis,0x00ff00);
        gwinLinePoint(
                    gw,
                    line_axis,
                    scale_time*(mintime-1),
                    19.5 + angle_offset);
        gwinLinePoint(
                    gw,
                    line_axis,
                    scale_time*(maxtime+1),
                    19.5 + angle_offset);

        line_axis = gwinLineCreate(gw);
        gwinLineName(gw,line_axis,0);
        gwinLineColor(gw,line_axis,0x00ff00);
        gwinLinePoint(
                    gw,
                    line_axis,
                    scale_time*(mintime-1),
                    27.5 + angle_offset);
        gwinLinePoint(
                    gw,
                    line_axis,
                    scale_time*(maxtime+1),
                    27.5 + angle_offset);


#if DRAW_EXTRA_CRAP
        line_axis = gwinLineCreate(gw);
        gwinLineName(gw,line_axis,0);
        gwinLineColor(gw,line_axis,0x00ffff);
        gwinLineScaleOffset(gw,line_axis,
                            1.0, 31.0/4.0, 0.0, 0.0);
        gwinLinePoint(
                    gw,
                    line_axis,
                    scale_time*(mintime-1),
                    3584.0/16.0);
        gwinLinePoint(
                    gw,
                    line_axis,
                    scale_time*(maxtime+1),
                    3584.0/16.0);
#endif


        line_axis = gwinLineCreate(gw);
        gwinLineName(gw,line_axis,0);
        gwinLineColor(gw,line_axis,0x00cfcf);
        gwinLineScaleOffset(gw,line_axis,
                            1.0, 32.0/(maxy), 0.0, -32.0);
        gwinLinePoint(
                    gw,
                    line_axis,
                    scale_time*(mintime-1),
                    0.0);
        gwinLinePoint(
                    gw,
                    line_axis,
                    scale_time*(maxtime+1),
                    0.0);

        line_axis = gwinLineCreate(gw);
        gwinLineName(gw,line_axis,0);
        gwinLineColor(gw,line_axis,0x00cfcf);
        gwinLineScaleOffset(gw,line_axis,
                            1.0, 32.0/(maxy), 0.0, -32.0);
        gwinLinePoint(
                    gw,
                    line_axis,
                    scale_time*(mintime-1),
                    256.0);
        gwinLinePoint(
                    gw,
                    line_axis,
                    scale_time*(maxtime+1),
                    256.0);

        if (maxy>1024) {

            line_axis = gwinLineCreate(gw);
            gwinLineName(gw,line_axis,0);
            gwinLineColor(gw,line_axis,0x00cfcf);
            gwinLineScaleOffset(gw,line_axis,
                                1.0, 32.0/(maxy), 0.0, -32.0);
            gwinLinePoint(
                        gw,
                        line_axis,
                        scale_time*(mintime-1),
                        1024.0);
            gwinLinePoint(
                        gw,
                        line_axis,
                        scale_time*(maxtime+1),
                        1024.0);
        }

        line_axis = gwinLineCreate(gw);
        gwinLineName(gw,line_axis,0);
        gwinLineColor(gw,line_axis,0xffff00);
        gwinLineScaleOffset(gw,line_axis,
                            1.0, 1.0, 0.0, 32.0);
        gwinLinePoint(
                    gw,
                    line_axis,
                    scale_time*(mintime-1),
                    (float)0x20);
        gwinLinePoint(
                    gw,
                    line_axis,
                    scale_time*(maxtime+1),
                    (float)0x20);


        line_x = gwinLineCreate(gw);
        gwinLineName(gw,line_x,"Angle");
        gwinLineColor(gw,line_x,0xff0000);

        line_y = gwinLineCreate(gw);
        if (OPT_fmtb) {
            gwinLineName(gw,line_y,"Imp");
        } else {
            gwinLineName(gw,line_y,"Mag");
        }
        gwinLineColor(gw,line_y,0x00ffff);

        line_z = gwinLineCreate(gw);
        gwinLineName(gw,line_z,"Magmin");
        gwinLineColor(gw,line_z,0xcfcf00);

        line_w = gwinLineCreate(gw);
        gwinLineName(gw,line_w,"MagMax");
        gwinLineColor(gw,line_w,0xffff00);

        line_f = gwinLineCreate(gw);
        gwinLineName(gw,line_f,"AvgMag");
        gwinLineColor(gw,line_f,0x00ffff);

        if (maxy<256) maxy = 256;
        gwinLineScaleOffset(gw,line_x,
                            1.0, 1.0, 0.0, 0.0);
        gwinLineScaleOffset(gw,line_y,
                            1.0, 32.0/(maxy), 0.0, -32.0);
        gwinLineScaleOffset(gw,line_z,
                            1.0, 1.0, 0.0, 32.0);
        gwinLineScaleOffset(gw,line_w,
                            1.0, 1.0, 0.0, 32.0);
        gwinLineScaleOffset(gw,line_f,
                            1.0, 1.0, 0.0, 32.0);

printf("%8.1f %8.1f  %8.1f %8.1f  %8.1f %8.1f\n",
miny,maxy,minz,maxz,minw,maxw);


#if DRAW_EXTRA_CRAP
        line_cmag = gwinLineCreate(gw);
        gwinLineName(gw,line_cmag,"CalcMag");
        gwinLineColor(gw,line_cmag,0xff00ff);
        gwinLineScaleOffset(gw,line_cmag,
                            1.0, 1.0, 0.0, 31.0*3584.0/64.0);

        line_cx = gwinLineCreate(gw);
        gwinLineName(gw,line_cx,"CalcX");
        gwinLineColor(gw,line_cx,0xff0000);
        gwinLineScaleOffset(gw,line_cx,
                            1.0, 1.0, 0.0, 31.0*3584.0/64.0);

        line_cy = gwinLineCreate(gw);
        gwinLineName(gw,line_cy,"CalcY");
        gwinLineColor(gw,line_cy,0x0000ff);
        gwinLineScaleOffset(gw,line_cy,
                            1.0, 1.0, 0.0, 31.0*3584.0/64.0);


        line_axis = gwinLineCreate(gw);
        gwinLineName(gw,line_axis,0);
        gwinLineColor(gw,line_axis,0x00ffff);
        gwinLineScaleOffset(gw,line_axis,
                            1.0, 31.0/4.0, 0.0, 64.0);
        gwinLinePoint(
                    gw,
                    line_axis,
                    scale_time*(mintime-1),
                    3584.0/16.0);
        gwinLinePoint(
                    gw,
                    line_axis,
                    scale_time*(maxtime+1),
                    3584.0/16.0);

        line_axis = gwinLineCreate(gw);
        gwinLineName(gw,line_axis,0);
        gwinLineColor(gw,line_axis,0x00ffff);
        gwinLineScaleOffset(gw,line_axis,
                            1.0, 31.0/4.0, 0.0, 32.0+64.0);
        gwinLinePoint(
                    gw,
                    line_axis,
                    scale_time*(mintime-1),
                    3584.0/16.0);
        gwinLinePoint(
                    gw,
                    line_axis,
                    scale_time*(maxtime+1),
                    3584.0/16.0);


        line_cx2 = gwinLineCreate(gw);
        gwinLineName(gw,line_cx2,"CalcX");
        gwinLineColor(gw,line_cx2,0xff0000);
        gwinLineScaleOffset(gw,line_cx2,
                            1.0, 1.0, 0.0, 64.0 + 31.0*3584.0/64.0);

        line_cy2 = gwinLineCreate(gw);
        gwinLineName(gw,line_cy2,"CalcY");
        gwinLineColor(gw,line_cy2,0x0000ff);
        gwinLineScaleOffset(gw,line_cy2,
                            1.0, 1.0, 0.0, 64.0+32.0 + 31.0*3584.0/64.0);
#endif



    } else {
        line_axis = gwinLineCreate(gw);
        gwinLineName(gw,line_axis,0);
        gwinLineColor(gw,line_axis,0xff0000);
        gwinLinePoint(
                    gw,
                    line_axis,
                    scale_time*(mintime-1),
                    OPT_avgx);
        gwinLinePoint(
                    gw,
                    line_axis,
                    scale_time*(maxtime+1),
                    OPT_avgx);

        line_axis = gwinLineCreate(gw);
        gwinLineName(gw,line_axis,0);
        gwinLineColor(gw,line_axis,0x0000ff);
        gwinLinePoint(
                    gw,
                    line_axis,
                    scale_time*(mintime-1),
                    OPT_avgy);
        gwinLinePoint(
                    gw,
                    line_axis,
                    scale_time*(maxtime+1),
                    OPT_avgy);

        line_axis = gwinLineCreate(gw);
        gwinLineName(gw,line_axis,0);
        gwinLineColor(gw,line_axis,0xff00ff);
        gwinLinePoint(
                    gw,
                    line_axis,
                    scale_time*(mintime-1),
                    offset_theta);
        gwinLinePoint(
                    gw,
                    line_axis,
                    scale_time*(maxtime+1),
                    offset_theta);

        line_axis = gwinLineCreate(gw);
        gwinLineName(gw,line_axis,0);
        gwinLineColor(gw,line_axis,0xffff00);
        gwinLinePoint(
                    gw,
                    line_axis,
                    scale_time*(mintime-2),
                    offset_mag + 127.0*scale_mag);
        gwinLinePoint(
                    gw,
                    line_axis,
                    scale_time*(mintime-1),
                    offset_mag);
        gwinLinePoint(
                    gw,
                    line_axis,
                    scale_time*(maxtime+1),
                    offset_mag);

        line_x = gwinLineCreate(gw);
        gwinLineName(gw,line_x,"AccX");
        gwinLineColor(gw,line_x,0x7f0000);

        line_y = gwinLineCreate(gw);
        gwinLineName(gw,line_y,"AccY");
        gwinLineColor(gw,line_y,0x00007f);
    }


    fp = fopen(filename,"r");
    getline(fp,&Ntime,&Nx,&Ny,&Nz,&Nw);
    for(i=0; ; i++) {
        float lltime;
        int flags = 0;

        time = Ntime;
        x = Nx;
        y = Ny;
        z = Nz;
        w = Nw;
        if (!getline(fp,&Ntime,&Nx,&Ny,&Nz,&Nw)) break;

        if (i<=OPT_skip) {
            time0 = time;
            ltime = 0;
            if (i != OPT_skip) continue;
        }
        while(time-time0+timeAdd < ltime) {
            time0 -= 65536;
        }


        lltime = ltime;
        ltime = time - time0 + timeAdd;

        f = 0;
        if (OPT_fmtb) {
            if (Ntime > time) {
                f = y/(Ntime-time);
            }
        }

        //
        // show stairstep if the same val for a long time
        //
        if (0 && !OPT_astate) {
            if (i != OPT_skip && scale_time * (ltime - lltime) > 0.2) {
                flags |= GW_LFLG_STEPY;
            }
        }

        if (OPT_astate) {
            float x2 = x;
            static float old_x2 = -1;
            if (x2 < 33 || !OPT_separate) {
                float d;
                if (x2 < 33) {
                    x2 += angle_offset;
                    while(x2<0) x2+=32;
                    while(x2>32) x2-=32;
                }
                if (old_x2 > 33) {
                    old_x2 = x2;
                }
                d = x2 - old_x2;
                if (d<0) d=-d;
                if (d>20) {
                    float xt = 0;
                    if (old_x2 > x2) {
                        xt = 32;
                    }
                    gwinLinePointFlags(
                                gw,
                                line_x,
                                scale_time*ltime,
                                xt,
                                flags);
                    line_x = gwinLineCreate(gw);
                    gwinLineName(gw,line_x,"Angle");
                    gwinLineColor(gw,line_x,0xff0000);

                    gwinLineScaleOffset(gw,line_x,
                                        1.0, 1.0, 0.0, 0.0);
                    xt = 32;
                    if (old_x2 > x2) {
                        xt = 0;
                    }
                    gwinLinePointFlags(
                                gw,
                                line_x,
                                scale_time*ltime,
                                xt,
                                flags);
                }
                gwinLinePointFlags(
                            gw,
                            line_x,
                            scale_time*ltime,
                            x2,
                            flags);
            } else {
                if (old_x2 < 33) {
                    gwinLinePointFlags(
                                gw,
                                line_x,
                                scale_time*ltime,
                                old_x2,
                                flags);
                }
                line_x = gwinLineCreate(gw);
                gwinLineName(gw,line_x,"Angle");
                gwinLineColor(gw,line_x,0xff0000);

                gwinLineScaleOffset(gw,line_x,
                                    1.0, 1.0, 0.0, 0.0);

            }
            old_x2 = x2;

            drawTick(gw,ltime,
                ((i % 10)==0) ? 2 : 1);

            if (OPT_fmtb) {
                // ltime = time
                // x = angle
                // y = impulse
                // z = minmag
                // w = maxmag
                gwinLinePointFlags(
                            gw,
                            line_y,
                            scale_time*ltime,
                            y,
                            flags);
                gwinLinePointFlags(
                            gw,
                            line_z,
                            scale_time*ltime,
                            z,
                            flags);
                gwinLinePointFlags(
                            gw,
                            line_w,
                            scale_time*ltime,
                            w,
                            flags);
                gwinLinePointFlags(
                            gw,
                            line_f,
                            scale_time*ltime,
                            f,
                            flags);
            } else {
                // ltime = time
                // x = angle
                // y = mag
                gwinLinePointFlags(
                            gw,
                            line_y,
                            scale_time*ltime,
                            sqrt(y),
                            flags);
            }
        } else {

            gwinLinePointFlags(
                        gw,
                        line_x,
                        scale_time*ltime,
                        x,
                        flags);


            gwinLinePointFlags(
                        gw,
                        line_y,
                        scale_time*ltime,
                        y,
                        flags);
        }

#if DRAW_EXTRA_CRAP
        if (OPT_astate) {
            float cmag = sqrt(y);
            float t = (x+0.5) * M_PI * 2 * (1/32.0);
            float cx = cos(t) * cmag;
            float cy = sin(t) * cmag;

            gwinLinePointFlags(
                        gw,
                        line_cmag,
                        scale_time*ltime,
                        cmag,
                        flags);

            gwinLinePointFlags(
                        gw,
                        line_cx,
                        scale_time*ltime,
                        cx,
                        flags);

            gwinLinePointFlags(
                        gw,
                        line_cy,
                        scale_time*ltime,
                        cy,
                        flags);

            gwinLinePointFlags(
                        gw,
                        line_cx2,
                        scale_time*ltime,
                        cx,
                        flags);

            gwinLinePointFlags(
                        gw,
                        line_cy2,
                        scale_time*ltime,
                        cy,
                        flags);
        }
#endif

#if 0
        //
        // stretch taps out
        //
        if (OPT_astate && y >250) {
            timeAdd += 500.0;
        }
#endif

    }
    fclose(fp);

    //
    // derived lines
    //
    if (OPT_raw) {
    } else if (OPT_astate) {
#if 0
        {
            static GWinArgDesc args_xf[] = {
                { GW_ARGTYPE_LINE, "AccX", },
                { 0,},
            };
            line_xf = gwinLineCreate(gw);
            gwinLineName(gw,line_xf, "AccX filt");
            gwinLineColor(gw,line_xf, 0xff0000);
            gwinLineFunc(gw, line_xf, func_filter, args_xf);
        }
#endif
    } else {
        {
            static GWinArgDesc args_xf[] = {
                { GW_ARGTYPE_VAR, "FiltDT", 0.001, },
                { GW_ARGTYPE_LINE, "AccX", },
                { 0,},
            };
            line_xf = gwinLineCreate(gw);
            gwinLineName(gw,line_xf, "AccX filt");
            gwinLineColor(gw,line_xf, 0xff0000);
            gwinLineFunc(gw, line_xf, func_filter, args_xf);
        }
        {
            static GWinArgDesc args_yf[] = {
                { GW_ARGTYPE_VAR, "FiltDT", 0.001, },
                { GW_ARGTYPE_LINE, "AccY", },
                { 0,},
            };
            line_yf = gwinLineCreate(gw);
            gwinLineName(gw,line_yf, "AccY filt");
            gwinLineColor(gw,line_yf, 0x0000ff);
            gwinLineFunc(gw, line_yf, func_filter, args_yf);
        }
        {
            static GWinArgDesc args_mag[] = {
                { GW_ARGTYPE_LINE, "AccX filt", },
                { GW_ARGTYPE_LINE, "AccY filt", },
                { 0,},
            };
            line_mag = gwinLineCreate(gw);
            gwinLineName(gw,line_mag, "Mag2");
            gwinLineColor(gw,line_mag, 0xffff00);
            gwinLineScaleOffset(gw,line_mag,
                            1.0, scale_mag, 0.0, offset_mag);
            gwinLineFunc(gw, line_mag, func_mag, args_mag);
        }
        {
            static GWinArgDesc args_angle[] = {
                { GW_ARGTYPE_LINE, "AccX filt", },
                { GW_ARGTYPE_LINE, "AccY filt", },
                { 0,},
            };
            line_theta = gwinLineCreate(gw);
            gwinLineName(gw,line_theta, "Theta");
            gwinLineColor(gw,line_theta,0xff00ff);
            gwinLineScaleOffset(gw,line_theta,
                            1.0, scale_theta, 0.0, offset_theta);
            gwinLineFunc(gw, line_theta, func_angle, args_angle);
        }
        {
            static GWinArgDesc args_tapmag[] = {
                { GW_ARGTYPE_LINE, "AccX filt", },
                { GW_ARGTYPE_LINE, "AccY filt", },
                { 0,},
            };
            line_tapmag = gwinLineCreate(gw);
            gwinLineName(gw,line_tapmag, "TapMag");
            gwinLineColor(gw,line_tapmag,0xff0000);
            gwinLineScaleOffset(gw,line_tapmag,
                            1.0, scale_theta, 0.0, offset_theta);
            gwinLineFunc(gw, line_tapmag, func_tapmag, args_tapmag);
        }
        {
            static GWinArgDesc args_tapmask[] = {
                { GW_ARGTYPE_LINE, "TapMag", },
                { 0,},
            };
            line_tapmask = gwinLineCreate(gw);
            gwinLineName(gw,line_tapmask, "TapMask");
            gwinLineColor(gw,line_tapmask,0xff0000);
            gwinLineScaleOffset(gw,line_tapmask,
                            1.0, scale_theta, 0.0, offset_theta);
            gwinLineFunc(gw, line_tapmask, func_tapmask, args_tapmask);
        }
    }

    if (filename2) do {
        float te = 0;
        float dte = 1;
        float tf = 0;
        float timax = 0.0;
        float lastd = 1.0;
        float lasttf= 0.0;
        int mo[1000],sp[1000], delta[1000];
        float ti[1000];
        int cnt=0;
        int i;
        int repeat=0;
        int deltasum=0;
        fp = fopen(filename2, "r");
        if (!fp) break;
        while (1) {
            if (!getline(fp,&time,&x,&y,&z,0)) break;
            ti[cnt] = time;
            sp[cnt] = (int)x;
            mo[cnt] = (int)y;
            delta[cnt] = (int)z;
            if (time > timax) {
                timax = time;
            }
            cnt++;
            if (cnt>sizeof(ti)/sizeof(ti[0])) break;
        }
        fclose(fp);
        if (cnt<2) break;
        dte = timax/(float)cnt;
        te = 0;
        printf("\nMotion(blu)");
        for (i=0; i<cnt; i++) {
            if (mo[i]<0) {
                printf(" --");
            } else {
                printf(" %02x", mo[i]&0xff);
            }
        }
        printf("\nSpell(yel) ");
        for (i=0; i<cnt; i++) {
            if (sp[i]<0) {
                printf(" --");
            } else {
                printf(" %02x", sp[i]&0xff);
            }
        }


        printf("\nErr deltas:");
        for (i=0; i<cnt; i++) {
            lasttf = tf;
            if (i!=0 && ti[i] <= 0.0) {
                int j;
                float tf2;
                for (j=i+1; j<cnt && ti[j]<= 0.0; j++);
                tf2 = (j<cnt)?ti[j]:ti[cnt-1];
                tf += (tf2 - tf) / (float)(j-i);
                if (lasttf < tf) {
                    lastd = tf - lasttf;
                } else if (lasttf > tf) {
                    tf = lasttf + lastd;
                }
            } else {
                tf = ti[i];
            }

            if (lasttf == tf) {
                repeat++;
                deltasum += delta[i];
            } else {
                repeat=0;
                deltasum  = delta[i];
            }

            drawSpellToken(gw,ti[i],sp[i],0,repeat);
            drawSpellToken(gw,tf,   sp[i],1,repeat);
            drawSpellToken(gw,te,   sp[i],2,repeat);

            drawMotionToken(gw,ti[i],mo[i],0,repeat);
            drawMotionToken(gw,tf,   mo[i],1,repeat);
            drawMotionToken(gw,te,   mo[i],2,repeat);

            drawDelta(gw,tf,deltasum,1);
            drawDelta(gw,te,delta[i],2);
            printf(" %02d", delta[i]);

            drawConnectToken(gw,tf, te,i);

            te += dte;
        }
        printf("\n\n");
    } while(0);

    printf("Found %d points\n",i);
    gwinDraw(gw);


    if (!OPT_astate) {
        printf("@@mag_max= %10.5f %s\n",g_mag_max,g_filename);
        printf("@@avgx   = %10.5f %s\n",OPT_avgx,g_filename);
        printf("@@avgy   = %10.5f %s\n",OPT_avgy,g_filename);
    }

    if (OPT_calc_exit) {
        exit(0);
    }

    gwinEventLoop(gw);

    gwinDestroy(gw);
    return 0;
}


This file Copyright (C) 2006 by Nathan (Acorn) Pooley
Go to TOP Wand page
Go to Acorn's personal webpage
Go to Hogwarts website: www.gotohogwarts.com
Snout: www.snout.org/game
Gadgets of Justice Unlimited
Snout GC (Wiki)
Snout Wiki
File created by do_doc at Wed May 30 03:29:27 PDT 2007