Módulo:Coordenadas
Ir para navegação
Ir para pesquisar
40x40px | This module is subject to page protection. It is a highly visible module in use by a very large number of pages, or is substituted very frequently. Because vandalism or mistakes would affect many pages, and even trivial editing might cause substantial load on the servers, it is protected from editing. |
Descrição
Este módulo implementa a predefinição {{Coor dms}}
. Por favor consulte a predefinição para mais instruções.
Uso
Outra documentação:
local math_mod = require( "Módulo:Math" ) local p = {} local current_page = mw.title.getCurrentTitle()local page_name = mw.uri.encode( current_page.prefixedText, 'WIKI' ); local coord_link = '//tools.wmflabs.org/geohack/geohack.php?pagename=' .. page_name .. '¶ms=' --Carregando a lista em /Au/Aux/A local gdata local success, resultado = pcall (mw.loadData, "Módulo:Bandeira/Dados" ) if success then gdata = resultado else -- Banco de dados minimo em caso de bug em Módulo:Língua/Dados gdata={} gdata.data={}; gdata.data[142]={qid="Q45", label="Portugal", genre="ms"} end local i18n = { N = 'N', Nlong = 'norte', W = 'O', Wlong = 'oeste', E = 'L', Elong = 'leste', S = 'S', Slong = 'sul', degrees = '° ', minutes = '′ ', seconds = '″ ', geohackurl = 'http://tools.wmflabs.org/geohack/geohack.php?language=pt', tooltip = 'Mapas, vistas aéreas, etc.', errorcat = '!Páginas com as etiquetas de coordenadas malformadas', sameaswikidata = '!Páginas com coordenadas similares na Wikidata', notaswikidata = '!Páginas com coordenadas diferente na Wikidata', nowikidata = '!Páginas sem coordenadas Wikidata', throughwikidata = '!Artigos com coordenadas no Wikidata', invalidFormat = 'formato inválido', -- 'invalid coordinate format', invalidNSEW = 'orientação inválida, deve ser "N", "S", "E" or "W"', -- 'invalid direction should be "N", "S", "E" or "O"', invalidNS = 'orientação de latitude inválida, deve ser "N" ou "S"', -- 'could not find latitude direction (should be N or S)', invalidEW = 'orientação de longitude inválida, deve ser "E" ou "W"', -- 'could not find longitude direction (should be W or E) ', noCardinalDirection = 'orientação cardinal não informada', -- 'no cardinal direction found in coordinates', invalidDirection = 'direção inválida', -- 'invalid direction', latitude90 = 'latitude > 90', longitude360 = 'longitude > 360', minSec60 = 'minutos ou segundos > 60', negativeCoode = 'em formato dms os graus devem ser positivos', -- 'dms coordinates should be positive', dmIntergers = 'graus e minutos devem ser números inteiros', -- 'degrees and minutes should be integers', tooManyParam = 'muitos parâmetros para latitude ou longitude', -- 'too many parameters for coordinates', coordMissing = 'latitude ou longitude ausente', -- 'latitude or longitude missing', invalidGlobe = 'globo inválido : ', -- 'invalid globe:', } local coordParse = { NORTH = 'N', NORTE = 'N', EAST = 'E', LESTE = 'E', L = 'E', WEST = 'W', W = 'W', O = 'W', OESTE = 'W', SOUTH = 'S', SUL = 'S', } --Ajuda:Function_genre (gênero) local genre = { ms = {le="a ", du="do ", de="de ", ao="ao ", em="em "}, msa = {le="a ", du="da ", de="de", ao="à ", em="em "}, msi = {le="", du="do ", de="de ", ao="à ", em="à "}, msia = {le="", du="do ", de="de ", ao="à ", em="à "}, msiae = {le="", du="do ", de="de ", ao="à ", em="em "}, fs = {le="a ", du="da ", de="de ", ao="à ",em="em "}, fsa = {le="a ", du="da ", de="de ", ao="à ", em="em "}, fsi = {le="", du="de ", de="de ", ao="à ", em="à "}, fsia = {le="", du="da ", de="de ", ao="à ", em="à "}, mp = {le="os ", du="dos ", de="dos ", ao="aos ", en="em "}, fp = {le="as ", du="das ", de="das ", ao="as ", em="em "} } local globedata = { --[[ notes: radius in kilometers (especially imprecise for non spheric bodies) defaultdisplay is currently disabled, activate it ? ]]-- ariel = {radius = 580, defaultdisplay = 'dec east' }, callisto = {radius = 2410, defaultdisplay = 'dec west' }, ceres = {radius = 470, defaultdisplay = 'dec east' }, charon = {radius = 1214, defaultdisplay = 'dec east' }, deimos = {radius = 7, defaultdisplay = 'dec west' }, dione = {radius = 560, defaultdisplay = 'dec west' }, enceladus = {radius = 255, defaultdisplay = 'dec west' }, ganymede = {radius = 2634, defaultdisplay = 'dec west' }, earth = {radius = 6371, defaultdisplay = 'dms' }, europa = {radius = 1561, defaultdisplay = 'dec east' }, hyperion = {radius = 140, defaultdisplay = 'dec west' }, iapetus = {radius = 725, defaultdisplay = 'dec west' }, ['io'] = {radius = 1322, defaultdisplay = 'dec west' }, jupiter = {radius = 68911, defaultdisplay = 'dec east' }, mars = {radius = 3389.5, defaultdisplay = 'dec east' }, mercury = {radius = 2439.7, defaultdisplay = 'dec west' }, mimas = {radius = 197, defaultdisplay = 'dec west' }, miranda = {radius = 335, defaultdisplay = 'dec east' }, moon = {radius = 1736, defaultdisplay = 'dec' }, neptune = {radius = 24553, defaultdisplay = 'dec east' }, oberon = {radius = 761, defaultdisplay = 'dec east' }, phoebe = {radius = 110, defaultdisplay = 'dec west' }, phobos = {radius = 11, defaultdisplay = 'dec west' }, pluto = {radius = 1185, defaultdisplay = 'dec east' }, rhea = {radius = 765, defaultdisplay = 'dec west' }, saturn = {radius = 58232, defaultdisplay = 'dec east' }, titan = {radius = 2575.5, defaultdisplay = 'dec west' }, tethys = {radius = 530, defaultdisplay = 'dec west' }, titania = {radius = 394, defaultdisplay = 'dec east' }, triton = {radius = 1353, defaultdisplay = 'dec east' }, umbriel = {radius = 584, defaultdisplay = 'dec east' }, uranus = {radius = 25266, defaultdisplay = 'dec east' }, venus = {radius = 6051.8, defaultdisplay = 'dec east' }, vesta = {radius = 260, defaultdisplay = 'dec east' } } globedata[''] = globedata.earth local wikidatathreshold = 10 -- Se a distância entre as coordenadas Wikipedia e Wikidata exceder o limite (em quilômetros), uma categoria de manutenção será adicionada local lang = mw.language.getContentLanguage() local default_zoom = 13 local function makecat(cat, sortkey) if type( sortkey ) == 'string' then return '[[Category:' .. cat .. '|' .. sortkey .. ']]' else return '[[Category:' .. cat .. ']]' end 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"> Coordenadas : ' .. 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) -- calcula a [[distância orthodromique]] em quilóimetros entre dois pontos do globo 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('coordenadas não informadas, não consegue calcular a distância') end if type(latA) ~= 'number' or type(latB) ~= 'number' or type(longA) ~= 'number' or type(longB) ~= 'number' then error('coordenadas não são numéricas, não consegue calcular a distância') end if not globe or not globedata[globe] then return error('globe: ' .. globe .. 'não é suportado') end -- calcular a distância angular em radians local convratio = math.pi / 180 -- converter em 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) -- calcular a distância em 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 local function geoHackUrl(decLat, decLong, globe, displayformat, objectname, extraparams) extraparams = extraparams or '' 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' elseif globedata[globe].defaultdisplay == 'dec west' then geohacklongitude = decLong .. '_W' else geohacklongitude = decLong .. '_E' end -- prepares the 'paramss=' parameter local geohackparams = geohacklatitude .. '_' .. geohacklongitude .. '_' ..extraparams -- concatenate parameteres for geohack return i18n.geohackurl .. "&pagename=" .. mw.uri.encode(mw.title.getCurrentTitle().prefixedText, "WIKI") .. "¶ms=" .. geohackparams .. (objectname and ("&title=" .. mw.uri.encode(objectname)) or "") end --HTML builder for a geohack link local function buildHTML(decLat, decLong, dmsLat, dmsLong, globe, displayformat, displayinline, displaytitle, objectname, extraparams) -- geohack url local url = geoHackUrl(decLat, decLong, globe, displayformat, objectname, extraparams) -- displayed coordinates local displaycoords if string.sub(displayformat,1,3) == 'dec' then displaycoords = p.displaydec(decLat, decLong, displayformat) else displaycoords = { p.displaydmsdimension(dmsLat, displayformat), p.displaydmsdimension(dmsLong, displayformat), } end -- build coordinate in h-geo / h-card microformat local globeNode if globe and globe ~= 'earth' then globeNode = mw.html.create('data') :addClass('p-globe') :attr{ value = globe } :done() end local coordNode = mw.html.create('') if objectname then coordNode = mw.html.create('span') :addClass('h-card') :tag('data') :addClass('p-name') :attr{ value = objectname } :done() end coordNode :tag('span') :addClass('h-geo') :addClass('geo-' .. string.sub(displayformat,1,3)) :tag('data') :addClass('p-latitude') :attr{ value = decLat } :wikitext( displaycoords[1] ) :done() :wikitext(", ") :tag('data') :addClass('p-longitude') :attr{ value = decLong } :wikitext( displaycoords[2] ) :done() :node( globeNode ) :done() -- buid GeoHack link local root = mw.html.create('span') :addClass('plainlinks nourlexpansion') :attr('title', i18n.tooltip) :wikitext('[' .. url ) :node(coordNode) :wikitext("]") :done() -- format result depending on args["display"] (nil, "inline", "title", "inline,title") local inlineText = displayinline and tostring(root) or '' local titleText = '' if displaytitle then local htmlTitle = mw.html.create('span') :attr{ id = 'coordinates' } :addClass( displayinline and 'noprint' or nil ) :node( root ) local frame = mw.getCurrentFrame() titleText = frame:extensionTag( 'indicator', tostring(htmlTitle), { name = 'coordinates' } ) end return inlineText .. titleText end local function zoom( extraparams ) local zoomParam = extraparams:match( '%f[%w]zoom: ?(%d+)' ) if zoomParam then return zoomParam end local scale = extraparams:match( '%f[%w]scale: ?(%d+)' ) if scale then return math.floor(math.log10( 1 / tonumber( scale ) ) * 3 + 25) end local extraType = extraparams:match( '%f[%w]type: ?(%w+)' ) if extraType then local zoomType = { country = 5, state = 6, adm1st = 7, adm2nd = 8, city = 9, isle = 10, mountain = 10, waterbody = 10, airport = 12, landmark = 13, } return zoomType[ extraType ] end end --HTML builder for a geohack link local function buildMaplinkHTML( decLat, decLong, dmsLat, dmsLong, globe, displayformat, displayinline, displaytitle, objectname, extraparams ) -- displayed coordinates local displaycoords if string.sub(displayformat,1,3) == 'dec' then displaycoords = p.displaydec(decLat, decLong, displayformat) else displaycoords = { p.displaydmsdimension(dmsLat, displayformat), p.displaydmsdimension(dmsLong, displayformat), } end -- JSON for maplink local jsonParams = { type = 'Feature', geometry = { type ='Point', coordinates = { math_mod._round( decLong, 6 ), -- max precision in GeoJSON format math_mod._round( decLat, 6 ) } }, properties = { ['marker-color'] = "228b22", } } if objectname then jsonParams.properties.title = objectname end -- adicionar a geoshape via externaldata local geoshape = extraparams:match( '%f[%w]geoshape: ?(Q%d+)' ) if not geoshape and displaytitle and mw.wikibase.getEntity() then geoshape = mw.wikibase.getEntity().id end if geoshape then jsonParams = { jsonParams, { type = 'ExternalData', service = 'geoshape', ids = geoshape, properties = { ['fill-opacity'] = 0.2 } } } end local maplink = mw.getCurrentFrame():extensionTag{ name = 'maplink', content = mw.text.jsonEncode( jsonParams ), args = { text = displaycoords[1] .. ", " .. displaycoords[2], zoom = zoom( extraparams ) or default_zoom, latitude = decLat, longitude = decLong, } } -- format result depending on args["display"] (nil, "inline", "title", "inline,title") local inlineText = displayinline and maplink or '' local titleText = '' if displaytitle then local htmlTitle = mw.html.create('span') :attr{ id = 'coordinates' } :addClass( displayinline and 'noprint' or nil ) :wikitext( maplink ) local frame = mw.getCurrentFrame() titleText = frame:extensionTag( 'indicator', tostring(htmlTitle), { name = 'coordinates' } ) end return inlineText .. titleText end -- dms specific funcions local function twoDigit( value ) if ( value < 10 ) then value = '0' .. lang:formatNum( value ) else value = lang:formatNum( value ) end return value end function p.displaydmsdimension(valuetable, format) -- formato em latitude ou 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 = lang:formatNum( valuetable.degrees ) .. i18n.degrees if valuetable.minutes then minutes = twoDigit( valuetable.minutes ) .. i18n.minutes end if valuetable.seconds then seconds = twoDigit( valuetable.seconds ) .. i18n.seconds 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 = i18n.invalidNSEW, sortkey = 'A'}) return false end end if type(degrees) ~= 'number' or type(minutes) ~= 'number' or type(seconds) ~= 'number' then makeerror({message = i18n.invalidFormat, sortkey = 'A'}) return false end if dimension == 'latitude' and direction ~= 'N' and direction ~= 'S' then makeerror({message = i18n.invalidNS, sortkey = 'A'}) return false end if dimension == 'longitude' and direction ~= 'W' and direction ~= 'E' then makeerror({message = i18n.invalidEW, sortkey = 'A'}) return false end if dimension == 'latitude' and degrees > 90 then makeerror({message = i18n.latitude90, sortkey = 'A'}) return false end if dimension == 'longitude' and degrees > 360 then makeerror({message = i18n.longitude360, sortkey = 'A'}) return false end if degrees < 0 or minutes < 0 or seconds < 0 then makeerror({message = i18n.negativeCoode, sortkey = 'A'}) return false end if minutes > 60 or seconds > 60 then makeerror({message = i18n.minSec60, sortkey = 'A'}) return false end if (math.floor(degrees) ~= degrees and minutes ~= 0) or (math.floor(minutes) ~= minutes and seconds ~= 0) then makeerror({message = i18n.dmIntergers, sortkey = 'A'}) return false end return true end local function builddmsdimension(degrees, minutes, seconds, direction, dimension) -- no error checking, done in function validdms local dimensionobject = {} -- direction and dimension (= latitude or longitude) dimensionobject.direction = direction if dimension then dimensionobject.dimension = dimension elseif direction == 'N' or direction == 'S' then dimensionobject.dimension = 'latitude' elseif direction == 'E' or direction == 'W' then 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 function p._parsedmsstring( str, dimension ) -- pega uma sequência e dá nomes aos parâmetros -- output table: { latitude=, longitude = , direction = } if type( str ) ~= 'string' then return nil end str = mw.ustring.gsub( mw.ustring.upper( str ), '%a+', coordParse ) if not tonumber( str ) and not str:find( '/' ) and str:find( '°' ) then local str2 = mw.ustring.gsub( str, '[°″′\"\'\194\160 ]+', '/' ) -- avoid cases were there is degree ans seconds but no minutes if not mw.ustring.find( str, '[″"]' ) or mw.ustring.find( str, '%d[′\'][ \194\160%d]' ) then str = str2 end end if not tonumber(str) and not string.find(str, '/') then makeerror({message = i18n.invalidFormat, sortkey= 'A'}) return nil end args = mw.text.split(str, '/', true) if #args > 4 then makeerror({message = i18n.tooManyParam, 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, dimension) if validdms(dimensionobject) then return dimensionobject else return nil end end --- decimal specific functions function p.displaydec(latitude, longitude, format) lat = lang:formatNum( latitude ) long = lang:formatNum( longitude ) if format == 'dec west' or format == 'dec east' then local symbolNS, symbolEW = i18n.N, i18n.E if latitude < 0 then symbolNS = i18n.S lat = lat:sub( 2 ) end if format == 'dec west' then symbolEW = i18n.W end if longitude < 0 then long = lang:formatNum( 360 + longitude ) end return { lat .. i18n.degrees .. symbolNS, long .. i18n.degrees .. symbolEW } else return { lat, long } end end local function parsedec(dec, coordtype, globe) -- coordtype = latitude or longitude dec = mw.text.trim(dec) if not dec then return nil end if coordtype ~= 'latitude' and coordtype ~= 'longitude' then makeerror({'invalid coord type', sortkey = "A"}) 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 dec = mw.ustring.gsub( mw.ustring.upper( dec ), '%a+', coordParse ) local 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' or direction == 'W' and globedata[globe].defaultdisplay == 'dec west' then numdec = tonumber( dec ) elseif direction == 'W' or direction == 'S' then dec = '-' .. dec numdec = tonumber( dec ) else if coordtype == 'latitude' then makeerror({message = i18n.invalidNS, sortkey = 'A'}) else makeerror({message = i18n.invalidEW, sortkey = 'A'}) end return nil end end if coordtype == 'latitude' and math.abs(numdec) > 90 then makeerror({message = i18n.latitude90 , sortkey = 'A'}) return nil end if coordtype == 'longitude' and math.abs(numdec) > 360 then makeerror({message = i18n.longitude360 , 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, globe) -- coordtype: latitude or longitude local degrees, minutes, seconds -- verificação do globo if not ( globe and globedata[ globe ] ) then globe = 'earth' end -- 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 local direction if coordtype == 'latitude' then if dec < 0 then direction = 'S' else direction = 'N' end elseif coordtype == 'longitude' then if dec < 0 or globedata[globe].defaultdisplay == 'dec west' then direction = 'W' else direction = 'E' end end -- conversion dec = math.abs(dec) -- as coordenadas em dms são sempre positivas 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 = i18n.invalidFormat, sortkey = 'A'}) return showerrors() end local dirpositive = string.lower(args[2] or '') local dirnegative = string.lower(args[3] or '') local precision = string.lower(args[4] or '') local displayformat, coordtype if dirpositive == 'n' or dirpositive == 'norte' then coordtype = 'latitude' else coordtype = 'longitude' end if dirpositive == 'norte' or dirpositive == 'leste' or dirnegative == 'oeste' or dirnegative == 'sul' 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) -- transformar uma tabela de minutos de segundo em um número decimal 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 = i18n.noCardinalDirection, sortkey = 'A'}) return nil else makeerror({message = i18n.invalidDirection, sortkey = 'A'}) return nil end if dmsobject.seconds then -- verifique a precisão dos dados iniciais precision = 5 + math.max( math_mod._precision(tostring(seconds), 0 ) ) -- passagem por cadeias de texto bastante complicada? 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] -- coordenadas já em decimal elseif not args[2] then local dmsobject = p._parsedmsstring(args[1]) if dmsobject then return p._dms2dec(dmsobject) -- coordena sob a proa 23/22/N else local coordType if args[1]:match( '[NS]' ) then coordType = 'latitude' elseif args[1]:match( '[EWO]') then coordType = 'longitude' end if coordType then local result = parsedec( args[1], coordType, args.globe or 'earth' ) if result then return result end end return showerrors() end else return p._dms2dec({direction = args[1], degrees = tonumber(args[2]), minutes = tonumber(args[3]), seconds = tonumber(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('Módulo:Infobox/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:Infobox/Wikidata local coords = wd.formatSnak(claim[1].mainsnak) -- todo: check for special values -- Wikidata does not handle correctly +West longitudes if globedata[ coords.globe ] and globedata[ coords.globe ].defaultdisplay == 'dec west' then coords.longitude = math.abs( coords.longitude ) end return coords.latitude, coords.longitude, coords.globe or 'earth', convertwikidataprecision(coords.precision or .001) end return nil end local function wikidatacat(globe) local entitycat = mw.wikibase.getEntity() local basecat = '!Páginas com mapas' local finalcat = {} --BADGES if entitycat then --BADGES for i, badgeId in ipairs( entitycat.sitelinks['ptwiki'].badges ) do if badgeId == 'Q17437796' then basecat= string.gsub(basecat, "!Páginas com mapas", "!Artigos por qualidade sobre geografia") end if badgeId == 'Q17437798' then basecat= string.gsub(basecat, "!Páginas com mapas", "!Artigos bons sobre geografia") end end end table.insert(finalcat,basecat) 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 = 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 rawlat == '' then rawlat = nil end if rawlong == '' then rawlong = nil end local globe = string.lower( args.globe or extraparams:match('globe:(%a+)') 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 local maplink = true -- use maplink whenever it is possible -- 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 = i18n.coordMissing, sortkey = 'A'}) return showerrors() end latitude = parsedec(rawlat, 'latitude', globe) if latitude then -- if latitude is decimal longitude = parsedec(rawlong, 'longitude', globe) -- 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 = i18n.invalidFormat, sortkey = 'A'}) end return showerrors() end dmslatitude, dmslongitude = p._dec2dms(latitude, 'latitude', precision), p._dec2dms(longitude, 'longitude', precision, globe) latitude, longitude = tonumber(latitude), tonumber(longitude) else -- if latitude is not decimal try to parse it as a dms string dmslatitude, dmslongitude = p._parsedmsstring(args.latitude, 'latitude'), p._parsedmsstring(args.longitude, '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, wikidataprecision 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, globe) 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 -- não adicione nada aqui para que a chamada para esta função retorne nil na ausência de dados end -- IV best guesses for missing parameters --- globe if globe == '' then globe = 'earth' end if not globedata[globe] then makeerror({message = i18n.invalidGlobe .. globe}) globe = 'earth' end if globe ~= 'earth' then extraparams = extraparams .. '_globe:' .. globe -- não há problema se o globo é duplicado maplink = false 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 --Recuperação dos 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 local mainstring = '' if maplink then mainstring = buildMaplinkHTML(latitude, longitude, dmslatitude, dmslongitude, globe, displayformat, displayinline, displaytitle, objectname,extraparams ) 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) -- parses 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 = i18n.coordMissing, sortkey = 'A'}) return showerrors() end table.remove(numericargs) 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 para infobox, a depreciar 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 para infobox, a depreciar 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 --[[ link Simple function to export the coordinates link for other uses. Usage: {{#invoke:Coordenadas | link }} ]] function p.link(frame) return coord_link; end return p