Modul:Mapframe

Fra Wikisida.no
Sideversjon per 3. jan. 2025 kl. 11:23 av nb>Haros (Bytter navn på kategorier fra "Artikler ..." til "Sider ..." ettersom dette kan inneholde sider som ikke er artikler)
Hopp til navigering Hopp til søk

Denne modulen benyttes av kartmalen {{Kart}}. Se dokumentasjonssiden til denne malen for bruk og instruksjoner.


local math_mod = require( "Module:Math" )

local useLanguage = {
	["Q17"] = "en",     -- Japan
	["Q79"] = "en",     -- Egypt
	["Q115"] = "en",    -- Etiopia
	["Q148"] = "en",    -- Kina
	["Q230"] = "en",    -- Georgia
	["Q399"] = "en",    -- Armenia
	["Q423"] = "en",    -- Nord-Korea
	["Q424"] = "en",    -- Kambodsja
	["Q668"] = "en",    -- India
	["Q711"] = "en",    -- Mongolia
	["Q794"] = "en",    -- Iran
	["Q796"] = "en",    -- Irak
	["Q801"] = "en",    -- Israel
	["Q810"] = "en",    -- Jordan
	["Q819"] = "en",    -- Laos
	["Q822"] = "en",    -- Libanon
	["Q836"] = "en",    -- Myanmar
	["Q842"] = "en",    -- Oman
	["Q843"] = "en",    -- Pakistan
	["Q846"] = "en",    -- Qatar
	["Q851"] = "en",    -- Saudi-Arabia
	["Q858"] = "en",    -- Syria
	["Q865"] = "en",    -- Republikken Kina - Taiwan
	["Q869"] = "en",    -- Thailand
	["Q878"] = "en",    -- De forente arabiske emirater
	["Q884"] = "en",    -- Sør-Korea
	["Q889"] = "en",    -- Afghanistan
	["Q902"] = "en",    -- Bangladesh
	["Q917"] = "en",    -- Bhutan
	["Q986"] = "en",    -- Eritrea
	["Q23792"] = "en"     -- Palestina
}


local p = {}

local legend = {}
local numLegend = 0
local maxLegend = 5

local bbox = {}
bbox.min = {}
bbox.max = {}
bbox.center = {}
bbox.dist = {}
bbox.txt = {"Koordinater funnet"}

autozoom = {
	{ dist=2000,zoom=3}, 
	{ dist=700,zoom=4}, 
	{ dist=300,zoom=5}, 
	{ dist=150,zoom=6}, 
	{ dist=50,zoom=7}, 
	{ dist=30,zoom=8}, 
	{ dist=10,zoom=9}, 
	{ dist=6,zoom=10}, 
	{ dist=4,zoom=11}, 
}

local function hasLocalCoord()
	local pageWikitext = mw.title.getCurrentTitle():getContent()
	local treff = pageWikitext:match("{{[Kk]oord|[^}]+}}")
	if treff then
		local treffVis = treff:match("vis")
		local treffTittel = treff:match("tittel")
		local treffTekst = treff:match("tekst")
		if treff and treffVis and treffTittel then 
			return treff
		end
	end
	return nil
end

local function lonlat(args)
	local newargs = args
	if not args["lat"] and not args["lon"] then
		if args["breddegrad"] and args["lengdegrad"] then
			newargs["lat"] = tonumber(args["breddegrad"]) or nil
			newargs["lon"] = tonumber(args["lengdegrad"]) or nil
		end
	end
	return newargs
end

local function selectSingleClaim(claims)
	if not claims then
		return nil
	end
	local selectedClaim = nil
	for idx,claim in pairs(claims) do
		if claim.rank == 'preferred' then
			return claim
		end
		if claim.rank == 'normal' then
			if not selectedClaim then
				selectedClaim = claim
			end
		end
	end
	return selectedClaim
end

local function osmLink(entity)
	local osm = ""
	local osmval = entity:getBestStatements("P402")
	if osmval and osmval[1] and osmval[1].mainsnak["datavalue"] then
		local osmid = osmval[1].mainsnak["datavalue"].value or ""
		if osmid and osmid ~= "" then
			--osm = "<br/> vis på [https://www.openstreetmap.org/relation/" .. osmid .. " OSM]"
			osm = "[[Kategori:Sider hvor Wikidata har lenker til OpenStreetMap relation]]"
		end
	end
	return osm
end

local function allOkSnaks(entity,datatype)
	local retur = {}
	if entity.claims then
		for propid,props in pairs(entity.claims) do
			for idx,claim in ipairs(props) do
				if claim.rank == 'preferred' or claim.rank == 'normal' then
					local snak = claim.mainsnak
					if snak.snaktype == "value" and snak.datatype == datatype then
						local sn = {}
						sn.snak = snak
						sn.qu = claim.qualifiers
						table.insert(retur,sn)
					end
				end
			end
		end
	end
	return retur
