From 84c51d9bde4ea16ac002e77d0c41bd384f21fe39 Mon Sep 17 00:00:00 2001 From: nick black Date: Sat, 16 May 2020 22:55:01 -0400 Subject: [PATCH] perfect exponential plots #606 Previously, we had the first interval top out at 1.0. This made clean mathematical sense, but it meant that we wasted the lowest |states - 1| representations. We now top out at ibase**(states - 1). The very bottom representation tops out at 1, meaning that any data is always distinguishable from no data. We no longer explicitly print spaces (aka the zeroth state for each glyph clade), so that we can exhibit more transparency. Properly account for miny at all times. Slots in an exponential plot are now exponential throughout; before, it was exponential across rows, and linear within a row. --- src/demo/xray.c | 1 - src/input/input.cpp | 1 + src/lib/plot.h | 27 +++++++++++++++++---------- 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/src/demo/xray.c b/src/demo/xray.c index 3f3514941..33181e2d5 100644 --- a/src/demo/xray.c +++ b/src/demo/xray.c @@ -25,7 +25,6 @@ make_slider(struct notcurses* nc, int dimy){ channels_set_fg_alpha(&channels, CELL_ALPHA_TRANSPARENT); channels_set_bg_alpha(&channels, CELL_ALPHA_TRANSPARENT); ncplane_set_base(n, " ", 0, channels); - ncplane_set_bg_alpha(n, CELL_ALPHA_BLEND); ncplane_set_scrolling(n, true); int r = 0x5f; int g = 0xaf; diff --git a/src/input/input.cpp b/src/input/input.cpp index 54edb675d..5a295fab7 100644 --- a/src/input/input.cpp +++ b/src/input/input.cpp @@ -215,6 +215,7 @@ int main(void){ auto n = nc.get_stdplane(&dimy, &dimx); ncpp::Plane pplane{PLOTHEIGHT, dimx, dimy - PLOTHEIGHT, 0, nullptr}; struct ncplot_options popts{}; + // FIXME would be nice to switch over to exponential at some level popts.flags = NCPLOT_OPTIONS_LABELTICKSD; popts.minchannel = popts.maxchannel = 0; channels_set_fg_rgb(&popts.minchannel, 0x40, 0x50, 0xb0); diff --git a/src/lib/plot.h b/src/lib/plot.h index bdce7e7e6..3fea0bb20 100644 --- a/src/lib/plot.h +++ b/src/lib/plot.h @@ -129,12 +129,13 @@ class ncppplot { // each transition is worth this much change in value const size_t states = geomdata[gridtype].height; // FIXME can we not rid ourselves of this meddlesome double? either way, the - // interval is one row's range (for linear plots), or the log10 of each row's - // range (for exponential plots). + // interval is one row's range (for linear plots), or the base (base^slots== + // maxy-miny) of the range (for exponential plots). double interval; if(exponentiali){ if(maxy > miny){ - interval = pow(maxy - miny, (double)1 / ((dimy - 1) * states)); + interval = pow(maxy - miny, (double)1 / (dimy * states)); +//fprintf(stderr, "miny: %ju maxy: %ju dimy: %d states: %zu\n", miny, maxy, dimy, states); }else{ interval = 0; } @@ -150,7 +151,7 @@ class ncppplot { for(int y = 0 ; y < dimy ; ++y){ char buf[PREFIXSTRLEN + 1]; if(exponentiali){ - ncmetric(pow(interval, y * states) * 100, 100, buf, 0, 1000, '\0'); + ncmetric(pow(interval, y * states + (states - 1)) * 100, 100, buf, 0, 1000, '\0'); }else{ ncmetric(interval * states * (y + 1) * 100, 100, buf, 0, 1000, '\0'); } @@ -187,7 +188,7 @@ class ncppplot { double intervalbase = miny; const wchar_t* egc = geomdata[gridtype].egcs; for(int y = 0 ; y < dimy ; ++y){ - size_t egcidx, sumidx = 0; + size_t egcidx = 0, sumidx = 0; // if we've got at least one interval's worth on the number of positions // times the number of intervals per position plus the starting offset, // we're going to print *something* @@ -196,11 +197,15 @@ class ncppplot { sumidx *= states; if(intervalbase < gvals[i]){ if(exponentiali){ - egcidx = (log(gvals[i]) - log(intervalbase)) * states / interval; + // we want the log-base-interval of gvals[i] + double scaled = log(gvals[i] - miny) / log(interval); + double sival = intervalbase ? log(intervalbase) / log(interval) : 0; + egcidx = scaled - sival; +//fprintf(stderr, "egcidx: %zu gvals: %u interval: %f scaled: %f sival: %f\n", egcidx, gvals[i], interval, scaled, sival); }else{ egcidx = (gvals[i] - intervalbase) / interval; } -//fprintf(stderr, "%d/%d ibase: %f egcidx: %zu\n", dimy - y - 1, x, intervalbase, egcidx); +//fprintf(stderr, "%d/%d ibase: %f ival: %f egcidx: %zu\n", dimy - y - 1, x, intervalbase, interval, egcidx); if(egcidx >= states){ egcidx = states - 1; done = false; @@ -210,14 +215,16 @@ class ncppplot { egcidx = 0; } } - if(ncplane_putwc_yx(ncp, dimy - y - 1, x, egc[sumidx]) <= 0){ - return -1; + if(sumidx){ + if(ncplane_putwc_yx(ncp, dimy - y - 1, x, egc[sumidx]) <= 0){ + return -1; + } } if(done){ break; } if(exponentiali){ - intervalbase = miny + pow(interval, y * states); + intervalbase = miny + pow(interval, (y + 1) * states - 1); }else{ intervalbase += (states * interval); }