209 lines
5.8 KiB
Plaintext
209 lines
5.8 KiB
Plaintext
// does not work for all .gpx files
|
|
// writes to output on every mouseup after edit
|
|
// move points with mouse, alt+click to delete
|
|
// click/drag to pan
|
|
// mousewheel to zoom
|
|
|
|
tab = 10000;
|
|
tabsz = 0;
|
|
|
|
is_dirty = 0;
|
|
circle_size = 5;
|
|
|
|
function scale(v) global() ( (v - this.min) / (this.max-this.min) );
|
|
function unscale(v) global() ( v * (this.max-this.min) + this.min);
|
|
function zoom(sc) global() local(c h) (
|
|
h = (this.max - this.min) * sc;
|
|
c = (this.max + this.min) * .5;
|
|
this.max = c + h*.5;
|
|
this.min = c - h*.5;
|
|
);
|
|
function include(v) global() ( this.min = min(v,this.min); this.max = max(v,this.max); );
|
|
|
|
function scroll(amt) global() ( amt *= (this.max-this.min); this.max += amt; this.min += amt; );
|
|
function zoom_view(sc) ( v_lon.zoom(sc); v_lat.zoom(sc); );
|
|
function scroll_view(dx, dy) ( v_lat.scroll(-dy/gfx_h); v_lon.scroll(-dx/gfx_w); );
|
|
|
|
function hit_test(x,y,p) global(tab tabsz circle_size gfx_w gfx_h v_lat.scale v_lon.scale) local(p hit) (
|
|
hit = -1;
|
|
while (p < tabsz && hit < 0) (
|
|
sqr(v_lat.scale(tab[p*2+1])*gfx_h-y)+sqr(v_lon.scale(tab[p*2])*gfx_w-x) < circle_size*circle_size ? hit = p;
|
|
p += 1;
|
|
);
|
|
hit
|
|
);
|
|
|
|
function linearize(p,sz, slon, slat, elon, elat, rev) local(x) global()
|
|
(
|
|
rev ? ( x=slon; slon=elon; elon=x; x=slat; slat=elat; elat=x; );
|
|
elon = (elon - slon) / sz;
|
|
elat = (elat - slat) / sz;
|
|
loop(sz,
|
|
p[0] = slon;
|
|
p[1] = slat;
|
|
slon += elon;
|
|
slat += elat;
|
|
p += 2;
|
|
);
|
|
);
|
|
|
|
function make_lowpass(f filtsize filtpos) global() local(windowpos sincpos x)
|
|
(
|
|
x = 0;
|
|
loop(filtsize,
|
|
x == filtsize/2 ? (
|
|
f[x] = 1.0;
|
|
) : (
|
|
windowpos = 2 * x * $pi / filtsize;
|
|
sincpos = filtpos * $pi * (x - filtsize/2);
|
|
|
|
// blackman-harris * window
|
|
f[x] = (0.35875 - 0.48829 * cos(windowpos) + 0.14128 * cos(2*windowpos) - 0.01168 * cos(3*windowpos)) * sin(sincpos) / sincpos;
|
|
);
|
|
x+=1;
|
|
);
|
|
);
|
|
|
|
function lowpass() local(src sz i j lpf_pos v sx sy filt p) global(tab tabsz)
|
|
(
|
|
lpf_pos>0.001 ? lpf_pos *= 0.95 : lpf_pos = 0.9;
|
|
sz = 64;
|
|
src = tab+tabsz*2 + sz*4 + 1024;
|
|
filt = src + tabsz*2 + sz*4 + 1024;
|
|
make_lowpass(filt, sz, lpf_pos);
|
|
memcpy(src, tab, tabsz*2);
|
|
i = src;
|
|
j = src + tabsz*2;
|
|
loop(sz/2,
|
|
memcpy(i-2,i,2);
|
|
memcpy(j,j-2,2);
|
|
j+=2;
|
|
i-=2;
|
|
);
|
|
i = 0;
|
|
loop(tabsz,
|
|
tab[i*2] != 10000 ? (
|
|
p = j = sx = sy = 0;
|
|
loop(sz,
|
|
v = src[(i+j-sz/2)*2];
|
|
v != 10000 ? (
|
|
p += filt[j];
|
|
sx += v * filt[j];
|
|
sy += src[(i+j-sz/2)*2 + 1] * filt[j];
|
|
);
|
|
j+=1;
|
|
);
|
|
tab[i*2] = sx/p;
|
|
tab[i*2+1] = sy/p;
|
|
);
|
|
i+=1;
|
|
);
|
|
|
|
);
|
|
|
|
function do_file(srcfn, destfn) local(fp fpout p lat lon skipping) (
|
|
(fp = fopen(srcfn,"r")) > 0 ? (
|
|
destfn < 0 || (fpout = fopen(destfn,"w")) > 0 ? (
|
|
p = tab;
|
|
skipping = 0;
|
|
while (fgets(fp,#line)) (
|
|
match("%s<trkpt lat=\"%f\" lon=\"%f\">%s",#line,#lead,lat,lon,#trail) ? (
|
|
destfn < 0 ? ( tabsz+=1; v_lat.include(p[1] = -lat); v_lon.include(p[0] = lon);) :
|
|
( !(skipping = p[0] == 10000) ? fprintf(fpout,"%s<trkpt lat=\"%.7f\" lon=\"%.7f\">%s",#lead,-p[1],p[0],#trail); );
|
|
p += 2;
|
|
) : destfn >= 0 ? ( skipping ? ( match("*</trkpt>*",#line) ? skipping = 0; ) : fwrite(fpout,#line,0) );
|
|
);
|
|
destfn >= 0 ? fclose(fpout);
|
|
);
|
|
fclose(fp);
|
|
);
|
|
);
|
|
|
|
|
|
function run() (
|
|
mouse_wheel ? ( zoom_view(mouse_wheel < 0 ? 1.1 : 1/1.1); mouse_wheel = 0;);
|
|
(mouse_cap&1)? (
|
|
!(last_mouse_cap & 1) ? (
|
|
cap_mode >= 0 && (mouse_cap&4) ? (
|
|
tmp = hit_test(mouse_x,mouse_y,0);
|
|
tmp >= 0 ? (
|
|
tmp < cap_mode ? (
|
|
cap_cnt = cap_mode+cap_cnt - tmp;
|
|
cap_mode = tmp;
|
|
) : (
|
|
cap_cnt = max(cap_mode+cap_cnt, tmp) - cap_mode;
|
|
);
|
|
) : cap_mode = tmp;
|
|
) : (
|
|
cap_mode = hit_test(mouse_x,mouse_y,0);
|
|
cap_mode >= 0 ? (
|
|
cap_cnt = 1;
|
|
while (hit_test(mouse_x,mouse_y,cap_mode+cap_cnt) >= 0) ( cap_cnt += 1; );
|
|
);
|
|
);
|
|
cap_start_lon = v_lon.unscale(mouse_x/gfx_w);
|
|
cap_start_lat = v_lat.unscale(mouse_y/gfx_h);
|
|
) : cap_mode >= 0 ? (
|
|
cap_cnt > 1 && (mouse_cap&4) ? (
|
|
linearize(tab + cap_mode*2,cap_cnt, cap_start_lon, cap_start_lat,
|
|
v_lon.unscale(mouse_x/gfx_w), v_lat.unscale(mouse_y/gfx_h),
|
|
mouse_cap&8);
|
|
) : (
|
|
tab[cap_mode*2] = v_lon.unscale(mouse_x/gfx_w);
|
|
tab[cap_mode*2+1] = v_lat.unscale(mouse_y/gfx_h);
|
|
);
|
|
is_dirty = 1;
|
|
) : scroll_view(mouse_x-last_mouse_x,mouse_y-last_mouse_y);
|
|
) : (
|
|
(last_mouse_cap & 1) && (last_mouse_cap & 16) && cap_mode >= 0 ? (
|
|
tab[cap_mode*2] = 10000;
|
|
is_dirty = 1;
|
|
);
|
|
is_dirty ? ( do_file(argv[1], argv[2]); is_dirty = 0; );
|
|
);
|
|
last_mouse_cap = mouse_cap;
|
|
last_mouse_x = mouse_x;
|
|
last_mouse_y = mouse_y;
|
|
|
|
p = tab;
|
|
hadprev = dist = 0;
|
|
loop(tabsz,
|
|
p[0] != 10000 ? (
|
|
x = v_lon.scale(p[0])*gfx_w;
|
|
y = v_lat.scale(p[1])*gfx_h;
|
|
hadprev ? (
|
|
gfx_set(0,.5,.7);
|
|
gfx_line(v_lon.scale(llon)*gfx_w,v_lat.scale(llat)*gfx_h,x,y);
|
|
dist += sqrt(sqr((p[0] - llon) * cos(llat*$pi/180.0)*69.172) + sqr((p[1] - llat)*60));
|
|
);
|
|
cap_mode == (p-tab)/2 ? gfx_set(1,0,1) : gfx_set(0,1,0);
|
|
gfx_circle(x,y,circle_size);
|
|
llon = p[0];
|
|
llat = p[1];
|
|
hadprev = 1;
|
|
);
|
|
p += 2;
|
|
);
|
|
|
|
gfx_x=gfx_y=0;
|
|
gfx_set(1,1,0);
|
|
gfx_printf("distance (approx) %.2f mi\n",dist);
|
|
|
|
gfx_update();
|
|
c = gfx_getchar();
|
|
c == 'l' ? ( lowpass(); is_dirty = 1; );
|
|
c >= 0 && c != 27 ? defer("run()");
|
|
);
|
|
|
|
argc < 2 ? printf("Usage: %s file.gpx output.gpx\n",argv[0]) : (
|
|
v_lat.min = v_lon.min = 100000;
|
|
v_lat.max = v_lon.max = -100000;
|
|
do_file(argv[1],-1);
|
|
tabsz > 0 ? (
|
|
zoom_view(1.3);
|
|
gfx_init("gpx edit",1024,768);
|
|
defer("run()");
|
|
) : printf("Error: %s has no <trkpt lines matching\n",argv[1]);
|
|
);
|
|
|