Modulis:Karte

Vikipēdijas lapa
Dokumentācijas ikona Moduļa dokumentācija[izveidot]
local p = {}

-- kasutamiseks teistest moodulitest
local function dms2dec_convert(instring, dimension)

	if tonumber(instring) then 
		return tonumber(instring) 
	elseif string.find(instring, '/') then
		local args = mw.text.split(instring, '/', true)
		if #args > 4 then
			error('Too many parameters.')
		end	
		local direction = ''
		if instring:match( '[NSEWO]') then
			direction = mw.text.trim(args[#args])
		elseif dimension == 'latitude' then
			direction = 'N'
		elseif dimension == 'longitude' then
			direction = 'E'
		end
		local degrees, minutes, seconds = tonumber(args[1]), tonumber(args[2]) or 0, tonumber(args[3]) or 0
	    
	    local factor
	    if direction == "S" or direction == "W" then
	        factor = -1
	    else
	        factor = 1
	    end
	    
	    local precision = 6
	    
	    local decimal = factor * (degrees+(minutes+seconds/60)/60)
	    return tonumber( string.format( "%." .. precision .. "f", decimal) )
	else
		error('Invalid format.')
	end
end


local function normalise(args)
	local lookup_table = {}
	lookup_table['lat']= 'latitude'
	lookup_table['long'] = 'longitude'
	lookup_table['suum'] = 'zoom'
	lookup_table['laius']= 'width'
	lookup_table['kõrgus'] = 'height'
	lookup_table['tekst'] = 'text'
	lookup_table['kirjeldus'] = 'description'
	lookup_table['pealkiri'] = 'title'
	lookup_table['raamita'] = 'frameless'
	lookup_table['tähis'] = 'symbol'
	lookup_table['värv'] = 'color'
	lookup_table['suurus'] = 'size'
	lookup_table['paksus'] = 'size'
	lookup_table['läbipaistvus'] = 'opacity'
	lookup_table['kontuuri paksus'] = 'size'
	lookup_table['kontuuri värv'] = 'color'
	lookup_table['kontuuri läbipaistvus'] = 'opacity'
	lookup_table['täitevärv'] = 'fill_color'
	lookup_table['täitevärvi läbipaistvus'] = 'fill_opacity'
	lookup_table['kontuur'] = 'contour'
	lookup_table['allikad'] = 'externes'
	lookup_table['päring'] = 'query'
	
	for k, v in pairs(lookup_table) do
		if args[k] ~= nil then
			args[v] = args[k]
		end
	end
	
	return args
end

function p.marker(frame)
	local args = normalise(frame:getParent().args)
	
	if args[1] == nil then --One coordinate is mandatory
		return
	end
	
	local properties = {}
	properties['marker-color'] = args.color == nil and '#555555' or args.color
	properties['marker-size'] = args.size == nil and 'medium' or args.size
	properties['marker-symbol'] = args.symbol == nil and '' or args.symbol
	properties['title'] = args.title == nil and '' or args.title
	properties['description'] = args.description == nil and '' or args.description
	
	local latlng = mw.text.split( args[1], ",", true )
	local geojson = {
            type = "Feature",
            properties = properties,
            geometry = {
                type = "Point",
                coordinates = {
                	dms2dec_convert(latlng[2], 'longitude'), 
                	dms2dec_convert(latlng[1], 'latitude')
                }
            }
        }
    return mw.text.jsonEncode(geojson) .. ','
end

function p.line(frame)
	local args = normalise(frame:getParent().args)
	
	if args[2] == nil then --At least two coordinates are mandatory
		return
	end
	
	local properties = {}
	properties["stroke"] = args.color == nil and '#555555' or args.color
	properties["stroke-width"] = args.size == nil and 2 or tonumber(args.size)
	properties["stroke-opacity"] = args.opacity == nil and 1 or tonumber(args.opacity)
	properties['title'] = args.title == nil and '' or args.title
	properties['description'] = args.description == nil and '' or args.description
	
	local coordinates = {}
	local i = 1
	while args[i] ~= nil do
		local latlng = mw.text.split( args[i], ",", true )
		coordinates[i] = {
        	tonumber(latlng[2]), 
        	tonumber(latlng[1]),
        }
		i = i+1
	end
	
	local geojson = {
            type = "Feature",
            properties = properties,
            geometry = {
                type = "LineString",
                coordinates = coordinates
            }
        }
    return mw.text.jsonEncode(geojson) .. ','
end

function p.polygon(frame)
	local args = normalise(frame:getParent().args)
	
	if args[3] == nil then --At least three coordinates are mandatory
		return
	end
	
	local properties = {}
	properties["stroke"] = args.color == nil and '#555555' or args.color
	properties["stroke-width"] = args.size == nil and 2 or tonumber(args.size)
	properties["stroke-opacity"] = args.opacity == nil and 1 or tonumber(args.opacity)
	properties["fill"] = args.fill_color == nil and '#555555' or args.fill_color
	properties["fill-opacity"] = args.fill_opacity == nil and 0.3 or tonumber(args.fill_opacity)
	properties['title'] = args.title == nil and '' or args.title
	properties['description'] = args.description == nil and '' or args.description
	
	local coordinates = {}
	local i = 1
	while args[i] ~= nil do
		local latlng = mw.text.split( args[i], ",", true )
		coordinates[i] = {
        	tonumber(latlng[2]), 
        	tonumber(latlng[1]),
        }
		i = i+1
	end
	local latlng = mw.text.split( args[1], ",", true )
	coordinates[i] = {
    	tonumber(latlng[2]), 
    	tonumber(latlng[1]),
    }
	
	local geojson = {
            type = "Feature",
            properties = properties,
            geometry = {
                type = "Polygon",
                coordinates = { coordinates }
            }
        }
    return mw.text.jsonEncode(geojson) .. ','
end

function p.query(frame)
	local args = normalise(frame:getParent().args)
	
	local query
	if args[1] ~= nil then
		query = args[1]
	else
		return
	end
	
	local properties = {}
	properties["stroke"] = args.color == nil and '#555555' or args.color
	properties["stroke-width"] = args.size == nil and 2 or tonumber(args.size)
	properties["stroke-opacity"] = args.opacity == nil and 1 or tonumber(args.opacity)
	properties["fill"] = args.fill_color == nil and '#555555' or args.fill_color
	properties["fill-opacity"] = args.fill_opacity == nil and 0.3 or tonumber(args.fill_opacity)
	properties['title'] = args.title == nil and '' or args.title
	properties['description'] = args.description == nil and '' or args.description
	
	local service = "geoshape"
	if args.contour ~= nil then
		service = "geoline"
	end
	
	local geojson = {
		type = "ExternalData",
		service = service,
		query = query,
		properties = properties,
	}
    return mw.text.jsonEncode(geojson) .. ','
end

function p.osm(frame)
	local args = normalise(frame:getParent().args)
	
	local qid
	if args[1] == nil then
		qid = mw.wikibase.getEntityIdForCurrentPage()
	else
		qid = args[1]
	end
	
	local properties = {}
	properties["stroke"] = args.color == nil and '#555555' or args.color
	properties["stroke-width"] = args.size == nil and 2 or tonumber(args.size)
	properties["stroke-opacity"] = args.opacity == nil and 1 or tonumber(args.opacity)
	properties["fill"] = args.fill_color == nil and '#555555' or args.fill_color
	properties["fill-opacity"] = args.fill_opacity == nil and 0.3 or tonumber(args.fill_opacity)
	properties['title'] = args.title == nil and '' or args.title
	properties['description'] = args.description == nil and '' or args.description
	
	local service = "geoshape"
	if args.contour ~= nil then
		service = "geoline"
	end
	
	local geojson = {
		type = "ExternalData",
		service = service,
		ids = qid,
		properties = properties,
	}
    return mw.text.jsonEncode(geojson) .. ','
end

function p.commons(frame)
	local args = normalise(frame:getParent().args)
	
	if args[1] == nil then
		return
	end
	
	local page_name = args[1]
	if mw.ustring.find(page_name, "Data:", 1, true) == 1 then
		page_name = string.sub(page_name, 6)
	end
	if mw.ustring.find(page_name, ".map", -4, true) == nil then
		page_name = page_name .. '.map'
	end
	
	local geojson = {
		type = "ExternalData",
		service = "page",
		title = page_name
	}
    return mw.text.jsonEncode(geojson) .. ','
end

function p.wikidata(frame)
	local args = normalise(frame:getParent().args)
	local qid, longitude, latitude
	
	local properties = {}
	properties['marker-color'] = args.color == nil and '#555555' or args.color
	properties['marker-size'] = args.size == nil and 'medium' or args.size
	properties['marker-symbol'] = args.symbol == nil and '' or args.symbol
	properties['title'] = args.title == nil and '' or args.title
	properties['description'] = args.description == nil and '' or args.description
	
	if args[1] == nil then
		qid = mw.wikibase.getEntityIdForCurrentPage()
	else
		qid = args[1]
	end
	
	local entity = mw.wikibase.getEntity( qid )
	local statements = entity:getBestStatements('P625')
	if (statements[1] and statements[1].mainsnak.snaktype == 'value') then
		longitude = statements[1].mainsnak.datavalue.value.longitude
		latitude = statements[1].mainsnak.datavalue.value.latitude
	end	
	if longitude == nil then
		error('La propriété P625 "coordonnées géographiques" n\'est pas renseigné sur Wikidata')
	end
	geojson = {
		type = "Feature",
		geometry = {
			type = "Point",
			coordinates = {
				longitude, 
				latitude
			}
		},
		properties = properties
	}
	
	return mw.text.jsonEncode(geojson) .. ','
end

function p.tag(frame)
	local args = normalise(frame:getParent().args)
	
	-- Choose the tagname
	local tagname = 'mapframe'
	if args.lien ~= nil then
		tagname = 'maplink'
	end

	-- Manage the basics tag params
	local tagArgs = {
		zoom = args.zoom == nil and args.commons == nil and 14 or tonumber(args.zoom),
		height = args.height == nil and 420 or tonumber(args.height),
		width = args.width == nil and 420 or tonumber(args.width),
		align = args.align == nil and 'right' or args.align,
		text = args.text,
	}
	
	if args.max_lat ~= nil and args.max_long ~= nil and args.min_lat ~= nil and args.min_long ~= nil then
		--date line
		if  tonumber(args.max_long) <  tonumber(args.min_long) and  tonumber(args.max_long) < 0 and  tonumber(args.min_long) > 0 then
			args.max_long = 360 + tonumber(args.max_long)
		end
	
		--portrait view with max_height
		if  args.max_height ~= nil and (tonumber(args.max_lat) - tonumber(args.min_lat)) > 0.7*(tonumber(args.max_long) - tonumber(args.min_long)) then
			tagArgs.height = tonumber(args.max_height)
		end
		local max_diff = (tonumber(args.max_long) - tonumber(args.min_long))
		if  (tonumber(args.max_lat) - tonumber(args.min_lat)) > max_diff then
			max_diff = (tonumber(args.max_lat) - tonumber(args.min_lat))
		end
		if max_diff < 0.36 then
			tagArgs.zoom = 10
		elseif max_diff < 0.73 then
			tagArgs.zoom = 9
		elseif max_diff < 1 then
			tagArgs.zoom = 8
		elseif max_diff < 3.7 then
			tagArgs.zoom = 7
		elseif max_diff < 7 then
			tagArgs.zoom = 6
		elseif max_diff < 13 then
			tagArgs.zoom = 5
		elseif max_diff < 24 then
			tagArgs.zoom = 4
		elseif max_diff < 48 then
			tagArgs.zoom = 3
		elseif max_diff < 80 then
			tagArgs.zoom = 2
		elseif max_diff < 170 then
			tagArgs.zoom = 1
		else
			tagArgs.zoom = 0
		end			
		tagArgs.latitude = tonumber(args.min_lat) + (tonumber(args.max_lat) - tonumber(args.min_lat)) / 2
		tagArgs.longitude = tonumber(args.min_long) + (tonumber(args.max_long) - tonumber(args.min_long)) / 2
		--date line
		if tonumber(tagArgs.longitude) > 180 then
			tagArgs.longitude = tonumber(tagArgs.longitude) - 360
		end		
	elseif args[1] ~= nil and (args.latitude ~= nil or args.longitude ~= nil) then
		error('La ou les valeurs de longitude et/ou de latitude ont été fournis via deux syntaxe différentes. Consultez la documentation du [[Modèle:Carte interactive]] pour obtenir une syntaxe correcte')
	elseif args.latitude ~= nil and args.longitude ~= nil then
		tagArgs.latitude = dms2dec_convert(args.latitude, 'latitude')
		tagArgs.longitude = dms2dec_convert(args.longitude, 'longitude')
	elseif args[1] ~= nil and args[2] ~= nil then
		tagArgs.latitude = dms2dec_convert(args[1], 'latitude')
		tagArgs.longitude = dms2dec_convert(args[2], 'longitude')
	elseif args.commons == nil then --get lat/long from wikidata
		args.wikidata = 'jah'
		-- error('Les paramètres de latitude et/ou de longitude sont absent')
	end
	
	if args.frameless then
		tagArgs.frameless = ''
	end
	
	-- Manage the basics GeoJSON params
	local geojson = {}
	
	if args.commons ~= nil then
		geojson[#geojson+1] = {
			type = "ExternalData",
			service = "page",
			title = args.commons,
		}
	end
	
	if args.marker ~= nil then
		geojson[#geojson+1] = {
			type = "Feature",
			geometry = {
				type = "Point",
				coordinates = {
					tagArgs.longitude, 
					tagArgs.latitude
				}
			},
			properties = {
				title = args.title == nil and '' or args.title,
				description = args.description == nil and '' or args.description,
			}
		}
	end
	
	if args.osm ~= nil then
		local qid
		if args.osm == 'jah' then
			qid = mw.wikibase.getEntityIdForCurrentPage()
		else
			qid = args.osm
		end
		
		local service = "geoshape"
		if args.contour ~= nil then
			service = "geoline"
		end
		
		geojson[#geojson+1] = {
			type = "ExternalData",
			service = service,
			ids = qid,
			properties = {
				title = args.title == nil and '' or args.title,
				description = args.description == nil and '' or args.description,
			}
		}
	end
	
	if args.wikidata ~= nil then
		local qid, longitude, latitude
		if args.wikidata == 'jah' then
			qid = mw.wikibase.getEntityIdForCurrentPage()
		else
			qid = args.wikidata
		end
		local entity = mw.wikibase.getEntity( qid )
		local statements = entity:getBestStatements('P625')
		if (statements[1] and statements[1].mainsnak.snaktype == 'value') then
			longitude = statements[1].mainsnak.datavalue.value.longitude
			latitude = statements[1].mainsnak.datavalue.value.latitude
		end		
		if longitude == nil then
			error('La propriété P625 "coordonnées géographiques" n\'est pas renseigné sur Wikidata')
		end
		geojson[#geojson+1] = {
			type = "Feature",
			geometry = {
				type = "Point",
				coordinates = {
					longitude, 
					latitude
				}
			},
			properties = {
				title = args.title == nil and '' or args.title,
				description = args.description == nil and '' or args.description,
			}
		}
	end
	
	if args.query ~= nil then
		local service = "geoshape"
		if args.contour ~= nil then
			service = "geoline"
		end
		
		geojson[#geojson+1] = {
			type = "ExternalData",
			service = service,
			query = args.query,
			properties = {
				title = args.title == nil and '' or args.title,
				description = args.description == nil and '' or args.description,
			}
		}
	end
	
	--Manage external GeoJSON datas included through models
	if args.objektid ~= nil then
		geojson[#geojson+1] = {
			type = "FeatureCollection",
			features = mw.text.jsonDecode('['..args.objektid..']')
		}
	end
	
	if args.externes ~= nil then
		local externes = mw.text.jsonDecode('['..args.externes..']')
		for k, externe in pairs(externes) do
			geojson[#geojson+1] = externe
		end
	end
	
	return frame:extensionTag(tagname, mw.text.jsonEncode(geojson), tagArgs)
end

return p