我正在寻找一种方法来生成以下数字序列(这是一个像素的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>
答案 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:您可以对三种不同的方法(数组查找,枚举边,模数算法)进行基准测试并发布结果吗?我会对此感兴趣,因为它是我现在正在编写的代码中使用的东西。