Hoppa till innehållet

Modul:Vatten OSM

Från Wikipedia

Dokumentation [visa] [redigera] [historik] [rensa sidcachen]


Detta är en modul för att visa vattendrag på OpenStreetMap-kartor baserat på Wikidata.

För att ett vattendrag ska visas krävs 1) att det finns en "relation" för vattendraget på OpenStreetMap samt 2) att den relationen har ett angivit Wikidata-id. För mer information vad ovanstående innebär se Wikipedia:Kartor och den information som länkas därifrån.

Hur modellen fungerar

[redigera wikitext]

Modulen

Användbara parametrar (som sätts för varje artikel)

[redigera wikitext]
  • deny: lista på wikidataobjekt som modulen ska ignorera. Det kan t.ex. gälla kanaler som annars risker att koppla samman vattendrag som inte naturligt hör samman (och därigenom skapa biflöden som inte finns).
  • basin: om vattendragets avrinningsområde ska visas (om en karta för det finns inlagd)
  • lakes: om sjöar ska visas
  • maxlevel: hur många "nivåer" av biflöden som modulen ska visa. Om den inte är satt visas alla biflöden och deras biflöden rekursivt. Om den är satt till 1 visas bara biflöden, är den satt till 2 visas även biflöden till biflöden o.s.v. I vissa fall (eller om flera kartor visas) kan det finnas så många biflöden och/eller sjöar inlagda att programvaran inte klarar av att visa alla. I det fallet är det motiverat att sätta en maxnivå.
  • zoom: zoom-nivå för kartan. Normalt behöver detta inte fyllas i då programvaran som visar kartor på Wikipedia sköter det automatiskt (så att allt visas på bild och fyller ut bilden så bra som möjligt), men i vissa fall kan det vara praktiskt att sätta den själv (för att t.ex. bara visa en del av ett objekt).
  • longitude: sätt longitud för kartans centrum, som för zoom behöver du vanligen inte sätta denna
  • latitude: sätt latitud för kartans centrum, som för zoom behöver du vanligen inte sätta denna
  • align: sätt justering för kartan

