【问题标题】:find the intersection point of X-axis like below找到X轴的交点,如下所示
【发布时间】:2017-11-30 03:50:58
【问题描述】:

输入为滑块范围值 Ex.(-5 to 5) or (X to 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 > D2 > D3.......D4

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 的输出之间的差异是 D1,D2,D3.... of -5 大于 D1,D2,D3.... of -4 同样这将复制结果直到滑块值达到中间点,这意味着 0

让我们解释一下 +Ve 方面:

如果滑块位于正侧,即 +5,则差值为 D1

如果滑块位于正侧,这意味着 +4,差异将是 D1

+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 任何滚动条位置和预设货架总宽度?

【问题讨论】:

  • 这似乎是一个有趣的挑战,但 StackOverflow 不是一个代码编写服务。
  • @barny,我只想让逻辑(公式)在 X 轴上形成交点。
  • 我想去加勒比海度假。到目前为止你尝试过什么?
  • 我尝试在滑块改变时改变X轴的交点。但这不是一个正确的公式计算。我做了一些手动计算,但没有帮助我获得所有场景的输出。
  • 关于您的问题,您拥有的信息比 SO 上的任何人都多(也许更多?),而且我想对解决方案更感兴趣。您也许可以测量 x 轴上几个点的波长如何变化,甚至可以将这些点绘制为三个不同滑块值的点。那么也许你可以看到它们之间存在某种系统/公式关系,或者波长变化的某种系统方式。

标签: javascript math canvas html5-canvas symbolic-math


【解决方案1】:

我看到你正在改变频率f0 -> f1 -> f0,其中滚动条Vf1 所在的位置。

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

将间隔划分为f0 -> f1f1 -> 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>

现在只需在此处简单地生成您的波形 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):

有关详细信息,请参阅类似的QA

[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=&lt;0.0,1.0&gt;代表滚动条设置&lt;0%,50%&gt;ix=&lt;0,8&gt;是你要获取的交点索引。 a[j][4],aj[j][4] 表示xi[][j] 表列的三次多项式系数。

现在您只需缩放输出以匹配您的视图,并为 50% 以上的滚动条设置添加镜像。在这里覆盖测试我检查了准确性:

红点是xi 的交点,青色点是为实际滚动条设置计算的交点。如您所见,它们非常匹配(GIF 中缺少最后一点,但也可以,我只是忘了渲染它)。 Y 轴表示滚动条设置 0% 在顶部,50% 在底部。

【讨论】:

    【解决方案2】:

    我能想到的最简单的模型会产生这样的结果,它是这样的非线性函数的正弦:

    X, Y 是您的绘图坐标,S 是您的滑块位置,a, b, c, d, e 是您需要调整的参数,以使绘图与所需结果相匹配。

    注意:d 相当不重要,因为它只是一个小的相移。 c 确定对滑块值变化的敏感度,b 确定频率/波长变化的速度。 a 只是一个垂直比例因子(幅度)。 e 决定频率变化的平滑程度 - 我发现 ~0.15 相当不错。


    编辑:

    好的,既然你只想要 X 轴点,我们需要解这个方程来找到根。以下是解决方案:

    n 是一个整数,它给出了你想要的每个 X 点。因此我们需要解决:

    考虑到这两种情况,只需遍历 n 的所有 X 点。


    编辑 2: 正如 Blindmann 所指出的,如果e &gt; 1,这个表达式会发散,所以约束是0 &lt; e &lt; 1;这将确保在 limitX 接近cS 它不会发散。

    【讨论】:

    • 我想要 X 轴相交点,我提到的波只是为了理解目的。我希望 x 轴值从增加到减少,反之亦然以进行滑块更改。我只有一个输入,即滑块值。
    • @Hornet 我已经添加了你想要的结果
    • 认为像 sin((2/(1+2^(-x+S))-1)*c) 这样的东西会在你的 (X-cS) 接近 0 时避免无穷大
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-30
    • 2019-08-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多