end

function dump(item)
	return "<pre>" .. mw.text.jsonEncode(item, mw.text.JSON_PRETTY) .. "</pre>"
end


local function addBbox(entity)
	for idx,sn in ipairs(allOkSnaks(entity,"globe-coordinate")) do
		local snak = sn.snak
		local val = snak.datavalue.value
		local qu = sn.qu
		local qutxt = ""
		if qu and qu.P518 then
			qutxt = " P518 " .. mw.wikibase.formatValues(qu.P518)
		end
		if not bbox.min.longitude or bbox.min.longitude > val.longitude then
			bbox.min.longitude = val.longitude
		end
		if not bbox.min.latitude or bbox.min.latitude > val.latitude then
			bbox.min.latitude = val.latitude
		end
		if not bbox.max.longitude or bbox.max.longitude < val.longitude then
			bbox.max.longitude = val.longitude
		end
		if not bbox.max.latitude or bbox.max.latitude < val.latitude then
			bbox.max.latitude = val.latitude
		end
		local txt = snak.property .. " " .. qutxt .. " " .. val.longitude .. " " .. val.latitude
		table.insert(bbox.txt,txt)
	end
	if (bbox.min.longitude) then
		bbox.center.longitude = (bbox.min.longitude + bbox.max.longitude)/2
		bbox.center.latitude = (bbox.min.latitude + bbox.max.latitude)/2
		bbox.dist.longitude = (bbox.max.longitude - bbox.min.longitude)
		bbox.dist.latitude = (bbox.max.latitude - bbox.min.latitude)
		bbox.haversine = HaversineDistance(
			bbox.max.latitude,bbox.max.longitude,
			bbox.min.latitude,bbox.min.longitude)
    end
	return 

end
local function bboxlist(ids)
	for ix,id in ipairs(ids) do
		local entity = mw.wikibase.getEntity(id)
		addBbox(entity)
	end
end

-- From en:Module:Sandbox/Hellknowz/CoordDistance
function HaversineDistance(lat1,lon1,lat2,lon2)

    local radius = 6371 -- km

    local dlat = math.rad(lat2-lat1)
    local dlon = math.rad(lon2-lon1)
    local a = math.sin(dlat/2) * math.sin(dlat/2) + math.cos(math.rad(lat1)) * math.cos(math.rad(lat2)) * math.sin(dlon/2) * math.sin(dlon/2)
    local c = 2 * math.atan2(math.sqrt(a), math.sqrt(1-a))
    return radius * c

end

-- the distances need to be adjusted according to the size of the frame of the map
local function bboxzoom(factor)
	for ix,v in ipairs(autozoom) do
		if bbox.haversine  and v.dist*factor < bbox.haversine then
			return v.zoom
		end
	end
	return 12
end

local function wdCoords(entity)
	local wdlat,wdlon = nil,nil
	local category = ""
	if entity.claims and entity.claims["P625"] then
		local claim = selectSingleClaim(entity.claims["P625"])
		if claim and claim.mainsnak.datavalue then
			local coord = claim.mainsnak.datavalue.value or nil
			wdlat = coord["latitude"] or nil
			wdlon = coord["longitude"] or nil
		end
	end
	if not wdlat then
		if entity.claims and entity.claims["P159"] then
			local claim = selectSingleClaim(entity.claims["P159"])
			if claim and claim.qualifiers then
				local qual = claim.qualifiers["P625"]
				if qual and  qual[1] and qual[1].datavalue then
					local coord = qual[1].datavalue.value or nil
					wdlat = coord["latitude"] or nil
					wdlon = coord["longitude"] or nil
				end
				if wdlat then
					category = "[[Kategori:Sider med koordinater hentet fra P159]]"
				end
			end
		end
	end
	return wdlat,wdlon,category
end


local function wdGeoShape(entity)
	local shape = nil
	if entity.claims and entity.claims["P3896"] then
		local claim = selectSingleClaim(entity.claims["P3896"])
		local value = claim.mainsnak.datavalue.value or nil
		if value then
			local prop = {}
			local shape = {
	       	["type"] = "ExternalData",
			["service"] = "page",
			["title"] =  value,
			["properties"] = prop
		}
		return shape
		end
	end
	return nil
end

local function selectMapLanguage(entity)
	local lang = "local"
	if entity.claims and entity.claims["P17"] then
		local claim = selectSingleClaim(entity.claims["P17"])
		if claim and claim.mainsnak.datavalue then
		    local value = claim.mainsnak.datavalue.value or nil
		    if value then
			    lang = useLanguage[value["id"]] or "local"
			end
		end
	end
	return lang
