【问题标题】:How do I know if a point is in triangle?我怎么知道一个点是否在三角形中?
【发布时间】:2012-09-27 14:13:08
【问题描述】:

我有一个简单的二维三角形。我一直在寻找如何知道给定点是否属于该三角形。这是算法(我在这里找到了:How to determine if a point is in a 2D triangle?),它非常好而且很快(根据其他人的说法):

float sign(int x0, int y0, int x1, int y1, int x2, int y2){
    return (x0 - x2) * (y1 - y2) - (x1 - x2) * (y0 - y2);
}

int ptintr(int sx, int sy, int x0, int y0, int x1, int y1, int x2, int y2){
    int b1, b2, b3;

    b1 = sign(sx, sy, x0, y0, x1, y1) < 0.0f ? 1 : 0;
    b2 = sign(sx, sy, x1, y1, x2, y2) < 0.0f ? 1 : 0;
    b3 = sign(sx, sy, x2, y2, x0, y0) < 0.0f ? 1 : 0;

    if((b1) == b2 && (b2 == b3))
        return 1;
    return 0;
}

我在 draw_ftriangle() 中调用了这个函数:

void draw_ftriangle(SDL_Surface * s, int x0, int y0, int x1, int y1, int x2, int y2, unsigned color){
    int ymin = min(y0, min(y1, y2));
    int xmin = min(x0, min(x1, x2));
    int ymax = max(y0, max(y1, y2));
    int xmax = max(x0, max(x1, x2));

    draw_line(s, x0, y0, x1, y1, color);
    draw_line(s, x1, y1, x2, y2, color);
    draw_line(s, x0, y0, x2, y2, color);

    for(; ymin < ymax; ymin++)
        for(; xmin < xmax; xmin++)
            if(ptintr(xmin, ymin, x0, y0, x1, y1, x2, y2))
                put_pixel(s, xmin, ymin, color);
}

这里 sx 和 sy 是给定点的坐标,x0, x1, x2, y0, y1, y2 是三角形的点。但是这个算法不起作用。每当我给这个函数一个点的坐标和三角形点的坐标时,它总是返回false。谁能告诉我这个算法是否正确,或者我在这里留下了一些错误?

【问题讨论】:

  • 出于好奇,如果将“&lt; 0.0f”更改为“&lt;= 0.0f”会怎样?或者更好,“&lt;= 0.0lf”?
  • 您还没有展示如何调用这些函数。假设这段代码是正确的(我个人不知道这两种方法),可能是你错误地调用了函数。
  • 我用 ptintr(0,0,0,0,1,0,1,1) 进行了尝试,它为我返回了 1。也许你可以提供一个失败的案例?
  • 我建议学习一点向量微积分……这是最简单的问题之一。点在三角形中,如果 mysign(t1,p,t2)、mysign(p,t3,t2) 和 mysign(t1,t3,p) 都是正数。 mysign(a,b,c) 是 (b-a,c-a) 矩阵的行列式。 (V,W) 矩阵的行列式是 V.xW.y-V.yW.x .
  • 一旦所有关于 2D 包含三角形中的点的说法,这将不是按像素为三角形着色的最有效方法:您使用三角形区域中像素顺序的决策只需要关心其圆周上的像素就足够了。

标签: c algorithm geometry pixel point


【解决方案1】:

您的循环只执行顶行,因为 xmin 未重置。

换句话说,第一次通过内部 x 循环时,您将增加 xmin 直到它变为 xmax。第二次执行内部 x 循环时,xmin 已经是 xmax,所以什么也没有发生。

试试

int x;
for(; ymin < ymax; ymin++)
    for(x=xmin; x < xmax; x++)
        if(ptintr(x, ymin, x0, y0, x1, y1, x2, y2))
            put_pixel(s, x, ymin, color);

【讨论】:

  • 谢谢!不错的收获。这个对我有用!再次感谢。
【解决方案2】:

我用两个输入尝试了这个算法:

ptintr(3,2,1,1,3,4,4,1)) =&gt; returned 1

ptintr(2,3,1,1,3,4,4,1)) =&gt; returned 0

他们都是正确的。

我可能错了,但您正在测试从 (x,y) 池中采样的最小和最大坐标,这意味着它们都将位于三角形的轮廓上。该算法将轮廓上的坐标视为不属于它的一部分。

ptintr(3,1,1,1,3,4,4,1)) =&gt; returns 0 因为点 (3,1) 在轮廓上。

尝试在函数ptintr 中将&lt; 运算符更改为&lt;=

【讨论】:

  • 嗯 ymin 保存 y 轴上的最高点,而 xmin 保存 x 轴上最左边的值。然后在 y 轴上向下,在 x 轴上向右,所以不是所有的点都在三角形的轮廓上,其中一些应该在三角形内。
  • @Arnas 然后找我们一个你的代码不起作用的案例。向我们报告它不起作用的确切值。
  • 我测试了多次,它工作正常。问题在于您的 xmin 增加但未重置。你永远不会第二次进入第二个 for 循环,因为 xmin 已经在 xmax。
猜你喜欢
  • 2014-02-12
  • 1970-01-01
  • 2011-11-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-18
  • 2018-09-24
  • 2010-09-20
相关资源
最近更新 更多