<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="es">
	<id>https://netxipedia.org/index.php?action=history&amp;feed=atom&amp;title=M%C3%B3dulo%3AMapa</id>
	<title>Módulo:Mapa - Historial de revisiones</title>
	<link rel="self" type="application/atom+xml" href="https://netxipedia.org/index.php?action=history&amp;feed=atom&amp;title=M%C3%B3dulo%3AMapa"/>
	<link rel="alternate" type="text/html" href="https://netxipedia.org/index.php?title=M%C3%B3dulo:Mapa&amp;action=history"/>
	<updated>2026-04-16T20:05:46Z</updated>
	<subtitle>Historial de revisiones de esta página en la wiki</subtitle>
	<generator>MediaWiki 1.44.0</generator>
	<entry>
		<id>https://netxipedia.org/index.php?title=M%C3%B3dulo:Mapa&amp;diff=3437&amp;oldid=prev</id>
		<title>Netxipedia: 1 revisión importada</title>
		<link rel="alternate" type="text/html" href="https://netxipedia.org/index.php?title=M%C3%B3dulo:Mapa&amp;diff=3437&amp;oldid=prev"/>
		<updated>2025-08-28T00:55:31Z</updated>

		<summary type="html">&lt;p&gt;1 revisión importada&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;es&quot;&gt;
				&lt;td colspan=&quot;1&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Revisión anterior&lt;/td&gt;
				&lt;td colspan=&quot;1&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revisión del 00:55 28 ago 2025&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-notice&quot; lang=&quot;es&quot;&gt;&lt;div class=&quot;mw-diff-empty&quot;&gt;(Sin diferencias)&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;</summary>
		<author><name>Netxipedia</name></author>
	</entry>
	<entry>
		<id>https://netxipedia.org/index.php?title=M%C3%B3dulo:Mapa&amp;diff=3436&amp;oldid=prev</id>
		<title>netxipedia&gt;Leoncastro: Actualizo según esta versión de Mòdul:Map de la Wikipedia en catalán, bajo licencia CC-BY-SA</title>
		<link rel="alternate" type="text/html" href="https://netxipedia.org/index.php?title=M%C3%B3dulo:Mapa&amp;diff=3436&amp;oldid=prev"/>
		<updated>2021-08-21T17:13:14Z</updated>

		<summary type="html">&lt;p&gt;Actualizo según &lt;a href=&quot;/index.php?title=Ca:Special:Permalink/26320001&amp;amp;action=edit&amp;amp;redlink=1&quot; class=&quot;new&quot; title=&quot;Ca:Special:Permalink/26320001 (la página no existe)&quot;&gt;esta versión&lt;/a&gt; de &lt;a href=&quot;/index.php?title=Ca:M%C3%B2dul:Map&amp;amp;action=edit&amp;amp;redlink=1&quot; class=&quot;new&quot; title=&quot;Ca:Mòdul:Map (la página no existe)&quot;&gt;Mòdul:Map&lt;/a&gt; de la Wikipedia en catalán, bajo licencia &lt;a href=&quot;/index.php?title=Ca:VP:CC-BY-SA&amp;amp;action=edit&amp;amp;redlink=1&quot; class=&quot;new&quot; title=&quot;Ca:VP:CC-BY-SA (la página no existe)&quot;&gt;CC-BY-SA&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Página nueva&lt;/b&gt;&lt;/p&gt;&lt;div&gt;-- Credits:&lt;br /&gt;
