La documentation pour ce module peut être créée à Module:Coordinates/doc
local math_mod = require( "Module:Math" ) local p = {} --Chargement de la liste En/Au/Aux/A local gdata local success, resultat = pcall (mw.loadData, "Module:Drapeau/Data" ) if success then gdata = resultat else -- Banque de données à minima en cas de bogue dans le Module:Langue/Data gdata={} gdata.data={}; gdata.data[142]={qid="Q142", label="France", genre="fs"} end local i18n = { N = ' N', Nlong = ' Nord', W = ' O', Wlong = ' Ouest', E = ' E', Elong = ' Est', S = ' S', Slong = ' Sud', degrees = '° ', minutes = '\′ ', seconds = '″ ', geohackurl = 'http://tools.wmflabs.org/geohack/geohack.php?language=fr', tooltip = 'Cartes, vues aériennes, etc.', errorcat = 'Page avec des balises de coordonnées mal formées', sameaswikidata = 'Page avec coordonnées similaires sur Wikidata', notaswikidata = 'Page avec coordonnées différentes sur Wikidata', nowikidata = 'Page sans coordonnées Wikidata', throughwikidata = 'Page géolocalisée par Wikidata' } --Aide:Fonction_genre local genre = { ms = {le="le ", du="du ", de="du ", au="au ", en="au "}, msa = {le="l'", du="de l'", de="d'", au="à l'", en="en "}, msi = {le="", du="de ", de="de ", au="à ", en="à "}, msia = {le="", du="d'", de="d'", au="à ", en="à "}, msiae = {le="", du="d'", de="d'", au="à ", en="en "}, fs = {le="la ", du="de la ", de="de ", au="à la ",en="en "}, fsa = {le="l'", du="de l'", de="d'", au="à l'", en="en "}, fsi = {le="", du="de ", de="de ", au="à ", en="à "}, fsia = {le="", du="d'", de="d'", au="à ", en="à "}, mp = {le="les ", du="des ", de="des ", au="aux ", en="aux "}, fp = {le="les ", du="des ", de="des ", au="aux ", en="aux "} } local globedata = { --[[ notes: radius in kilometers (especially imprecise for non spheric bodies) defaultdisplay is currently disabled, activate it ? ]]-- ariel = {radius = 580, defaultdisplay = 'dec east', trackingcat = 'Article géolocalisé extraterrestre'}, callisto = {radius = 2410, defaultdisplay = 'dec east', trackingcat = 'Article géolocalisé extraterrestre'}, ceres = {radius = 470, defaultdisplay = 'dec east', trackingcat = 'Article géolocalisé extraterrestre'}, deimos = {radius = 7, defaultdisplay = 'dec east', trackingcat = 'Article géolocalisé extraterrestre'}, dione = {radius = 560, defaultdisplay = 'dec east', trackingcat = 'Article géolocalisé extraterrestre'}, enceladus = {radius = 255, defaultdisplay = 'dec east', trackingcat = 'Article géolocalisé extraterrestre'}, ganymede = {radius = 1631, defaultdisplay = 'dec east', trackingcat = 'Article géolocalisé extraterrestre'}, earth = {radius = 6371, defaultdisplay = 'dms', trackingcat = 'Article géolocalisé sur Terre'}, europa = {radius = 1561, defaultdisplay = 'dec east', trackingcat = 'Article géolocalisé extraterrestre'}, hyperion = {radius = 140, defaultdisplay = 'dec east', trackingcat = 'Article géolocalisé extraterrestre'}, iapetus = {radius = 725, defaultdisplay = 'dec east', trackingcat = 'Article géolocalisé extraterrestre'}, ['io'] = {radius = 1322, defaultdisplay = 'dec east', trackingcat = 'Article géolocalisé extraterrestre'}, jupiter = {radius = 68911, defaultdisplay = 'dec east', trackingcat = 'Article géolocalisé extraterrestre'}, mars = {radius = 3389.5, defaultdisplay = 'dec east', trackingcat = 'Article géolocalisé sur Mars' }, mercury = {radius = 2439.7, defaultdisplay = 'dec east', trackingcat = 'Article géolocalisé extraterrestre'}, mimas = {radius = 197, defaultdisplay = 'dec east', trackingcat = 'Article géolocalisé extraterrestre'}, miranda = {radius = 335, defaultdisplay = 'dec east', trackingcat = 'Article géolocalisé extraterrestre'}, moon = {radius = 1736, defaultdisplay = 'dec east', trackingcat = 'Article géolocalisé sur la Lune'}, neptune = {radius = 24553, defaultdisplay = 'dec east', trackingcat = 'Article géolocalisé extraterrestre'}, oberon = {radius = 761, defaultdisplay = 'dec east', trackingcat = 'Article géolocalisé extraterrestre'}, phoebe = {radius = 110, defaultdisplay = 'dec east', trackingcat = 'Article géolocalisé extraterrestre'}, phobos = {radius = 11, defaultdisplay = 'dec east', trackingcat = 'Article géolocalisé extraterrestre'}, rhea = {radius = 765, defaultdisplay = 'dec east', trackingcat = 'Article géolocalisé extraterrestre'}, saturn = {radius = 58232, defaultdisplay = 'dec east', trackingcat = 'Article géolocalisé extraterrestre'}, titan = {radius = 2575.5, defaultdisplay = 'dec west', trackingcat = 'Article géolocalisé extraterrestre'}, tethys = {radius = 530, defaultdisplay = 'dec east', trackingcat = 'Article géolocalisé extraterrestre'}, titania = {radius = 394, defaultdisplay = 'dec east', trackingcat = 'Article géolocalisé extraterrestre'}, triton = {radius = 1353, defaultdisplay = 'dec west', trackingcat = 'Article géolocalisé extraterrestre'}, umbriel = {radius = 584, defaultdisplay = 'dec east', trackingcat = 'Article géolocalisé extraterrestre'}, uranus = {radius = 25266, defaultdisplay = 'dec east', trackingcat = 'Article géolocalisé extraterrestre'}, venus = {radius = 6051.8, defaultdisplay = 'dec east', trackingcat = 'Article géolocalisé extraterrestre'}, vesta = {radius = 260, defaultdisplay = 'dec east', trackingcat = 'Article géolocalisé extraterrestre'} } local wikidatathreshold = 10 -- si la distance entre coordonnées Wikipédia et Wikidata dépasse se seuil (en kilomètes), une catégorie de maintenance est ajoutée local function makecat(cat, sortkey) return '[[Category:' .. cat .. '|' .. (sortkey or '*') .. ']]' end ---------------------------------------- --Error handling --[[ Notes: when errors occure a new error message is concatenated to errorstring an error message contains an error category with a sortkey For major errors, it can also display an error message (the error message will the usually be returned and the function terminated) More minor errors do only add a category, so that readers are not bothered with error texts sortkeys: * A: invalid latitude, longitude or direction * B: invalid globe * C: something wrong with other parameters * D: more than one primary coord ]]-- local errorstring = '' local function makeerror(args) local errormessage = '' if args.message then errormessage = '<strong class="error">Coordonnées: ' .. args.message .. '</strong>' end local errorcat = '' if mw.title.getCurrentTitle().namespace == 0 then errorcat = makecat(i18n.errorcat, args.sortkey) end errorstring = errormessage .. errorcat -- reinitializes the string to avoid absurdly long messages return nil end local function showerrors() return errorstring end -- Distance computation function p._distance(a, b, globe) -- calcule la [[distance orthodromique]] en kilomètres entre deux points du globe globe = string.lower(globe or 'earth') -- check arguments and converts degreees to radians local latA, latB, longA, longB = a.latitude, b.latitude, a.longitude, b.longitude if (not latA) or (not latB) or (not longA) or (not longB) then return error('coordinates missing, can\'t compute distance') end if type(latA) ~= 'number' or type(latB) ~= 'number' or type(longA) ~= 'number' or type(longB) ~= 'number' then error('coordinates are not numeric, can\'t compute distance') end if not globe or not globedata[globe] then return error('globe: ' .. globe .. 'is not supported') end -- calcul de la distance angulaire en radians local convratio = math.pi / 180 -- convertit en radians latA, latB, longA, longB = convratio * latA, convratio * latB, convratio * longA, convratio * longB local cosangle = math.sin(latA) * math.sin(latB) + math.cos(latA) * math.cos(latB) * math.cos(longB - longA) if cosangle >= 1 then -- may be above one because of rounding errors return 0 end local angle = math.acos(cosangle) -- calcul de la distance en km local radius = globedata[globe].radius return radius * angle end function p.distance(frame) local args = frame.args return p._distance( {latitude = tonumber(args.latitude1), longitude = tonumber(args.longitude1)}, {latitude = tonumber(args.latitude2), longitude = tonumber(args.longitude2)}, args.globe) end --HTML builder for a geohack link local function buildHTML(decLat, decLong, dmsLat, dmsLong, globe, displayformat, displayinline, displaytitle, objectname, extraparams) local root, text, url, noprint extraparams = extraparams or '' -- geohack url and parameters local decimalcoords = p.displaydec(decLat, decLong, displayformat) local geohacklatitude, geohacklongitude -- format latitude and longitude for the URL if tonumber(decLat) < 0 then geohacklatitude = tostring(-tonumber(decLat)) .. '_S' else geohacklatitude = decLat .. '_N' end if tonumber(decLong) < 0 then geohacklongitude = tostring(-tonumber(decLong)) .. '_W' else geohacklongitude = decLong .. '_E' end -- prepares the 'paramss=' parameter local geohackparams = geohacklatitude .. '_' .. geohacklongitude .. '_' ..extraparams -- concatenate parameteres for geohack local url = i18n.geohackurl .. "&pagename=" .. mw.uri.encode(mw.title.getCurrentTitle().prefixedText, "WIKI") .. "¶ms=" .. geohackparams .. (objectname and ("&title=" .. mw.uri.encode(objectname)) or "") root = mw.html.create('') root :tag("span") :addClass("plainlinks nourlexpansion") :attr('title', i18n.tooltip) :wikitext("[" .. url) :tag("span") :addClass(string.sub(displayformat,1,3) == "dec" and "geo-nondefault" or "geo-default") :tag("span") :addClass("geo-dms") :tag("span") :addClass("latitude") :wikitext(p.displaydmsdimension(dmsLat, displayformat)) :done() :wikitext(" ") :tag("span") :addClass("longitude") :wikitext(p.displaydmsdimension(dmsLong, displayformat)) :done() :done() :done() :tag("span") :addClass("geo-multi-punct") :wikitext(" / ") :done() :tag("span") :addClass(string.sub(displayformat,1,3) == 'dec' and "geo-default" or "geo-nondefault") :wikitext(objectname and "<span class=\"vcard\">" or "") :tag("span") :addClass("geo-dec") :wikitext(decimalcoords) :done() :wikitext(objectname and ("<span style=\"display:none\"> (<span class=\"fn org\">" .. objectname .. "</span>)</span></span>") or "") :done() :wikitext("]") :done() -- formatta il risultato a seconda di args["display"] (nil, "inline", "title", "inline,title") text = tostring(root) noprint = displayinline and "class=\"noprint\" " or "" htmlTitle = "<span style=\"font-size: small;\"><span " .. noprint .. "id=\"coordinates\">" return (displayinline and text or "") .. (displaytitle and (htmlTitle .. text .. "</span></span>") or "") end -- dms specific funcions function p.displaydmsdimension(valuetable, format) -- formate en latitude ou une longitude dms local str = '' local direction = valuetable.direction local degrees, minutes, seconds = '', '', '' local dimension if format == 'dms long' then direction = i18n[direction .. 'long'] else direction = i18n[direction] end degrees = valuetable.degrees .. i18n.degrees if valuetable.minutes then minutes = valuetable.minutes .. i18n.minutes if (valuetable.minutes < 10) then minutes = '0' .. minutes end end if valuetable.seconds then seconds = valuetable.seconds .. i18n.seconds if (valuetable.seconds < 10) then seconds = '0' .. seconds end end return degrees .. minutes .. seconds .. direction end local function validdms(coordtable) local direction = coordtable.direction local degrees = coordtable.degrees or 0 local minutes = coordtable.minutes or 0 local seconds = coordtable.seconds or 0 local dimension = coordtable.dimension if not dimension then if direction == 'N' or direction == 'S' then dimension = 'latitude' elseif direction == 'E' or direction == 'W' then dimension = 'longitude' else makeerror({message = 'invalid direction should be "N", "S", "E" or "W"', sortkey = 'A'}) return false end end if type(degrees) ~= 'number' or type(minutes) ~= 'number' or type(seconds) ~= 'number' then makeerror({message = 'invalid format', sortkey = 'A'}) return false end if dimension == 'latitude' and direction ~= 'N' and direction ~= 'S' then makeerror({message = 'could not find latitude direction (should be N or S)', sortkey = 'A'}) return false end if dimension == 'longitude' and direction ~= 'W' and direction ~= 'E' then makeerror({message = 'could not find longitude direction (should be W or E) ', sortkey = 'A'}) return false end if dimension == 'latitude' and degrees > 90 then makeerror({message = 'latitude > 90', sortkey = 'A'}) return false end if dimension == 'longitude' and degrees > 360 then makeerror({message = 'longitude > 360', sortkey = 'A'}) return false end if degrees < 0 or minutes < 0 or seconds < 0 then makeerror({message = 'dms coordinates should be positive', sortkey = 'A'}) return false end if minutes > 60 or seconds > 60 then makeerror({message = 'minutes or seconds > 60', sortkey = 'A'}) return false end if (math.floor(degrees) ~= degrees and minutes ~= 0) or (math.floor(minutes) ~= minutes and seconds ~= 0) then makeerror({message = 'degrees and minutes should be integers', sortkey = 'A'}) return false end return true end local function builddmsdimension(degrees, minutes, seconds, direction) -- no error checking, done in function validdms local dimensionobject = {} -- direction and dimension (= latitude or longitude) dimensionobject.direction = direction if direction == 'N' or direction == 'S' then dimensionobject.dimension = 'latitude' else dimensionobject.dimension = 'longitude' end -- degrees, minutes, seconds dimensionobject.degrees = tonumber(degrees) dimensionobject.minutes = tonumber(minutes) dimensionobject.seconds = tonumber(seconds) if degrees and not dimensionobject.degrees then dimensionobject.degrees = 'error' end if minutes and not dimensionobject.minutes then dimensionobject.minutes = 'error' end if seconds and not dimensionobject.seconds then dimensionobject.seconds = 'error' end return dimensionobject end local function parsedmsstring(str) -- prend une séquence et donne des noms aux paramètres -- output table: {latitude=, longitude = , direction = } if not str then return nil end if not tonumber(str) and not string.find(str, '/') then makeerror({message ='invalid coordinate format', sortkey= 'A'}) return nil end args = mw.text.split(str, '/', true) if #args > 4 then makeerror({message = "too many parameters for coordinates", sortkey= 'A' }) end local direction = mw.text.trim(args[#args]) table.remove(args) local degrees, minutes, seconds = args[1], args[2], args[3] local dimensionobject = builddmsdimension(degrees, minutes, seconds, direction) if validdms(dimensionobject) then return dimensionobject else return nil end end --- decimal specific functions function p.displaydec(latitude, longitude, format) if format == 'dec west' then local latsymbol = i18n.N longitude = - longitude if latitude < 0 then latsymbol = i18n.S end if longitude < 0 then longitude = 360 + longitude end return latitude .. i18n.degrees .. latsymbol .. ', ' .. longitude .. i18n.degrees .. i18n.W elseif format == 'dec east' then local latsymbol = i18n.N if latitude < 0 then latsymbol = i18n.S end if longitude < 0 then longitude = 360 + longitude end return latitude .. i18n.degrees .. latsymbol .. ', ' .. longitude .. i18n.degrees .. i18n.E else return latitude .. ', ' .. longitude end end local function parsedec(dec, coordtype) -- coordtype = latitude or longitude dec = mw.text.trim(dec) if coordtype ~= 'latitude' and coordtype ~= 'longitude' then makeerror({'invalid coord type', sortkey = "A"}) return nil end if not dec then return nil end local numdec = tonumber(dec) -- numeric value, kept separated as it looses significant zeros if not numdec then -- tries the decimal + direction format direction = mw.ustring.sub(dec, mw.ustring.len(dec), mw.ustring.len(dec)) dec = mw.ustring.sub(dec, 1, mw.ustring.len(dec)-2) -- removes the /N at the end if not dec or not tonumber(dec) then return nil end if direction == 'N' or direction == 'E' then return dec elseif direction == 'W' or direction == 'S' then return '-' .. dec else makeerror({message = 'could not find longitude direction (should be W or E) ', sortkey = 'A'}) return nil end end if coordtype == 'latitude' and math.abs(numdec) > 90 then makeerror({message = 'latitude > 90' , sortkey = 'A'}) return nil end if coordtype == 'longitude' and math.abs(numdec) > 360 then makeerror({message = 'longitude > 360' , sortkey = 'A'}) return nil end return dec end -- dms/dec conversion functions local function convertprecision(precision) -- converts a decimal precision like "2" into "dm" if precision >= 3 then return 'dms' elseif precision >=1 then return 'dm' else return 'd' end end local function determinedmsprec(decs) -- returns the most precision for a dec2dms conversion, depending on the most precise value in the decs table local precision = 0 for d, val in ipairs(decs) do precision = math.max(precision, math_mod._precision(val)) end return convertprecision(precision) end local function dec2dms_d(dec) local degrees = math_mod._round( dec, 0 ) return degrees end local function dec2dms_dm(dec) dec = math_mod._round( dec * 60, 0 ) local minutes = dec % 60 dec = math.floor( (dec - minutes) / 60 ) local degrees = dec % 360 return degrees, minutes end local function dec2dms_dms(dec) dec = math_mod._round( dec * 60 * 60, 0 ) local seconds = dec % 60 dec = math.floor( (dec - seconds) / 60 ) local minutes = dec % 60 dec = math.floor( (dec - minutes) / 60 ) local degrees = dec % 360 return degrees, minutes, seconds end function p._dec2dms(dec, coordtype, precision) -- type: latitude or longitude local degrees, minutes, seconds -- precision if not precision or precision == '' then precision = determinedmsprec({dec}) end if precision ~= 'd' and precision ~= 'dm' and precision ~= 'dms' then return makeerror({sortkey = 'C'}) end local dec = tonumber(dec) -- direction if coordtype == 'latitude' then if dec < 0 then direction = 'S' else direction = 'N' end elseif coordtype == 'longitude' then if dec < 0 then direction = 'W' else direction = 'E' end end -- conversion dec = math.abs(dec) -- les coordonnées en dms sont toujours positives if precision == 'dms' then degrees, minutes, seconds = dec2dms_dms(dec) elseif precision == 'dm' then degrees, minutes = dec2dms_dm(dec) else degrees = dec2dms_d(dec) end return builddmsdimension(degrees, minutes, seconds, direction) end function p.dec2dms(frame) -- legacy function somewhat cumbersome syntax args = frame.args local dec = args[1] if not tonumber(dec) then makeerror({message='invalid coordinate format', sortkey = 'A'}) return showerrors() end local precision = string.lower(args[4] or '') local displayformat, coordtype if args[2] == 'N' or args[2] == 'Nord' then coordtype = 'latitude' else coordtype = 'longitude' end if args[2] == 'Nord' or args[2] == 'Est' or args[3] == 'Ouest' or args[3] == 'Sud' then displayformat = 'dms long' end local coordobject = p._dec2dms(dec, coordtype, precision) if coordobject then return p.displaydmsdimension(coordobject, displayformat) .. showerrors() else return showerrors() end end function p._dms2dec(dmsobject) -- transforme une table degré minute secondes en nombre décimal local direction, degrees, minutes, seconds = dmsobject.direction, dmsobject.degrees, dmsobject.minutes, dmsobject.seconds local factor = 0 local precision = 0 if not minutes then minutes = 0 end if not seconds then seconds = 0 end if direction == "N" or direction == "E" then factor = 1 elseif direction == "W" or direction == "S" then factor = -1 elseif not direction then makeerror({message = 'no cardinal direction found in coordinates', sortkey = 'A'}) return nil else makeerror({message = 'invalid direction', sortkey = 'A'}) return nil end if dmsobject.seconds then -- vérifie la précision des données initiales precision = 5 + math.max( math_mod._precision(tostring(seconds), 0 ) ) -- passage par des strings assez tarabiscoté ? elseif dmsobject.minutes then precision = 3 + math.max( math_mod._precision(tostring(minutes), 0 ) ) else precision = math.max( math_mod._precision(tostring(degrees), 0 ) ) end local decimal = factor * (degrees+(minutes+seconds/60)/60) return math_mod._round(decimal, precision) end function p.dms2dec(frame) -- legacy function, somewhat bizarre syntax local args = frame.args if tonumber(args[1]) then return args[1] -- coordonnées déjà en décimal elseif not args[2] then local dmsobject = parsedmsstring(args[1]) if dmsobject then return p._dms2dec(dmsobject) -- coordonnées sous la fore 23/22/N else return showerrors() end else return p._dms2dec({direction = args[1], degrees = args[2], minutes = args[3], seconds = args[4]}) end end -- Wikidata local function convertwikidataprecision(precision) -- converts a decima like "0.1" into "dm" if precision < 0.016 then return 'dms' elseif precision < 1 then return 'dm' else return 'd' end end local function wikidatacoords(query) query = query or {property = 'p625'} query.formatting = 'raw' local wd = require('Module:Wikidata') local claim = wd.getClaims(query) if claim and claim[1] then -- redundant but more robust in case of a change in the code of Module:Wikidata local coords = wd.formatSnak(claim[1].mainsnak) -- todo: check for special values return coords.latitude, coords.longitude, coords.globe or 'earth', convertwikidataprecision(coords.precision or .001) end return nil end local function wikidatacat(globe) --catbase= Article géolocalisé sur Terre local entitycat = mw.wikibase.getEntityObject() local basecat = 'Article géolocalisé' local finalcat = {} --BADGES if entitycat then --BADGES for i, badgeId in ipairs( entitycat.sitelinks['frwiki'].badges ) do if badgeId == 'Q17437796' then basecat=string.gsub(basecat, "Article géolocalisé", "Article de qualité géolocalisé") end if badgeId == 'Q17437798' then basecat=string.gsub(basecat, "Article géolocalisé", "Bon article géolocalisé") end end end if globe == 'earth' then if entitycat and entitycat.claims then local country=entitycat.claims['P17'] if not country then --pas pays à récupérer basecat=basecat .. ' sur Terre' table.insert(finalcat,basecat) else --parfois plusieurs pays for i, paysId in ipairs( country ) do --on fait confiance au label wikidata local gdataone,qid if paysId.mainsnak.snaktype == 'value' then qid=paysId.mainsnak.datavalue.value['numeric-id'] gdataone=gdata.data[qid] else --Bir Tawil n'a pas de pays connu qid='?' end if gdataone ~= nil then local prep=genre[gdataone['genre']]['en'] or 'en ' local thecat=basecat .. ' '..prep ..mw.wikibase.label( 'Q'.. qid) if mw.title.new('category:'..thecat).exists then table.insert(finalcat,thecat) else --Dommage! mw.log(thecat .. ' à créer') end else --pas d'id? mw.log(qid .. ' à paramétrer') end end if #finalcat == 0 then --pas pays à récupérer basecat=basecat .. ' sur Terre' table.insert(finalcat,basecat) end end else --pas wikidata basecat=basecat .. ' sur Terre' table.insert(finalcat,basecat) end elseif globe == 'moon' then basecat=basecat .. ' sur la Lune' table.insert(finalcat,basecat) elseif globe == 'mars' then basecat=basecat .. ' sur Mars' table.insert(finalcat,basecat) else basecat=basecat .. ' extraterrestre' table.insert(finalcat,basecat) end return finalcat end -- main function for displaying coordinates function p._coord(args) -- I declare variable local displayformat = args.format -- string: one of: 'dms', 'dms long', 'dec', 'dec east' and 'dec west' local displayplace = string.lower(args.display or 'inline') --string: one of 'inline', 'title' or 'inline,title' local objectname = (args.name ~= '') and args.name -- string: name of the title displayed in geohack local notes = (' ' and args.notes) or '' -- string: notes to de displayed after coordinates local wikidata = args.wikidata -- string: set to "true" if needed local wikidataquery = args.wikidataquery -- table: see [[Module:Wikidata]] see function wikidatacoords local dmslatitude, dmslongitude -- table (when created) local extraparams = string.lower(args.extraparams or '') -- string (legacy, corresponds to geohackparams) local trackingstring = '' -- tracking cats except error cats (already in errorstring) local rawlat, rawlong = args.latitude, args.longitude if ralwat == '' then rawlat = nil end if rawlong == '' then rawlong = nil end local globe = string.lower(args.globe or '') -- string: see the globedata table for accepted values local latitude, longitude, precision, dmslatitude, dmslongitude -- latitude and longitude in decimal / dmslatitude and dmslongitude: tables withdms coords -- II extract coordinates from Wikitext if (rawlat or rawlong) then if (not rawlat) or (not rawlong) then -- if latitude is provided so should be longitude makeerror({message = 'latitude or longitude missing', sortkey = 'A'}) return showerrors() end latitude = parsedec(rawlat, 'latitude') if latitude then -- if latitude is decimal longitude = parsedec(rawlong, 'longitude') -- so should be longitude precision = determinedmsprec({latitude, longitude}) -- before conversion from string to number for trailing zeros if not latitude or not longitude then if errorstring == '' then makeerror({message = 'invalid format', sortkey = 'A'}) end return showerrors() end dmslatitude, dmslongitude = p._dec2dms(latitude, 'latitude', precision), p._dec2dms(longitude, 'longitude', precision) latitude, longitude = tonumber(latitude), tonumber(longitude) else -- if latitude is not decimal try to parse it as a dms string dmslatitude, dmslongitude = parsedmsstring(args.latitude), parsedmsstring(args.longitude) if not dmslatitude or not dmslongitude then return showerrors() end latitude, longitude = p._dms2dec(dmslatitude), p._dms2dec(dmslongitude) end end -- III extract coordinate data from Wikidata and compare them to local data local wikidatalatitude, wikidatalongitude, wikidataglobe if wikidata == 'true' then wikidatalatitude, wikidatalongitude, wikidataglobe, wikidataprecision = wikidatacoords(wikidataquery) if wikidatalatitude and latitude and longitude then local maxdistance = tonumber(args.maxdistance) or wikidatathreshold if p._distance({latitude = latitude, longitude= longitude}, {latitude = wikidatalatitude, longitude= wikidatalongitude}, wikidataglobe) < maxdistance then trackingstring = trackingstring .. makecat(i18n.sameaswikidata) else trackingstring = trackingstring .. makecat(i18n.notaswikidata) end end if wikidatalatitude and not latitude then latitude, longitude, globe, precision = wikidatalatitude, wikidatalongitude, wikidataglobe, wikidataprecision dmslatitude, dmslongitude = p._dec2dms(latitude, 'latitude', precision), p._dec2dms(longitude, 'longitude', precision) trackingstring = trackingstring .. makecat(i18n.throughwikidata) end if latitude and not wikidatalatitude then if mw.title.getCurrentTitle().namespace == 0 then trackingstring = trackingstring .. makecat(i18n.nowikidata) end end end -- exit if stil no latitude or no longitude if not latitude and not longitude then return nil -- ne rien ajouter ici pour que l'appel à cette fonction retourne bien nil en l'absence de données end -- IV best guesses for missing parameters --- globe if globe == '' then -- cherche le globe dans l'extraparams destinée à geohack local globe2 = string.match(extraparams, 'globe\:%a+') if globe2 then globe = string.sub(globe2, 7) end if globe == '' then globe = 'earth' end end if not globedata[globe] then makeerror({message = 'invalid globe:' .. globe}) globe = 'earth' end --- diplayformat if not displayformat or displayformat == '' then displayformat = globedata[globe].defaultdisplay end -- displayinline/displaytitle local displayinline = string.find(displayplace, 'inline') local displaytitle = string.find(displayplace, 'title') if not displayinline and not displaytitle then displayinline = true if displayplace ~= '' then makeerror({sortkey = 'C'}) --error if display not empty, but not not a major error, continue end end if displaytitle and mw.title.getCurrentTitle().namespace == 0 then --local cattoappend=globedata[globe].trackingcat --Récupération des badges local cats=wikidatacat(globe) for i, cat in ipairs( cats ) do trackingstring = trackingstring .. makecat(cat) end end -- V geodata local geodata = '' if latitude and longitude then local latstring, longstring = tostring(latitude), tostring(longitude) local primary = '' local frame = mw.getCurrentFrame() local geodataparams = {[1] = latstring, [2] = longstring, [3] = extraparams } if displaytitle then geodataparams[4] = 'primary' end if objectname then geodataparams.name = objectname end geodata = frame:callParserFunction('#coordinates', geodataparams ) if string.find(geodata, 'error') then -- the only error that has not been caught yet is primary key geodata = '' makeerror({sortkey='D'}) end end -- VI final output if globe ~= 'earth' then extraparams = extraparams .. '_globe:' .. globe -- pas de problème si le globe est en double end local mainstring = '' if args.formatitle then if displaytitle then mainstring = mainstring .. buildHTML(latitude, longitude, dmslatitude, dmslongitude, globe, args.formatitle, false, true, objectname,extraparams ) end if displayinline then mainstring = mainstring .. buildHTML(latitude, longitude, dmslatitude, dmslongitude, globe, displayformat, true, false, objectname,extraparams ) end else mainstring = buildHTML(latitude, longitude, dmslatitude, dmslongitude, globe, displayformat, displayinline, displaytitle, objectname,extraparams ) end return mainstring .. notes .. trackingstring .. geodata .. showerrors() end function p.coord(frame) -- parrses the strange parameters of Template:Coord before sending them to p.coord local args = frame.args local numericargs = {} for i, j in ipairs(args) do args[i] = mw.text.trim(j) if type(i) == 'number' and args[i] ~= '' then table.insert(numericargs, args[i]) end end if #numericargs %2 == 1 then -- if the number of args is odd, the last one provides formatting parameters args.extraparams = numericargs[#numericargs] if #numericargs == 1 and tonumber(numericargs[1]) then makeerror({message = 'latitude or longitude missing', sortkey = 'A'}) return showerrors() end table.remove(numericargs) end if #numericargs == 1 then makeerror({message = 'missing data for coords', sortkey = 'A'}) return showerrors() end for i, j in ipairs(numericargs) do if i <= (#numericargs / 2) then if not args.latitude then args.latitude = j else args.latitude = args.latitude .. '/' .. j end else if not args.longitude then args.longitude = j else args.longitude = args.longitude .. '/' .. j end end end if string.find(args.latitude or '', 'E') or string.find(args.latitude or '', 'W') then args.latitude, args.longitude = args.longitude, args.latitude end return p._coord(args) end function p.Coord(frame) return p.coord(frame) end function p.latitude(frame) -- helper function pour infobox, à déprécier local args = frame.args local latitude = frame.args[1] if latitude and mw.text.trim(latitude) ~= '' then return latitude elseif frame.args['wikidata'] == 'true' then local lat, long = wikidatacoords() return lat end end function p.longitude(frame) -- helper function pour infobox, à déprécier local args = frame.args local longitude = frame.args[1] if longitude and mw.text.trim(longitude) ~= '' then return longitude elseif frame.args['wikidata'] == 'true' then local lat, long = wikidatacoords() return long end end return p