end

local function mappoint(latitude,longitude,title,description,symbol)
	local point = {}
    point["type"] = "Feature"
    local geo = {}
    geo["type"] = "Point"
	local pos = {}
    geo["coordinates"] = pos
    -- ensure the coordinates are not too long for the geojson
    geo["coordinates"][1] = math_mod._round( longitude, 6 )
    geo["coordinates"][2] = math_mod._round( latitude, 6 )
    local prop = {}
    if title then
    	prop["title"] = title
    end
    if description then
    	prop["description"] = description
    end
    if symbol and title then
		numLegend = numLegend + 1
		prop["marker-symbol"] = tostring(numLegend)
		table.insert(legend,title)
    end
    prop["marker-size"] = "small"
    point["properties"] = prop
    point["geometry"] = geo
    return point
end

local function geoline(id,stroke,title)
	local line = {
		["type"] = "ExternalData",
		["service"] = "geoline",
		["ids"] =  id,
        ['properties'] = {
        	["stroke"] = stroke,
        	["stroke-width"] = 2,
        	["marker-size"] = "small",
        	--["marker-symbol"] = "-letter",
        	["title"] = title
        }
     }
     return line
end

local function geoshape(id,stroke,opacity)
	local line = {
		["type"] = "ExternalData",
		["service"] = "geoshape",
		["ids"] =  id,
        ['properties'] = {
        	["stroke"] = stroke,
        	["stroke-width"] = 2,
        	["fill"] = "#ff0000",
        	["fill-opacity"] = opacity or 0.1
        }
     }
     return line
end

local function geomask(id,stroke,opacity)
	local line = {
		["type"] = "ExternalData",
		["service"] = "geomask",
		["ids"] =  id,
        ['properties'] = {
        	["stroke"] = stroke,
        	["stroke-width"] = 1,
        	["fill-opacity"] = opacity or 0.05
        }
     }
     return line
end

local function showEnt(geojson,id,wdlat,wdlon,artikkel,description,stroke,title,opacity,createLink,method,symbol)
	local text = title
	if createLink and text and link then
		text = "[[" .. artikkel .. "|" .. title .. "]]"
	end
	local shape = nil
	if method == "geoshape" then
		shape = geoshape(id,stroke,opacity)
		table.insert(geojson, shape)
		local line = geoline(id,stroke,title)
		table.insert(geojson, line)
		if wdlat and wdlon then
    		local point = mappoint(wdlat,wdlon,text,description,symbol)
			table.insert(geojson, point)
		end
	elseif method == "geomask" then
		shape = geomask(id,stroke,opacity)
		table.insert(geojson, shape)
	end
	return geojson
end
local function showEntity(geojson,id,entity,stroke,title,opacity,createLink,method,symbol)
	local wdlat,wdlon = wdCoords(entity)
	local text = title  or mw.wikibase.label(id)
	local link = mw.wikibase.sitelink(id)
	if createLink and text and link then
		text = "[[" .. link .. "|" .. text .. "]]"
	end
	local meth = method or "geoshape"
	local bilde = nil
	if entity.claims and entity.claims["P18"] then
		local claim = selectSingleClaim(entity.claims["P18"])
		if claim then
			local snak = claim.mainsnak
			if snak.snaktype == "value" then
   				bilde = snak.datavalue.value or nil
   			end
		end
	end
	local description = nil
	if createLink and bilde then
		description = "[[File:" .. bilde .. "]]"
	end
	geojson = showEnt(geojson,id,wdlat,wdlon,link,description,stroke,text,opacity,createLink,meth,symbol)

	return geojson
end

-- Visualize an entity through boundary, marker with name of entity. geojson updated by showEntity
local function visEntity(geojson,id,stroke,opacity,method,symbol)
	if not id then
		return nil
	end
	local entity = mw.wikibase.getEntity(id)
	if not entity then
		return nil
	end
	return showEntity(geojson,id,entity,stroke,nil,opacity,"createLink",method,symbol)
end

local function getcurrentqids(claims)
	local qids = {}
	for idx,claim in pairs(claims) do
		local qualifiers = claim.qualifiers
		local endtime = nil
		if qualifiers then
			endtime = claim.qualifiers["P582"] or nil
		end
		-- todo: Test on end time simplified. This assumes that all end times are in the past
		if not endtime then
			if claim.mainsnak and claim.mainsnak.datavalue and claim.mainsnak.datavalue.value then
				local qid = claim.mainsnak.datavalue.value['id'] or nil
				if qid then
					table.insert(qids, qid)
				end
			end
		end
	end
	return qids
