Módulo:Map draw: diferenças entre revisões

Conteúdo apagado Conteúdo adicionado
m Protegeu "Módulo:Map draw": Módulo com impacto significativo em outras páginas ([Editar=Permitir apenas autorrevisores] (indefinidamente) [Mover=Permitir apenas autorrevisores] (indefinidamente))
update
Linha 5:
-- CSGNetwork at http://www.csgnetwork.com/degreelenllavcalc.html via @enwiki
-- OpenStreetMap
-- Version: 2017022320200509
 
local p = {}
Linha 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'] = "",
Linha 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
 
Linha 165 ⟶ 186:
-- maximum zoom fitting all points
local latRad = math.rad(latMid)
for zoom = 1819, 0, -1 do
-- see https://wiki.openstreetmap.org/wiki/Zoom_levels#Metres_per_pixel_math
-- equatorial circumference 40 075 036 m: [[Equator#Exact length]]
Linha 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)
Linha 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]]
Linha 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 = {}
Linha 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
Linha 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
Linha 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)
Linha 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
 
Linha 291 ⟶ 357:
if tagname ~= 'maplink' and tagname ~= 'mapframe' then printError('type-invalid', tagname) end
local geojson
local tagArgs = {
text = args.text,
Linha 298 ⟶ 363:
longitude = tonumber(args.longitude)
}
local defaultzoom = tonumber(args.default_zoom)
if tagname == 'mapframe' then
tagArgs.width = args.width or 300
Linha 306 ⟶ 372:
tagArgs.class = args.class
end
local wdid = args.item or mw.wikibase.getEntityIdForCurrentPage()
if args['coordinates1'] == nil and args['geotype1'] == nil then -- single feature
Linha 312 ⟶ 380:
args['coordinates1'] = args['latitude'] .. ',' .. args['longitude']
elseif args['coordinates1'] == nil then
args['coordinates1'] = getCoordinatesById(mw.wikibase.getEntityIdForCurrentPage()wdid)
end
local par = {'title', 'image', 'description', 'geotype', 'commons', 'radius', 'radiuskm', 'edges', 'turn'}
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}
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)
Linha 331 ⟶ 402:
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 externalData[geotypex or ''] then
mystack[j] = {}
mystack[j]['type'] = "ExternalData"myexternal
j = #mystack + 1
mystack[j]['service'] = geotypex
mystack[j] = {}
mystack[j]['ids'] = args['ids'..i] or args['ids'] or mw.wikibase.getEntityIdForCurrentPage()
if mystack[j]['idstype'] == nil then printError('ids-not-found'); break end"ExternalData"
mystack[j]['service'] = geotypex
local mycoordinates = args['coordinates'..i]
if geotypex == "page" then
if mycoordinates == nil and (tagArgs.latitude == nil or tagArgs.longitude == nil or tagArgs.zoom == nil) then
local page_name = args['commons'..i]
mycoordinates = getCoordinatesById(mystack[j]['ids'])
if mw.ustring.find(page_name, "Data:", 1, true) == 1 then
end
page_name = string.sub(page_name, 6)
if mycoordinates ~= nil then
end
local mypoints = getBoundsById(mystack[j]['ids'], mycoordinates)
if #mypointsmw.ustring.find(page_name, ".map", -4, true) == 0nil then
page_name = page_name .. '.map'
mypoints = parseGeoSequence(mycoordinates, mycoordinates:find(';') and 'MultiPoint' or 'Point')
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]
allpoints = mergePoints(allpoints, mypoints)
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
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'])
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
mystack[j]['properties'] = {}
mystack[j]['properties']['title'] = args['title'..i] or (geotypex and geotypex .. i) or mystack[j]['geometry']['type'] .. i
if args['image'..i] then
args['description'..i] = (args['description'..i] or '') .. '[[File:' .. args['image'..i] .. '|300px]]'
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
Linha 386 ⟶ 480:
end
end
if tagArgs.zoom == nil andthen
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
allpoints uniquepoints = mergePoints(allpointsuniquepoints, mybounds)
end
if #uniquepoints <= 1 then
tagArgs.zoom = defaultzoom or 9
else
tagArgs.zoom = getZoom(uniquepoints, tagArgs.height, tagArgs.width)
end
else
tagArgs.zoom = defaultzoom
end
tagArgs.zoom = #allpoints <= 1 and 9 or getZoom(allpoints, tagArgs.height, tagArgs.width)
end
Linha 404 ⟶ 506:
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
Linha 410 ⟶ 516:
 
function p.tag(frame)
--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)
Linha 421 ⟶ 527:
if errormessage then
if errormessage == '' then -- no map data
categories = mw.message.new('Kartographer-broken-category'):inLanguage(mw.language.getContentLanguage().code):plain()
return
return errormessage .. '[[Category:' .. categories .. ']]'
else
categories = mw.message.new('Kartographer-broken-category'):inLanguage(mw.language.getContentLanguage().code):plain()
return errormessage .. '[[Category:' .. categories .. ']]'
end
end