Module:Carte
Révision datée du 9 mars 2015 à 17:01 par Zolo (discussion) (bon ça n'a pas l'air très convaincant, ajoute une catégorie de maintenance pour surveiller (pour être amélioré lorsque l'arbitrary access de Wikidata sera activé)
La documentation pour ce module peut être créée à Module:Carte/doc
local p = {} local pointmod = require('Module:Carte/Points') local linguistic = require('Module:Linguistique') local maintenance = '' local coord = require('Module:Coordinates') local function loaddata(name) return require('Module:Carte/données/' .. mw.ustring.lower(name)) end local divstyle = { ['clear'] = 'right', ['width'] ='25em', ['text-align'] = 'center', ['font-size'] = '0.9em', ['line-height'] = '1.4em', ['margin'] = '0 0 0.5em 1em', ['max-width'] = '325px', ['word-wrap'] = 'break-word', ['max-width'] = '99%', ['height'] = 'auto', ['justify-content'] = 'space-around', ['align-items'] = 'center', } local function addmaintenancecat(cat, sortkey) -- ajoute du texte à la string maintenance en cas de problème if mw.title.getCurrentTitle().namespace ~= 0 then return end maintenance = maintenance .. '[[Category:' .. cat .. ']]' end -- 'Projection conique avec DL' local function dllat(latitude, longitude, mapdata) -- conique avec DL local val = (mapdata.y0 + ( mapdata.iheight/2 - mapdata.y0 ) * (1 - mapdata.t * (latitude - mapdata.centrallat) * (0.01745329252 + 0.00000177219231 * (latitude - mapdata.centrallat) ^2) )* ( 1- 0.00015230871 * (longitude-mapdata.centrallong) ^2 * mapdata.s^2) ) / mapdata.iheight return val end local function dllong(latitude, longitude, mapdata) local val = ( (mapdata.x0 or (mapdata.iwidth/2)) + ( mapdata.iheight/2 - mapdata.y0 ) * ( 1 -mapdata.t * (latitude-mapdata.centrallat) * ( 0.01745329252 + 0.00000177219231 * (latitude-mapdata.centrallat) * (latitude-mapdata.centrallat) ) ) * (longitude-mapdata.centrallong) * mapdata.s * (0.01745329252 - 0.000000886096156 * (longitude-(mapdata.centrallong)) * (longitude-(mapdata.centrallong)) * mapdata.s^2 ) ) / mapdata.iwidth return val end --longitude équirectangulaire local function equirecLong(longitude, mapdata) local left, right = mapdata.left, mapdata.right if right < left then -- si la carte passe le méridien 180 right = 360 + right if longitude < 0 then longitude = (360 + longitude) end end return (longitude - left) / (right - left) end local function equirecLat(latitude, mapdata) return (latitude - mapdata.top) / (mapdata.bottom - mapdata.top) end ---------------------------------- local function pointposition(latitude, longitude, mapdata) local latitude = tonumber(latitude) or tonumber(coord.dms2dec({args={latitude}})) local longitude = tonumber(longitude) or tonumber(coord.dms2dec({args={longitude}})) local ypos, xpos if mapdata.x and mapdata.y then -- pour les cartes complexes : calcul de la position à partir de formules en Wikicode dans les clés "x" et "y" xpos = mapdata.x(latitude, longitude) / 100 ypos = mapdata.y(latitude, longitude) / 100 elseif mapdata.projection == 'Projection équirectangulaire' then ypos = equirecLat(latitude, mapdata) xpos = equirecLong(longitude, mapdata) elseif mapdata.projection == 'Projection conique avec DL' then ypos = dllat(latitude, longitude, mapdata) xpos = dllong(latitude, longitude, mapdata) end return ypos, xpos end local function placepoint(mapdata, point) -- fonction d'aige pour buildmap point est une table contenant latitude, longitude, type de point... local ypos, xpos = pointposition(point.latitude, point.longitude, mapdata) if (not xpos) or (not ypos) then return "données de géolocalisation invalides" end if (ypos > 1.1) or (xpos) > 1.1 or (ypos < -0.1) or (xpos < -0.1) then return '[[Category:Article avec une géolocalisation hors-carte]]' .. 'les coordonnées indiquées sont hors de la carte de géolocalisation demandée' end local pointsize = tostring(point.pointsize or '8') local pointtext = point.text or '' local pointtype = point.pointtype or 'default' local pointimage = pointmod[pointtype] if not pointimage then pointimage = pointmod[pointtype] addmaintenancecat('Page avec un modèle de point de carte non supporté') end local htmlheight = tostring(ypos * 100) .. '%' local htmlwidth = tostring(xpos * 100) .. '%' local pointdiv = mw.html.create('div') :css{position = 'absolute', border = 'none', top = htmlheight, left = htmlwidth} :tag('div') :css{position = 'absolute', top = '-4px', left = '-4px', ['line-height'] = '0', width = '8px'} :wikitext('[[Image:' .. pointimage .. '|' .. pointsize .. 'px]]') :tag('span') :css{position = 'absolute', ['text-align'] = 'left', width = '150px'} :wikitext(pointtext) :done() :allDone() return pointdiv end local function buildmap(map, maptype, width, pointtable, caption) -- fonction d'aige pour multimap if map == '-' then return end local success, mapdata = pcall(loaddata, map) if not success or not mapdata.images then addmaintenancecat('Page avec des données de géolocalisation non supportées') end local name = mapdata.name or '?' -- analyse linguistique pour le texte de la carte local datagender = mapdata.genre or '' local gender = string.sub(datagender, 1, 1) -- ms = masculin-singulier, fp = féminin pluriel etc. local number = string.sub(datagender, 2, 2) local determiner = mapdata.determiner local ofstring = linguistic.of(name, gender, number, determiner) -- restitue "de France" ou "du Japon" local mapname = mapdata.name local file = mapdata.images[maptype] or mapdata.images['default'] or mapdata.images[1] if not file then file = mapdata.images['default'] end local alt = 'voir sur la carte ' .. ofstring local map = mw.html.create('div') :css(divstyle) :addClass("geobox") :wikitext(caption or ('Localisation sur la carte ' .. ofstring)) :tag('table') :addClass('DebutCarte') :attr({border="0", cellspacing="0", cellpadding="0"}) :css({margin = '0', border = 'none', padding = '0'}) :tag('tr') :tag('td') :tag('div') :css({position= 'relative', margin = "auto", width = '100%', ['text-align'] = 'right' }) :wikitext('[[File:' .. file .. '|frameless|' .. width .. 'px' .. '|' .. alt .. ']]' ) for i, j in pairs(pointtable) do -- pour chque point à placer, do map:node(placepoint(mapdata,j)) end return map:done():done():done():done() end local function guessmaps(params) local data = require('Module:Carte/données') local validmaps = {} local lat = tonumber(params.latitude) or tonumber(coord.dms2dec({args={params.latitude}})) local long = tonumber(params.longitude) or tonumber(coord.dms2dec({args={params.longitude}})) if not lat or not long then return nil end for i, map in pairs(data) do if lat < map.top and lat > map.bottom then if map.left > map.right then -- correction pour les cartes passant le méridien 180 map.right = 360 + map.right if long < 0 then long = 360 + long end end if (long > map.left and long < map.right) then table.insert(validmaps, map) end end end if #validmaps == 0 then return nil end local function area(map) -- fonction simple juste pour pouvoir classer apprximativement les cartes pas superficie return (math.abs(map.top - map.bottom)) * (math.abs(map.left- map.right)) end table.sort(validmaps, function(a, b) return area(a) < area(b) end) local chosenmaps = {} -- on ne les gardes pas toutes, ça serait souvent trop local havezone = {} -- paramètre "zone" des carte déjà obtenu, pour ne pas avoir le même deux fois: { zone = {nom de la carte, position de la carte} } local forbiddenzones = { -- zone peu utiles, à ne pas utiliser par défaut ['future région française'] = true } local function addmap(map, pos) -- ajoute la carte à la liste et enregistre qu'elle a une carte avec ce paramètre "zone" if pos then chosenmaps[pos] = map.name havezone[map.zone] = {map, pos} else table.insert(chosenmaps, map.name) if map.zone then havezone[map.zone] = {map, #chosenmaps} end end end local function centrality(map) -- retourne un indice ah hoc de centralité, plus faible si le point est près d'un bord local function compute(point, end1, end2) local pct = (point - end1) / (end2- end1) return 0.5 - math.abs(0.5 - pct) end local latcentrality = compute(lat, map.top, map.bottom) local longcentrality = compute(long, map.left, map.right) return math.min(latcentrality, longcentrality) end for i, map in pairs(validmaps) do if not(havezone[map.zone]) and (not forbiddenzones[map.zone]) and #chosenmaps < 3 then addmap(map) end if map.zone and havezone[map.zone] and (centrality(map) > centrality(havezone[map.zone][1] )) then -- si deux cartes ont le même paramètre "zone", on prend la mieux centrée addmap(map, havezone[map.zone][2]) end end addmaintenancecat('Carte de localisation ajoutée par Module:Carte') return chosenmaps end function p.multimap(params) local maplist = params.maplist if not maplist then maplist = guessmaps(params) end if type(maplist) == 'string' then if maplist == 'non' or maplist == 'pas pertinent' or maplist == 'non' then return end maplist = mw.text.split(maplist, '/', true) end if not maplist then return nil end local maptype = params.maptype -- à retravailler pour quand on veut la même région, mais avec plusieurs types de carte local width = params.width local pointtable = params.pointtable local caption = params.caption if not pointtable then -- pointtable est la liste des points à placer, mais lorsqu'il n'y a qu'un seul point, on peut avoir des paramètres distinctions : pointtable = {{latitude = params.latitude, longitude = params.longitude, pointtype = params.pointtype}} end -- traitement de la largeur if width and tonumber(width) then width = tonumber(width) else width = 280 end-- si pas un nombre, erreur ? local div = mw.html.create('div'):addClass('img_toogle') -- met la carte à afficher par défaut à la fin, pour qu'elle soit affichée en premier table.insert(maplist, maplist[1]) table.remove(maplist, 1) --transition: appel aux [[Modèle:Géolocalisation/]] n en l'absence de données dans le module for i, j in pairs(maplist) do if j == '' then break end local success, data = pcall(loaddata, j) if not success then local mapliststring = '' for i, j in pairs(maplist) do mapliststring = j .. '/' .. mapliststring end return mw.getCurrentFrame():expandTemplate{ title = 'Infobox/Géolocalisation multiple/transition', args = {['géolocalisation'] = mapliststring, type = maptype, latitude = params.latitude, longitude = params.longitude }} .. '[[Catégorie:Page avec des données de géolocalisation non supportées]]' end end for i, j in pairs(maplist) do if j == '' then break end local newmap = buildmap( j, maptype, width, pointtable, caption) div:node(newmap) end return div end function p.map(frame) local args = frame.args -- utilisation du franaçs args.maplist = mw.text.split( args.carte, '/', true) return p.multimap(args) end return p