پودمان:OSM Map
توضیحات این پودمان میتواند در پودمان:OSM Map/توضیحات قرار گیرد.
require('Module:No globals')
local getArgs = require('Module:Arguments').getArgs
local mWikidata = require('Module:Wikidata')
local errorCategory = '[[Category:Errors of OSM Map module]]'
local p = {}
-- Error handler per xpcall, formatta l'errore.
local function errhandler(msg)
local cat = mw.title.getCurrentTitle().namespace == 0 and errorCategory or ''
return string.format('<span class="error">%s</span>%s', msg, cat)
end
local function getLegend(points, ncols)
local divStyle = {
['margin-top'] = '5px',
['column-count'] = ncols,
['-moz-column-count'] = ncols,
['-webkit-column-count'] = ncols
}
local divNode = mw.html.create('div'):css(divStyle)
local currNum = 1
local currChar = 'A'
for _, point in ipairs(points) do
local pNode = mw.html.create('p')
:css('font-size', '90%')
:css('margin-top', '0')
local codeNode = mw.html.create('code')
:css('font-weight', 'bold')
:css('color', 'white')
:css('border-radius', '6px')
:css('border', '2px solid ' .. point.col)
:css('background', point.col)
if not point.symb then
codeNode:wikitext(' ')
elseif point.symb:find('-number') == 1 then
codeNode:wikitext(currNum)
currNum = currNum + 1
elseif point.symb:find('-letter') == 1 then
codeNode:wikitext(currChar)
currChar = ('ABCDEFGHIJKLMNOPQRSTUVWXYZA'):match(currChar .. '(.)')
elseif point.symb == '' then
else
codeNode
:css('padding-left', '0')
:css('padding-right', '0')
:css('background', 'white')
codeNode:wikitext(string.format('[[File:Maki2-%s-18.svg|18px]]', point.symb))
end
pNode:node(codeNode):wikitext(' ' .. point.name)
divNode:node(pNode)
end
return tostring(divNode)
end
function p._osm(args)
local points = {}
local infobox = tonumber(args.infobox) or 0
local mcolor = args.color or '#b80000'
local msymbol = args.symbol or '-number'
local mgroup = args.group or ''
local autozoom = args.autozoom or 'y'
local mlist = (args.list == '1' or args.list == '2') and args.list or nil
local symbol_size = 'medium'
local mframe = tonumber(args.frame) or 1
local lat1, lat2, lon1, lon2 = 400, -400, 400, -400
local map_args = {
width = args.width or (infobox == 1 and 260 or 350),
height = args.height or (infobox == 1 and 260 or 300),
align = args.align or (infobox == 1 and 'center' or 'right'),
frameless = (mframe == 0 or infobox == 1) and 1 or nil
}
if not args.data then
local num = 1
if infobox == 1 and args.lat1 == nil and args.lon1 == nil then
args.lat1 = mWikidata._getProperty({ 'P625', coord = 'latitude', n = 1 })
args.lon1 = mWikidata._getProperty({ 'P625', coord = 'longitude', n = 1 })
end
while args['name' .. num] do
points[num] = {
name = args['name' .. num],
desc = args['desc' .. num],
lat = tonumber(args['lat' .. num]) or -400,
lon = tonumber(args['lon' .. num]) or -400,
col = args['color' .. num] or mcolor,
symb = args['symbol' .. num] or msymbol,
symbsz = args['size' .. num] or symbol_size,
}
if points[num].symb == '-number' and mgroup ~= '' then
points[num].symb = '-number-' .. mgroup
end
if points[num].lat > 85 or points[num].lat < -85 then
error(string.format('Invalid value for lat%d', num), 2)
elseif points[num].lon > 180 or points[num].lon < -180 then
error(string.format('Invalid value for lon%d', num), 2)
else
lat1 = math.min(lat1, points[num].lat)
lat2 = math.max(lat2, points[num].lat)
lon1 = math.min(lon1, points[num].lon)
lon2 = math.max(lon2, points[num].lon)
end
num = num + 1
end
if #points == 1 and args.symbol == nil and args.symbol1 == nil then
points[1].symb = nil
end
end
if args.zoom then
map_args.zoom = tonumber(args.zoom)
elseif not args.data then
if #points == 1 then
map_args.zoom = 10
if infobox == 1 then
map_args.zoom = 13
end
elseif autozoom == 'y' then
local dx = 1.1 * (lon2 - lon1) / 360
local dy = 1.1 * (math.log(math.tan(math.pi * (1 + lat2 / 90) / 4)) - math.log(math.tan( math.pi * (1 + lat1 / 90) / 4))) / (2 * math.pi)
local scalex, scaley
if dx == 0 then scalex = 18 else scalex = math.floor(-math.log(dx) / math.log(2)) end
if dy == 0 then scaley = 18 else scaley = math.floor(-math.log(dy) / math.log(2)) end
if dx == 0 and dy == 0 then
map_args.zoom = 10
else
map_args.zoom = math.max(0, math.min(18, scalex, scaley))
end
end
end
if mframe == 1 and infobox ~= 1 then
map_args.text = (args.caption or '') .. (mlist and getLegend(points, mlist) or '')
end
if args.centre_lon then
map_args.longitude = tonumber(args.centre_lon)
elseif not args.data then
if #points == 1 then
map_args.longitude = points[1].lon
else
map_args.longitude = (lon1 + lon2) / 2
end
end
if args.centre_lat then
map_args.latitude = tonumber(args.centre_lat)
elseif not args.data then
if #points == 1 then
map_args.latitude = points[1].lat
else
local l1 = 1 - math.log(math.tan(math.pi * (1 + lat1 / 90) / 4)) / math.pi
local l2 = 1 - math.log(math.tan(math.pi * (1 + lat2 / 90) / 4)) / math.pi
local centrey = (l1 + l2) / 2
centrey = (math.atan(math.exp(math.pi * (1 - centrey))) - math.pi / 4) * 360 / math.pi
map_args.latitude = centrey
end
end
local m_data
if args.data then
m_data = args.data
else
m_data = { type = 'FeatureCollection', features = {} }
for i, point in ipairs(points) do
m_data.features[i] = {
type = 'Feature',
properties = {
['marker-symbol'] = point.symb,
['marker-color'] = point.col,
['marker-size'] = point.symbsz,
title = point.name,
description = point.desc
},
geometry = {
type = 'Point',
coordinates = { point.lon, point.lat }
}
}
end
m_data = mw.text.jsonEncode(m_data)
end
if args.debug then
local mdebug = mw.text.jsonEncode(map_args)
return string.format('<pre>%s\n\n%s</pre>', mdebug, m_data)
else
return mw.getCurrentFrame():extensionTag('mapframe', m_data, map_args)
end
end
function p.osm(frame)
return select(2, xpcall(function()
return p._osm(getArgs(frame, { parentOnly = true }))
end, errhandler))
end
return p