生成8邻居坐标最干净的方法

时间:2012-11-23 22:56:59

标签: language-agnostic pixel pixels flip-flop

我正在寻找一种方法来生成以下数字序列(这是一个像素的8个邻居的相对坐标,从西北像素开始,以西方结束)。第一个数字是y坐标,第二个是x坐标:

 y,  x
 _____

 1, -1   // N-W
 1,  0   // N
 1,  1   // N-E
 0,  1   // E
-1,  1   // S-E
-1,  0   // S
-1, -1   // S-W
 0, -1   // W

我可以通过几种丑陋的方式来实现这一目标,例如将坐标放在一个数组中,但我想知道是否有一种我没有想过的干净有效的方法。

编辑:由于我尝试实现的算法的设计方式,像素必须按特定顺序(NW到W)进行迭代。< / p>

2 个答案:

答案 0 :(得分:3)

首先考虑以下生成Y-coords的方法。

从NW开始,我们想要实现{1,1,1,0,-1,-1,-1,0}。 这是循环给出的重复模式:

for( int i = 0; i < 8; i++ )
{
    // You can combine into one ternary if you are adventurous
    int y = (i % 4 == 3) ? 0 : 1;
    y *= (i > 3) ? -1 : 1;
}

因此,这将为y值生成所需的序列。

现在考虑从NE 开始的x值序列:{1,1,1,0,-1,-1,-1,0}。 你可以看到它是相同的序列。

因此,我们可以使用偏移量2到前一个循环生成所需的序列从NW 开始,并在最后一个三元素上进行处理,以适应序列末尾的包装:

for (int i = 2; i < 10; i++ )
{
    int x = (i % 4 == 3) ? 0 : 1;
    x *= (i % 8 > 3) ? 1 : -1;   
}

现在将两者合并为一个循环是微不足道的:

for (int i = 0; i < 8; i++)
{
    int y = (i % 4 == 3) ? 0 : 1;
    y *= (i > 3) ? -1 : 1;

    int x = ( (i+2) % 4 == 3) ? 0 : 1;
    x *= ( (i+2) % 8 > 3) ? 1 : -1;
}

答案 1 :(得分:1)

另一个可读的替代方案是明确枚举各方,如下所示:

int x = -1;
int y = 1;
for (int side = 0; side < 4; side++)
{
    for (int steps = 0; steps < 2; steps++)
    {
        // use coordinates here
        printf("%d, %d\n", y, x);

        if (side == 0) { x++; }
        else if (side == 1) { y--; }
        else if (side == 2) { x--; }
        else /* if side == 3) */ { y++; }
    }
}

/*
result:
1, -1
1, 0
1, 1
0, 1
-1, 1
-1, 0
-1, -1
0, -1
*/

这样做的另一个好处是,可以通过改变起始角和一侧的步数来遍历任何大小的邻域。

@louism:“我可以想出几种难看的方法来实现这一点,例如将坐标放在一个数组中” - 我认为这是最好的方法,实际上。它清晰可读(与上述@ose描述的模数运算方法不同),可能是最快的。

@louism:您可以对三种不同的方法(数组查找,枚举边,模数算法)进行基准测试并发布结果吗?我会对此感兴趣,因为它是我现在正在编写的代码中使用的东西。