end

local function visClaims(geojson,claims,stroke,opacity,method,usesymbol)
	local count = 0
	for idx,claim in pairs(claims) do
		local qualifiers = claim.qualifiers
		local endtime = nil
		if qualifiers then
			endtime = claim.qualifiers["P582"] or nil
		end
		-- todo: Test on end time simplified. This assumes that all end times are in the past
		if not endtime then
			local id = claim.mainsnak.datavalue.value['id'] or nil
			local symbol = nil
			if usesymbol and numLegend < 99 then
				symbol = "1"
			end
			visEntity(geojson,id,stroke,opacity,method,symbol)
			count = count+1
			
		end
	end

	return geojson
end

local function includeLocation(geojson,entity)
	if not entity or not entity.claims then
		return geojson
	end
	local claims = entity.claims["P131"] or entity.claims["P276"] or nil
	if not claims then
		return geojson
	end	
	qids = getcurrentqids(claims)
	if #qids>1 then
		bboxlist(qids)
	end
	local stroke = "#888888"
	local opacity = 0.1
	local shape = geomask(qids,stroke,opacity)
	table.insert(geojson, shape)
	return geojson
end

local function includeProp(geojson,entity,prop)
	if not entity or not prop or not entity.claims then
		return nil
	end
	local claims = entity.claims[prop] or nil
	if not claims then
		return nil
	end
	
	local stroke = "#880000"
	local opacity = 0.1
	visClaims(geojson,claims,stroke,opacity,"geoshape","bruk symbol")

	return geojson
end

local function makeLegend()
	local text = ""
	for idx,leg in ipairs(legend) do
		text = text  .. idx .. " = " .. leg .. "<br/>"
	end
	if numLegend>maxLegend then
    	text = string.format([[
				<div class="mw-collapsible mw-collapsed">
					<div class="sentrert">%s nummererte markører</div>
					<div class="mw-collapsible-content">%s</div>
				</div>
			]], numLegend, text)
	end
	if numLegend > 0 then
		text = text .. "[[Kategori:Sider med kart med nummererte markører]]"
	end
	return text
end

local function mapNoWikidata(args,infoboks)
	local geojson = {}
	local zoom = args["zoom"] or 8
	local lat = args["latitude"] or args["lat"]
	local lon = args["longitude"] or args["lon"]
	if not lat or not lon then
		return ""
	end
    local point = mappoint(lat,lon)
	local width = tonumber(args["width"]) or 300
	local height  = tonumber(args["height"]) or width
	local text = args["text"]  or ""
	table.insert(geojson, point)
	local frameargs = {
    		['height'] = height,
    		['width'] = width,
    		['align'] = align
    		}
    if zoom and zoom ~= 'auto' then
    	frameargs['zoom'] = zoom
    	frameargs['latitude'] = lat
    	frameargs['longitude'] = lon
    end
	local linkargs = {
    		['height'] = height,
    		['width'] = width,
    		['align'] = align,
    		['latitude'] = lat,
    		['longitude'] = lon,
    		['zoom'] = zoom or 8
    	}
    local mlink = ''
    local klink = ''
    if infobox then
--    	mlink = '<br/>' .. mw.getCurrentFrame():extensionTag('maplink', mw.text.jsonEncode(geojson), linkargs)
    	klink = '<br/>' .. mw.getCurrentFrame():expandTemplate{title='koord',args = { lat, lon, vis='tekst'} }
    end
   	frameargs['text'] = text .. mlink .. klink
	return  mw.getCurrentFrame():extensionTag('mapframe', mw.text.jsonEncode(geojson), frameargs)

end

local function getIds(args)
	local ids= {}
	local id = args['id'] or args[1] or nil	
	if id == "" then
		id = nil
	end
	if id ~= "" then
		local ida = {}
		for ident in mw.ustring.gmatch(id, 'Q%d+' )  do
			local entity = mw.wikibase.getEntity(ident) or nil
			local id1 = entity.id
			local lab = mw.wikibase.label( id1 )
			if lab then
				ida[lab] = id1
			end
			table.insert(ids,id1)
		end
		for lab,id2 in pairs(ida) do
			--table.insert(ids,id2)
		end
		--ids = mw.text.split( id, ',', true )
		if #ids ~= 1 then
			id = nil
		end
	end
	--local entity = mw.wikibase.getEntity(id) or nil
	--if not id then
	--	if not entity then
	--		return ""
	--	end
	--	id = entity.id
	--	table.insert(ids, id)
	--end
	return ids
end

