Modulo:Sandbox/M.casanova/DatiMappa

Da Wikipedia, l'enciclopedia libera.
Vai alla navigazione Vai alla ricerca
require('strict')
local getArgs = require('Module:Arguments').getArgs

local p = {}
local pp = {}
local ss = {}

local function agg(t)
	table.insert(ss,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(ss))
	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