Modulo:Maplink

Questo è un modulo scritto in Lua. Le istruzioni che seguono sono contenute nella sottopagina Modulo:Maplink/man (modifica · cronologia)
Sandbox: Modulo:Maplink/sandbox (modifica · cronologia) · Sottopagine: lista · Test: Modulo:Maplink/test (modifica · cronologia · Esegui)
Questo modulo è utilizzato dal template {{Maplink}} per il calcolo del centro della mappa e della scala.
È utilizzata la proiezione Web Mercator (EPSG:3857).
- zoom
- calcola l'ingrandimento adeguato sulla base delle dimensioni dell'immagine e delle coordinate inserite.
- La funzione utilizza quattro parametri obbligatori:
- larghezza in pixel della carta (al momento non utilizzata)
- altezza in pixel della carta (al momento non utilizzata)
- lista separata da virgole con la longitudine dei singoli punti (x1,x2,x3,...)
- lista separata da virgole con la latitudine dei singoli punti (y1,y2,y3,...)
- centro_lon
- calcola la longitudine del punto medio rispetto al valore minimo e a quello massimo tra quelli inseriti.
- La funzione utilizza un solo parametro:
- lista separata da virgole con la longitudine dei singoli punti (x1,x2,x3,...)
- centro_lat
- calcola la latitudine del punto medio rispetto al valore minimo e a quello massimo tra quelli inseriti (utilizza una correzione dovuta alla proiezione utilizzata da OpenStreetMap).
- La funzione utilizza un solo parametro:
- lista separata da virgole con la latitudine dei singoli punti (y1,y2,y3,...)
require('Module:No globals')
local getArgs = require('Module:Arguments').getArgs
local p = {}
local pp = {}
local txt = {}
local function agg(t)
table.insert(txt,t)
end
function p.mappa(frame)
local t = getArgs(frame)
local err = '-'
local cornice
if (t['cornice']) then cornice = tonumber(t['cornice']) or 1 else cornice = 1 end
local allinea = t['allinea'] or 'right'
local dida = t['didascalia'] or ''
local elenco = t['mostra elenco'] or 0
local largh = t['larghezza'] or 350
local altezza = t['altezza'] or 300
local gruppo = t['gruppo'] or ''
if not (gruppo == '') then gruppo = '-'..gruppo end
local zoom = tonumber(t['zoom']) or '-1'
local centrox = t['centro_lon'] or ''
local centroy = t['centro_lat'] or ''
local colore = t['colore'] or '#b80000'
local lat1, lat2, lon1, lon2 = 400, -400, 400, -400
local num = 1
while (t['nome'..num]) do
pp[num] = {
nome = t['nome'..num],
lat = tonumber(t['lat'..num]) or -400,
lon = tonumber(t['lon'..num]) or -400,
col = t['colore'..num] or colore,
num = t['numero'..num] or num
}
if (pp[num].lat > 85 or pp[num].lat<-85) then
err = string.format('latitudine non valida per il punto %d', num)
elseif (pp[num].lon > 180 or pp[num].lon<-180) then
err = string.format('longitudine non valida per il punto %d', num)
else
lat1 = math.min(lat1, pp[num].lat)
lat2 = math.max(lat2, pp[num].lat)
lon1 = math.min(lon1, pp[num].lon)
lon2 = math.max(lon2, pp[num].lon)
end
num = num + 1
end
if (err == '-') then
if (centrox == '') then centrox = (lon1+lon2)/2 end
if (centroy == '') then
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
centroy = (l1+l2)/2
centroy = (math.atan(math.exp(math.pi*(1-centroy)))-math.pi/4)*360/math.pi
end
if (zoom == '-1') 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 scalax, scalay
if (dx == 0) then scalax = 18 else scalax = math.floor(-math.log(dx)/math.log(2)) end
if (dy == 0) then scalay = 18 else scalay = math.floor(-math.log(dy)/math.log(2)) end
if ((dx == 0) and (dy == 0)) then
zoom = 10 --valore default per singolo punto
else
zoom = math.max(0,math.min(18,scalax, scalay))
end
end
if (zoom < 0) then zoom = 0 elseif (zoom>18) then zoom = 18 end
if (cornice == 1) then
agg('\n{| class="wikitable')
if (allinea == 'right') then agg(' floatright') elseif (allinea == 'left') then agg(' foatleft') end
agg('" style="border: 1px solid darkgray;')
if (allinea == 'center') then agg('margin-left: auto; margin-right: auto') end
agg('"\n|-\n|style="width: '..largh..'px;"|')
end
agg('{{Graph:Street map with marks|lat='..centroy..'|lon='..centrox..'|zoom='..zoom..'|width='..largh..'|height='..altezza..'| minimap=0')
agg('|{"lat":'..centroy..',"lon":'..centrox..',"img":"wikirawupload:{{filepath:Mapscaleline.svg|120}}","width":50,"height":8,"offsetX":'..(math.floor(largh/2)-37))
agg(',"offsetY": '..(math.floor(altezza/2)-10)..',"textAlign":"right","textDx":22,"textDy":-2,"textColor": "grey","textFont":"Tahoma","textFontSize":9,"text": "')
local zz = {}
if (math.abs(centroy)<20) then
zz = {'10 000km','5000km','3000km','1500km','1000km','400km','200km','100km','60km','20km','10km','6km','4km','2km','1km','400m','200m','100m','60m' }
elseif (math.abs(centroy)<40) then
zz = {'10 000km','5000km','3000km','1200km','800km','300km','150km','75km','45km','15km','8km','5km','3km','1.5km','750m','300m','150m','75m','45m' }
elseif (math.abs(centroy)<40) then
zz = {'10 000km','5000km','3000km','1000km','500km','200km','100km','50km','30km','10km','5km','3km','2km','1km','500m','200m','100m','50m','30m' }
else
zz = {'10 000km','5000km','3000km','900km','400km','160km','80km','40km','20km','7km','4km','2km','1km','600m','350m','160m','80m','40m','20m' }
end
agg(zz[zoom+1]..'" }')
for i=1,#pp do
agg(',{"lat":'..pp[i].lat..',"lon":'..pp[i].lon..',"size":"200","color":"'..pp[i].col..'","strokeColor":"","shape":"circle","text":"","textAlign":"left","textBaseline":"middle","textDx":0,"textDy":1,"textFontSize":10}')
agg(',{"lat":'..pp[i].lat..',"lon":'..pp[i].lon..',"shape":"square","size": "0","text":"'..pp[i].num..'","textAlign":"center","textBaseline":"bottom","textDx":0,"textDy":5.5,"textFont":"Arial","textFontSize": 11,"textFontWeight":"bold","textColor":"white"}')
end
agg(' }}\n<div style="text-align:left;font-size:70%;color:grey"><span style="font-size:125%">{{#tag:maplink|\n[ {"type": "FeatureCollection", "features": [')
for i=1,#pp do
if (i>1) then agg(',') end
agg('{"type":"Feature","geometry":{"type":"Point","coordinates":['..pp[i].lon..','..pp[i].lat..'] }')
agg(',"properties":{"title": "'..pp[i].nome..'","description":"","marker-symbol": "-number'..gruppo..'","marker-size":"medium","marker-color":"'..pp[i].col..'" } }')
end
agg('] } ]|zoom='..zoom..'|latitude='..centroy..'|longitude='..centrox..'|text="[Schermo intero]"}}</span>')
agg('<div style="float:right" class="plainlinks nourlexpansion">[https://wikimediafoundation.org/wiki/Maps_Terms_of_Use Wikimedia] | © [https://www.openstreetmap.org/copyright OSM]</div></div>')
if (cornice == 1) then
agg('\n|-')
if not (dida == '') then agg('\n|style="font-size:90%"|'..dida) end
if (elenco == '2') then
agg('\n|\n{| width="100%"\n|-\n|width=50% valign=top|<small>')
for i=1,#pp do
agg('{{NumLegenda|'..pp[i].num..'|'..pp[i].col..'|'..pp[i].nome..'}}<br/>')
if (i == math.floor(#pp/2 +0.5)) then agg('</small>\n|width=50% valign=top|<small>') end
end
agg('</small>\n|}')
elseif (elenco == '1') then
if (dida == '') then agg('\n|style="font-size:90%"|') else agg('<br/>') end
agg('<small>')
for i=1,#pp do
agg('{{NumLegenda|'..pp[i].num..'|'..pp[i].col..'|'..pp[i].nome..'}}<br/>')
end
end
agg('</small>\n|}')
end
return frame:preprocess(table.concat(txt))
else
return err
end
end
-- Calcola centro per longitudine
-- esempio chiamata di funzione {{#invoke:Mappa OSM|centro_lon|x1,x2,...}}
function p.centro_lon(frame)
local t = getArgs(frame)
local mn, mx = 400, -400
local xval
for x in string.gmatch(t[1],'([^,]+)') do
xval = tonumber(x)
if (mn > xval) then mn = xval end
if (mx < xval) then mx = xval end
end
return (mn+mx)/2
end
-- Calcola centro per latitudine
-- esempio chiamata di funzione {{#invoke:Mappa OSM|centro_lat|x1,x2,...}}
function p.centro_lat(frame)
local t = getArgs(frame)
local mn, mx = 400, -400
local xval
for x in string.gmatch(t[1],'([^,]+)') do
xval = tonumber(x)
if (mn > xval) then mn = xval end
if (mx < xval) then mx = xval end
end
if ((mx>85) or (mn<-85)) then return 0 end
local lat1 = 1-math.log(math.tan( math.pi*(1 + mn/90)/4))/math.pi
local lat2 = 1-math.log(math.tan( math.pi*(1 + mx/90)/4))/math.pi
local latm = (lat1+lat2)/2
local coord = (math.atan(math.exp(math.pi*(1-latm)))-math.pi/4)*360/math.pi
return coord
end
-- Calcola la scala adeguata per mappa OSM
-- esempio chiamata di funzione {{#invoke:Mappa OSM|zoom|w|h|x1,x2,...|y1,y2...}}
function p.zoom(frame)
local t = getArgs(frame)
local lat1, lat2, lon1, lon2 = 400, -400, 400, -400
local dimx = tonumber(t[1]) or 1 --larghezza
local dimy = tonumber(t[2]) or 1 --altezza
local vlr
for x in string.gmatch(t[3],'([^,]+)') do
vlr = tonumber(x)
if (lon1 > vlr) then lon1 = vlr end
if (lon2 < vlr) then lon2 = vlr end
end
for x in string.gmatch(t[4],'([^,]+)') do
vlr = tonumber(x)
if (lat1 > vlr) then lat1 = vlr end
if (lat2 < vlr) then lat2 = vlr end
end
-- problemi con latitudine oltre 85°
if ((lat2>85) or (lat1<-85)) then return 0 end
-- calcola posizione rispetto a Web Mercator per griglia di lato 1
-- con fattore 1.1 per evitare punti troppo vicini al margine
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)
-- calcolo scale per coordinate
local scalax, scalay
if (dx == 0) then scalax = 18 else scalax = math.floor(-math.log(dx)/math.log(2)) end
if (dy == 0) then scalay = 18 else scalay = math.floor(-math.log(dy)/math.log(2)) end
local scala
if ((dx == 0) and (dy == 0)) then
scala = 10 --valore default per singolo punto
else
scala = math.max(0,math.min(18,scalax, scalay)) --calcolo scala minima compresa tra 0 e 18
end
return scala
end
-- Calcola gradi decimali
-- esempio chiamata di funzione {{#invoke:Mappa OSM|gradi|numero gradi|numero primi|numero secondi|punto cardinale}}
function p.gradi(frame)
local t = getArgs(frame)
local t1 = tonumber(t[1]) or 0
local t2 = tonumber(t[2]) or 0
local t3 = tonumber(t[3]) or 0
local s = 1;
if ((t[4] == 'S') or (t[4] == 'W')) then s = -1 end
return (s*(t1+t2/60+t3/3600))
end
return p