local function map2(args,infobox,visKoord)
	local id = args['id'] or args[1] or nil
	if id == "" then
		id = nil
	end
	local entity = mw.wikibase.getEntity(id) or nil
	if not id then
		if not entity then
			return ""
		end
		id = entity.id
	end
	local out = args["out"] or nil
	local width = args["width"] or nil
	if width ~= "full" then
		width = tonumber(args["width"]) or 300
	end
	local height  = tonumber(args["height"]) or width
	if height == "full" then
		return ""
	end
	addBbox(entity)
	
	local zoom = args["zoom"] or 8
	local lat = args["latitude"] or args["lat"]
	local lon = args["longitude"] or args["lon"]
	local includeProperty = args["vis egenskap"]  or args["include property"] or nil
	local wdlat,wdlon,coordcat = wdCoords(entity)
	if not lat or not lon then
		lat = wdlat
		lon = wdlon
	end
	local centerLat = lat
	local centerLon = lon
    if not lon or not lat then
    	return "[[Kategori:Sider hvor kartmodul mangler koordinater]]"
    end
	local text = args["text"]  or mw.wikibase.label(id) or ""
	local align = args["align"]  or 'right'
	local lang = selectMapLanguage(entity) 
	
	local geojson = {}
	local stroke = "#ff0000"
	local title = nil
	local opacity = 0.1
	if includeProperty then
		opacity = 0.0
	end
	showEntity(geojson,id,entity,stroke,title,opacity)
	if args['marker'] and lat and lon then
    	local point = mappoint(lat,lon)
		table.insert(geojson, point)
	end
	includeLocation(geojson,entity)
	if includeProperty then
		local props = mw.text.split( includeProperty, ',', true )
		for i,pid in ipairs(props) do
			includeProp(geojson,entity,pid)
		end
	end
	local frameargs = {
    		['height'] = height,
    		['width'] = width,
    		['align'] = align,
    		['lang'] = lang
    	}
	if zoom and zoom == 'auto' then
  	
    	centerLat = bbox.center.latitude
    	centerLon = bbox.center.longitude
    	local factor = width/300
    	zoom = bboxzoom(factor)
    	if visKoord == "debug" then
    		text = text .. " " .. dump(bbox)   -- for debug
    	end
	end
    if zoom and zoom ~= 'auto' then
   	
    	frameargs['zoom'] = zoom
    	frameargs['latitude'] = centerLat
    	frameargs['longitude'] = centerLon
    end
	local linkargs = {
    		['height'] = height,
    		['width'] = width,
    		['align'] = align,
    		['latitude'] = lat,
    		['longitude'] = lon,
    		['zoom'] = zoom or 8,
    		['lang'] = lang
    	}
    if out == "geojson" then
    	return "<pre>" .. mw.text.jsonEncode(geojson, mw.text.JSON_PRETTY) .. "</pre>"
    else
    	local mlink = ''
        local klink = ''
     	if text then
    		if infobox then
    			local koordmal = "[[Kategori:Sider med lokal koord mal til tittelfelt]]"
    			if not hasLocalCoord() then
    				visKoord = "tittel"
    				koordmal = ""
    			end
--    			mlink = '<br/>' .. mw.getCurrentFrame():extensionTag('maplink', mw.text.jsonEncode(geojson), linkargs)
                if visKoord and visKoord == 'tittel' then
    	            klink = '<br/>' .. mw.getCurrentFrame():expandTemplate{title='koord',args = { lat, lon , vis='tekst,tittel'} }
    	        else
    	            klink = '<br/>' .. mw.getCurrentFrame():expandTemplate{title='koord',args = { lat, lon , vis='tekst'} }
    	        end
    			frameargs['frameless'] = 'frameless'
    			return  mw.getCurrentFrame():extensionTag('mapframe', mw.text.jsonEncode(geojson), frameargs) .. '<br/>'
    			.. makeLegend() .. text .. mlink .. klink
    			.. osmLink(entity) .. koordmal .. coordcat
    		end
    		frameargs['text'] = makeLegend() .. text .. mlink .. klink
    	end
	return  mw.getCurrentFrame():extensionTag('mapframe', mw.text.jsonEncode(geojson), frameargs)
	end
--    return "<pre>" .. mw.text.jsonEncode(geojson, mw.text.JSON_PRETTY) .. "</pre>" 
end


