图形 - 考虑到一条线的宽度,我如何知道一条线在屏幕上是否可见

发布于 2024-10-31 11:43:42 字数 145 浏览 5 评论 0原文

我正在做一些核心图形,我想知道如何知道一条线的某些部分是否在屏幕上可见。

让我们画一条从 x-5, y3 到 x2, y-7 的线。如果宽度为 1 像素,则屏幕上不会显示任何内容。如果宽度为 15 像素,则会显示其中的某些部分。

我该如何检查?

I'm doing some core graphics, and I wonder how I may know if a line will have some parts of it visible on screen.

Let's take a line going from x-5, y3 to x2, y-7. If it's 1 pixel wide, nothing will be displayed onscreen. If it's 15 pixels wide, some parts of it will be displayed.

How may I check that ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

请爱~陌生人 2024-11-07 11:43:42

如果您只有线路,则可以使用以下功能。否则,我建议遍历线条的整个长度,并在特定距离内创建线条宽度尺寸的平方,并检查它是否在您的视图内。示例:如果有一条从 x0y0 到 x7y0 的线。您可以使用 x1y0 创建一个绘制线大小的正方形(在本例中为 15),然后查看它是否与您的屏幕重叠。接下来转到 x2y0 等等。优点是它甚至可以与贝塞尔曲线一起使用(一点维基信息如何贝塞尔曲线就足够了)。

// 编辑:(做了一个小贝塞尔曲线检查功能,应该可以工作,但还没有测试)我认为在绘制之前检查每条线的性能效率并不高:

- (void)bezierWithStart:(CGPoint)start cp1:(CGPoint)cp1 cp2:(CGPoint)cp2 end:(CGPoint)end withWidth:(float)wid {
    for (float i = 0.0; i<=1.0; i+=0.05) { // how many steps
        CGPoint chk1 = CGPointMake(start.x+((cp1.x-start.x)*i), start.y+((cp1.y-start.y)*i));
        CGPoint chk2 = CGPointMake(cp1.x+((cp2.x-cp1.x)*i), cp1.y+((cp2.y-cp1.y)*i));
        CGPoint chk3 = CGPointMake(cp2.x+((end.x-cp2.x)*i), cp2.y+((end.y-cp2.y)*i));

        CGPoint chk4 = CGPointMake(chk1.x+((chk2.x-chk1.x)*i), chk1.y+((chk2.y-chk1.y)*i));
        CGPoint chk5 = CGPointMake(chk2.x+((chk3.x-chk2.x)*i), chk2.y+((chk3.y-chk2.y)*i));

        CGPoint cPoint = CGPointMake(chk4.x+((chk5.x-chk4.x)*i), chk4.y+((chk5.y-chk4.y)*i));

        CGRect drawLine = CGRectMake(cPoint.x-(wid/2), cPoint.y-(wid/2), wid, wid);

        // check if rect is in view
    }
}

// 编辑结束

但现在让我们看看简单的线功能:

- (void)testLine:(CGPoint)fp toSecond:(CGPoint)sp withWidth:(float)wid {
    float xratio = sp.x - fp.x;
    float yratio = sp.y - fp.y;
    double a = sqrt(((wid*wid)*(xratio*xratio))/((yratio*yratio)+(xratio*xratio)));
    a/=2; // because line width goes in both direction
    double b = (yratio/xratio)*a;
    if ((xratio<0.0 && yratio<0.0) || (xratio>0.0 && yratio>0.0))b*=-1;
    CGPoint diffFrom1 = CGPointMake(fp.x+a, fp.y+b);
    CGPoint diffTo1 = CGPointMake(sp.x+a, sp.y+b);
    a*=-1;
    b*=-1;
    CGPoint diffFrom2 = CGPointMake(fp.x+a, fp.y+b);
    CGPoint diffTo2 = CGPointMake(sp.x+a, sp.y+b);
}

您将获得4分。 2 条线,一根在原始线上方,一根在原始线下方,尺寸为绘制宽度的一半。后面的计算是获取绘制方向以及与原始线的差异。但对于那些想要了解它的人,这是我的预先计算:

在此处输入图像描述

If you have lines only you can work with the function below. Otherwise I would recommend to go through the whole length of your line and create in a specific distance an square of the line width size and check if it is inside your view. An example: If you have a line from x0y0 to x7y0. You would go to x1y0 create a square of your draw line size (in this example 15) and see if this overlaps your screen. Next go to x2y0 and so on. The advantage is it will even work with bezier curves (a little wiki information how bezier work will be enough).

// EDIT: (made a little bezier check function, should work, but haven't tested) And I don't think its more performance efficient to check each line before drawing:

- (void)bezierWithStart:(CGPoint)start cp1:(CGPoint)cp1 cp2:(CGPoint)cp2 end:(CGPoint)end withWidth:(float)wid {
    for (float i = 0.0; i<=1.0; i+=0.05) { // how many steps
        CGPoint chk1 = CGPointMake(start.x+((cp1.x-start.x)*i), start.y+((cp1.y-start.y)*i));
        CGPoint chk2 = CGPointMake(cp1.x+((cp2.x-cp1.x)*i), cp1.y+((cp2.y-cp1.y)*i));
        CGPoint chk3 = CGPointMake(cp2.x+((end.x-cp2.x)*i), cp2.y+((end.y-cp2.y)*i));

        CGPoint chk4 = CGPointMake(chk1.x+((chk2.x-chk1.x)*i), chk1.y+((chk2.y-chk1.y)*i));
        CGPoint chk5 = CGPointMake(chk2.x+((chk3.x-chk2.x)*i), chk2.y+((chk3.y-chk2.y)*i));

        CGPoint cPoint = CGPointMake(chk4.x+((chk5.x-chk4.x)*i), chk4.y+((chk5.y-chk4.y)*i));

        CGRect drawLine = CGRectMake(cPoint.x-(wid/2), cPoint.y-(wid/2), wid, wid);

        // check if rect is in view
    }
}

// EDIT end

But now lets go to the simple line function:

- (void)testLine:(CGPoint)fp toSecond:(CGPoint)sp withWidth:(float)wid {
    float xratio = sp.x - fp.x;
    float yratio = sp.y - fp.y;
    double a = sqrt(((wid*wid)*(xratio*xratio))/((yratio*yratio)+(xratio*xratio)));
    a/=2; // because line width goes in both direction
    double b = (yratio/xratio)*a;
    if ((xratio<0.0 && yratio<0.0) || (xratio>0.0 && yratio>0.0))b*=-1;
    CGPoint diffFrom1 = CGPointMake(fp.x+a, fp.y+b);
    CGPoint diffTo1 = CGPointMake(sp.x+a, sp.y+b);
    a*=-1;
    b*=-1;
    CGPoint diffFrom2 = CGPointMake(fp.x+a, fp.y+b);
    CGPoint diffTo2 = CGPointMake(sp.x+a, sp.y+b);
}

you will get 4 points. 2 lines, one above and one below the original line, half the size of your draw width. The calculation behind is to get the draw direction and for that the difference to the original line. But for those who want to get into it, heres my pre calculation:

enter image description here

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文