-- Original from Wikivoyage&lt;br /&gt;
-- Developed for Kartographer version on Wikipedia by Vriullop @cawiki&lt;br /&gt;
-- Formulae:&lt;br /&gt;
--    CSGNetwork at http://www.csgnetwork.com/degreelenllavcalc.html via @enwiki&lt;br /&gt;
--    OpenStreetMap&lt;br /&gt;
-- Version: 20210211&lt;br /&gt;
&lt;br /&gt;
local p = {}&lt;br /&gt;
&lt;br /&gt;
-- Localization on [[Module:Map/i18n]]&lt;br /&gt;
local i18n = {&lt;br /&gt;
	[&amp;quot;coordinate-invalid&amp;quot;] = &amp;quot;Parameter $1 is an invalid value of \&amp;quot;latitude,longitude\&amp;quot;.&amp;quot;,&lt;br /&gt;
	[&amp;quot;type-invalid&amp;quot;] = &amp;quot;Type $1 is invalid. Use mapframe or maplink.&amp;quot;,&lt;br /&gt;
	[&amp;quot;geotype-invalid&amp;quot;] = &amp;quot;Geotype $1 is an invalid value.&amp;quot;,&lt;br /&gt;
	[&amp;quot;ids-invalid&amp;quot;] = &amp;quot;Parameter ids $1 is invalid.&amp;quot;,&lt;br /&gt;
	[&amp;quot;polygon-required-points&amp;quot;] = &amp;quot;A polygon requires a minimum of 4 coordinate points.&amp;quot;,&lt;br /&gt;
	[&amp;quot;polygon-not-closed&amp;quot;] = &amp;quot;A closed polygon requires last point equal to first one.&amp;quot;,&lt;br /&gt;
	[&amp;#039;ids-not-found&amp;#039;] = &amp;quot;Ids not found for external data.&amp;quot;,&lt;br /&gt;
	--[&amp;#039;not-from-content-page&amp;#039;] = &amp;quot;Do not invoke from content page. Use a template or use a module subpage like /sandbox for testing .&amp;quot;,&lt;br /&gt;
	-- local categories&lt;br /&gt;
	[&amp;#039;cat-several-features&amp;#039;] = &amp;quot;&amp;quot;,&lt;br /&gt;
	[&amp;#039;cat-linestring-drawn&amp;#039;] = &amp;quot;&amp;quot;,&lt;br /&gt;
	[&amp;#039;cat-polygon-drawn&amp;#039;] = &amp;quot;&amp;quot;,&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
local cat = {[&amp;#039;cat-several-features&amp;#039;] = false, [&amp;#039;cat-linestring-drawn&amp;#039;] = false, [&amp;#039;cat-polygon-drawn&amp;#039;] = false}&lt;br /&gt;
&lt;br /&gt;
-- Credit to http://stackoverflow.com/a/1283608/2644759, cc-by-sa 3.0&lt;br /&gt;
local function tableMerge(t1, t2)&lt;br /&gt;
	for k, v in pairs(t2) do&lt;br /&gt;
		if type(v) == &amp;quot;table&amp;quot; then&lt;br /&gt;
			if type(t1[k] or false) == &amp;quot;table&amp;quot; then&lt;br /&gt;
				tableMerge(t1[k] or {}, t2[k] or {})&lt;br /&gt;
			else&lt;br /&gt;
				t1[k] = v&lt;br /&gt;
			end&lt;br /&gt;
		else&lt;br /&gt;
			t1[k] = v&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return t1&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function loadI18n()&lt;br /&gt;
	local exist, res = pcall(require, &amp;quot;Module:Mapa/i18n&amp;quot;)&lt;br /&gt;
	if exist and next(res) ~= nil then&lt;br /&gt;
		tableMerge(i18n, res.i18n)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
loadI18n()&lt;br /&gt;
&lt;br /&gt;
local errormessage&lt;br /&gt;
local function printError(key, par)&lt;br /&gt;
	-- just print first error&lt;br /&gt;
	errormessage = errormessage or (&amp;#039;&amp;lt;span class=&amp;quot;error&amp;quot;&amp;gt;&amp;#039; .. (par and mw.ustring.gsub(i18n[key], &amp;quot;$1&amp;quot;, par) or i18n[key]) .. &amp;#039;&amp;lt;/span&amp;gt;&amp;#039;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Convert coordinates input format to geojson table&lt;br /&gt;
local function parseGeoSequence(data, geotype)&lt;br /&gt;
	local coordsGeo = {}&lt;br /&gt;
	for line_coord in mw.text.gsplit(data, &amp;#039;:&amp;#039;, true) do -- Polygon - linearRing:linearRing...&lt;br /&gt;
		local coordsLine = {}&lt;br /&gt;
		for point_coord in mw.text.gsplit(line_coord, &amp;#039;;&amp;#039;, true) do -- LineString or MultiPoint - point;point...&lt;br /&gt;
			local valid = false&lt;br /&gt;
			local val = mw.text.split(point_coord, &amp;#039;,&amp;#039;, true) -- Point - lat,lon&lt;br /&gt;
			-- allow for elevation&lt;br /&gt;
			if #val &amp;gt;= 2 and #val &amp;lt;= 3 then&lt;br /&gt;
				local lat = tonumber(val[1])&lt;br /&gt;
				local lon = tonumber(val[2])&lt;br /&gt;
				if lat ~= nil and lon ~= nil then&lt;br /&gt;
					table.insert(coordsLine, {lon, lat})&lt;br /&gt;
					valid = true&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
			if not valid and point_coord ~= &amp;#039;&amp;#039; then printError(&amp;#039;coordinate-invalid&amp;#039;, point_coord) end&lt;br /&gt;
		end&lt;br /&gt;
		if geotype == &amp;#039;Polygon&amp;#039; then&lt;br /&gt;
			if #coordsLine &amp;lt; 4 then&lt;br /&gt;
				printError(&amp;#039;polygon-required-points&amp;#039;)&lt;br /&gt;
			elseif table.concat(coordsLine[1]) ~= table.concat(coordsLine[#coordsLine]) then&lt;br /&gt;
				printError(&amp;#039;polygon-not-closed&amp;#039;)&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		table.insert(coordsGeo, coordsLine)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	if geotype == &amp;#039;Point&amp;#039; then&lt;br /&gt;
		coordsGeo = coordsGeo[1][1]&lt;br /&gt;
	elseif geotype == &amp;quot;LineString&amp;quot; or geotype == &amp;quot;MultiPoint&amp;quot; then&lt;br /&gt;
		coordsGeo = coordsGeo[1]&lt;br /&gt;
	elseif geotype ~= &amp;#039;Polygon&amp;#039; then&lt;br /&gt;
		printError(&amp;#039;geotype-invalid&amp;#039;, geotype)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
    return coordsGeo&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- data Point - {lon,lat}&lt;br /&gt;
-- data LineString - { {lon,lat}, {lon,lat}, ... }&lt;br /&gt;
-- data Polygon - { { {lon,lat}, {lon,lat} }, { {lon,lat}, {lon,lat} }, ... }&lt;br /&gt;
-- output as LineString format&lt;br /&gt;
local function mergePoints(stack, merger)&lt;br /&gt;
	if merger == nil then return stack end&lt;br /&gt;
	for _, val in ipairs(merger) do&lt;br /&gt;
		if type(val) == &amp;quot;number&amp;quot; then -- Point format&lt;br /&gt;
			stack[#stack + 1] = merger&lt;br /&gt;
			break&lt;br /&gt;
		elseif type(val[1]) == &amp;quot;table&amp;quot; then -- Polygon format&lt;br /&gt;
			for _, val2 in ipairs(val) do&lt;br /&gt;
				stack[#stack + 1] = val2&lt;br /&gt;
			end&lt;br /&gt;
		else -- LineString format&lt;br /&gt;
			stack[#stack + 1] = val&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return stack&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- remove duplicated points, they may affect zoom calculation&lt;br /&gt;
local function setUniquePoints(t)&lt;br /&gt;
	-- build set of unique values&lt;br /&gt;
	local uniqueElements = {}&lt;br /&gt;
	for _, point in ipairs(t) do&lt;br /&gt;
		if not uniqueElements[point[1]] then&lt;br /&gt;
			uniqueElements[point[1]] = {}&lt;br /&gt;
		end&lt;br /&gt;
		uniqueElements[point[1]][point[2]] = true&lt;br /&gt;
	end&lt;br /&gt;
	-- convert the set&lt;br /&gt;
	local result = {}&lt;br /&gt;
	for lon, _ in pairs(uniqueElements) do&lt;br /&gt;
		for lat, _ in pairs(uniqueElements[lon]) do&lt;br /&gt;
			table.insert(result, {lon, lat})&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return result&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function getCoordBounds(data)&lt;br /&gt;
	local latN, latS = -90, 90&lt;br /&gt;
	local lonE, lonW = -180, 180&lt;br /&gt;
	for i, val in ipairs(data) do&lt;br /&gt;
		latN = math.max(val[2], latN)&lt;br /&gt;
		latS = math.min(val[2], latS)&lt;br /&gt;
		lonE = math.max(val[1], lonE)&lt;br /&gt;
		lonW = math.min(val[1], lonW)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return latN, latS, lonE, lonW&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function getCoordCenter(data)&lt;br /&gt;
	local latN, latS, lonE, lonW = getCoordBounds(data)&lt;br /&gt;
	&lt;br /&gt;
	local latCenter = latS + (latN - latS) / 2&lt;br /&gt;
	local lonCenter = lonW + (lonE - lonW) / 2&lt;br /&gt;
	&lt;br /&gt;
	return lonCenter, latCenter&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- meters per degree by latitude&lt;br /&gt;
local function mxdByLat(lat)&lt;br /&gt;
	local latRad = math.rad(lat)&lt;br /&gt;
	-- see [[Geographic coordinate system#Expressing latitude and longitude as linear units]], by CSGNetwork&lt;br /&gt;
	local mxdLat = 111132.92 - 559.82 * math.cos(2 * latRad) + 1.175 * math.cos(4 * latRad) - 0.023 * math.cos(6 * latRad)&lt;br /&gt;
	local mxdLon = 111412.84 * math.cos(latRad) - 93.5 * math.cos(3 * latRad) + 0.118 * math.cos(5 * latRad)&lt;br /&gt;
	return mxdLat, mxdLon&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Calculate zoom to fit coordinate bounds into height and width of frame&lt;br /&gt;
local function getZoom(data, height, width)&lt;br /&gt;
	local lat1, lat2, lon1, lon2 = getCoordBounds(data)&lt;br /&gt;
	&lt;br /&gt;
	local latMid = (lat1 + lat2) / 2 -- mid latitude&lt;br /&gt;
	local mxdLat, mxdLon = mxdByLat(latMid)&lt;br /&gt;
	-- distances in meters&lt;br /&gt;
	local distLat = math.abs((lat1 - lat2) * mxdLat)&lt;br /&gt;
	local distLon = math.abs((lon1 - lon2) * mxdLon)&lt;br /&gt;
	&lt;br /&gt;
	-- margin 100px in height and width, right upper icon is about 50x50px&lt;br /&gt;
	local validHeight = math.max(height - 100, 100)&lt;br /&gt;
	local validWidth = math.max(width - 100, 100)&lt;br /&gt;
	&lt;br /&gt;
	-- maximum zoom fitting all points&lt;br /&gt;
	local latRad = math.rad(latMid)&lt;br /&gt;
	for zoom = 19, 0, -1 do&lt;br /&gt;
		-- see https://wiki.openstreetmap.org/wiki/Zoom_levels#Metres_per_pixel_math&lt;br /&gt;
		-- equatorial circumference 40 075 036 m: [[Equator#Exact length]]&lt;br /&gt;
		local distLatFrame = 40075036 * validHeight * math.cos(latRad) / (2 ^ (zoom + 8))&lt;br /&gt;
		local distLonFrame = 40075036 * validWidth * math.cos(latRad) / (2 ^ (zoom + 8))&lt;br /&gt;
		if distLatFrame &amp;gt; distLat and distLonFrame &amp;gt; distLon then&lt;br /&gt;
			return zoom&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return 0&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Geotype based on coordinates format pattern&lt;br /&gt;
local function findGeotype(coord)&lt;br /&gt;
	local _, semicolons = string.gsub(coord, &amp;#039;;&amp;#039;, &amp;#039;&amp;#039;)&lt;br /&gt;
	local firstcoord = string.match(coord, &amp;quot;[0-9%.%-]+%s*,%s*[0-9%.%-]+&amp;quot;)&lt;br /&gt;
	local lastcoord = string.match(string.reverse(coord), &amp;quot;[0-9%.%-]+%s*,%s*[0-9%.%-]+&amp;quot;)&lt;br /&gt;
	if firstcoord == nil or lastcoord == nil then&lt;br /&gt;
		printError(&amp;#039;coordinate-invalid&amp;#039;, coord)&lt;br /&gt;
	else&lt;br /&gt;
		lastcoord = string.reverse(lastcoord)&lt;br /&gt;
	end&lt;br /&gt;
	if string.find(coord, &amp;#039;:&amp;#039;) or (semicolons &amp;gt; 2 and firstcoord == lastcoord) then&lt;br /&gt;
		return &amp;#039;Polygon&amp;#039;&lt;br /&gt;
	elseif semicolons &amp;gt; 0 then&lt;br /&gt;
		return &amp;#039;LineString&amp;#039; -- or MultiPoint&lt;br /&gt;
	else&lt;br /&gt;
		return &amp;#039;Point&amp;#039;&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function fetchWikidata(id, snak)&lt;br /&gt;
	-- snak is a table like {&amp;#039;claims&amp;#039;, &amp;#039;P625&amp;#039;, 1, &amp;#039;mainsnak&amp;#039;, &amp;#039;datavalue&amp;#039;, &amp;#039;value&amp;#039;}&lt;br /&gt;
	local value&lt;br /&gt;
	id = mw.text.trim(id)&lt;br /&gt;
	if not string.find(id, &amp;quot;^Q%d+$&amp;quot;) then&lt;br /&gt;
		printError(&amp;#039;ids-invalid&amp;#039;, id)&lt;br /&gt;
	else&lt;br /&gt;
		value = mw.wikibase.getBestStatements(id, snak[2])&lt;br /&gt;
		for i = 3, #snak do&lt;br /&gt;
			if value == nil then break end&lt;br /&gt;
			value = value[snak[i]]&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return value&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Fetch coordinates from Wikidata for a list of comma separated ids&lt;br /&gt;
local function getCoordinatesById(ids)&lt;br /&gt;
	local function roundPrec(num, prec)&lt;br /&gt;
		if prec == nil or prec &amp;lt;= 0 then return num end&lt;br /&gt;
		local sig = 10^math.floor(math.log10(prec)+.5) -- significant figure from sexagesimal precision: 0.00123 -&amp;gt; 0.001&lt;br /&gt;
		return math.floor(num / sig + 0.5) * sig&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	if ids == nil then return end&lt;br /&gt;
	local coord = {}&lt;br /&gt;
	local snak = {&amp;#039;claims&amp;#039;, &amp;#039;P625&amp;#039;, 1, &amp;#039;mainsnak&amp;#039;, &amp;#039;datavalue&amp;#039;, &amp;#039;value&amp;#039;}&lt;br /&gt;
	for idx in mw.text.gsplit(ids, &amp;#039;%s*,%s*&amp;#039;) do&lt;br /&gt;
		local value = fetchWikidata(idx, snak)&lt;br /&gt;
		if value then&lt;br /&gt;
			local prec = value.precision&lt;br /&gt;
			coord[#coord+1] = roundPrec(value.latitude, prec) .. &amp;#039;,&amp;#039; .. roundPrec(value.longitude, prec)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return #coord &amp;gt; 0 and table.concat(coord, &amp;#039;;&amp;#039;) or nil&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function getBoundsById(ids, coordInput)&lt;br /&gt;
	if ids == nil then return {} end&lt;br /&gt;
	local coord = mw.text.split(coordInput, &amp;#039;%s*;%s*&amp;#039;)&lt;br /&gt;
	local id = mw.text.split(ids, &amp;#039;%s*,%s*&amp;#039;)&lt;br /&gt;
	if #coord ~= #id then return {} end&lt;br /&gt;
	local id_parent = nil&lt;br /&gt;
	if #id == 1 then&lt;br /&gt;
		id_parent = fetchWikidata(id[1], {&amp;#039;claims&amp;#039;, &amp;#039;P131&amp;#039;, 1, &amp;#039;mainsnak&amp;#039;, &amp;#039;datavalue&amp;#039;, &amp;#039;value&amp;#039;, &amp;#039;id&amp;#039;})&lt;br /&gt;
		if id_parent ~= nil then&lt;br /&gt;
			id[2] = id_parent -- P131: located in the administrative territorial entity, last try&lt;br /&gt;
			coord[2] = coord[1]&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	local bounds = {}&lt;br /&gt;
	-- try to fetch Wikidata in this order: area, watershed area, population, and finally by administrative entity&lt;br /&gt;
	local snak_area = {&amp;#039;claims&amp;#039;, &amp;#039;P2046&amp;#039;, 1, &amp;#039;mainsnak&amp;#039;, &amp;#039;datavalue&amp;#039;, &amp;#039;value&amp;#039;} -- area and unit&lt;br /&gt;
	local snak_warea = {&amp;#039;claims&amp;#039;, &amp;#039;P2053&amp;#039;, 1, &amp;#039;mainsnak&amp;#039;, &amp;#039;datavalue&amp;#039;, &amp;#039;value&amp;#039;} -- area and unit&lt;br /&gt;
	local snak_pop = {&amp;#039;claims&amp;#039;, &amp;#039;P1082&amp;#039;, 1, &amp;#039;mainsnak&amp;#039;, &amp;#039;datavalue&amp;#039;, &amp;#039;value&amp;#039;} -- population&lt;br /&gt;
	local convert_area = {[&amp;#039;Q712226&amp;#039;] = 1000000, [&amp;#039;Q35852&amp;#039;] = 10000, [&amp;#039;Q232291&amp;#039;] = 2589988.110336, [&amp;#039;Q81292&amp;#039;] = 4046.8564224,&lt;br /&gt;
		[&amp;#039;Q935614&amp;#039;] = 1600, [&amp;#039;Q857027&amp;#039;] = 0.09290304, [&amp;#039;Q21074767&amp;#039;] = 1138100, [&amp;#039;Q25343&amp;#039;] = 1} -- to square metres&lt;br /&gt;
		-- query Wikidata: http://tinyurl.com/j8aez2g&lt;br /&gt;
	for i = 1, #id do&lt;br /&gt;
		if i == 2 and id[2] == id_parent and #bounds &amp;gt; 0 then break end -- only if not found previously&lt;br /&gt;
		local amount, unit, area&lt;br /&gt;
		local value = fetchWikidata(id[i], snak_area) or fetchWikidata(id[i], snak_warea)&lt;br /&gt;
		if value then&lt;br /&gt;
			amount = tonumber(value.amount)&lt;br /&gt;
			unit = string.match(value.unit, &amp;quot;(Q%d+)&amp;quot;)&lt;br /&gt;
			if convert_area[unit] then&lt;br /&gt;
				area = amount * convert_area[unit]&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		if area == nil then&lt;br /&gt;
			value = fetchWikidata(id[i], snak_pop)&lt;br /&gt;
			if value then&lt;br /&gt;
				amount = tonumber(value.amount)&lt;br /&gt;
				-- average density estimated for populated areas: 100; see [[Population density]]&lt;br /&gt;
				area = amount / 100 * 1000000&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		if area then&lt;br /&gt;
			local radius = math.sqrt(area / math.pi) -- approximation with a circle&lt;br /&gt;
			local latlon = mw.text.split(coord[i], &amp;#039;%s*,%s*&amp;#039;)&lt;br /&gt;
			local mxdLat, mxdLon = mxdByLat(latlon[1])&lt;br /&gt;
			bounds[#bounds+1] = {latlon[2] + (radius / mxdLon), latlon[1] + (radius / mxdLat)} -- NE bound, geoJSON format&lt;br /&gt;
			bounds[#bounds+1] = {latlon[2] - (radius / mxdLon), latlon[1] - (radius / mxdLat)} -- SW bound&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return bounds&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function circleToPolygon(center, radius, edges, turn)&lt;br /&gt;
	-- From en:Module:Mapframe, based on https://github.com/gabzim/circle-to-polygon, ISC licence&lt;br /&gt;
	&lt;br /&gt;
	local function offset(cLat, cLon, distance, bearing)&lt;br /&gt;
		local lat1 = math.rad(cLat)&lt;br /&gt;
		local lon1 = math.rad(cLon)&lt;br /&gt;
		local dByR = distance / 6378137 -- distance divided by 6378137 (radius of the earth) wgs84&lt;br /&gt;
		local lat = math.asin(&lt;br /&gt;
			math.sin(lat1) * math.cos(dByR) +&lt;br /&gt;
			math.cos(lat1) * math.sin(dByR) * math.cos(bearing)&lt;br /&gt;
		)&lt;br /&gt;
		local lon = lon1 + math.atan2(&lt;br /&gt;
			math.sin(bearing) * math.sin(dByR) * math.cos(lat1),&lt;br /&gt;
			math.cos(dByR) - math.sin(lat1) * math.sin(lat)&lt;br /&gt;
		)&lt;br /&gt;
		return math.deg(lat) .. &amp;#039;,&amp;#039; .. math.deg(lon)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local coords = mw.text.split(center, &amp;#039;,&amp;#039;, true)&lt;br /&gt;
	local lat = tonumber(coords[1])&lt;br /&gt;
	local long = tonumber(coords[2])&lt;br /&gt;
	edges = edges or 32&lt;br /&gt;
	local move = 2 * math.pi * (turn or 0)&lt;br /&gt;
	local coordinates = {}&lt;br /&gt;
	for i = 0, edges do&lt;br /&gt;
		table.insert(coordinates, offset(lat, long, radius, ((2*math.pi*-i)/edges) + move))&lt;br /&gt;
	end&lt;br /&gt;
	return table.concat(coordinates, &amp;#039;;&amp;#039;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function addCategories(geotype, i)&lt;br /&gt;
	if not mw.title.getCurrentTitle().isContentPage then return end&lt;br /&gt;
	&lt;br /&gt;
	if i &amp;gt; 2 and i18n[&amp;quot;cat-several-features&amp;quot;] ~= &amp;#039;&amp;#039; then&lt;br /&gt;
		cat[&amp;quot;cat-several-features&amp;quot;] = true&lt;br /&gt;
	end&lt;br /&gt;
	if geotype == &amp;quot;LineString&amp;quot; and i18n[&amp;quot;cat-linestring-drawn&amp;quot;] ~= &amp;#039;&amp;#039; then&lt;br /&gt;
		cat[&amp;quot;cat-linestring-drawn&amp;quot;] = true&lt;br /&gt;
	elseif geotype == &amp;quot;Polygon&amp;quot; and i18n[&amp;quot;cat-polygon-drawn&amp;quot;] ~= &amp;#039;&amp;#039; then&lt;br /&gt;
		cat[&amp;quot;cat-polygon-drawn&amp;quot;] = true&lt;br /&gt;
	end&lt;br /&gt;
	return&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Recursively extract coord templates which have a name parameter.&lt;br /&gt;
-- from en:Module:Mapframe&lt;br /&gt;
local function extractCoordTemplates(wikitext)&lt;br /&gt;
	local output = {}&lt;br /&gt;
	local templates = mw.ustring.gmatch(wikitext, &amp;#039;{%b{}}&amp;#039;)&lt;br /&gt;
	local subtemplates = {}&lt;br /&gt;
	for template in templates do&lt;br /&gt;
		local name = mw.ustring.match(template, &amp;#039;{{([^}|]+)&amp;#039;) -- get the template name&lt;br /&gt;
		local nameParam = mw.ustring.match(template, &amp;quot;|%s*name%s*=%s*[^}|]+&amp;quot;)&lt;br /&gt;
		if not nameParam then&lt;br /&gt;
			nameParam = mw.ustring.match(template, &amp;quot;|%s*nom%s*=%s*[^}|]+&amp;quot;)&lt;br /&gt;
		end&lt;br /&gt;
		if mw.ustring.lower(mw.text.trim(name)) == &amp;#039;coord&amp;#039; then&lt;br /&gt;
			if nameParam then table.insert(output, template) end&lt;br /&gt;
		elseif mw.ustring.find(template, &amp;#039;coord&amp;#039;) then&lt;br /&gt;
			local subOutput = extractCoordTemplates(mw.ustring.sub(template, 2))&lt;br /&gt;
			for _, t in pairs(subOutput) do&lt;br /&gt;
				table.insert(output, t)&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	-- ensure coords are not using title display&lt;br /&gt;
	for k, v in pairs(output) do&lt;br /&gt;
		output[k] = mw.ustring.gsub(v, &amp;quot;|%s*display%s*=[^|}]+&amp;quot;, &amp;quot;|display=inline&amp;quot;)&lt;br /&gt;
	end&lt;br /&gt;
	return output&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Gets all named coordiates from a page or a section of a page.&lt;br /&gt;
-- dependency: Module:Transcluder&lt;br /&gt;
local function getNamedCoords(page)&lt;br /&gt;
	local parts = mw.text.split(page or &amp;quot;&amp;quot;, &amp;quot;#&amp;quot;, true)&lt;br /&gt;
	local name = parts[1] == &amp;quot;&amp;quot; and mw.title.getCurrentTitle().prefixedText or parts[1]&lt;br /&gt;
	local section = parts[2]&lt;br /&gt;
	local pageWikitext = require(&amp;#039;Module:Transcluder&amp;#039;).get(section and name..&amp;quot;#&amp;quot;..section or name)&lt;br /&gt;
	local coordTemplates = extractCoordTemplates(pageWikitext)&lt;br /&gt;
	local frame = mw.getCurrentFrame()&lt;br /&gt;
	local sep = &amp;quot;________&amp;quot;&lt;br /&gt;
	local expandedContent = frame:preprocess(table.concat(coordTemplates, sep))&lt;br /&gt;
	local expandedTemplates = mw.text.split(expandedContent, sep)&lt;br /&gt;
	local namedCoords = {}&lt;br /&gt;
	for _, expandedTemplate in pairs(expandedTemplates) do&lt;br /&gt;
		local coord = mw.ustring.match(expandedTemplate, &amp;quot;&amp;lt;span class=\&amp;quot;geo\&amp;quot;&amp;gt;(.-)&amp;lt;/span&amp;gt;&amp;quot;)&lt;br /&gt;
		if coord then&lt;br /&gt;
			coord = mw.ustring.gsub(coord, &amp;quot;;&amp;quot;, &amp;quot;,&amp;quot;)&lt;br /&gt;
			local name = mw.ustring.match(expandedTemplate, &amp;quot;&amp;amp;title=(.-)&amp;lt;span&amp;quot;) or coord&lt;br /&gt;
			name = mw.uri.decode(name)&lt;br /&gt;
			local description = name ~= coord and coord&lt;br /&gt;
			table.insert(namedCoords, {coord=coord, name=name, description=description})&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return namedCoords&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Main function&lt;br /&gt;
local function main(args)&lt;br /&gt;
	local tagname = args.type or &amp;#039;mapframe&amp;#039;&lt;br /&gt;
	if tagname ~= &amp;#039;maplink&amp;#039; and tagname ~= &amp;#039;mapframe&amp;#039; then printError(&amp;#039;type-invalid&amp;#039;, tagname) end&lt;br /&gt;
	&lt;br /&gt;
	local tagArgs = {&lt;br /&gt;
		text = args.text,&lt;br /&gt;
		zoom = tonumber(args.zoom),&lt;br /&gt;
		latitude = tonumber(args.latitude),&lt;br /&gt;
		longitude = tonumber(args.longitude)&lt;br /&gt;
	}&lt;br /&gt;
	local defaultzoom = tonumber(args.default_zoom)&lt;br /&gt;
	if tagname == &amp;#039;mapframe&amp;#039; then&lt;br /&gt;
		tagArgs.width = args.width or 300&lt;br /&gt;
		tagArgs.height = args.height or 300&lt;br /&gt;
		tagArgs.align = args.align or &amp;#039;right&amp;#039;&lt;br /&gt;
		if args.frameless ~= nil and tagArgs.text == nil then tagArgs.frameless = true end&lt;br /&gt;
	else&lt;br /&gt;
		tagArgs.class = args.class&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local wdid = args.item or mw.wikibase.getEntityIdForCurrentPage()&lt;br /&gt;
	&lt;br /&gt;
	if args[&amp;#039;coordinates1&amp;#039;] == nil and args[&amp;#039;geotype1&amp;#039;] == nil then -- single feature&lt;br /&gt;
		args[&amp;#039;coordinates1&amp;#039;] = args[&amp;#039;coordinates&amp;#039;] or args[1]&lt;br /&gt;
		if args[&amp;#039;coordinates1&amp;#039;] == nil and args[&amp;#039;latitude&amp;#039;] and args[&amp;#039;longitude&amp;#039;] then&lt;br /&gt;
			args[&amp;#039;coordinates1&amp;#039;] = args[&amp;#039;latitude&amp;#039;] .. &amp;#039;,&amp;#039; .. args[&amp;#039;longitude&amp;#039;]&lt;br /&gt;
		elseif args[&amp;#039;coordinates1&amp;#039;] == nil then&lt;br /&gt;
			args[&amp;#039;coordinates1&amp;#039;] = getCoordinatesById(wdid)&lt;br /&gt;
		end&lt;br /&gt;
		local par = {&amp;#039;title&amp;#039;, &amp;#039;image&amp;#039;, &amp;#039;description&amp;#039;, &amp;#039;geotype&amp;#039;, &amp;#039;commons&amp;#039;, &amp;#039;radius&amp;#039;, &amp;#039;radiuskm&amp;#039;, &amp;#039;edges&amp;#039;, &amp;#039;turn&amp;#039;, &amp;#039;from&amp;#039;}&lt;br /&gt;
		for _, v in ipairs(par) do&lt;br /&gt;
			args[v .. &amp;#039;1&amp;#039;] = args[v .. &amp;#039;1&amp;#039;] or args[v]&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local externalData = {[&amp;#039;geoshape&amp;#039;] = true, [&amp;#039;geomask&amp;#039;] = true, [&amp;#039;geoline&amp;#039;] = true, [&amp;#039;page&amp;#039;] = true, [&amp;#039;none&amp;#039;] = true, [&amp;#039;named&amp;#039;] = true}&lt;br /&gt;
	local featureCollection = {[&amp;#039;Point&amp;#039;] = true, [&amp;#039;MultiPoint&amp;#039;] = true, [&amp;#039;LineString&amp;#039;] = true, [&amp;#039;Polygon&amp;#039;] = true, [&amp;#039;circle&amp;#039;] = true}&lt;br /&gt;
	local myfeatures, myexternal, allpoints = {}, {}, {}&lt;br /&gt;
	local i, j = 1, 1&lt;br /&gt;
	while args[&amp;#039;coordinates&amp;#039;..i] or args[&amp;#039;ids&amp;#039;..i] or externalData[args[&amp;#039;geotype&amp;#039;..i]] or args[&amp;#039;commons&amp;#039;..i] do&lt;br /&gt;
		local geotypex = args[&amp;#039;geotype&amp;#039;..i] or args[&amp;#039;geotype&amp;#039;]&lt;br /&gt;
		if geotypex == nil and args[&amp;#039;commons&amp;#039;..i] then&lt;br /&gt;
			geotypex = &amp;#039;page&amp;#039;&lt;br /&gt;
		end&lt;br /&gt;
		if geotypex ~= nil and not (featureCollection[geotypex] or externalData[geotypex]) then&lt;br /&gt;
			printError(&amp;#039;geotype-invalid&amp;#039;, geotypex)&lt;br /&gt;
			break&lt;br /&gt;
		end&lt;br /&gt;
		&lt;br /&gt;
		if geotypex == &amp;#039;none&amp;#039; then -- skip this object&lt;br /&gt;
			i = i + 1&lt;br /&gt;
		else&lt;br /&gt;
			local mystack&lt;br /&gt;
			if geotypex == &amp;#039;named&amp;#039; then&lt;br /&gt;
				local namedCoords = getNamedCoords(args[&amp;#039;from&amp;#039;..i])&lt;br /&gt;
				mystack = myfeatures&lt;br /&gt;
				for _, namedCoord in pairs(namedCoords) do&lt;br /&gt;
					j = #mystack + 1&lt;br /&gt;
					mystack[j] = {}&lt;br /&gt;
					mystack[j][&amp;#039;type&amp;#039;] = &amp;quot;Feature&amp;quot;&lt;br /&gt;
					mystack[j][&amp;#039;geometry&amp;#039;] = {}&lt;br /&gt;
					mystack[j][&amp;#039;geometry&amp;#039;][&amp;#039;type&amp;#039;] = &amp;quot;Point&amp;quot;&lt;br /&gt;
					mystack[j][&amp;#039;geometry&amp;#039;][&amp;#039;coordinates&amp;#039;] = parseGeoSequence(namedCoord.coord, &amp;#039;Point&amp;#039;)&lt;br /&gt;
					allpoints = mergePoints(allpoints, mystack[j][&amp;#039;geometry&amp;#039;][&amp;#039;coordinates&amp;#039;])&lt;br /&gt;
					mystack[j][&amp;#039;properties&amp;#039;] = {}&lt;br /&gt;
					mystack[j][&amp;#039;properties&amp;#039;][&amp;#039;title&amp;#039;] = namedCoord.name&lt;br /&gt;
					mystack[j][&amp;#039;properties&amp;#039;][&amp;#039;description&amp;#039;] = namedCoord.description&lt;br /&gt;
					mystack[j][&amp;#039;properties&amp;#039;][&amp;#039;marker-size&amp;#039;] = args[&amp;#039;marker-size&amp;#039;..i] or args[&amp;#039;marker-size&amp;#039;]&lt;br /&gt;
					mystack[j][&amp;#039;properties&amp;#039;][&amp;#039;marker-symbol&amp;#039;] = args[&amp;#039;marker-symbol&amp;#039;..i] or args[&amp;#039;marker-symbol&amp;#039;]&lt;br /&gt;
					mystack[j][&amp;#039;properties&amp;#039;][&amp;#039;marker-color&amp;#039;] = args[&amp;#039;marker-color&amp;#039;..i] or args[&amp;#039;marker-color&amp;#039;]&lt;br /&gt;
				end&lt;br /&gt;
				break&lt;br /&gt;
			elseif externalData[geotypex or &amp;#039;&amp;#039;] then&lt;br /&gt;
				mystack = myexternal&lt;br /&gt;
				j = #mystack + 1&lt;br /&gt;
				mystack[j] = {}&lt;br /&gt;
				mystack[j][&amp;#039;type&amp;#039;] = &amp;quot;ExternalData&amp;quot;&lt;br /&gt;
				mystack[j][&amp;#039;service&amp;#039;] = geotypex&lt;br /&gt;
				if geotypex == &amp;quot;page&amp;quot; then&lt;br /&gt;
					local page_name = args[&amp;#039;commons&amp;#039;..i]&lt;br /&gt;
					if mw.ustring.find(page_name, &amp;quot;Data:&amp;quot;, 1, true) == 1 then&lt;br /&gt;
						page_name = string.sub(page_name, 6)&lt;br /&gt;
					end&lt;br /&gt;
					if mw.ustring.find(page_name, &amp;quot;.map&amp;quot;, -4, true) == nil then&lt;br /&gt;
						page_name = page_name .. &amp;#039;.map&amp;#039;&lt;br /&gt;
					end&lt;br /&gt;
					mystack[j][&amp;#039;title&amp;#039;] = page_name&lt;br /&gt;
				else&lt;br /&gt;
					mystack[j][&amp;#039;ids&amp;#039;] = args[&amp;#039;ids&amp;#039;..i] or args[&amp;#039;ids&amp;#039;] or wdid&lt;br /&gt;
					if mystack[j][&amp;#039;ids&amp;#039;] == nil then printError(&amp;#039;ids-not-found&amp;#039;); break end&lt;br /&gt;
				end&lt;br /&gt;
				local mycoordinates = args[&amp;#039;coordinates&amp;#039;..i]&lt;br /&gt;
				if mycoordinates == nil and (tagArgs.latitude == nil or tagArgs.longitude == nil or tagArgs.zoom == nil) then&lt;br /&gt;
					mycoordinates = getCoordinatesById(mystack[j][&amp;#039;ids&amp;#039;])&lt;br /&gt;
				end&lt;br /&gt;
				if mycoordinates ~= nil then&lt;br /&gt;
					local mypoints = getBoundsById(mystack[j][&amp;#039;ids&amp;#039;], mycoordinates)&lt;br /&gt;
					if #mypoints == 0 then&lt;br /&gt;
						mypoints = parseGeoSequence(mycoordinates, mycoordinates:find(&amp;#039;;&amp;#039;) and &amp;#039;MultiPoint&amp;#039; or &amp;#039;Point&amp;#039;)&lt;br /&gt;
					end&lt;br /&gt;
					allpoints = mergePoints(allpoints, mypoints)&lt;br /&gt;
				end&lt;br /&gt;
			else&lt;br /&gt;
				args[&amp;#039;coordinates&amp;#039;..i] = args[&amp;#039;coordinates&amp;#039;..i] or getCoordinatesById(args[&amp;#039;ids&amp;#039;..i])&lt;br /&gt;
				if geotypex == &amp;#039;circle&amp;#039; then&lt;br /&gt;
					if not args[&amp;#039;radius&amp;#039;..i] and args[&amp;#039;radiuskm&amp;#039;..i] then&lt;br /&gt;
						args[&amp;#039;radius&amp;#039;..i] = args[&amp;#039;radiuskm&amp;#039;..i] * 1000&lt;br /&gt;
					end&lt;br /&gt;
					args[&amp;#039;coordinates&amp;#039;..i] = circleToPolygon(args[&amp;#039;coordinates&amp;#039;..i], args[&amp;#039;radius&amp;#039;..i], args[&amp;#039;edges&amp;#039;..i], args[&amp;#039;turn&amp;#039;..i])&lt;br /&gt;
					geotypex = &amp;#039;Polygon&amp;#039;&lt;br /&gt;
				end&lt;br /&gt;
				mystack = myfeatures&lt;br /&gt;
				j = #mystack + 1&lt;br /&gt;
				mystack[j] = {}&lt;br /&gt;
				mystack[j][&amp;#039;type&amp;#039;] = &amp;quot;Feature&amp;quot;&lt;br /&gt;
				mystack[j][&amp;#039;geometry&amp;#039;] = {}&lt;br /&gt;
				mystack[j][&amp;#039;geometry&amp;#039;][&amp;#039;type&amp;#039;] = geotypex or findGeotype(args[&amp;#039;coordinates&amp;#039;..i])&lt;br /&gt;
				mystack[j][&amp;#039;geometry&amp;#039;][&amp;#039;coordinates&amp;#039;] = parseGeoSequence(args[&amp;#039;coordinates&amp;#039;..i], mystack[j][&amp;#039;geometry&amp;#039;][&amp;#039;type&amp;#039;])&lt;br /&gt;
				allpoints = mergePoints(allpoints, mystack[j][&amp;#039;geometry&amp;#039;][&amp;#039;coordinates&amp;#039;])&lt;br /&gt;
				addCategories(mystack[j][&amp;#039;geometry&amp;#039;][&amp;#039;type&amp;#039;], i)&lt;br /&gt;
			end&lt;br /&gt;
			mystack[j][&amp;#039;properties&amp;#039;] = {}&lt;br /&gt;
			mystack[j][&amp;#039;properties&amp;#039;][&amp;#039;title&amp;#039;] = args[&amp;#039;title&amp;#039;..i] or (geotypex and geotypex .. i) or mystack[j][&amp;#039;geometry&amp;#039;][&amp;#039;type&amp;#039;] .. i&lt;br /&gt;
			if args[&amp;#039;image&amp;#039;..i] then&lt;br /&gt;
				args[&amp;#039;description&amp;#039;..i] = (args[&amp;#039;description&amp;#039;..i] or &amp;#039;&amp;#039;) .. &amp;#039;[[File:&amp;#039; .. args[&amp;#039;image&amp;#039;..i] .. &amp;#039;|300px]]&amp;#039;&lt;br /&gt;
			end&lt;br /&gt;
			mystack[j][&amp;#039;properties&amp;#039;][&amp;#039;description&amp;#039;] = args[&amp;#039;description&amp;#039;..i]&lt;br /&gt;
			mystack[j][&amp;#039;properties&amp;#039;][&amp;#039;marker-size&amp;#039;] = args[&amp;#039;marker-size&amp;#039;..i] or args[&amp;#039;marker-size&amp;#039;]&lt;br /&gt;
			mystack[j][&amp;#039;properties&amp;#039;][&amp;#039;marker-symbol&amp;#039;] = args[&amp;#039;marker-symbol&amp;#039;..i] or args[&amp;#039;marker-symbol&amp;#039;]&lt;br /&gt;
			mystack[j][&amp;#039;properties&amp;#039;][&amp;#039;marker-color&amp;#039;] = args[&amp;#039;marker-color&amp;#039;..i] or args[&amp;#039;marker-color&amp;#039;]&lt;br /&gt;
			mystack[j][&amp;#039;properties&amp;#039;][&amp;#039;stroke&amp;#039;] = args[&amp;#039;stroke&amp;#039;..i] or args[&amp;#039;stroke&amp;#039;]&lt;br /&gt;
			mystack[j][&amp;#039;properties&amp;#039;][&amp;#039;stroke-opacity&amp;#039;] = tonumber(args[&amp;#039;stroke-opacity&amp;#039;..i] or args[&amp;#039;stroke-opacity&amp;#039;])&lt;br /&gt;
			mystack[j][&amp;#039;properties&amp;#039;][&amp;#039;stroke-width&amp;#039;] = tonumber(args[&amp;#039;stroke-width&amp;#039;..i] or args[&amp;#039;stroke-width&amp;#039;])&lt;br /&gt;
			mystack[j][&amp;#039;properties&amp;#039;][&amp;#039;fill&amp;#039;] = args[&amp;#039;fill&amp;#039;..i] or args[&amp;#039;fill&amp;#039;]&lt;br /&gt;
			mystack[j][&amp;#039;properties&amp;#039;][&amp;#039;fill-opacity&amp;#039;] = tonumber(args[&amp;#039;fill-opacity&amp;#039;..i] or args[&amp;#039;fill-opacity&amp;#039;])&lt;br /&gt;
			&lt;br /&gt;
			i = i + 1&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- calculate defaults for static mapframe; maplink is dynamic&lt;br /&gt;
	if (tagArgs.latitude == nil or tagArgs.longitude == nil) and #allpoints &amp;gt; 0 then&lt;br /&gt;
		if tagname == &amp;quot;mapframe&amp;quot; or tagArgs.text == nil then -- coordinates needed for text in maplink&lt;br /&gt;
			tagArgs.longitude, tagArgs.latitude = getCoordCenter(allpoints)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	if tagArgs.zoom == nil then&lt;br /&gt;
		if tagname == &amp;quot;mapframe&amp;quot; then&lt;br /&gt;
			local uniquepoints = setUniquePoints(allpoints)&lt;br /&gt;
			if #uniquepoints == 1 then&lt;br /&gt;
				local coordInput = uniquepoints[1][2] .. &amp;#039;,&amp;#039; .. uniquepoints[1][1]&lt;br /&gt;
				local mybounds = getBoundsById(wdid, coordInput) -- try to fetch by area&lt;br /&gt;
				uniquepoints = mergePoints(uniquepoints, mybounds)&lt;br /&gt;
			end&lt;br /&gt;
			if #uniquepoints &amp;lt;= 1 then&lt;br /&gt;
				tagArgs.zoom = defaultzoom or 9&lt;br /&gt;
			else&lt;br /&gt;
				tagArgs.zoom = getZoom(uniquepoints, tagArgs.height, tagArgs.width)&lt;br /&gt;
			end&lt;br /&gt;
		else&lt;br /&gt;
			tagArgs.zoom = defaultzoom&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local geojson = myexternal&lt;br /&gt;
	if #myfeatures &amp;gt; 0 then&lt;br /&gt;
		geojson[#geojson + 1] = {type = &amp;quot;FeatureCollection&amp;quot;, features = myfeatures}&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	if args.debug ~= nil then&lt;br /&gt;
		local html = mw.text.tag{name = tagname, attrs = tagArgs, content = mw.text.jsonEncode(geojson, mw.text.JSON_PRETTY)}&lt;br /&gt;
		return &amp;#039;syntaxhighlight&amp;#039;, tostring(html) .. &amp;#039; Arguments:&amp;#039; .. mw.text.jsonEncode(args, mw.text.JSON_PRETTY), {lang = &amp;#039;json&amp;#039;}&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	if geojson and #geojson == 0 then&lt;br /&gt;
		errormessage = erromessage or &amp;#039;&amp;#039; -- previous message or void for no map data&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return tagname, geojson and mw.text.jsonEncode(geojson) or &amp;#039;&amp;#039;, tagArgs&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function addCat(cat)&lt;br /&gt;
	local categories = &amp;#039;&amp;#039;&lt;br /&gt;
	&lt;br /&gt;
	for k, v in pairs(cat) do&lt;br /&gt;
		if v then&lt;br /&gt;
			categories = categories .. &amp;#039;[[Category:&amp;#039; .. i18n[k] .. &amp;#039;]]&amp;#039;&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return categories&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function errorMessage(message)&lt;br /&gt;
	if message == &amp;#039;&amp;#039; then -- no map data&lt;br /&gt;
		return&lt;br /&gt;
	else&lt;br /&gt;
		categories = mw.message.new(&amp;#039;Kartographer-broken-category&amp;#039;):inLanguage(mw.language.getContentLanguage().code):plain()&lt;br /&gt;
		return message .. &amp;#039;[[Category:&amp;#039; .. categories .. &amp;#039;]]&amp;#039;&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.tag(frame) -- entry point from invoke&lt;br /&gt;
	local getArgs = require(&amp;#039;Module:Arguments&amp;#039;).getArgs&lt;br /&gt;
	local args = getArgs(frame)&lt;br /&gt;
	local tag, geojson, tagArgs = main(args)&lt;br /&gt;
	&lt;br /&gt;
	if errormessage then return errorMessage(errormessage) end&lt;br /&gt;
	return frame:extensionTag(tag, geojson, tagArgs) .. addCat(cat)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p._tag(args) -- entry point from require&lt;br /&gt;
	local tag, geojson, tagArgs = main(args)&lt;br /&gt;
	if errormessage then return errorMessage(errormessage) end&lt;br /&gt;
	return mw.getCurrentFrame():extensionTag(tag, geojson, tagArgs) .. addCat(cat)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>netxipedia&gt;Leoncastro</name></author>
	</entry>
</feed>