local function maptest(args,infobox,visKoord)
	local ids = getIds(args)
	local id = ids[1] or nil
	if id == "" then
		id = nil
	end
	local entity = mw.wikibase.getEntity(id) or nil
	if not id then
		if not entity then
			return ""
		end
		id = entity.id
	end
	local out = args["out"] or nil
	local width = args["width"] or nil
	if width ~= "full" then
		width = tonumber(args["width"]) or 300
	end
	local height  = tonumber(args["height"]) or width
	if height == "full" then
		return ""
	end
	
	for idx,ident in ipairs(ids) do
		local entity = mw.wikibase.getEntity(ident) or nil
		addBbox(entity)
	end
	local zoom = args["zoom"] or 8
	local zoomadd = args["zoomadd"] or 0
	local lat = args["latitude"] or args["lat"]
	local lon = args["longitude"] or args["lon"]
	local includeProperty = args["vis egenskap"]  or args["include property"] or nil
	local wdlat,wdlon,coordcat = wdCoords(entity)
	if not lat or not lon then
		lat = wdlat
		lon = wdlon
	end
	local centerLat = lat
	local centerLon = lon
    if #ids<2 and (not lon or not lat) then
    	return "[[Kategori:Sider hvor kartmodul mangler koordinater]]"
    end
	local text = args["text"]  or mw.wikibase.label(id) or ""
	local align = args["align"]  or 'right'
	local lang = selectMapLanguage(entity) 
	
	local geojson = {}
	local stroke = "#ff0000"
	local title = nil
	local opacity = 0.1
	if includeProperty then
		opacity = 0.0
	end
	for idx,ident in ipairs(ids) do
		local entity = mw.wikibase.getEntity(ident) or nil
		local symbol = nil
		if numLegend < 99 then
				symbol = "1"
			end
		visEntity(geojson,ident,stroke,opacity,"geoshape",symbol)
		--showEntity(geojson,ident,entity,stroke,title,opacity)
	end

	
	if args['marker'] and lat and lon then
    	local point = mappoint(lat,lon)
		table.insert(geojson, point)
	end
	includeLocation(geojson,entity)
	if includeProperty then
		local props = mw.text.split( includeProperty, ',', true )
		for i,pid in ipairs(props) do
			includeProp(geojson,entity,pid)
		end
	end
	local frameargs = {
    		['height'] = height,
    		['width'] = width,
    		['align'] = align,
    		['lang'] = lang
    	}
	if zoom and zoom == 'auto' then
  	
    	centerLat = bbox.center.latitude
    	centerLon = bbox.center.longitude
    	local factor = width/300
    	zoom = tostring(tonumber(bboxzoom(factor))+tonumber(zoomadd))
    	if visKoord == "debug" then
    		text = text .. " " .. dump(bbox)   -- for debug
    	end
	end
    if zoom and zoom ~= 'auto' then
   	
    	frameargs['zoom'] = zoom
    	frameargs['latitude'] = centerLat
    	frameargs['longitude'] = centerLon
    end
	local linkargs = {
    		['height'] = height,
    		['width'] = width,
    		['align'] = align,
    		['latitude'] = lat,
    		['longitude'] = lon,
    		['zoom'] = zoom or 8,
    		['lang'] = lang
    	}
    if out == "geojson" then
    	return "<pre>" .. mw.text.jsonEncode(geojson, mw.text.JSON_PRETTY) .. "</pre>"
    else
    	local mlink = ''
        local klink = ''
     	if text then
    		if infobox then
    			local koordmal = "[[Kategori:Sider med lokal koord mal til tittelfelt]]"
    			if not hasLocalCoord() then
    				visKoord = "tittel"
    				koordmal = ""
    			end
--    			mlink = '<br/>' .. mw.getCurrentFrame():extensionTag('maplink', mw.text.jsonEncode(geojson), linkargs)
                if visKoord and visKoord == 'tittel' then
    	            klink = '<br/>' .. mw.getCurrentFrame():expandTemplate{title='koord',args = { lat, lon , vis='tekst,tittel'} }
    	        else
    	            klink = '<br/>' .. mw.getCurrentFrame():expandTemplate{title='koord',args = { lat, lon , vis='tekst'} }
    	        end
    			frameargs['frameless'] = 'frameless'
    			return  mw.getCurrentFrame():extensionTag('mapframe', mw.text.jsonEncode(geojson), frameargs) .. '<br/>'
    			.. makeLegend() .. text .. mlink .. klink
    			.. osmLink(entity) .. koordmal .. coordcat
    		end
    		frameargs['text'] = text ..  "<br />(test)<br />" ..makeLegend() ..  mlink .. klink
    	end
		return  mw.getCurrentFrame():extensionTag('mapframe', mw.text.jsonEncode(geojson), frameargs)
	end
end

