// // 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