Inställningar (som är gemensamma för alla artiklar för en viss språkversion av Wikipedia

[redigera wikitext]

I början av modulen finns ett antal inställningar (raderna som börjar med "settings"), dessa är:

  • settings.width: bredden på kartan
  • settings.height: höjden på kartan
  • settings.paths.width.main: tjockleken på linjen för (huvud)vattendraget
  • settings.paths.width.tributary: tjockleken på linjen för biflöden
  • settings.paths.colour.main: färg på linjen för (huvud)vattendraget
  • settings.paths.colour.tributary: färg på linjen för biflöden
  • settings.areas.width: tjockleken på linjen runt sjöar
local wd = require( 'Modul:Referenshantering' )

p={}

localisation={}
localisation.txtTributary='med biflöden '
localisation.templates={}
localisation.templates.txtColour='Färg'
localisation.templates.txtMap='maplink'
localisation.arguments={}
localisation.arguments.frame={}
localisation.arguments.frame.text='ram'
localisation.arguments.frame.width='rambredd'
localisation.arguments.frame.height='ramhöjd'
localisation.arguments.line={}
localisation.arguments.line.text='linje'
localisation.arguments.line.colour='linjefärg'
localisation.arguments.line.width='linjetjocklek'
localisation.arguments.form={}
localisation.arguments.form.text='form'
localisation.arguments.form.colour=localisation.arguments.line.colour
localisation.arguments.form.width=localisation.arguments.line.width
localisation.arguments._type='typ'
localisation.arguments._title='titel'
localisation.arguments._raw='rå'

localisation.arguments.zoom='zoom'
localisation.arguments.from='från'
localisation.txtYes='ja'

settings={}
settings.width=250
settings.height=250
settings.paths={}
settings.paths.width={}
settings.paths.width.main=5
settings.paths.width.tributary=1
settings.paths.width.tributary_secondary=1
settings.paths.colour={}
settings.paths.colour.main='#000080' --'#9090FF'
settings.paths.colour.tributary='#000080'
settings.paths.colour.tributary_secondary='#000080'
settings.areas={}
settings.areas.width=1

local iRiver=1
local myArgs={};
local iCounter=1
local denylist={}
local allrivers={}
local allakes={}

local riverdatabase={}
local basinsdatabase={}
local lakedatabase={}

local denyassource={Q46831=true,Q3958626=true,Q3777462=true,Q2074737=true} 
-- bergskedje, alpine section, alpine group, kommun i Spanien

function bHasArgument(args,txtName)
	    -- Check for the presence of 'hydropower'
    for _, arg in pairs(args) do
        if arg == txtName then
            -- Do something if 'hydropower' is found
            return true
        end
    end
    return false
end

p.addQueriedLocations=function (qid,iInstanceOf,txtIcon,txtIconSize,txtIconColour)
  txtQuery="SELECT DISTINCT ?id ?geo ?idLabel (concat('[[',?idLabel,']]') as ?title) WHERE { ?id wdt:P31 ?type;  wdt:P625 ?geo. SERVICE wikibase:label { bd:serviceParam wikibase:language 'sv, en'. ?id rdfs:label ?idLabel. ?type rdfs:label ?typeLabel. } ?id wdt:P206 wd:" .. qid .. ". ?id wdt:P31 wd:" .. iInstanceOf .. "}"
  return p.addContent ("{" .. p.addArgument("type","ExternalData")  .. " ," .. p.addArgument("service","geopoint")  .. " ," ..p.addArgument("query",txtQuery)  .. " , \"properties\":{"..p.addArgument("marker-size",txtIconSize)  .. " ," .. p.addArgument("marker-color",txtIconColour) .. " ," .. p.addArgument("marker-symbol",txtIcon) .. "} }"	)
end

p.addQueriedAreas=function (qid,iInstanceOf,iWidth,txtColour,fOpacity)
  txtQuery="SELECT DISTINCT ?id ?geo ?idLabel (concat('[[',?idLabel,']]') as ?title) ('" .. txtColour .. "' as ?fill) WHERE { ?id wdt:P31 ?type;  wdt:P625 ?geo. SERVICE wikibase:label { bd:serviceParam wikibase:language 'sv, en'. ?id rdfs:label ?idLabel. ?type rdfs:label ?typeLabel. } ?id wdt:P206 wd:" .. qid .. ". ?id wdt:P31 wd:" .. iInstanceOf .. "}"
  return p.addContent ("{" .. p.addArgument("type","ExternalData")  .. " ," .. p.addArgument("service","geoshape")  .. " ," ..p.addArgument("query",txtQuery)  .. " , \"properties\":{"..p.addArgumentNoQuote("stroke-width",iWidth)  .. " ," .. p.addArgument("stroke",txtColour) .. " ," .. p.addArgumentNoQuote("fill-opacity",fOpacity) .. "} }"	)
end

p.addNatureReserves=function (qid)
	return p.addQueriedAreas(qid,"Q179049",1,"#008000",0.2)
end

p.addHydropower=function (qid)
	return p.addQueriedLocations(qid,"Q15911738","dam","small","#0000AA")
end

p.addBattles=function (qid)
	return p.addQueriedLocations(qid,"Q178561","historic","small","#8B4513")
end

p.addTowns=function (qid)
	return p.addQueriedLocations(qid,"Q515","city","small","#800000") ..  p.addQueriedLocations(qid,"Q3957","city","small","#800000")
end

p.addVillages=function (qid)
	return p.addQueriedLocations(qid,"Q532","home","small","#008000")
end

p.data=function(frame,bTributaries)
	many=false
	if (frame.args['id']) then
		if (string.find(frame.args['id'], ",")) then
			mw.log("hittat")
			mw.log(frame.args['id'])
			ids=p.split(frame.args['id'],",")
			many=true
			else
			mw.log("ensam")
			id=frame.args['id']
			end
		else
		id=mw.wikibase.getEntityIdForCurrentPage()
	end
	if (frame.args['deny']) then
		denylist=p.split(frame.args['deny'],",")
		end
	if (frame.args['basin']) then
		bBasin=frame.args['basin'] == "true"
		else
		bBasin=true
	end
	if (frame.args['lakes']) then
		bLakes=frame.args['lakes'] == "true"
		else
		bLakes=true
	end
	if (bTributaries==nil) then
		bTributaries=true		-- Default value
		end
	if (many) then
		for key, value in pairs( ids ) do
			p.addRiver(key,0,bTributaries)
		end
		else
			p.addRiver(id,0,bTributaries)
		end
	return tprint(riverdatabase) .. tprint(lakedatabase) .. tprint(denylist)
end

p.show=function (frame)
	myArgs={}
	if (frame.args['height']) then
		iHeight=frame.args['height']
		else
		iHeight=250
		end
	if (frame.args['width']) then
		iWidth=frame.args['width']
		else
		iWidth=250
		end
	if (frame.args['maxlevel']) then
		bHasMaxLevel=true
		iMaxLevel=tonumber(frame.args['maxlevel'])
		else
		bHasMaxLevel=false
		end
	if (frame.args['zoom']) then
		myArgs['zoom']=frame.args['zoom']
	end
	if (frame.args['longitude']) then
		myArgs['longitude']=frame.args['longitude']
	end
	if (frame.args['latitude']) then
		myArgs['latitude']=frame.args['latitude']
	end
	if (frame.args['align']) then
		myArgs['align']=frame.args['align']
	end
	if (frame.args['zoom']) then
		myArgs['zoom']=frame.args['zoom']
	end
	if (frame.args['tributaries']) then
		bTributaries=frame.args['tributaries'] == "true"
		else
		bTributaries=true
	end
	p.data(frame,bTributaries)
	p.iItems=0
	
	myArgs['height']=iHeight
	myArgs['width']=iWidth

	local txtContent=''
	for key, valueRiver in pairs( riverdatabase ) do
		if (valueRiver.level==0) then
			iThickness=settings.paths.width.main
			end
		if (valueRiver.level==1) then
			iThickness=settings.paths.width.tributary
			end
		if (valueRiver.level>1) then
			iThickness=settings.paths.width.tributary_secondary
			end
		txtContent=	txtContent..p.addLineWD(valueRiver.id,settings.paths.colour.tributary_secondary,iThickness,valueRiver.name)
		if (bHasArgument(frame.args,'hydropower') or bHasArgument(frame.args,'all')) then
			txtContent=txtContent .. p.addHydropower(valueRiver.id)
			end
		if (bHasArgument(frame.args,'battles') or bHasArgument(frame.args,'all')) then
			txtContent=txtContent .. p.addBattles(valueRiver.id)
			end
		if (bHasArgument(frame.args,'towns') or bHasArgument(frame.args,'all')) then
			txtContent=txtContent .. p.addTowns(valueRiver.id)
			end
		if (bHasArgument(frame.args,'villages') or bHasArgument(frame.args,'all')) then
			txtContent=txtContent .. p.addVillages(valueRiver.id)
			end
		if (bHasArgument(frame.args,'naturereserves') or bHasArgument(frame.args,'all')) then
			txtContent=txtContent .. p.addNatureReserves(valueRiver.id)
			end
	end			
	if (bLakes) then
		for keyLake, valueLake in pairs( lakedatabase ) do
			txtContent=	txtContent..p.addAreaWD(valueLake.id,settings.paths.colour.main,settings.areas.width,valueLake.name)
		end
	end

	if (bBasin) then
		for keyBasin, valueBasin in pairs( basinsdatabase ) do
			txtContent=txtContent .. p.addAreaCommons(keyBasin,"#FFFF00","10","0.1")
			end
	end

	if (frame.args['inverse']) then
		txtContent=txtContent .. p.addInverse(frame.args['inverse'],'#FFFFFF',1,'#000000',0.9,3)
	end

	if (txtContent) then
		txtContent="["..txtContent.."]"
		end

	return frame:extensionTag{ name = 'mapframe', content = txtContent, args = myArgs }
end

p.addArgument=function(txtLabel,txtValue)
	if (txtValue) then return "\"" .. txtLabel .. "\"" .. ":" ..  "\"" .. txtValue .. "\""  end
end

p.addArgumentNoQuote=function(txtLabel,txtValue)
	return "\"" .. txtLabel .. "\"" .. ":" ..   txtValue 
end

p.addContent=function(txt)
	if (p.iItems>0) then
		txtConnect=","
		else
		txtConnect=" "
	end
	p.iItems=p.iItems+1
	return txtConnect .. txt	
end

p.addLineWD=function(qid,txtColour,iWidth,txtTitle)
  return p.addContent ("{" .. p.addArgument("type","ExternalData")  .. " ," .. p.addArgument("service","geoline")  .. " ," ..p.addArgument("ids",qid)  .. " , \"properties\":{"..p.addArgument("title",txtTitle)  .. " ," .. p.addArgument("stroke",txtColour)  .. " ," .. p.addArgumentNoQuote("stroke-width",iWidth) .. "} }"	)
end

p.addAreaWD=function(qid,txtColour,iWidth,txtTitle)
	if (txtTitle) then
		return p.addContent ("{" .. p.addArgument("type","ExternalData")  .. " ," .. p.addArgument("service","geoshape")  .. " ," ..p.addArgument("ids",qid)  .. " , \"properties\":{"..p.addArgument("title",txtTitle)  .. " ," .. p.addArgument("stroke",txtColour)  .. " ," .. p.addArgumentNoQuote("stroke-width",iWidth) .. "} }")	
		else
		return p.addContent ("{" .. p.addArgument("type","ExternalData")  .. " ," .. p.addArgument("service","geoshape")  .. " ," ..p.addArgument("ids",qid)  .. " , \"properties\":{"..p.addArgument("stroke",txtColour)  .. " ," .. p.addArgumentNoQuote("stroke-width",iWidth) .. "} }")	
		end
	
end

p.addAreaCommons=function(txtFilename,txtColour,iWidth,fOpacity)
	return p.addContent("{" .. p.addArgument("type","ExternalData")  .. " ," .. p.addArgument("service","page")  .. " ," ..p.addArgument("title",txtFilename)  .. " , \"properties\":{"..p.addArgument("stroke",txtColour)  .. " ," .. p.addArgumentNoQuote("stroke-width",iWidth)  .. " ," ..p.addArgumentNoQuote("fill-opacity",fOpacity) .. "} }")
end

p.addLineWD=function(qid,txtColour,iWidth,txtTitle)
	if (txtTitle) then
		return p.addContent ("{" .. p.addArgument("type","ExternalData")  .. " ," .. p.addArgument("service","geoline")  .. " ," ..p.addArgument("ids",qid)  .. " , \"properties\":{"..p.addArgument("title",txtTitle)  .. " ," .. p.addArgument("stroke",txtColour)  .. " ," .. p.addArgumentNoQuote("stroke-width",iWidth) .. "} }"	)
		else
		return p.addContent ("{" .. p.addArgument("type","ExternalData")  .. " ," .. p.addArgument("service","geoline")  .. " ," ..p.addArgument("ids",qid)  .. " , \"properties\":{"..p.addArgument("stroke",txtColour)  .. " ," .. p.addArgumentNoQuote("stroke-width",iWidth) .. "} }"	)
		end
end

p.addInverse=function(qid,txtFillColour,fFillOpacity,txtStrokeColour,fStrokeOpacity,iWidth)
	return p.addContent ("{" .. p.addArgument("type","ExternalData")  .. " ," .. p.addArgument("service","geomask")  .. " ," ..p.addArgument("ids",qid)  .. " , \"properties\":{"..p.addArgument("fill",txtFillColour)  .. " ," .. p.addArgumentNoQuote("fill-opacity",fFillOpacity) .. " ," .. p.addArgument("stroke",txtStrokeColour)  .. " ," .. p.addArgumentNoQuote("stroke-opacitity",fStrokeOpacity) .. " ," .. p.addArgumentNoQuote("stroke-width",iWidth) ..  "} }"	)
end

p.show2=function (frame)
	return p.show(frame)
end

p.addLake=function(qid,iLevel)
	if (qid and ((not bHasMaxLevel) or (iLevel<=iMaxLevel)) and (not denylist[qid]) and p.isAllowed(qid)) then
		if not allakes[qid] then
			local item={}
			item.id=qid
			item.name=mw.wikibase.getLabel(qid)
			table.insert(lakedatabase,item)
			allakes[qid]=true
			local entityTributary=mw.wikibase.getBestStatements(qid, 'P200' )	
			for key, value in pairs( entityTributary ) do
				local qidTributary=read(value,'id')
				if (p.isLake(qidTributary)) then
					p.addLake(qidTributary,iLevel)
					else
					p.addRiver(qidTributary,iLevel+1,true)
					end
			end
			local entityPart=mw.wikibase.getBestStatements(qid, 'P527' )	
			for key, value in pairs( entityPart ) do
				qidPart=read(value,'id')
				if (p.isLake(qidPart)) then
					p.addLake(qidPart,iLevel)
					end
			end
			local entityBorders=mw.wikibase.getBestStatements(qid, 'P47' )	
			for key, value in pairs( entityBorders ) do
				qidBorder=read(value,'id')
				if (p.isLake(qidBorder)) then
					p.addLake(qidBorder,iLevel)
					end
			end
		end
	end
end

p.isAllowed=function(qid)
	local entity=mw.wikibase.getBestStatements(qid, 'P31' )	
	for key, value in pairs( entity ) do
		id=read(value,'id')
		if (denyassource[id]) then
			return false
		end
	end
	return true
end	

p.isLake=function(qid)
	if (not qid) then return false end
	local entity=mw.wikibase.getBestStatements(qid, 'P31' )	
	for key, value in pairs( entity ) do
		id=read(value,'id')
		if (id=='Q23397') or (id=='Q104093746') then
			return true
		end
	end
	return false
end

p.addRiver=function(qid,iLevel,bTributaries)
	local level=iLevel
	if qid and ((not allrivers[qid]) and ((not bHasMaxLevel) or (iLevel<=iMaxLevel)) and (not denylist[qid])) then
		local item={}
		item.id=qid
		item.level=level
		item.name=mw.wikibase.getLabel(qid)
		table.insert(riverdatabase,item)
		allrivers[qid]=true
		if (bTributaries) then
		-- Tributaries directly from the river
			local entityTributary=mw.wikibase.getBestStatements(qid, 'P974' )	
			local id
			for key, value in pairs( entityTributary ) do
				id=read(value,'id')
				if not allrivers[id] then
					tblRiver=p.addRiver(id,level+1,bTributaries)
					end
			end
			if (bLakes) then
				-- Tributaries via the river's source (assuming it is a lake)
				local entitySources=mw.wikibase.getBestStatements(qid, 'P885' )	
				for keyLake, valueLake in pairs( entitySources ) do
					local id=read(valueLake,'id')
					if (p.isLake(id)) then
						p.addLake(id,level)
						end
				end
				-- Tributaries via lakes the river pass by
				local entityLakes=mw.wikibase.getBestStatements(qid, 'P469' )	
				for keyLake, valueLake in pairs( entityLakes ) do
					local iLake=read(valueLake,'id')
					p.addLake(iLake,level)
				end
			end		
		end
		
		if (bBasin) then
			iBasin=readFirstStatementId(qid,'P4614')
			if (iBasin) then
				statements=mw.wikibase.getBestStatements(iBasin,'P3896')
				if not(next(statements)==nil) then
					if not(statements[1]==nil) then
						local txtBasin=statements[1].mainsnak.datavalue.value
						local newtxt=txtBasin:gsub("^Data:%s*", "")
						if not(basinsdatabase[newtxt]) then basinsdatabase[newtxt]=true end
	--					table.insert(basinsdatabase,newtxt)
					end
				end
			end
		end
	end
end

--[=====[ 
--]=====]


-- Funktion från https://stackoverflow.com/questions/41942289/display-contents-of-tables-in-lua
function tprint (tbl, indent)
  if not indent then indent = 0 end
  local toprint = string.rep(" ", indent) .. "{\r\n"
  indent = indent + 2 
  for k, v in pairs(tbl) do
    toprint = toprint .. string.rep(" ", indent)
    if (type(k) == "number") then
      toprint = toprint .. "[" .. k .. "] = "
    elseif (type(k) == "string") then
      toprint = toprint  .. k ..  "= "   
    end
    if (type(v) == "number") then
      toprint = toprint .. v .. ",\r\n"
    elseif (type(v) == "string") then
      toprint = toprint .. "\"" .. v .. "\",\r\n"
    elseif (type(v) == "table") then
      toprint = toprint .. tprint(v, indent + 2) .. ",\r\n"
    else
      toprint = toprint .. "\"" .. tostring(v) .. "\",\r\n"
    end
  end
  toprint = toprint .. string.rep(" ", indent-2) .. "}"
  return toprint
end

-- Function to split a string by a delimiter (by chatgpt)
p.split=function(inputStr, delimiter)
    local result = {}
    for match in (inputStr .. delimiter):gmatch("(.-)" .. delimiter) do
--        table.insert(result, match)
		result[match]=true      
    end
    return result
end

return p