1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
|
-- grid.lua
-- routines taking the tracks and building a grid out of them
local tm = advtrains.trackmap
-- Maximum scan length for track iterator
local TS_MAX_SCAN = 1000
-- Get a character matching the class requested by chr, in the correct orientation for conndir
-- The characters will be chosen from the unicode frame set if appropriate
-- valid character classes -, =, |
local char_equiv = {
["-"] = {"│", "/", "─", "\\\\"}, -- single-line
["="] = {"║", "/", "═", "\\\\"}, -- double-line
["|"] = {"─", "\\\\", "│", "/"}, -- break (i.e. TCB, perpendicular to orientation)
}
local dir_to_charmap = {
[15] = 1,
[ 0] = 1,
[ 1] = 1,
[ 2] = 2,
[ 3] = 3,
[ 4] = 3,
[ 5] = 3,
[ 6] = 4,
[ 7] = 1,
[ 8] = 1,
[ 9] = 1,
[10] = 2,
[11] = 3,
[12] = 3,
[13] = 3,
[14] = 4,
}
function tm.rotate_char_class_by_conn(chr, conndir)
--atdebug("rotatechar", chr, conndir, "dircharmap", dir_to_charmap[conndir], "charequiv", char_equiv[chr])
return char_equiv[chr][dir_to_charmap[conndir]]
end
-- Generate a grid map by walking tracks starting from the given position start_pos
-- For every track that is visited, node_callback is called.
-- signature: node_callback(pos, conns, connid)
-- should return a table as follows:
-- {
-- char = "X" -- the character to use in this place, defaults to guessing a fitting frame character
-- color = "colorstring" or nil -- the color to render the character with
-- stop = false -- if true, the iterator will stop following this branch
-- }
-- Returning nil will assume defaults.
-- return value: a table:
-- {
-- grid = <grid> - access abs_grid[x][y] - contains one character per cell
-- min_pos = <pos> - the minimum pos contained in this grid
-- max_pos = <pos> - the maximum pos
-- }
function tm.generate_grid_map(start_pos, node_callback)
local ti = advtrains.get_track_iterator(start_pos, nil, TS_MAX_SCAN, true)
local grid = {} -- grid[x][y]
local gcolor = {} -- grid[x][y]
local gylev = {} -- grid[x][y]
local gminx, gmaxx, gminz, gmaxz = start_pos.x, start_pos.x, start_pos.z, start_pos.z
while ti:has_next_branch() do
pos, connid = ti:next_branch()
repeat
local ok, conns = advtrains.get_rail_info_at(pos)
local c = node_callback(pos, conns, connid)
local chr = c and c.char
--atdebug("init",pos.x,pos.z,chr,"")
if not chr then
chr = tm.rotate_char_class_by_conn("=", conns[connid].c)
end
-- add the char to the grid
if not grid[pos.x] then
grid[pos.x] = {}
gcolor[pos.x] = {}
gylev[pos.x] = {}
end
-- ensure that higher rails are rendered on top
local prev_ylev = gylev[pos.x][pos.z]
if not prev_ylev or prev_ylev < pos.y then
grid[pos.x][pos.z] = chr
gylev[pos.x][pos.z] = pos.y
if c and c.color then
gcolor[pos.x][pos.z] = c.color
end
end
gminx = math.min(gminx, pos.x)
gmaxx = math.max(gmaxx, pos.x)
gminz = math.min(gminz, pos.z)
gmaxz = math.max(gmaxz, pos.z)
if c and c.stop then break end
pos, connid = ti:next_track()
until not pos
end
return {
grid = grid,
gcolor = gcolor,
min_pos = {x=gminx, z=gminz},
max_pos = {x=gmaxx, z=gmaxz},
}
end
|