Diferencia entre revisiones de «Módulo:Mapa»

Contenido eliminado Contenido añadido
Vriullop (discusión · contribs.)
título de la subpágina /i18n
Actualizo según esta versión de Mòdul:Map de la Wikipedia en catalán, bajo licencia CC-BY-SA
 
Línea 5:
-- CSGNetwork at http://www.csgnetwork.com/degreelenllavcalc.html via @enwiki
-- OpenStreetMap
-- Version: 2018270520210211
 
local p = {}
Línea 18:
["polygon-not-closed"] = "A closed polygon requires last point equal to first one.",
['ids-not-found'] = "Ids not found for external data.",
--['not-from-content-page'] = "Do not invoke from content page. Use a template or use a module subpage like /sandbox for testing .",
-- local categories
['cat-several-features'] = "",
Línea 116:
end
return stack
end
 
-- remove duplicated points, they may affect zoom calculation
local function setUniquePoints(t)
-- build set of unique values
local uniqueElements = {}
for _, point in ipairs(t) do
if not uniqueElements[point[1]] then
uniqueElements[point[1]] = {}
end
uniqueElements[point[1]][point[2]] = true
end
-- convert the set
local result = {}
for lon, _ in pairs(uniqueElements) do
for lat, _ in pairs(uniqueElements[lon]) do
table.insert(result, {lon, lat})
end
end
return result
end
 
