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)
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')