如何在Lua中实现brushfire算法?

时间:2015-01-19 20:46:43

标签: algorithm lua adjacency-list breadth-first-search

我正致力于实施"基于目标的矢量场寻路" (在this link的文章中说明)它要求我用我的世界图中的每个节点标记距离目标节点的路径距离,并建议使用brushfire(波前)算法来执行此操作。这是我遇到问题的区域。当我进入while循环的第8次迭代和嵌套for的第6次迭代时,我在标记的行上得到一个nil引用错误。

g 是我的图表,它有一个8向邻接列表表单。

q this FIFO lua库的实例。

rtx rty 是根节点的x和y坐标。

d 是为了跟踪分配给每个节点的路径距离而添加的迭代器。

图中每个节点的结构与正在处理的节点的结构不同。

要处理的节点:

n = {}
n[1] = x coord
n[2] = y coord
n[3] = adjacency list (eight entries)
n.vX = x componant of vector for vector field
n.vY = y componant of vector for vector field

节点存储在图表中:

n = {}
n[1] = adjacency list
n.vX = x componant of vector for vector field
n.vY = y componant of vector for vector field

Beneath是我迄今为止的实施方式。 for循环中的t只是一个临时节点,用于将信息传递给队列。 BTW t是所有节点的距离设置的地方。

local function brushFire( g, rtx, rty )
    local q = q.new()
    local s = {}
    s[1] = rtx
    s[2] = rty
    s[3] = g[rtx][rty][3]
    s.dist = 0
    q:pushRight( s )
    s = nil
    local d = 0

    while( table.getn( q.list[q.first] ) ~= 0 ) do
        print( d )
        local n = q:popLeft()
        setDist( g, n )
        print( #n[3] )
        for i = 1, #n[3] do
            print( ":"..i )
            if( g[n[3][i][4]][n[3][i][2]].v ~= true ) then
                g[n[3][i][5]][n[3][i][2]].v = true
                local t = {}
                t[1] = n[3][i][1]
                t[2] = n[3][i][2]
                t[3] = g[n[3][i][7]][n[3][i][2]][1]  <------Error here
                t.dist = d
                q:pushRight( t )
                t = nil
            end
        end
        d = d + 1
    end
end

如果您需要更多信息以便回答我的问题,请与我们联系。

1 个答案:

答案 0 :(得分:1)

我找到了问题的答案。如果有人想使用该来源,我将在下面发布:

队列模块:

local q = {}
local q_mt = { __index = q }

function q.new()
    local nq = { first = 0, last = -1, list = {} }

    return setmetatable( nq, q_mt )
end

function q:pushLeft( value )
    local first = self.first - 1
    self.first = first
    self.list[first] = value
end

function q:pushRight( value )
    local last = self.last + 1
    self.last = last
    self.list[last] = value
end

function q:popLeft()
    local first = self.first
    if first > self.last then error( "list is empty" ) end
    local value = self.list[first]
    self.list[first] = nil
    self.first = first + 1
    return value
end

function q:popRight()
    local last = self.last
    if self.first > last then error( "list is empty" ) end
    local value = self.list[last]
    self.list[last] = nil
    self.last = last - 1
    return value
end

return q

以下模块创建一个向量字段,当调用pathFind.findPath时,该字段指向目标:

local q = require( "Queue" )

local pathFind = {}
local pathFind_mt = { __index = pathFind }

--  Private Functions

local function genDistMap( g, rtx, rty )      -<-<-<- genDistMap is the brushfire part
    local q = q.new()
    local g = g
    g[rtx][rty].v = true
    g[rtx][rty].dist = 0
    local s = {}
    s[1] = rtx
    s[2] = rty
    s[3] = g[rtx][rty][1]
    s.dist = 0
    q:pushRight( s )
    s = nil

    while( q.list[q.first] ~= nil ) do
        local n = q:popLeft()
        for i = 1, #n[3] do
            local x, y = n[3][i][1], n[3][i][2]
            if( g[x][y].v ~= true ) then
                g[x][y].v = true
                local t = {}
                t[1] = x
                t[2] = y
                t[3] = g[x][y][1]
                t.dist = n.dist + 1
                g[x][y].dist = n.dist + 1
                q:pushRight( t )
                t = nil
            end
        end
    end

    return g
end

local function genVectorField( nodes )
    local nodes = nodes

    for i = 2, #nodes - 1 do
        for j = 2, #nodes[i] - 1 do
            local a = nodes[i - 1][j].dist - nodes[i + 1][j].dist
            local b = nodes[i][j - 1].dist - nodes[i][j + 1].dist
            local c = math.sqrt( a*a + b*b )
            nodes[i][j].vX = a/c*5
            nodes[i][j].vY = b/c*5
        end
    end

    return nodes
end

--  Public Functions

function pathFind.new()
    local newPathFind = {}

    return setmetatable ( newPathFind, pathFind_mt )
end

function pathFind.findPath( nodeSet, rootX, rootY )
    local nodes = nodeSet

    nodes = genDistMap( nodes, rootX, rootY )

    nodes = genVectorField( nodes )

    return( nodes )
end

return pathFind