包装二维网格索引

Wrapping 2d grid indices

我有这个功能,我在 python 中制作了原型,用于导航网格索引。它在 python 中完美运行,但由于模运算符处理负数的方式,它在 C++ 中下降了。任何人都可以建议进行修改以使这项工作有效吗?

当坐标 nxny 为负时函数失败。

int wrap_grid(int index, int x, int y, int nx, int ny) {

        //first calculate positon on row by adding nx -
        //assuming an infinite grid of indices (no limits or wrap)
        int a = (index + (y * nx));
        //then wrap around the width (x) of the row
        int b = a % (x * y);

        //now do column, calculate the bottom index of the column
        int start = b - b % y;
        //and the top index
        int limit = b - b % y + y;

        //now wrap the ny value around the columns
        return start + (b + ny) % (limit - start);
}

编辑:解释函数参数

index是矩形网格的索引,像这样:

col1 col2 col3
5 11 17
4 10 16
3 9 15
2 8 14
1 7 13
0 6 12

x 是网格的宽度,在本例中为 3.
y 是网格的高度,在本例中为 6。
nx是坐标方格偏移,所以nx = 1是向右一格,类似ny=1是一格'upwards'.

return值为坐标nxny.

变换index后的新索引号

编辑:根据 jwezorek 的方法更新了函数。请注意,唯一有效的更改(函数因素除外)是必须允许零值的比较运算符。

int wrap_grid(int index, int rows, int columns, int offset_x, int offset_y) {

    //index to grid coordinates always positive
    int x = (index / rows) + (offset_x);
    x = x >= 0 ? x : x + columns;

    int y = (index % rows) + (offset_y);
    y = y >= 0 ? y : y + rows;

    //grids to coords
    int column = x % columns;
    column = column >= 0 ? column : column + columns;

    int row = y % rows;
    row = row >= 0 ? row : row + rows;

    int bottom_of_column_index = column * rows;

    return bottom_of_column_index + row;
    }

您只需要一个 mod 函数,它只会为您提供非负值。要做到这一点,直接的方法如下所示(为清楚起见移动代码后)。

#include <tuple>
#include <iostream>

int grid_coords_to_index(int cols, int rows, int x, int y) {
    // wrap the coordinates...
    int column = x % cols;
    column = column >= 0 ? column : column + cols;

    int row = y % rows;
    row = row >= 0 ? row : row + rows;

    int bottom_of_column_index = column * rows;
    return bottom_of_column_index + row;
}

std::tuple<int,int> index_to_grid_coords(int cols, int rows, int index) {
    // TODO: handle negatives correctly here too, if we cannot 
    // assume indices are positive.
    return { index / rows, index % rows };
}

int wrap_grid(int initial_index, int cols, int rows, int x_offset, int y_offset) {
    auto [x, y] = index_to_grid_coords(cols, rows, initial_index);
    return grid_coords_to_index(cols, rows, x + x_offset, y + y_offset);
}

int main()
{  
    /*
    5   11  17
    4   10  16
    3   9   15
    2   8   14
    1   7   13
    0   6   12

    index 9 is (1,3) so two to the left and one down should be 14 given wrapping

    */

    std::cout << wrap_grid(9, 3, 6, -2, -1) << "\n";
}