“拼接”多个二维数组

Posted

技术标签:

【中文标题】“拼接”多个二维数组【英文标题】:"Stitching" multiple 2d Arrays 【发布时间】:2016-10-02 08:55:30 【问题描述】:

编辑(改写的问题): 我将如何使用提供的 smoothstep 函数在相邻的二维数组之间创建渐变?每个数组的大小相同,包含范围在 0 和 1 之间的值,通过单纯形噪声从边缘到边缘平滑过渡。因此,我希望相邻数组值之间的差异最大为 0.04

function smoothstep (min, max, value) 
    var x = Math.max(0, Math.min(1, (value-min)/(max-min)));
    return x*x*(3 - 2*x);
;

我有 6 个二维数组,其中包含 0 到 1 之间的值来表示球体表面的高度。要遍历数组的所有值,我有这个:

for (var i = 0; i < cube.faces.length; i++) 
    for (var x = 0; x < cube.faces[i].heightMap.length; x++) 
        for (var z = 0; z < cube.faces[i].heightMap.length; z++) 
            if (x == 0 || x == cube.faces[i].heightMap.length - 1 || z == 0 || z == cube.faces[i].heightMap.length - 1) 
                switch (i) 
                    case 0:
                        if (x == 0) 
                            //match left of face 1 to top of face 4
                         else if (z == 0) 
                            //match top of face 1 to top of face 6
                         else if (z == cube.faces[i].heightMap.length - 1) 
                            //match bottom of face 1 to top of face 5
                         else 
                            //match right of face 1 to top of face 3
                        
                        break;
                    case 1:
                        if (x == 0) 
                            //match left of face 2 to bottom of face 3
                         else if (z == 0) 
                            //match top of face 2 to bottom of face 6
                         else if (z == cube.faces[i].heightMap.length - 1) 
                            //match bottom of face 2 to bottom of face 5
                         else 
                            //match right of face 2 to bottom of face 4
                        
                        break;
                    case 2:
                        if (x == 0) 
                            //match left of face 3 to right of face 5
                         else if (z == 0) 
                            //~~match top of face 3 to right of face 1~~
                         else if (z == cube.faces[i].heightMap.length - 1) 
                            //~~match bottom of face 3 to left of face 2~~
                         else 
                            //match right of face 3 to left of face 6
                        
                        break;
                    case 3:
                        if (x == 0) 
                            //match left of face 4 to right of face 6
                         else if (z == 0) 
                            //~~match top of face 4 to left of face 1~~
                         else if (z == cube.faces[i].heightMap.length - 1) 
                            //~~match bottom of face 4 to right of face 2~~
                         else 
                            //match right of face 4 to left of face 5
                        
                        break;
                    case 4:
                        break;
                    case 5:
                        break;
                    default:
                        break;
                
            
        
    

但是,我在让面孔匹配时遇到了一些麻烦。调查这个我发现了一个名为“smoothstep”的函数,这似乎正是我所需要的。我不知道如何实现它,我还没有找到对我有用的解释。

function smoothstep(min, max, value) 
    var x = Math.max(0, Math.min(1, (value - min) / (max - min)));
    return x * x * (3 - 2 * x);
;

以下页面是我学习此方法的地方,但我无法理解要说的内容。如果有人有时间,您能解释一下我如何将其实施到我的情况中吗? Link to related question

【问题讨论】:

示例输入、预期输出、实际输出,解释问题所在。不要只是发布一大段代码并说它不起作用。 问题是如何对两个包含 0 到 1 值的二维数组实现平滑步长算法,以使它们当前不无缝的边缘变得无缝。如果你真的需要一个例子,我可以给出一个,但是任何符合这些参数的输入都可以。 那么想要的结果是什么?它有什么作用?你有参考吗?你已经提供了一个实现,那么有什么问题呢?请输入和输出。 输入量很大,但总是一个包含 0 和 1 之间值的二维数组。任何介于 0 和 1 之间的二维数组。所有数组的大小都相同。预期输出是相邻数组边缘上的值大致相等,而不会影响整个原始数组的斜率。我现在得到的输出没有,因为我要求解释这个平滑步骤,以便我可以开始处理这个问题。我对这个主题的研究使我相信smoothstep 是正确的算法,但是我无法掌握它,这是我的全部问题。也许您误解了要问的内容。 我尝试对您链接的question 实施解决方案,但我不确定result 是否是您想要实现的(高度图缝合在一起,接缝是已删除,但您仍然可以看到地图被缝合在一起的位置,因为地图边缘的区域已部分镜像)。 【参考方案1】:

