-4

The input is slider range value Ex.(-5 to 5) or (X to Y)

I want the X axis intersection points like this (-5,0) (-2,0)(-0.5,0) (0.5,0) (2,0) (5,0) and consider the Point naming from P1 to P6 from left to right. So the difference(x2-x1) for the P1 and P2 also the P5 and P6 should be same when the slider value in middle, that is 0. Likewise the difference should be D1 > D2 > D3.......D4 < D5 < D6

D1 = (P2x - P1x) D2 = (P3x - P2x) ........ ........ D5 = (P4x - P5x) D6 = (P5x - P6x)

the difference should be like this

D1 == D6 D2 == D5 .... ....

this result will come when the slider on middle position (Ex) if the range is (-5 to 5), the slider value is 0

Let explain -Ve side:

If the slider comes on negative side which means -5 the difference will be D1 > D2 > D3 >......D5 > D6

If the slider comes on negative side which means -4 the difference will be D1 > D2 > D3 >......D5 > D6

and so on...

Difference between the output of -5 and -4 is D1,D2,D3.... of -5 is greater than D1,D2,D3.... of -4 like wise this will replicate result upto the slider value reaches middle point which means 0

let explain the +Ve side:

If the slider comes on positive side which means +5 the difference will be D1 < D2 < D3 <......D5 < D6

If the slider comes on positive side which means +4 the difference will be D1 < D2 < D3 <......D5 < D6

Difference between the output of +5 and +4 is D1,D2,D3.... of +5 is greater than D1,D2,D3.... of +4 like wise this will replicate result upto the slider value reaches middle point which means 0

Note : slider value will be any number between the range

Please refer the below image of X axis intersection points for slider value range

img

[Edit by Spektre]

Ok the original problem description has nothing to do with the actual problem. The problem statement is as this: Find out (reverse engineer) position of shelf dividers to match density slider for this page. (click on gradient and use density scrollbar). The scrollbar is symmetrical so start with 0-50% the rest can be mirrored. I manage to obtain these parameters:

int xi[6][5]=
    {
    {0,82,145,237,344},     // 0%
    {0,100,162,245,348},    // 10%
    {0,124,180,254,353},    // 20%
    {0,140,198,264,357},    // 30%
    {0,153,224,280,365},    // 40%
    {0,161,245,294,370}     // 50%
    };
int Ti[6][4]=
    {
    {  82, 63, 92, 107 },   // 0%
    { 100, 62, 83, 103 },   // 10%
    { 124, 56, 74,  99 },   // 20%
    { 140, 58, 66,  93 },   // 30%
    { 153, 71, 56,  85 },   // 40%
    { 161, 84, 49,  76 }    // 50%
    };

where xi[scrollbar] is list of approximate shelf divider positions and Ti[scrollbar] are the shelf sizes (periods) obtained for slider states { 0,10,20,30,40,50 } [%] if you want more precise positions do ityourself from this screenshot mix:

shelfs vs. scrollbar

The brown like V lines are the shelf dividers and the last one is constant due to set shelf width so ignore it. Here extra width for more points to enhance precision:

extra width

So the question is how to compute xi for any scrollbar position and preset shelf total width ?

Spektre
  • 49,595
  • 11
  • 110
  • 380
