流氓线被绘制到窗口 [英] Rogue line being drawn to window

查看:22
本文介绍了流氓线被绘制到窗口的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 SFML 库在 C++ 中制作图形程序.到目前为止,我已经能够在屏幕上绘制一个函数.一路上我遇到了两个问题.第一条线似乎返回到我的飞机的原点,从我的函数的末尾开始.

I am making a graphing program in C++ using the SFML library. So far I have been able to draw a function to the screen. I have run into two problems along the way. The first is a line which seems to return to the origin of my the plane, starting from the end of my function.

你可以在这张图片中看到:

You can see it in this image:

如您所见,这条流氓"线在接近原点时似乎会改变颜色.我的第一个问题是这条线是什么以及如何从我的窗口中根除它?

As you can see this "rogue" line seems to change colour as it nears the origin. My first question is what is this line and how may I eradicate it from my window?

在这张图片中可以看到第二个问题稍微不相关且更数学化:

The second problem which is slightly unrelated and more mathematical can be seen in this image:

如您所见,渐近线是正在绘制图形未定义或不连续的点.这让我想到了我的第二个问题:有没有办法(在代码中)识别渐近线而不是将其绘制到窗口中.

As you can see the asymptotes which are points where the graph is undefined or non continuous are being drawn. This leads me to my second question: is there a way ( in code ) to identify an asymptote and not draw it to the window.

我的任何绘制到窗口的代码是:

My code for anything drawn to the window is:

VertexArray axis(Lines, 4);
VertexArray curve(PrimitiveType::LinesStrip, 1000);

axis[0].position = Vector2f(100000, 0);
axis[1].position = Vector2f(-100000, 0);
axis[2].position = Vector2f(0, -100000);
axis[3].position = Vector2f(0, 100000);

float x;

for (x = -pi; x < pi; x += .0005f)
{
    curve.append(Vertex(Vector2f(x, -tan(x)), Color::Green));
}

我非常感谢任何输入:)

I would very much appreciate any input : )

更新:

多亏了很多人的意见,这段代码似乎可以很好地解决渐近线问题:

Thanks to the input of numerous people this code seems to work fine in fixing the asymptote problem:

for (x = -30*pi; x < 30*pi; x += .0005f)
{
    x0 = x1; y0 = y1;
    x1 = x; y1 = -1/sin(x);
    a = 0; 
    a = fabs(atan2(y1 - y0, x1 - x0));
    if (a > .499f*pi)
    {
        curve.append(Vertex(Vector2f(x1, y1), Color::Transparent));
    }
    else
    {
        curve.append(Vertex(Vector2f(x1, y1), Color::Green));
    }
}

更新 2:

下面的代码去掉了流氓行:

The following code gets rid of the rogue line:

VertexArray curve(Lines, 1000);
float x,y;
for (x = -30 * pi; x < 30 * pi; x += .0005f)
{
    y = -asin(x);
    curve.append(Vertex(Vector2f(x, y)));
}
for (x = -30 * pi + .0005f; x < 30 * pi; x += .0005f)
{
    y = -asin(x);
    curve.append(Vertex(Vector2f(x, y)));
}

推荐答案

第一个问题看起来像是错误的折线/曲线处理.不知道您使用什么 API 进行渲染,但有些像 GDI 需要正确启动 pen 位置.例如,如果你这样画:

The first problem looks like a wrong polyline/curve handling. Don't know what API are you using for rendering but some like GDI need to start the pen position properly. For example if you draw like this:

Canvas->LineTo(x[0],y[0]);
Canvas->LineTo(x[1],y[1]);
Canvas->LineTo(x[2],y[2]);
Canvas->LineTo(x[3],y[3]);
...

那么你应该这样做:

Canvas->MoveTo(x[0],y[0]);
Canvas->LineTo(x[1],y[1]);
Canvas->LineTo(x[2],y[2]);
Canvas->LineTo(x[3],y[3]);
...

如果您的 API 需要 MoveTo 命令而您没有设置它,则使用最后一个位置(或默认 (0,0)) 将曲线的起点与上次绘制的直线或默认笔位置连接起来.

In case your API needs MoveTo command and you are not setting it then last position is used (or default (0,0)) which will connect start of your curve with straight line from last draw or default pen position.

第二个问题

在连续数据中,您可以通过检查随后的 y 值来确定渐近线或不连续性的阈值.如果您的曲线渲染如下所示:

In continuous data you can threshold the asymptotes or discontinuities by checking the consequent y values. If your curve render looks like this:

Canvas->MoveTo(x[0],y[0]);
for (i=1;i<n;i++) Canvas->LineTo(x[i],y[i]);

然后你可以把它改成这样:

Then you can change it to something like this:

y0=y[0]+2*threshold;
for (i=0;i<n;i++)
 {
 if (y[1]-y0>=threshold) Canvas->MoveTo(x[i],y[i]);
  else                   Canvas->LineTo(x[i],y[i]);
 y0=y[i];
 }

问题在于阈值的选择,因为它取决于采样点的x密度以及xx对y数据的第一次推导代码>(斜角)

The problem is selection of the threshold because it is dependent on x density of sampled points and on the first derivation of your y data by x (slope angles)

如果你要堆叠更多的函数,曲线附加会创建你不需要的线......而是将每个数据作为单独的绘制处理或在它们之间放置 MoveTo 命令

If you are stacking up more functions the curve append will create your unwanted line ... instead handle each data as separate draw or put MoveTo command in between them

我是这样看的(假拆分):

I see it like this (fake split):

double x0,y0,x1,y1,a;
for (e=1,x = -pi; x < pi; x += .0005f)
    {
    // last point
    x0=x1; y0=y1;
    // your actual point
    x1=x; y1=-tan(x);
    // test discontinuity
    if (e) { a=0; e=0; } else a=fabs(atan2(y1-y0,x1-x0));
    if (a>0.499*M_PI) curve.append(Vertex(Vector2f(x1,y1), Color::Black));
     else             curve.append(Vertex(Vector2f(x1,y1), Color::Green));
    }

0.499*M_PI 是你的阈值,越接近 0.5*M_PI 它检测到的跳跃越大......我伪造了由黑色(背景)分割的曲线) 它将在轴交叉点上产生间隙(除非使用透明度)......但不需要曲线列表......

the 0.499*M_PI is you threshold the more closer is to 0.5*M_PIthe bigger jumps it detects... I faked the curve split by black color (background) it will create gaps on axis intersections (unless transparency is used) ... but no need for list of curves ...

这篇关于流氓线被绘制到窗口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