RE:Smoothstep,我在 Python 的 IDLE 解释器中快速重新创建了该函数,以便我可以将值插入其中并获得即时结果,据我所知,它所做的只是将你的最小值拉伸到 0,你的最大值为 1,然后相应地对 value 参数进行归一化。

例如,如果您提供参数(0.2, 0.4, 0.3) 0.3 介于 0.2 和 0.4 之间,因此该函数会将值标准化为大约 0.5

您是否只是想用 50 个数组行/列与边 A 和边 B 相交来创建一个实心的数字渐变?

如果是这样,我不知道smoothstep是否可行。

不管怎样,对于这样的事情,我会拿出一张纸,拿出一张纸,画出这样的东西,中间有数组 id 并标记边缘(假设在下面的例子中是一个骰子面图案):

        |--A--|
        D  3  B
        |--C--|

        |--A--|
        D  1  B
        |--C--|

|--A--| |--A--| |--A--|
D  2  B D  4  B D  5  B
|--C--| |--C--| |--C--|

        |--A--|
        D  6  B
        |--C--|

然后在你的脑海中将它折叠起来(或将它剪下来并物理折叠立方体)以找到边缘对并绘制箭头指示从边缘向内进入面部的方向。 (我喜欢使用 N(orth)、E(ast)、S(outh)、W(est) 来可视化从边缘朝哪个方向前进。

前进方向:

N = Same columnID, Start at max RowID and decrement  (going north)
E = Same rowID, Start at min ColumnID and increment  (going east)
S = Same columnID, Start at min RowID and increment  (going south)
W = Same rowID, Start at max ColumnID and decrement  (going west)

您最终会得到一个类似var list = [1,B,W,, 5,A,S,], [4,B,W,, 5,D,E,]...etc...] 的列表(额外的逗号是有意的,表示列表中的空格,接下来填写)

现在,随着该列表的构建,您可以从边缘沿您为每个数组指定的任何方向获取值,25 行或列,将其插入到空白区域的列表中,您将获得绝对最小值和渐变的最大值。例如var list = [[1,B,W,0.3, 5,A,S,0.7],...etc...]

然后,如果它是一个实心渐变,您只需做一些简单的数学运算 step_value = Math.abs(list[n][3] - list[n][7])/50 然后在适当的方向上从每个边缘的起始值递增或递减,具体取决于它是最小值还是最大值。

如果它比二维数组边缘之间的直线渐变更复杂,我深表歉意,但可能需要更好地可视化您正在尝试做什么。

【讨论】:

您想要我的数据值,还是看到我的整个项目更令人满意?它们是从 0 到 1 的值范围,相邻的值相差不超过 0.04,呈现出渐变的起伏地形。 我想我只是不完全清楚形成边缘的 25 个值是否重要,或者如果你只想取两个值,从任一边缘 25 英寸,并绘制一个直线渐变他们之间? 我从 1/0.04 中得到了 25 分,以确保考虑到最坏的情况,但我再次不确定我是否在正确的轨道上。 所以你实际上可以从每条边走 13 英寸(总共 26 条),以低于 0.04 变化最坏情况情景上限。在所有边缘上都有一个直线渐变,“立方体”的角落看起来有点傻。不过,不确定最好的解决方法是什么。 啊,没错!从那里我会平均每侧的高度,然后从每个边缘变化值继续向内迈进到公差(0.04)内?因为这会让我重新寻找特定算法,以便从平均值平滑过渡到公差内的差异点,在这种情况下最多 13 步。【参考方案2】:

尝试解释smoothstep。您首先从两个值之间的线性插值开始,然后使用三次函数对其进行修改。

该图以绿色显示 0 和 1 之间的线性插值,红色显示平滑版本。我已将 x 的值限制在范围之外,但您也可以看到黑色立方的延续。

在函数中

function smoothstep(min, max, value) 
    var x = Math.max(0, Math.min(1, (value - min) / (max - min)));
    return x * x * (3 - 2 * x);
;

该函数将始终返回一个介于 0 和 1 之间的值。如果 value max 返回 1。如果 value 在 min 和 max 之间,则得到一个插值。

在数学上它是立方 3 x^2 - 2 x^3 的一部分。


我的第一直觉是在每个边缘应用Gaussian blurring。

【讨论】:

我不确定如何在容差范围内实现高斯模糊,因为数组边缘的值将被修改得最多,并且越接近原始值越远走向他们的中心。

以上是关于“拼接”多个二维数组的主要内容,如果未能解决你的问题,请参考以下文章

lua 二维数组

如何在java中将二维数组拆分为多个不同大小的二维数组

python中如何将多个一维数组变成二维数组

php 一个二维数组求二维数组内的并集

跨多个单元格最有效地搜索二维数字数组

二维数组java - 多个错误[重复]