Honey
  • 366
  • 2
  • 4
  • 17
  • That seems like an interesting challenge, but StackOverflow is not a code writing service. – DisappointedByUnaccountableMod Jun 27 '17 at 07:27
  • @barny, I just want the logic(formula) to make the intersecting point on X-axis. – Honey Jun 27 '17 at 07:31
  • I want to have a holiday in the Caribbean. what have you tried so far? – DisappointedByUnaccountableMod Jun 27 '17 at 07:32
  • I tried to change the X-axis intersecting point when the slider change. But it's not a proper formula calculation. I did some manual calculation but not helps for me to obtain the output on all the scenario. – Honey Jun 27 '17 at 07:34
  • You have as much information (perhaps more?) than anyone on SO about your problem, and I imagine a lot more interest in a solution. You can perhaps measure how the wavelength changes at a few points on the x-axis and perhaps even plot those as points against the three different slider values. Then perhaps you can see that there is some systematic/formulaic relationship between these, or some systematic way the wavelength changes. – DisappointedByUnaccountableMod Jun 27 '17 at 07:37
  • Oh hang on I see you want the formula in Javascript. Right. – DisappointedByUnaccountableMod Jun 27 '17 at 07:39
  • I tried with my knowledge. Sin, Cos... all are having equal wavelength for their theta value. I want to be wavelength like increasing to decrease if the slider on max value and vise versa for the slider on min value. If the slider on middle, wavelength should be increasing then decreasing again increasing. – Honey Jun 27 '17 at 07:43
  • Yes, I want the formula. The wave like electromagnetic / Radio wave. – Honey Jun 27 '17 at 07:47
  • what do you know about the frequencies ? is the change linear or not ... – Spektre Jun 27 '17 at 07:49
  • @Spektre he should load the image into a pixel editor and count the pixel positions of the x-axis crossings to work out how the a in sin(ax). Doesn't seem like rocket science. Then fiddle around in excel, make a table with x and sin(ax) and plot a chart, fiddle some more until it looks close enough. Or maybe OP hopes someone will hand him a solution on a plate. – DisappointedByUnaccountableMod Jun 27 '17 at 07:53
  • @Spektre, I don't the exact answer, but frequency inversely proportional to wavelength. – Honey Jun 27 '17 at 07:56
  • @Hornet that is not what I asked ... scroll bar is position of your peak frequency but what is the transition between start/end frequency and the peak .... linear, logarithmic, polynomial ??? – Spektre Jun 27 '17 at 07:58
  • @Spektre, start / end frequency is not matter for me. I want the X-axis value where wave intersecting. But the main thing is the result x- points should be increasing to decreasing and vice versa based on slider. – Honey Jun 27 '17 at 08:02
  • @Hornet no that is not what you want that way of generating will make you insane (unless I miss understood what you are trying to achieve) I am writing answer wait few mins – Spektre Jun 27 '17 at 08:04
  • This looks like a chirp: https://en.wikipedia.org/wiki/Chirp – duffymo Jun 27 '17 at 12:17
  • @Hornet I added edit1 to your question with the actual problem description. It seems like the transition is nonlinear so I would try polynomial fit of the `Ti` as function of scrollbar and shelf divider position. I estimate you would need at least cubic fit for this (quadratic was not enough during my tests) that needs more points so the extra wide image is the only option. You can try to use this [How approximation search works](https://stackoverflow.com/a/36163847/2521214) but the fit itself requires some more thinking about what should depend on what ... may be latter – Spektre Jun 28 '17 at 12:24

2 Answers2

0

The simplest model I can think of which would produce a result like this is the sine of a non-linear function like this:

enter image description here

Where X, Y are your plotting coordinates, S is your slider position, and a, b, c, d, e are parameters you need to adjust to match the plot to the desired result.

Note: d is rather unimportant since it is just a small phase shift. c determines the sensitivity to slider value changes, and b determines how fast the frequency / wavelength changes. a is just a vertical scaling factor (the amplitude). e determines how smoothly the frequency changes - I found ~0.15 was quite good.


EDIT:

Ok, since you only want the X-axis points, we need to solve this equation to find the roots. These are the solutions to:

enter image description here

Where n is some integer which gives each X-point you want. Therefore we need to solve:

enter image description here

Just iterate through n for all the X-points, taking into account the two cases.


EDIT 2: As Blindmann pointed out, this expression will diverge if e > 1, so the constraint is 0 < e < 1; this will ensure that in the limit as X approaches cS it does not diverge.

meowgoesthedog
  • 14,670
  • 4
  • 27
  • 40
  • I want the X-axis intersecting points, the wave that I mentioned only for understanding purpose. I want the x axis value from increasing to decreasing and vise versa for slider change. I have only one input which is slider value. – Honey Jun 27 '17 at 08:22
  • @Hornet i've added the result you want – meowgoesthedog Jun 27 '17 at 08:38
  • Think something like sin((2/(1+2^(-x+S))-1)*c) will avoid the infinity as your (X-cS) approaches 0 – Blindman67 Jun 27 '17 at 09:18
0

I see it like you are doing frequency change f0 -> f1 -> f0 where scroll bar V is the position where the f1 is present.

f(-Ve) = f0 if V!=-Ve
f( V ) = f1
f(+Ve) = f0 if V!=+Ve

Divide the intervals to f0 -> f1 and f1 -> f0. Try linear interpolation first:

f(x) = f0 + (f1-f0)*(x+Ve)/(V+Ve)    x = <-Ve, V >
f(x) = f1 + (f0-f1)*(x-V )/(Ve-V)    x = < V ,+Ve>

Now just generate your wave here simple C++/VCL I busted for this:

    // clear buffer
    bmp->Canvas->Brush->Color=clBlack;
    bmp->Canvas->FillRect(TRect(0,0,xs,ys));

    float y0=ys/2,A=ys/3; // zero is in middle of image and amplitudes is 1/3 image height
    float f0= 5.0*(2.0*M_PI/float(xs)); // 5 periods per image width
    float f1=25.0*(2.0*M_PI/float(xs)); // 25 periods per image width
    float V=ScrollBar1->Position; // scroll bar is from -Ve to +Ve
    const float Ve=1000;
    float f,t,x,xx,yy;

    t=0; yy=y0+A*sin(t);
    bmp->Canvas->Pen->Color=clWhite;
    bmp->Canvas->MoveTo(0,yy);
    if (V>-Ve) for (x=-Ve;x<=V;x++)
        {
        xx=(x+Ve)*xs/(2.0*Ve);          // convert x to screen position
        yy=y0+A*sin(t);                 // compute actual amplitude
        bmp->Canvas->LineTo(xx,yy);     // render it
        f=f0+(f1-f0)*(x+Ve)/(V+Ve);     // compute actual frequency
        t+=f;                           // update actual time with it
        }
    if (V<+Ve) for (x=V;x<+Ve;x++)
        {
        xx=(x+Ve)*xs/(2.0*Ve);          // convert x to screen position
        yy=y0+A*sin(t);                 // compute actual amplitude
        bmp->Canvas->LineTo(xx,yy);     // render it
        f=f1+(f0-f1)*(x-V )/(Ve-V);     // compute actual frequency
        t+=f;                           // update actual time with it
        }

    // render backbuffer
    Main->Canvas->Draw(0,0,bmp);

Just ignore the rendering stuff (replace it with your environment style of coding) the xs,ys is image bmp resolution and M_PI=3.1415 Here preview:

img

And here captured animated GIF (lower the f0,f1 slightly):

animation

For more info see similar QA:

[Edit1] in case you really need the intersection points

Then just detect zero crossings by detecting sign change in y axis and interpolate the position from 2 consequent points. The program changes just slightly:

// clear buffer
bmp->Canvas->Brush->Color=clBlack;
bmp->Canvas->FillRect(TRect(0,0,xs,ys));

float y0=ys/2,A=ys/3;
float f0= 1.5*(2.0*M_PI/float(xs)); // 1.5 periods per image width
float f1=10.0*(2.0*M_PI/float(xs)); // 10 periods per image width
float V=ScrollBar1->Position;
const float Ve=1000;
float f,t,x,xx,xx0,yy,yy0,r=4;

bmp->Canvas->Pen->Color=clWhite;
bmp->Canvas->Brush->Color=clWhite;
x=-Ve; t=0;
xx=(x+Ve)*xs/(2.0*Ve);          // convert x to screen position
yy=y0+A*sin(t);                 // compute actual amplitude
bmp->Canvas->MoveTo(xx,yy);     // render it
if (V>-Ve) for (x=-Ve;x<=V;x++)
    {
    xx0=xx; yy0=yy;                 // remember last point
    xx=(x+Ve)*xs/(2.0*Ve);          // convert x to screen position
    yy=y0+A*sin(t);                 // compute actual amplitude
    bmp->Canvas->LineTo(xx,yy);     // render it
    f=f0+(f1-f0)*(x+Ve)/(V+Ve);     // compute actual frequency
    t+=f;                           // update actual time with it
    if ((yy0-y0)*(yy-y0)<0.0)       // zero crossing?
        {
        if (yy!=yy0) xx0=xx0+(xx-xx0)*(yy-y0)/(yy-yy0); // interpolate crossing position
        bmp->Canvas->Ellipse(xx0-r,y0-r,xx0+r,y0+r);    // render it
        }
    }
if (V<+Ve) for (x=V;x<+Ve;x++)
    {
    xx0=xx; yy0=yy;                 // remember last point
    xx=(x+Ve)*xs/(2.0*Ve);          // convert x to screen position
    yy=y0+A*sin(t);                 // compute actual amplitude
    bmp->Canvas->LineTo(xx,yy);     // render it
    f=f1+(f0-f1)*(x-V )/(Ve-V);     // compute actual frequency
    t+=f;                           // update actual time with it
    if ((yy0-y0)*(yy-y0)<0.0)       // zero crossing?
        {
        if (yy!=yy0) xx0=xx0+(xx-xx0)*(yy-y0)/(yy-yy0); // interpolate crossing position
        bmp->Canvas->Ellipse(xx0-r,y0-r,xx0+r,y0+r);    // render it
        }
    }

// render backbuffer
Main->Canvas->Draw(0,0,bmp);

crossings

[Edit2] cubic fit for intersection points

As described before I use the screenshots and create a table of intersection points for 0%,10%,20%,30%,40%,50% density scrollbar positions with the extra wide settings.

extra wide

In pixels it lead to this table of intersection points in pixels:

int xi[6][9]=
    {
    { 0, 48, 102, 160, 223, 289, 358, 429, 502 },  //  0%
    { 0, 77, 124, 177, 235, 299, 364, 434, 506 },  // 10%
    { 0, 98, 150, 197, 250, 309, 372, 439, 510 },  // 20%
    { 0, 107, 175, 222, 268, 319, 379, 444, 513 }, // 30%
    { 0, 114, 190, 247, 289, 334, 389, 450, 517 }, // 40%
    { 0, 120, 200, 263, 313, 354, 400, 457, 521 }  // 50%
    };

Then I applied cubic polynomial fit using my approximation search minimizing avg error:

const int N=6,M=9;
double aj[M][4];
void fit_data() // fit polynomials
    {
    int i,j;
    double a0,t,dt;
    approx a1,a2,a3; double ee,e;
    dt=1.0/double(N-1);
    // fit points
    for (j=0;j<M;j++)
        {
        a0=xi[0][j];    // first coefficient is start point
        //            a0, a1,  da,n, ee
        for (a1.init(-500.0,+500.0,10.0,3,&ee); !a1.done; a1.step())
         for (a2.init(-500.0,+500.0,10.0,3,&ee); !a2.done; a2.step())
          for (a3.init(-500.0,+500.0,10.0,3,&ee); !a3.done; a3.step())
           for (ee=0.0,t=0.0,i=0;i<N;i++,t+=dt)
            ee+=fabs(double(xi[i][j])-(a0+(a1.a*t)+(a2.a*t*t)+(a3.a*t*t*t)));
        aj[j][0]=a0;
        aj[j][1]=a1.aa;
        aj[j][2]=a2.aa;
        aj[j][3]=a3.aa;
        }
    j=0;
    }

So the fitted intersection is computed like this:

double compute_point(int ix,double t)
    {
    double a[9][4]=
        {
        { 0, 1.9, -9.10000000000001, 6.2 },
        { 48, 181.5, -184.1, 74.1999999999999 },
        { 102, 93.4999999999999, 105.5, -101.8 },
        { 160, 49.8, 139.9, -87.8000000000001 },
        { 223, 54.9, 26.9, 6.2 },
        { 289, 57.8, -41.2, 48.2 },
        { 358, 28.7, 3.8, 8.2 },
        { 429, 29, -18.1, 16.2 },
        { 502, 21.7, -13.1, 9.2 }
        };
    if ((ix<0)||(ix>=9)) return 0.0;
    return (a[ix][0]+(a[ix][1]*t)+(a[ix][2]*t*t)+(a[ix][3]*t*t*t));
    }

Where t=<0.0,1.0> represent the scrollbar setting <0%,50%> and ix=<0,8> is the intersection point index you want to obtain. a[j][4],aj[j][4] are the same thing representing cubic polynomial coefficients of xi[][j] table column.

Now you just need to scale the output to match your view and add the mirror for scrollbar settings above 50%. Here overlay test I checked the accuracy with:

overlay

red dots are intersection points from the xi and cyan dots are intersection points computed for actual scrollbar settings. As you can see they match pretty close (last point is missing in the GIF but works too I just forgot to render it). Y axis means scrollbar settings 0% is on the top and 50% is on the bottom.

Spektre
  • 49,595
  • 11
  • 110
  • 380