function p.infoboxLocation(frame)
--	return "<pre>" .. mw.text.jsonEncode(frame:getParent().args, mw.text.JSON_PRETTY) .. "</pre>"
    local args = lonlat(mw.getCurrentFrame():getParent().args)
    local argframe = mw.getCurrentFrame().args
    local vis = args["vis"] or argframe["vis"] or ""
    if vis == "nei" then
    	return ""
    end
    args["width"] = args["width"] or argframe["width"] or 300
    local zoom = args["zoom"] or argframe["zoom"] or nil
    if zoom and zoom ~= 'auto' then
	    args["zoom"] = tonumber(args["zoom"]) or tonumber(argframe["zoom"]) or 8
	else 
		if not zoom then
			args["zoom"] = 8
		else
			args["zoom"] = 'auto'
		end
    end
	if not args["vis egenskap"] then
		args["vis egenskap"] = argframe["vis egenskap"] or nil
	end
    args[1] = ""
    args["align"] = "center"
    if argframe["karttest"] == "ja" then
		return maptest(args)
	end

	local maptxt = map2(args,1,vis)
	if not maptxt or maptxt =="" then
		return mapNoWikidata(args,1)
	end
	return maptxt
end

function mapkilde(args)
	local pageWikitext = mw.title.getCurrentTitle():getContent()
	local kartid = args["kartid"] or ""

	local regtxt = "{{[Kk]artlenke|[^}]+}}"
	local txt = kartid

	for kartmal in mw.ustring.gmatch(pageWikitext, regtxt )  do
		local aa = {}
		local xxx = mw.text.split(kartmal, '|', true )
		for j,pkval in ipairs(xxx) do
			local pk = mw.text.split(pkval, '=', true )
		
			aa[pk[1]] = pk[2]
		end
		if aa["kartid"] and mw.ustring.find(aa["kartid"], kartid ) then

		txt = txt .. "<br/>" .. kartmal
		end
	end
	local argmap = {}
	argmap["zoom"] = "auto"
	argmap["id"] = txt
	return maptest(argmap)
--	return nil

	--return txt
end

local regtxtid = "Q%d+"
local regtxtpoint = "Point%(.*%)"
local regtxtlink = "https://no.wikipedia.org/wiki/.*>" -- <https://no.wikipedia.org/wiki/Vikeholmen_fyr>
local regtxtimg = "commons:.*"

local function gsparqlid(txt)
	for ident in mw.ustring.gmatch(txt, regtxtid )  do
		return ident
	end
	return nil
end

local function gsparqltxt(txt,regtxt,lstart,lend)
	if not txt then return nil end
	for ix, txt1 in ipairs(txt )  do
		for txt2 in mw.ustring.gmatch(txt1, regtxt )  do
			local len = mw.ustring.len( txt2 )
			return mw.ustring.sub( txt2, lstart, len-lend )
			--return mw.text.split(p, '[ ,]', false )
		end
	end
	return nil
end

local function gsparqlpos(txt)
	local p = gsparqltxt(txt,regtxtpoint,7,1)
	if P then
		return mw.text.split(p, '[ ,]', false )
	end
	return nil
end

local function gsparqlimg(txt)
	return gsparqltxt(txt,regtxtimg,9,0)
end

local function gsparqlpos2(txt)
	if not txt then return nil end
	for ix, txt1 in ipairs(txt )  do
		for postxt in mw.ustring.gmatch(txt1, regtxtpoint )  do
			local len = mw.ustring.len( postxt )
			local p = mw.ustring.sub( postxt, 7, len-1 )
			return mw.text.split(p, '[ ,]', false )
		end
	end
	return nil
end

local function gsparqllink(txt)
	if not txt then return nil end
	for postxt in mw.ustring.gmatch(txt, regtxtlink )  do
		local len = mw.ustring.len( postxt )
		return mw.ustring.sub( postxt, 31, len-1 )
		--return mw.text.split(p, '[ ,]', false )
	end
	return nil
end

local log = ""

function gsparqlLine(geojson,line,ix)
	local g = {}
	local g2 = {}
	local xxx = mw.text.split(line, '	', true )
	local id = gsparqlid(xxx[1])
	local pos = gsparqlpos2(xxx)
	local link = gsparqllink(line)
	local img = gsparqlimg(xxx) or ""
	if id and pos then
		g["ix"] = ix
		
		g["xxx"] = xxx
		g["id"] = id
		g["name"] = xxx[2]
		local title = xxx[2]
		--title = gsparqllink(line)
		--local link = nil -- mw.wikibase.label(id)
		if title and link then
			title = "[[" .. link .. "|" .. title .. "]]"
		end
		g["pos"] = pos
		local description = nil
		if xxx[3] and (img and img ~= "") then
			local lang = mw.language.getContentLanguage()
			description = lang:ucfirst( xxx[3]) .. "[[File:" .. img .. "]]"
		end
		local artikkel = nil
		local stroke = "#880000"
		local opacity = 0.1
		local symbol = "1"
		log = g
		--local marker = mappoint(tonumber(pos[1]),tonumber(pos[2]),title,bilde,symbol)
		showEnt(geojson,id,tonumber(pos[2]),tonumber(pos[1]),artikkel,description,stroke,title,opacity,true,"geoshape",symbol)
		--table.insert(geojson,marker)
	end
	return geojson
