0

我有一个定义为 mxn 128x128 的矩阵。我已经将我的 2d x,y 位置转换到这个 1D 矩阵网格上。我的二维坐标接受使用数字 0->127 的位置,即范围 {x=0,y=0}-->{x=127,y=127} 中的任何组合。我正在实现采用这些节点的相邻位置的算法。特别是距离 i 的 8 个周围位置(假设 i=1)。所以考虑 node={0,0},我的邻居是通过将这些向量添加到所述节点来生成的:

two_d_nodes={
        {0,i*1},{0,-i*1},{-i*1,0},{i*1,0},
        {i*1,i*1},{i*1,-i*1},{-i*1,-i*1},{-i*1,i*1}
    }

就二维而言,尽管我不包括边界外的邻居。所以在上面的 node={0,0} 中,只生成了邻居 {0,1},{1,1}{1,0}。设置边界基本上只是实现某种形式:

if x>=0 and y>=0 and x<=127 and y<=127 then... 

node={0,0} 的 1d 转换是 node={0} ,我的向量加法转换为 1d 是:

one_d_nodes={{128},{-128},{-1},{1},{129},{-127},{-129},{127}}

然而,与 2d 边界表达式的关系在这里并不成立。或者至少我不知道如何翻译它。作为回应,我尝试生成网格的所有松散案例:

{0,127,16256,16383} --the 4 corner positions  
node%128==0 --right-side boundary  
node%128==1 --left-side boundary  
node>1 and node<128 --top-side boundary  
node>127*128 and node<128*128 --bottom-side boundary    

然后尝试实现特殊情况……我只是忽略了生成特定的越界邻居。这很混乱,甚至由于某种原因没有工作。无论如何,我觉得我错过了一种更清洁的方法。

所以我的问题是:我如何将我的 2d 边界转换为我的 1d 网格,以便仅在边界内生成邻居?


以下是关于下面的答案:

function newmatrix(node) --node={x=0,y=0}
    local matrix={}
    add(matrix,{(node.y<<8)+node.x}) --matrix= {{0},...}
--lets say [1 2 3] is a width=3; height=1 matrix, 
--then the above line maps my 2d coord to a matrix of width=256, height=128 
    matrix.height, matrix.width = #node,#node[1] --1,1
    return matrix
 end

function indexmatrix(matrix, r,c)
    if r > 1 and r <= matrix.height and c > 1 and c <= matrix.width then
        return matrix[matrix.width * r + c]
    else
        return false
    end
end

function getneighbors(matrix, r, c)
    local two_d_nodes={
        {0,1},{0,-1},{-1,0},{1,0},
        {1,1},{1,-1},{-1,-1},{-1,1}
    }
    local neighbors = {}
    for index, node in ipairs(two_d_nodes) do
        table.insert(neighbors, indexmatrix(matrix, r + node[1], c + node[2]))
    end
    return neighbors
end
--Usage:
m={x=0,y=0}
matrix=newmatrix(m) --{{0}}
--here's where I'm stuck, cause idk what r and c are
--normally I'd grab my neighbors next....
neighbors=getneighbors(matrix)
--then I have indexmatrix for...?
--my understanding is that I am using indexmatrix to
--check if the nieghbors are within the bounds or not, is that right?
--can you illustrate how it would work for my code here, it should
--toss out anything with x less then 0 and y less than 0. Same as in OP's ex 
indexmatrix(matrix) ---not sure what to do here

关于以下评论部分的尝试 2:

function indexmatrix(matrix, x ,y)
    if x > 1 and x <= matrix['height'] and y > 1 and y <= matrix['width'] then
        return matrix[matrix['width'] * x + y]
    else
        return false
    end
end
function getneighbors(matrix, pos_x, pos_y)
    local two_d_nodes={
        {0,1},{0,-1},{-1,0},{1,0},
        {1,1},{1,-1},{-1,-1},{-1,1}
    }
    local neighbors = {}
    for _, node in ipairs(two_d_nodes) do
        add(neighbors, indexmatrix(matrix, pos_x + node[1], pos_y + node[2]))
    end
    return neighbors
end

matrix={} --128 columns/width, 128 rows/height 
for k=1,128 do
add(matrix,{}) ----add() is same as table.insert()
    for i=1,128 do
        matrix[k][i]=i
    end
end

id_matrix={{}} --{ {1...16k}}
for j=1,128*128 do
    id_matrix[1][j]=j
end
id_matrix.height, id_matrix.width = 128,128 
    
