Module:OSM Map: Difference between revisions
m (1 revision imported) |
(No difference)
|
Revision as of 12:11, 20 January 2020
Documentation for this module may be created at Module:OSM Map/doc
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