Пример #1
0
def main():
    random.seed(38272932)
    points = getrandompoints(
        30, 1000, (0.0, 0.0), None,
        30, 600,
        30, 200,
        30, 50
    )
    # mix them up for a specified amount of time
    imax = len(points) - 1
    st = time.time()
    random.seed(time.time())
    print('rendering output image of nodes..')
    tga = TGAImage(1000, 1000)
    tga.drawpoints(points)
    tga.save('test.tga')
    print('mixing initial node list..')
    random.shuffle(points)
    #while time.time() - st < 10:
    #    a = random.randint(0, imax)
    #    b = random.randint(0, imax)
    #    tmp = points[a]
    #    points[a] = points[b]
    #    points[b] = tmp
    print('starting solver..')
    st = time.time()
    path = solve(points)
    tt = time.time() - st
    if len(path) < len(points):
        raise Exception('All points must be included in the path.')

    td = getpathdistance(points, path)

    print('total-distance:   %.2f' % td)
    print('time-taken:       %.2f' % tt)
Пример #2
0
def solve(grid, w, h, toohigh, start, end):
    # build rectangle portals across grid
    rportals = []

    UNUSED = 1000000
    used = array.array('I', (UNUSED for x in range(0, w * h)))

    y = 0
    ri = 0
    while y < w:
        x = 0
        while x < h:
            # is valid point?
            if grid[y * w + x] < toohigh and used[y * w + x] == UNUSED:
                # find right most point
                for nx in range(x, w):
                    if grid[y * w + nx] >= toohigh or used[y * w + nx] != UNUSED:
                        nx = nx - 1
                        break
                nx = nx + 1
                # see how tall we can make it
                for ny in range(y, h):
                    for _x in range(x, nx):
                        if grid[ny * w + _x] >= toohigh or used[ny * w + _x] != UNUSED:
                            _x = _x - 1
                            break
                    _x = _x + 1

                    if _x < nx:
                        break
                # create rect
                rect = (x, y, nx, ny)
                # gill area and mark rect's index in rportals
                # we will use this later when building an actual
                # graph of the portals
                for __y in range(y, ny):
                    for __x in range(x, nx):
                        used[__y * w + __x] = len(rportals)

                rportals.append(rect)
                x = nx
            else:
                x = x + 1
        y = y + 1
    # go through and build what other rect portals are accessible from
    # each rect portal
    graph = []
    for rpi in range(0, len(rportals)):
        rect = rportals[rpi]
        # break out components
        sx, sy, ex, ey = rect
        # go around border looking for other portals
        bportals = set()
        if sy - 1 > -1:
            for x in range(sx, ex):
                i = used[(sy - 1) * w + x]
                if i != UNUSED:
                    bportals.add(i)
        if ey < h:
            for x in range(sx, ex):
                i = used[ey * w + x]
                if i != UNUSED:
                    bportals.add(i)
        if sx - 1 > -1:
            for y in range(sy, ey):
                i = used[y * w + (sx - 1)]
                if i != UNUSED:
                    bportals.add(i)
        if ex < w:
            for y in range(sy, ey):
                i = used[y * w + ex]
                if i != UNUSED:
                    bportals.add(i)
        # we now have all the portals that are adjacent
        node = [rect, bportals]
        graph.append(node)

    # go through and optimize graph to include a direct
    # link to the border node instead of using an index
    for gni in range(0, len(graph)):
        gn = graph[gni]

        bportals = gn[1]
        _bportals = list()
        for bp in bportals:
            _bportals.append(graph[bp])
        gn[1] = _bportals

    # our graph is now complete and usable

    tga = TGAImage(w, h)
    # first render impassable areas
    ivp = 0
    for y in range(0, h):
        for x in range(0, w):
            if grid[y * w + x] >= toohigh:
                tga.put(x, y, (0, 0, 0))
                ivp = ivp + 1
    tga.save('passable.tga')

    tga = TGAImage(w, h, 12)
    # first render impassable areas
    ivp = 0
    for y in range(0, h):
        for x in range(0, w):
            if grid[y * w + x] >= toohigh:
                tga.put(x, y, (190, 190, 190))
                ivp = ivp + 1

    pc = len(grid) - ivp
    print('portals', len(graph))
    print('valid-pixels', pc)
    print('speed-factor', pc / len(graph))

    colors = (
        (0, 170, 0),
        (0, 90, 170)
    )
    ci = 0
    rc = 0
    # go through and color and mark portals and links
    for gn in graph:
        rect = gn[0]          # our rect
        bnodes = gn[1]        # our border nodes

        sx, sy, ex, ey = rect
        # calculate our center
        cx = sx + ((ex - sx) / 2)
        cy = sy + ((ey - sy) / 2)

        tga.putboxoutline(sx, sy, ex, ey, (90, rc, 90))

        # iterate through border nodes
        rc = (rc + 40) & 0xff
        for bn in bnodes:
            bsx, bsy, bex, bey = bn[0]
            bcx = bsx + ((bex - bsx) / 2)
            bcy = bsy + ((bey - bsy) / 2)            
            # draw line denoting connection (portal)
            tga.putline(cx, cy, bcx, bcy, (rc, 90, 90))

    tga.save('graph_scaled.tga')