position={x=0,y=0}
neighbors = getNeighbors(matrix, position.x, position.y)

尝试 3:给定代码的工作简化版本。根本不是我想要的。

function indexmatrix(x,y)
    if x>=0 and y>=0 and x<127 and y<127 then
        return 128 * x + y
    else
        return false
    end
end
function getneighbors(posx,posy)
    local two_d_nodes={
        {0,1},{0,-1},{-1,0},{1,0},
        {1,1},{1,-1},{-1,-1},{-1,1}
    }
    local neighbors = {}
    for _, node in pairs(two_d_nodes) do
        add(neighbors, indexmatrix(posx+node[1], posy + node[2]))
    end
    return neighbors
end

pos={x=0,y=10}
neighbors = getneighbors(pos.x,pos.y)
4

1 回答 1

1

编辑:将 2D 坐标映射到 1D 的方程y = mx + z是两个变量的函数。一个多变量方程不可能有一个单一的解,除非给出一个方程组,它得到xz根据另一个变量。因为xz彼此独立,所以对这个问题的简短回答是:

相反,必须使用 和 的约束来确保一维坐标的完整性xz

下面是一个如何处理一维数组的示例,就好像它是一个二维矩阵一样。

假设我们有一个将 2D 表映射到 1D 矩阵的构造函数

local function newMatrix(m) -- m is 128x128 Matrix
    local Matrix = {}
    --logic to map m to 1D array
    -- ...
   return Matrix -- Matrix is m 1x16384 Array
end

数字索引是保留的,但我们可以添加非数字键来存储有关矩阵的信息。让我们将行数和列数存储为heightwidth。我们可以在构造函数中做到这一点

local function newMatrix(m)
    local Matrix = {}
    --logic to map to 1D array
    -- ...
    -- Store row and column info in the matrix
    Matrix.height, Matrix.width = #m, #m[1] -- Not the best way
    return Matrix
end

虽然矩阵现在是一个 1x16384 数组,但我们可以创建一个函数,允许我们与 1D 数组交互,就像它仍然是一个 2D 矩阵一样。此函数将获取矩阵中某个位置的值,但如果索引超出范围,我们将返回false/ 。nil

需要明确的是,将二维坐标映射到矩阵的一维坐标的公式可以在此处找到:

1D position = 2D.x * Matrix-Width + 2D.y

这是该函数的样子:

local function indexMatrix(Matrix, r,c)
    if r >= 1 and r <= Matrix.height and c >= 1 and c <= Matrix.width then
        return Matrix[Matrix.width * r + c] -- the above formula
    else
        return false -- out of bounds
    end
end

我们现在可以用任何边界索引我们的矩阵,而不必担心返回不正确的元素。

最后,我们可以创建一个函数来抓取给定2D 位置的邻居。在此函数中,我们将向量添加到给定的 2D 位置以获取周围位置,然后使用该indexMatrix函数对矩阵进行索引。因为indexMatrix检查 2D 位置是否在原始矩阵的范围内(在它被转换之前),我们只得到存在的邻居。

local function getNeighbors(Matrix, r, c) -- r,c = row, column (2D position)
    local two_d_nodes={
        {0,1},{0,-1},{-1,0},{1,0},
        {1,1},{1,-1},{-1,-1},{-1,1}
    }
    local neighbors = {}
    for index, node in ipairs(two_d_nodes) do
        -- Add each vector to the given position and get the node from the Matrix
        table.insert(neighbors, indexMatrix(Matrix, r + node[1], c + node[2]))
    end
    return neighbors
end

您可以跳过返回 false 的元素,也可以indexMatrix在事后删除它们。或者任何其他听起来更好的东西(这段代码不是很好,它只是一个例子)。将它包裹在一个for i ... do循环中,您可以出去任意距离。

我希望我没有假设太多,这很有帮助。只要知道它不是万无一失的(例如,#操作员首先停止计数nil

编辑:用法

Matrix = {
    {1,2,3...128}, -- row 1
    {1,2,3...128},
    ...
    {1,2,3...128}, -- row 128
}

Array = newMatrix(Matrix) -- Convert to 1D Array ({1,2,3,...,16384})
--Array.width = 128, Array.height = 128
position = {x=0, y=0}
neighbors = getNeighbors(Array, position.x, position.y)
-- neighbors is: {{0,1}, false, false, {1,0}, {1,1}, false, false, false}
于 2021-08-08T22:38:42.733 回答