Línea 199 ⟶ 220:
local function fetchWikidata(id, snak)
-- snak is a table like {'claims', 'P625', 1, 'mainsnak', 'datavalue', 'value'}
-- see function ViewSomething on Module:Wikidata
local value
id = mw.text.trim(id)
Línea 205 ⟶ 225:
printError('ids-invalid', id)
else
value = mw.wikibase.getEntityObjectgetBestStatements(id, snak[2])
for i in= ipairs(3, #snak) do
if value == nil then break end
value = value[snak[i]]
Línea 217 ⟶ 237:
-- Fetch coordinates from Wikidata for a list of comma separated ids
local function getCoordinatesById(ids)
local function roundPrec(num, prec)
if prec == nil or prec <= 0 then return num end
local sig = 10^math.floor(math.log10(prec)+.5) -- significant figure from sexagesimal precision: 0.00123 -> 0.001
return math.floor(num / sig + 0.5) * sig
end
if ids == nil then return end
local coord = {}
Línea 223 ⟶ 249:
local value = fetchWikidata(idx, snak)
if value then
local prec = value.precision
coord[#coord+1] = value.latitude .. ',' .. value.longitude
coord[#coord+1] = roundPrec(value.latitude, prec) .. ',' .. roundPrec(value.longitude, prec)
end
end
Línea 235 ⟶ 262:
local id = mw.text.split(ids, '%s*,%s*')
if #coord ~= #id then return {} end
local id_parent = nil
if #id == 1 then
id_parent = fetchWikidata(id[1], {'claims', 'P131', 1, 'mainsnak', 'datavalue', 'value', 'id'})
if id_parent ~= nil then
id[2] = id_parent -- P131: located in the administrative territorial entity, last try
coord[2] = coord[1]
end
end
local bounds = {}
-- try to fetch Wikidata in this order: area, watershed area, population, and finally by administrative entity
local snak_area = {'claims', 'P2046', 1, 'mainsnak', 'datavalue', 'value'} -- area and unit
local snak_warea = {'claims', 'P2053', 1, 'mainsnak', 'datavalue', 'value'} -- area and unit
Línea 244 ⟶ 279:
-- query Wikidata: http://tinyurl.com/j8aez2g
for i = 1, #id do
if i == 2 and id[2] == id_parent and #bounds > 0 then break end -- only if not found previously
local amount, unit, area
local value = fetchWikidata(id[i], snak_area) or fetchWikidata(id[i], snak_warea)
Línea 270 ⟶ 306:
end
return bounds
end
 
local function circleToPolygon(center, radius, edges, turn)
-- From en:Module:Mapframe, based on https://github.com/gabzim/circle-to-polygon, ISC licence
local function offset(cLat, cLon, distance, bearing)
local lat1 = math.rad(cLat)
local lon1 = math.rad(cLon)
local dByR = distance / 6378137 -- distance divided by 6378137 (radius of the earth) wgs84
local lat = math.asin(
math.sin(lat1) * math.cos(dByR) +
math.cos(lat1) * math.sin(dByR) * math.cos(bearing)
)
local lon = lon1 + math.atan2(
math.sin(bearing) * math.sin(dByR) * math.cos(lat1),
math.cos(dByR) - math.sin(lat1) * math.sin(lat)
)
return math.deg(lat) .. ',' .. math.deg(lon)
end
local coords = mw.text.split(center, ',', true)
local lat = tonumber(coords[1])
local long = tonumber(coords[2])
edges = edges or 32
local move = 2 * math.pi * (turn or 0)
local coordinates = {}
for i = 0, edges do
table.insert(coordinates, offset(lat, long, radius, ((2*math.pi*-i)/edges) + move))
end
return table.concat(coordinates, ';')
end
 
Línea 284 ⟶ 350:
end
return
end
 
-- Recursively extract coord templates which have a name parameter.
-- from en:Module:Mapframe
local function extractCoordTemplates(wikitext)
local output = {}
local templates = mw.ustring.gmatch(wikitext, '{%b{}}')
local subtemplates = {}
for template in templates do
local name = mw.ustring.match(template, '{{([^}|]+)') -- get the template name
local nameParam = mw.ustring.match(template, "|%s*name%s*=%s*[^}|]+")
if not nameParam then
nameParam = mw.ustring.match(template, "|%s*nom%s*=%s*[^}|]+")
end
if mw.ustring.lower(mw.text.trim(name)) == 'coord' then
if nameParam then table.insert(output, template) end
elseif mw.ustring.find(template, 'coord') then
local subOutput = extractCoordTemplates(mw.ustring.sub(template, 2))
for _, t in pairs(subOutput) do
table.insert(output, t)
end
end
end
-- ensure coords are not using title display
for k, v in pairs(output) do
output[k] = mw.ustring.gsub(v, "|%s*display%s*=[^|}]+", "|display=inline")
end
return output
end
 
-- Gets all named coordiates from a page or a section of a page.
-- dependency: Module:Transcluder
local function getNamedCoords(page)
local parts = mw.text.split(page or "", "#", true)
local name = parts[1] == "" and mw.title.getCurrentTitle().prefixedText or parts[1]
local section = parts[2]
local pageWikitext = require('Module:Transcluder').get(section and name.."#"..section or name)
local coordTemplates = extractCoordTemplates(pageWikitext)
local frame = mw.getCurrentFrame()
local sep = "________"
local expandedContent = frame:preprocess(table.concat(coordTemplates, sep))
local expandedTemplates = mw.text.split(expandedContent, sep)
local namedCoords = {}
for _, expandedTemplate in pairs(expandedTemplates) do
local coord = mw.ustring.match(expandedTemplate, "<span class=\"geo\">(.-)</span>")
if coord then
coord = mw.ustring.gsub(coord, ";", ",")
local name = mw.ustring.match(expandedTemplate, "&title=(.-)<span") or coord
name = mw.uri.decode(name)
local description = name ~= coord and coord
table.insert(namedCoords, {coord=coord, name=name, description=description})
end
end
return namedCoords
end
 
-- Main function
local function p._tagmain(args)
local tagname = args.type or 'mapframe'
if tagname ~= 'maplink' and tagname ~= 'mapframe' then printError('type-invalid', tagname) end
local geojson
local tagArgs = {
text = args.text,
Línea 307 ⟶ 426:
tagArgs.class = args.class
end
local wdid = args.item or mw.wikibase.getEntityIdForCurrentPage()
if args['coordinates1'] == nil and args['geotype1'] == nil then -- single feature
Línea 312 ⟶ 433:
if args['coordinates1'] == nil and args['latitude'] and args['longitude'] then
args['coordinates1'] = args['latitude'] .. ',' .. args['longitude']
elseif args['coordinates1'] == nil and not args.commons then
args['coordinates1'] = getCoordinatesById(mw.wikibase.getEntityIdForCurrentPage()wdid)
end
local par = {'title', 'image', 'description', 'geotype', 'commons', 'radius', 'radiuskm', 'edges', 'turn', 'from'}
for _, v in ipairs(par) do
args[v .. '1'] = args[v .. '1'] or args[v]
end
args['title1'] = args['title1'] or args['title']
args['image1'] = args['image1'] or args['image']
args['description1'] = args['description1'] or args['description']
args['geotype1'] = args['geotype1'] or args['geotype']
end
local externalData = {['geoshape'] = true, ['geomask'] = true, ['geoline'] = true, ['page'] = true, ['none'] = true, ['named'] = true}
local featureCollection = {['Point'] = true, ['MultiPoint'] = true, ['LineString'] = true, ['Polygon'] = true, ['circle'] = true}
local myfeatures, myexternal, allpoints = {}, {}, {}
local i, j = 1, 1
while args['coordinates'..i] or args['ids'..i] or externalData[args['geotype'..i]] or args['commons'..i] do
local geotypex = args['geotype'..i] or args['geotype']
if geotypex == nil and args['commons'..i] then
geotypex = 'page'
end
if geotypex ~= nil and not (featureCollection[geotypex] or externalData[geotypex]) then
printError('geotype-invalid', geotypex)
Línea 332 ⟶ 456:
end
if geotypex == 'none' then -- skip this object
local mystack
i = i + 1
if externalData[geotypex or ''] then
else
mystack = myexternal
jlocal = #mystack + 1
if geotypex == 'named' then
mystack[j] = {}
local namedCoords = getNamedCoords(args['from'..i])
mystack[j]['type'] = "ExternalData"
mystack[j]['service'] = geotypexmyfeatures
for _, namedCoord in pairs(namedCoords) do
mystack[j]['ids'] = args['ids'..i] or args['ids'] or mw.wikibase.getEntityIdForCurrentPage()
j = #mystack + 1
if mystack[j]['ids'] == nil then printError('ids-not-found'); break end
mystack[j] = {}
local mycoordinates = args['coordinates'..i]
mystack[j]['type'] = "Feature"
if mycoordinates == nil and (tagArgs.latitude == nil or tagArgs.longitude == nil or tagArgs.zoom == nil) then
mycoordinates = getCoordinatesById( mystack[j]['idsgeometry']) = {}
mystack[j]['geometry']['type'] = "Point"
end
mystack[j]['geometry']['coordinates'] = parseGeoSequence(namedCoord.coord, 'Point')
if mycoordinates ~= nil then
local mypoints allpoints = getBoundsByIdmergePoints(allpoints, mystack[j]['idsgeometry']['coordinates'], mycoordinates)
mystack[j]['properties'] = {}
if #mypoints == 0 then
mystack[j]['properties']['title'] = namedCoord.name
mypoints = parseGeoSequence(mycoordinates, mycoordinates:find(';') and 'MultiPoint' or 'Point')
mystack[j]['properties']['description'] = namedCoord.description
mystack[j]['properties']['marker-size'] = args['marker-size'..i] or args['marker-size']
mystack[j]['properties']['marker-symbol'] = args['marker-symbol'..i] or args['marker-symbol']
mystack[j]['properties']['marker-color'] = args['marker-color'..i] or args['marker-color']
end
break
elseif externalData[geotypex or ''] then
mystack = myexternal
j = #mystack + 1
mystack[j] = {}
mystack[j]['type'] = "ExternalData"
mystack[j]['service'] = geotypex
if geotypex == "page" then
local page_name = args['commons'..i]
if mw.ustring.find(page_name, "Data:", 1, true) == 1 then
page_name = string.sub(page_name, 6)
end
if mw.ustring.find(page_name, ".map", -4, true) == nil then
page_name = page_name .. '.map'
end
mystack[j]['title'] = page_name
else
mystack[j]['ids'] = args['ids'..i] or args['ids'] or wdid
if mystack[j]['ids'] == nil then printError('ids-not-found'); break end
end
local mycoordinates = args['coordinates'..i]
if mycoordinates == nil and (tagArgs.latitude == nil or tagArgs.longitude == nil or tagArgs.zoom == nil) then
mycoordinates = getCoordinatesById(mystack[j]['ids'])
end
if mycoordinates ~= nil then
local mypoints = getBoundsById(mystack[j]['ids'], mycoordinates)
if #mypoints == 0 then
mypoints = parseGeoSequence(mycoordinates, mycoordinates:find(';') and 'MultiPoint' or 'Point')
end
allpoints = mergePoints(allpoints, mypoints)
end
else
args['coordinates'..i] = args['coordinates'..i] or getCoordinatesById(args['ids'..i])
if geotypex == 'circle' then
if not args['radius'..i] and args['radiuskm'..i] then
args['radius'..i] = args['radiuskm'..i] * 1000
end
args['coordinates'..i] = circleToPolygon(args['coordinates'..i], args['radius'..i], args['edges'..i], args['turn'..i])
geotypex = 'Polygon'
end
mystack = myfeatures
allpoints = mergePoints(allpoints, mypoints)
j = #mystack + 1
mystack[j] = {}
mystack[j]['type'] = "Feature"
mystack[j]['geometry'] = {}
mystack[j]['geometry']['type'] = geotypex or findGeotype(args['coordinates'..i])
mystack[j]['geometry']['coordinates'] = parseGeoSequence(args['coordinates'..i], mystack[j]['geometry']['type'])
allpoints = mergePoints(allpoints, mystack[j]['geometry']['coordinates'])
addCategories(mystack[j]['geometry']['type'], i)
end
mystack[j]['properties'] = {}
else
mystack[j]['properties']['title'] = args['title'..i] or (geotypex and geotypex .. i) or mystack[j]['geometry']['type'] .. i
mystack = myfeatures
if args['image'..i] then
j = #mystack + 1
args['description'..i] = (args['description'..i] or '') .. '[[File:' .. args['image'..i] .. '|300px]]'
mystack[j] = {}
end
mystack[j]['type'] = "Feature"
mystack[j]['geometryproperties']['description'] = {}args['description'..i]
mystack[j]['geometryproperties']['typemarker-size'] = geotypex or findGeotype(args['coordinatesmarker-size'..i]) or args['marker-size']
mystack[j]['geometryproperties']['coordinatesmarker-symbol'] = parseGeoSequence(args['coordinatesmarker-symbol'..i], mystack[j]['geometry']or args['typemarker-symbol'])
mystack[j]['properties']['marker-color'] = args['marker-color'..i] or args['marker-color']
allpoints = mergePoints(allpoints, mystack[j]['geometry']['coordinates'])
addCategories(mystack[j]['geometryproperties']['typestroke'], = args['stroke'..i)] or args['stroke']
mystack[j]['properties']['stroke-opacity'] = tonumber(args['stroke-opacity'..i] or args['stroke-opacity'])
end
mystack[j]['properties']['stroke-width'] = {}tonumber(args['stroke-width'..i] or args['stroke-width'])
mystack[j]['properties']['titlefill'] = args['titlefill'..i] or (geotypex and geotypex .. i) or mystack[j]args['geometryfill']['type'] .. i
mystack[j]['properties']['fill-opacity'] = tonumber(args['fill-opacity'..i] or args['fill-opacity'])
if args['image'..i] then
args['description'..i] = (args['description'..i] or '') .. '[[File:' .. args['image'..i] .. '|300px]]'
i = i + 1
end
mystack[j]['properties']['description'] = args['description'..i]
mystack[j]['properties']['marker-size'] = args['marker-size'..i] or args['marker-size']
mystack[j]['properties']['marker-symbol'] = args['marker-symbol'..i] or args['marker-symbol']
mystack[j]['properties']['marker-color'] = args['marker-color'..i] or args['marker-color']
mystack[j]['properties']['stroke'] = args['stroke'..i] or args['stroke']
mystack[j]['properties']['stroke-opacity'] = tonumber(args['stroke-opacity'..i] or args['stroke-opacity'])
mystack[j]['properties']['stroke-width'] = tonumber(args['stroke-width'..i] or args['stroke-width'])
mystack[j]['properties']['fill'] = args['fill'..i] or args['fill']
mystack[j]['properties']['fill-opacity'] = tonumber(args['fill-opacity'..i] or args['fill-opacity'])
i = i + 1
end
Línea 389 ⟶ 555:
if tagArgs.zoom == nil then
if tagname == "mapframe" then
local uniquepoints = setUniquePoints(allpoints)
if #allpoints == 1 then
if #uniquepoints == 1 then
local currentId = mw.wikibase.getEntityIdForCurrentPage()
local coordInput = allpointsuniquepoints[1][2] .. ',' .. allpointsuniquepoints[1][1]
local mybounds = getBoundsById(currentIdwdid, coordInput) -- try to fetch by area
allpointsuniquepoints = mergePoints(allpointsuniquepoints, mybounds)
end
if #allpointsuniquepoints <= 1 then
tagArgs.zoom = defaultzoom or 9
else
tagArgs.zoom = getZoom(allpointsuniquepoints, tagArgs.height, tagArgs.width)
end
else
Línea 406 ⟶ 572:
local geojson = myexternal
if args.commons ~= nil then
geojson[#geojson+1] = {
type = "ExternalData",
service = "page",
title = args.commons,
}
end
if #myfeatures > 0 then
geojson[#geojson + 1] = {type = "FeatureCollection", features = myfeatures}
Línea 422 ⟶ 579:
local html = mw.text.tag{name = tagname, attrs = tagArgs, content = mw.text.jsonEncode(geojson, mw.text.JSON_PRETTY)}
return 'syntaxhighlight', tostring(html) .. ' Arguments:' .. mw.text.jsonEncode(args, mw.text.JSON_PRETTY), {lang = 'json'}
end
if geojson and #geojson == 0 then
errormessage = erromessage or '' -- previous message or void for no map data
end
Línea 427 ⟶ 588:
end
 
local function p.tagaddCat(framecat)
if mw.title.new(frame:getParent():getTitle()).isContentPage and not mw.title.new(frame:getTitle()).isSubpage then
-- invoked from a content page and not invoking a module subpage
printError('not-from-content-page')
end
local getArgs = require('Module:Arguments').getArgs
local args = getArgs(frame)
local tag, geojson, tagArgs = p._tag(args)
local categories = ''
if errormessage then
categories = mw.message.new('Kartographer-broken-category'):inLanguage(mw.language.getContentLanguage().code):plain()
return errormessage .. '[[Category:' .. categories .. ']]'
end
for k, v in pairs(cat) do
Línea 449 ⟶ 597:
end
return frame:extensionTag(tag, geojson, tagArgs) .. categories
end
 
local function errorMessage(message)
if message == '' then -- no map data
return
else
categories = mw.message.new('Kartographer-broken-category'):inLanguage(mw.language.getContentLanguage().code):plain()
return message .. '[[Category:' .. categories .. ']]'
end
end
 
function p.tag(frame) -- entry point from invoke
local getArgs = require('Module:Arguments').getArgs
local args = getArgs(frame)
local tag, geojson, tagArgs = main(args)
if errormessage then return errorMessage(errormessage) end
return frame:extensionTag(tag, geojson, tagArgs) .. addCat(cat)
end
 
function p._tag(args) -- entry point from require
local tag, geojson, tagArgs = main(args)
if errormessage then return errorMessage(errormessage) end
return mw.getCurrentFrame():extensionTag(tag, geojson, tagArgs) .. addCat(cat)
end