end
function gsparqlLines(geojson,sparql)
	local lines = mw.text.split(sparql, '\n', true )
	for ix,line in ipairs(lines) do
		geojson = gsparqlLine(geojson,line,ix)
	end
	return geojson
end

function mapsparql(args)
	local sparql = 
	--"wd:Q12316978	Vikeholmen fyr	Point(5.27605 59.1408)	commons:Vikaholmen, Karmøy - S-1602U1 114.jpg	<https://no.wikipedia.org/wiki/Vikeholmen_fyr>"--
	args["id"] or "wd:Q281492	Birtevatn	Point(7.94993 59.04772)"

	local geojson = {}
	geojson = gsparqlLines(geojson,sparql)
	if true then
		frameargs = {}
		frameargs["width"] = "600"
		frameargs["height"] = "600"
		frameargs['text'] = makeLegend() --.. text --.. mlink .. klink
	    			return  mw.getCurrentFrame():extensionTag('mapframe', mw.text.jsonEncode(geojson), frameargs) --.. '<br/>'
    		--	.. makeLegend()  -- .. text .. mlink .. klink
    		--	.. osmLink(entity) .. koordmal .. coordcat
	end
	return "<pre>" .. mw.text.jsonEncode(geojson, mw.text.JSON_PRETTY) .. "</pre>"
	.. "<br />" .. "<pre>" .. mw.text.jsonEncode(log, mw.text.JSON_PRETTY) .. "</pre>"
	.. "<br />" .. makeLegend()
end


local function gjsonpos(txt)
	local len = mw.ustring.len(txt)
	local p =  mw.ustring.sub( txt, 7, len-1 )
	return mw.text.split(p, '[ ,]', false )
end

function gsparqlJson(geojson,line,ix)
	local point = line["loc"]
	if false then
		geojson[ix] = point
		return geojson
	end
	local pos = gjsonpos(point)
	local qid = gsparqlid(line["item"])
	local artikkel = nil
	local description = line["itemDescription"]
	local stroke = "#880000"
	local opacity = 0.1
	local symbol = "1"
	local title = line["itemLabel"]
	showEnt(geojson,qid,tonumber(pos[2]),tonumber(pos[1]),artikkel,description,stroke,title,opacity,true,"geoshape",symbol)

	return geojson
end

function mapjson2(json)
	local geojson = {}
	for ix,line in ipairs(json) do
		geojson = gsparqlJson(geojson,line,ix)
	end
	if true then
		frameargs = {}
		frameargs["width"] = "600"
		frameargs["height"] = "600"
		frameargs['text'] = makeLegend() --.. text --.. mlink .. klink
	    			return  mw.getCurrentFrame():extensionTag('mapframe', mw.text.jsonEncode(geojson), frameargs) --.. '<br/>'
    		--	.. makeLegend()  -- .. text .. mlink .. klink
    		--	.. osmLink(entity) .. koordmal .. coordcat
	end
end

function jsonfilter(json,type,val)
	local json2 = {}
	for ix,line in ipairs(json) do
		if line[type] and ( gsparqlid(line[type]) == gsparqlid(val) ) then
			
			table.insert(json2, line)
		end
	end

	return json2
end

function mapjson(args)
	local a = args["json"]
	local b = mw.text.jsonDecode(a)
	local c = {"Q2245","Q2272"}
	local maps = ""
	for ix,cc in ipairs(c) do
		local d = jsonfilter(b,"adm",cc)
		maps = maps .. mapjson2(d)
		legend = {}
		numLegend = 0
	end
	return maps
--	local c = mw.text.decode(a,true)
--	return dump(geojson)
end

function p.map(frame)
--	return "<pre>" .. mw.text.jsonEncode(frame:getParent().args, mw.text.JSON_PRETTY) .. "</pre>"
	local args = mw.getCurrentFrame():getParent().args
	if args["karttest"] == "ja" then
		return maptest(args)
	end
	if args["test"] == "ja" then
		return maptest(args)
	end
	if args["test"] == "test" then
		return mapsparql(args)
	end
	if args["test"] == "kilde" then
		return mapkilde(args)
	end
	if args["test"] == "json" then
		return mapjson(args)
	end

	return map2(args)
end

return p