Create a gist now

Instantly share code, notes, and snippets.

@osnr /geokit-engine.lua Secret
Last active Aug 17, 2018

What would you like to do?
Geokit engine
-- Geokit 4th try: perfect fit
local function deg2num(lon, lat, zoom)
local n = 2 ^ zoom
local lon_deg = tonumber(lon)
local lat_rad = math.rad(lat)
local xtile = n * ((lon_deg + 180) / 360)
local ytile = n * (1 - (math.log(math.tan(lat_rad) + (1 / math.cos(lat_rad))) / math.pi)) / 2
return xtile, ytile
To know when tile URL /known url/ is downloaded to path /known path/:
local f = -- Try to open that path.
if f ~= nil then -- Tile was downloaded already.
Claim tile URL (url) is downloaded to path (path).
else -- Make HTTP request to get the tile.
When URL (url) has contents /contents/:
write_file(path, contents)
Claim tile URL (url) is downloaded to path (path).
function get_tile_url_and_path(url_template, zoom, xtile, ytile)
local url = string.format(url_template, zoom, xtile, ytile)
local filename = url:gsub("%W", "_")
local path = "shared/geokit-tiles/"..filename..".png"
return url, path
When /someone/ wishes /page/ shows tilelayer /url_template/ with options /opts/,
/page/ wishes /target/ shows tilelayer /something/ with options /something/,
page ~= target:
opts = rt.table(opts) -- Make a mutable copy of opts
opts.priority = 1 + (opts.priority or 1)
Wish (target) shows tilelayer (url_template) with options (opts).
When /someone/ wishes /map/ shows tilelayer /url_template/ with options /opts/,
/map/ is geomap of bbox /bbox/,
/map/ has width /width/, /map/ has height /height/:
-- Made-up formula to guess a good zoom from width of bbox.
local zoom = math.log(360 / (bbox.right - bbox.left)) / math.log(2)
zoom = math.ceil(zoom + width/16 - 1) -- experimentally determined width factor
local max_zoom = opts.max_zoom or 17
if zoom > max_zoom then zoom = max_zoom end
local xtile_left, ytile_top = deg2num(bbox.left,, zoom)
local xtile_right, ytile_bottom = deg2num(bbox.right, bbox.bottom, zoom)
local tilesize = width / (xtile_right - xtile_left)
for xtile=math.floor(xtile_left),math.floor(xtile_right) do
for ytile=math.floor(ytile_top),math.floor(ytile_bottom) do
local url, path = get_tile_url_and_path(url_template, zoom, xtile, ytile)
When tile URL (url) is downloaded to path (path):
local ill = new_illumination()
ill:image { filename=path, scale=1,
x=tilesize * (xtile - xtile_left),
y=tilesize * (ytile - ytile_top),
width=tilesize, height=tilesize }
Wish (map) has illumination (ill) with priority (opts.priority or 1).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment