为啥在 Cohen-Sutherland 裁剪算法中计算水平线的 x 截距时需要舍入?

Posted

技术标签:

【中文标题】为啥在 Cohen-Sutherland 裁剪算法中计算水平线的 x 截距时需要舍入?【英文标题】:Why do we need to round when computing x-intercept of horizontal line in Cohen-Sutherland clipping algorithm?为什么在 Cohen-Sutherland 裁剪算法中计算水平线的 x 截距时需要舍入? 【发布时间】:2016-06-02 14:05:48 【问题描述】:

我正在学习计算机图形学,遇到了 Cohen-Sutherland 线裁剪算法。我们有一条由点P1P2 定义的线段,我们试图找出它是否被裁剪在裁剪矩形内(通常由屏幕的宽度和高度定义,左上角是 [ 0, 0])

算法很简单,我们只需检查每个点,看看该点的 x 和 y 是否超出范围:

if (y1 < min_clip_y)
        p1_code |= CLIP_NORTH;
else if (y1 > max_clip_y)
        p1_code |= CLIP_SOUTH;

if (x1 < min_clip_x)
        p1_code |= CLIP_WEST;
else if (x1 > max_clip_x)
        p1_code |= CLIP_EAST;

// Same deal with x2, y2

如果p1_codep2_code 都不等于0,我们拒绝这条线,如果它们都为零,我们接受它,否则我们继续测试以找到与裁剪矩形相交边缘的裁剪交点:

switch(p1_code)

    case CLIP_NORTH:
    
         yc1 = min_clip_y;
         xc1 = x1 + 0.5f + (min_clip_y - y1) * (x2-x1) / (y2-y1);
     break;

    // other cases...

我是从一本书中读到的。我理解我们如何推导出 x 截距的方程,我只是不明白为什么我们要添加 0.5f 来舍入到下一个整数。为什么我们需要四舍五入?

谢谢!

【问题讨论】:

【参考方案1】:

许多计算机图形文本都有这样的错误。 C-S 是大约 50 年前发明的,当时浮点比整数数学要慢得多,所以规范是使用整数算术或整数指令来模拟定点。结果是对旧代码进行了奇怪的重新实现,用浮点移植了旧的定点。这显然是其中之一。

正如您所怀疑的,您希望使用浮点进行整个计算,然后在最后绝对需要时四舍五入到最近的像素。但是对于现代 GPU,您甚至可以跳过它,因为抗锯齿线条绘制会在浮点坐标上做正确的事情。

事实上,奇怪的是图形文本仍然如此突出地使用剪线,因为现代图形更多地是关于多边形。有很多不错的三角形和多边形算法,它们比线裁剪更具有实际意义。太多的教科书作者是他们学徒工具的奴隶。

【讨论】:

感谢您的回答。我的书比较老是的,但它是一种,至少我没有看过很多类似的书。它由 Andre Lamothe 编写,完成了软件渲染器的创建,但首先您创建了一个线框引擎,您可以在其中通过 Bresenham 绘制线条和三角形,从而进行线条剪裁。我不明白的是,为什么要四舍五入到下一个整数,而不是当前整数?即如果结果是2.3,为什么要舍入到 3 而不是下降到 2? @vexe 你错了。 (int)(x + 0.5) 具有舍入到最接近的 int 的效果,因为转换为 int 会截断。 (2.3 + 0.5) 截断是 2,而不是 3。我的意思是,这是一个转换为整数的愚蠢地方。它使算法的准确性大大降低。完全以浮点数进行裁剪,然后四舍五入到像素坐标。 “剪裁完全在浮点数中,然后四舍五入到像素坐标” - 你的意思是让输入坐标在浮点数中,然后在最后四舍五入? “你错了”——OK 2.3 是一个坏例子。取 2.7, int(2.7) == 2, int(2.7 + 0.5) == 3,我想现在看我知道答案了,因为 2.7 比 2 更接近 3,所以我们取整的原因是更接近实际浮点值的整数值。 是的,所有变量都浮动,除了最终结果(如果你真的需要整数输出)。

以上是关于为啥在 Cohen-Sutherland 裁剪算法中计算水平线的 x 截距时需要舍入?的主要内容,如果未能解决你的问题,请参考以下文章

[计算机图形学 with OpenGL] Chapter8 习题8.6 线段旋转后使用Cohen-Sutherland算法裁剪

opengl算法学习--- 直线裁剪算法

opengl算法学习--- 直线裁剪算法

Liang-Barsky算法

[计算机图形学 with OpenGL] Chapter8 习题8.12 NLN二维线段裁剪算法实现

你能告诉我这个 Cohen-Sutherland 算法的实现有啥问题吗?