输入是滑块范围值Ex。( - 5到5)或(X到Y)
我希望X轴交点像这样(-5,0)( - 2,0)( - 0.5,0)(0.5,0)(2,0)(5,0)并考虑点命名从左到右从P1到P6。因此,当滑块值在中间时,P1和P2的差值(x2-x1)也是P5和P6应该相同,即0。同样,差值应该是D1> 0。 D2> D3 ....... D4< D5< D6
D1 = (P2x - P1x)
D2 = (P3x - P2x)
........
........
D5 = (P4x - P5x)
D6 = (P5x - P6x)
区别应该是这样的
D1 == D6 D2 == D5 .... ....
如果滑块位于中间位置(Ex),如果范围为(-5到5),则滑块值为0
让我们解释一下-Ve方面:
如果滑块位于负侧,这意味着-5将是差异 D1> D2> D3> ...... D5> D6
如果滑块位于负侧,这意味着-4将是差异 D1> D2> D3> ...... D5> D6
依旧......
-5和-4的输出之间的差异是 -5的D1,D2,D3 ....大于D1,D2,D3 ...... -4这样将复制结果直到滑块值达到中间点,这意味着0
让我们解释+ Ve侧:
如果滑块位于正侧,这意味着差异为+5 D1< D2< D3< ...... D5< D6
如果滑块位于正侧,这意味着差异为+4 D1< D2< D3< ...... D5< D6
+5和+4的输出之间的差异是 +5的D1,D2,D3 ....大于+ 4的D1,D2,D3 ....这样会将结果复制到滑块值到达中间点,这意味着0
注意:滑块值为范围
之间的任意数字请参考以下X轴交点的图像作为滑块值范围
[Spektre编辑]
好的原始问题描述与实际问题无关。问题陈述如下:找出货架分隔线的(逆向工程)位置以匹配此page的密度滑块。 (单击渐变并使用密度滚动条)。滚动条是对称的,因此从0-50%
开始,其余部分可以镜像。我设法获得这些参数:
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%
};
其中xi[scrollbar]
是近似货架分隔符位置的列表,Ti[scrollbar]
是滑块状态{ 0,10,20,30,40,50 } [%]
获得的货架尺寸(期间),如果您想要更精确的位置,请从此屏幕截图中获取自定义:
棕色像V线是货架分隔线,最后一个是由于设置货架宽度而不变,所以忽略它。这里有额外的宽度以增加精度:
所以问题是如何为任何滚动条位置和预设货架总宽度计算xi
?
答案 0 :(得分:0)
我能想到的最简单的模型会产生这样的结果,就像这样的非线性函数的正弦函数:
X, Y
是您的绘图坐标,S
是您的滑块位置,a, b, c, d, e
是您需要调整以使绘图与所需结果匹配的参数。
注意:d
相当不重要,因为它只是一个小的相移。 c
确定滑块值更改的敏感度,b
确定频率/波长变化的速度。 a
只是一个垂直比例因子(幅度)。 e
确定频率变化的平滑程度 - 我发现~0.15非常好。
编辑:
好的,既然你只想要X轴点,我们需要求解这个方程来找到根。以下是解决方案:
其中n
是一个整数,它给出了你想要的每个X点。因此我们需要解决:
考虑到这两种情况,只需迭代所有X点的n
。
编辑2:
正如Blindmann指出的那样,如果e > 1
,这个表达式将会出现分歧,因此约束为0 < e < 1
;这将确保在{em> limit 中X
接近cS
它不会分歧。
答案 1 :(得分:0)
我认为您正在进行频率更改f0 -> f1 -> f0
,其中滚动条V
是f1
所在的位置。
f(-Ve) = f0 if V!=-Ve
f( V ) = f1
f(+Ve) = f0 if V!=+Ve
将时间间隔划分为f0 -> f1
和f1 -> f0
。首先尝试线性插值:
f(x) = f0 + (f1-f0)*(x+Ve)/(V+Ve) x = <-Ve, V >
f(x) = f1 + (f0-f1)*(x-V )/(Ve-V) x = < V ,+Ve>
现在只需在这里生成你的wave简单 C ++ / VCL 我为此付出了代价:
// 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);
忽略渲染内容(将其替换为您的环境编码风格)xs,ys
是图像bmp
分辨率和M_PI=3.1415
此处预览:
此处捕捉到动画 GIF (稍微降低f0,f1
):
有关详细信息,请参阅类似的质量检查:
[Edit1],以防您确实需要交叉点
然后通过检测y轴上的符号变化来检测过零点,并从2个后续点插入位置。程序稍有变化:
// 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);
[Edit2]立方体适合交叉点
如前所述,我使用屏幕截图并为0%,10%,20%,30%,40%,50%
密度滚动条位置创建一个交叉点表,并使用超宽设置。
以像素为单位,它会以像素为单位生成此交点表:
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%
};
然后我使用我的approximation search最小化平均误差来应用三次多项式拟合:
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;
}
所以拟合的交点计算如下:
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));
}
其中t=<0.0,1.0>
表示滚动条设置<0%,50%>
,ix=<0,8>
是您要获取的交叉点索引。 a[j][4]
,aj[j][4]
表示xi[][j]
表格列的三次多项式系数是相同的。
现在您只需缩放输出以匹配您的视图,并将滚动条设置的镜像添加到50%以上。这里叠加测试我检查了准确性:
红点是xi
的交点,青点是为实际滚动条设置计算的交点。正如你所看到的那样,它们非常接近(GIF中缺少最后一点,但也有效,我只是忘了渲染它)。 Y轴表示滚动条设置0%位于顶部,50%位于底部。