所以我有一个二维数组。让我们想象如下:
1 2 3 4 5 6 7 8 9 0
1 2 3 4 5 6 7 8 9 0
1 2 3 4 5 6 7 8 9 0
1 2 3 4 5 6 7 8 9 0
1 2 3 4 5 6 7 8 9 0
现在我想说的是将值保持在以粗体 5(上图)为中心的半径为 2 的圆中。所以结果应该是:
0 0 0 0 5 0 0 0 0 0
0 0 0 4 5 6 0 0 0 0
0 0 3 4 5 6 7 0 0 0
0 0 0 4 5 6 0 0 0 0
0 0 0 0 5 0 0 0 0 0
我现在没有笔记本电脑,所以我不能分享代码,但基本上我所做的是遍历所有单元格(数组的值)并通过毕达哥拉斯定理计算单元格与中心之间的距离。如果值小于或等于 2,则保留它,否则将其更改为 0.
现在,我的代码运行得非常好并且不是非常性能密集型(100x100 阵列大约 0.1 秒不知道这对 4.2GHz CPU 来说是好是坏)但我想知道是否有更好的方法来做到这一点就像某种矩阵运算或其他任何东西,或者如果这是唯一的方法。
所以你有一个中心(
row = 2, column = 4
)和radius = 2
.
然后我们应该根据
metric将
0
分配给项目[r, c]
:
Math.Abs(row - r) + Math.Abs(column - c) > radius
(row - r) * (row - r) + (column - c) * (column - c) > radius * radius
n
)Math.Pow(Math.Abs(row - r), n) + Math.Pow(Math.Abs(column - c), n) > Math.Pow(radius, n)
Math.Abs(row - r) > radius || Math.Abs(colum - c) > radius
假设您使用 L2(欧几里德)度量:
private static void ClearExceptCircle(int[,] array, int row, int column, int radius) {
int rowCount = array.GetLength(0);
int colCount = array.GetLength(1);
// micro optimization: compute criterium once
int limit = radius * radius;
// Micro optimization: comparing with 0 is faster than with other numbers
for (int r = rowCount - 1; r >= 0 ; --r)
for (int c = colCount - 1; c >= 0; --c)
if ((row - r) * (row - r) + (column - c) * (column - c) > limit)
array[r, c] = 0;
}
有更高效的画圆的方法。总体思路是逐行处理图像,如果圆覆盖了行,则计算圆开始和结束的列。这应该允许您通过进行单个索引比较来清除所有行。
要计算开始和结束列,您可以使用 中点圆算法 或 Bresenham 圆算法。
就是说,如果您当前的算法足够快我不会打扰。请注意,避免平方根有点昂贵的常见微优化是比较平方距离:
var distSquared = dist * dist;
...
if((x*x + y*y) < distSquared) {...}