让我们说我有一个二维数组,例如[7] [7],全部为零,如下:
0000000
0000000
0000000
0000000
0000000
0000000
0000000
我试图找出如何取任何数字范围(例如:0到3)并从中心创建一个径向渐变的排序,如下所示:
0000000
0011100
0122210
0123210
0122210
0011100
0000000
基本上,边应该始终是最低的值,并且数组的中心应该是最高的。控制强度'是非常棒的。中锋(更多的三分球,更快的下降),但我可能会想出那个部分。
我真的很难理解这样的事情背后的数学。我认为这将使用正弦波或其他东西来实现,但不知道从哪里开始或如何将其应用于2D数组值。
(注意 - 我真正想要做的是在HTML中创建DIV网格,然后使用Javascript设置每个元素的alpha,使得中心是最不透明的,边缘是最透明的。在此期间,使用像这样的简单圆形数字,我更容易理解。
答案 0 :(得分:2)
这个帖子上唯一的答案对我来说并不是很令人满意,我最终自己搞清楚了,这是我用过的方法:
首先我创建了一个空值数组
var values = [];
for(var x = 0; x < 8; x++) {
values[x] = [];
for(var y = 0; y < 6; y++) {
values[x].push(0);
}
}
然后我决定使用渐变的中心坐标,我决定使用数组的中心。
var centerX = values.length / 2;
var centerY = values.length / 2;
然后我决定了我想要渐变的大小。我决定最佳半径为3(确保它不超过数组中最宽点的一半,否则它将不合适。)
var radius = 3;
var maxRadius = radius + 1;
我的计划是绘制一个圆,然后缩小半径并在其中画一个圆,直到半径为0,此时我无法再绘制,我会有一个倾斜的渐变。
要画一个圆圈,我需要弄清楚圆圈的坐标是什么。所以我查了一下,事实证明你可以使用这个等式来计算圆上坐标的位置:
x = centerX + radius * cos(angle)
y = centerY + radius * sin(angle)
因此,如果我们以角度0开始并递增它,直到它为360,我们就会有一个完整的圆圈。
function drawCircle(r) {
while(angle < 360) {
x = centerX + r * Math.cos(angle);
y = centerY + r * Math.sin(angle);
values[x][y] = maxRadius - r;
angle += 1;
}
}
drawCircle(radius);
这会将第一个圆圈放入我们的数组中。所以它现在看起来像这样:
[[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[0, 0, 1, 1, 1, 0],
[0, 1, 0, 0, 0, 1],
[0, 1, 0, 0, 0, 1],
[0, 1, 0, 0, 0, 1],
[0, 0, 1, 1, 1, 0],
[0, 0, 0, 0, 0, 0]]
现在我们只需要缩小半径以在其中绘制一个圆圈。虽然它确实在这个数组中画了一个正方形,但这只是因为它只是一个小例子,更大的例子看起来看起来更像一个圆圈,请看帖子底部的截图以获得更大的例子。
我编写了一个减少半径的循环,以便我们可以获得渐变效果。
while(radius > 0) {
drawCircle(radius);
angle = 0;
radius --;
}
Et瞧。运行该循环,你会看到这样的东西:
[ [ 0, 0, 0, 0, 0, 0 ],
[ 0, 0, 0, 0, 0, 0 ],
[ 0, 0, 1, 1, 1, 0 ],
[ 0, 1, 2, 2, 2, 1 ],
[ 0, 1, 2, 3, 2, 1 ],
[ 0, 1, 2, 2, 2, 1 ],
[ 0, 0, 1, 1, 1, 0 ],
[ 0, 0, 0, 0, 0, 0 ] ]
这是一个更大的例子:
HTH
答案 1 :(得分:1)
一种可能性是进行高斯梯度。因为高斯函数是可分的,所以可以单独将它应用于x值和y值。
您可以在此页面上获取公式并在代码中实现它。 https://en.wikipedia.org/wiki/Gaussian_function#Two-dimensional_Gaussian_function
为此,x0和y0将是数组中心的索引(3,3)。您只需遍历数组并计算每个数组元素的链接函数的值。这将提供你的alpha因素。
最后,这只是一种梯度衰减函数。它是一条正常的曲线,所以它给你一个从最强烈到最低强度的愉快渐变。如果您想要一种不同类型的曲线,可以使用d = sqrt((x-x0)^2 + (y-y0)^2)
模板与矩阵中心的距离来构建基于d
的函数
答案 2 :(得分:1)
我已经在这里留下了一个答案,但是有一种不同的(更好的)方法来实现。
此解决方案假定数组的中心是渐变的源(最高点)。
前提是您要遍历数组中的每个项目,并使用Euclidean distance计算它到中间点的距离。
这实质上表明可以通过计算∆x 2 + ∆y ^ 2 的平方根来找到两点之间的距离。
这是9x9
数组的实现:
var grid = []
var gridWidth = 9
var gridHeight = 9
var euclideanDistance = (point1, point2) => {
return Math.sqrt(
Math.abs(Math.pow(point1.x - point2.x, 2)) +
Math.abs(Math.pow(point1.y - point2.y, 2))
)
}
var centrePoint = {x: Math.floor(gridWidth / 2), y: Math.floor(gridHeight / 2)}
var furthestDistanceFromCentre = euclideanDistance(
{x: 0, y: 0}, centrePoint
)
for (var x = 0; x < gridWidth; x++) {
grid[x] = []
for (var y = 0; y < gridHeight; y++) {
grid[x][y] = Math.floor(
furthestDistanceFromCentre - euclideanDistance(
{x: x, y: y}, centrePoint
)
)
}
}
以下是输出:
[0, 0, 1, 1, 1, 1, 1, 0, 0]
[0, 1, 2, 2, 2, 2, 2, 1, 0]
[1, 2, 2, 3, 3, 3, 2, 2, 1]
[1, 2, 3, 4, 4, 4, 3, 2, 1]
[1, 2, 3, 4, 5, 4, 3, 2, 1]
[1, 2, 3, 4, 4, 4, 3, 2, 1]
[1, 2, 2, 3, 3, 3, 2, 2, 1]
[0, 1, 2, 2, 2, 2, 2, 1, 0]
[0, 0, 1, 1, 1, 1, 1, 0, 0]
之所以如此有效,是因为您不会遗漏任何点,网格中的每个单元格都被考虑在内。如果您使用的是我发布的其他解决方案,可能到处都是空白,这不理想。
这将为您每次提供平滑,流畅的结果。
I wrote an article on a use case of this here.
这是圆技巧上的点生成的渐变:
这是欧几里德距离技术生成的梯度: