包装二维网格索引
Wrapping 2d grid indices
我有这个功能,我在 python 中制作了原型,用于导航网格索引。它在 python 中完美运行,但由于模运算符处理负数的方式,它在 C++ 中下降了。任何人都可以建议进行修改以使这项工作有效吗?
当坐标 nx
和 ny
为负时函数失败。
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值为坐标nx
和ny
.
变换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";
}
我有这个功能,我在 python 中制作了原型,用于导航网格索引。它在 python 中完美运行,但由于模运算符处理负数的方式,它在 C++ 中下降了。任何人都可以建议进行修改以使这项工作有效吗?
当坐标 nx
和 ny
为负时函数失败。
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值为坐标nx
和ny
.
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";
}