Jump to content

Module:Infobox dim

Permanently protected module
From Wikipedia, the free encyclopedia
This is an old revision of this page, as edited by Hike395 (talk | contribs) at 14:46, 3 October 2024 (implement Template:Infobox dim). The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.

--[[
geohackTypeToScale

Convert from Geohack's scale and dim levels to OSM style zoom levels as used by <maplink>
]]
local function geohackScaleToMapZoom(scale)
	scale = tonumber(scale)
	if not scale or scale <= 0 then return end
	-- Approximation of https://wiki.openstreetmap.org/wiki/Zoom_levels
    -- pixel/m from OSM is exact, so use zoom level 9 and 0.3 mm/pixel
	return math.log(305.748*ppm/scale)/log2 + 9
end

local function geohackDimToScale(dim, units)
	dim = tonumber(dim)
	if not dim or dim <= 0 then return end
	if units and string.lower(units) == 'km' then
		dim = dim*1000
	end
	-- Using 0.3 mm/pixel from https://wiki.openstreetmap.org/wiki/Zoom_levels, and
	-- assuming dim spans a map width of 800px (= 24cm on screen)
	return ppm/800 * dim
end

--[[
geohackTypeToScale

Convert from Geohack's types to Geohack's scale levels
]]
local function geohackTypeToScale(type, population)
	local typeScale = {
		adm1st = 1000000,
		adm2nd = 300000,
		adm3rd = 100000,
		airport = 30000,
		city = 100000,
		country = 10000000,
		edu = 10000,
		event = 50000,
		forest = 50000,
		glacier = 50000,
		isle = 100000,
		landmark = 10000,
		mountain = 100000,
		pass = 10000,
		railwaystation = 10000,
		river = 100000,
		satellite = 10000000,
		waterbody = 100000,
		camera = 10000
	}
	local scale
	if typeScale[type] then
		scale = typeScale[type]
	end
	population = tonumber(population)
	if type == 'city' and population and population > 0 then
		-- assume city is a circle with density of 1000/square kilometer
		-- compute diameter, in meters
		local diam = 35.68*math.sqrt(population)
		-- convert to scale
		scale = geohackDimToScale(diam)
		-- don't zoom in too far
		if scale < 25000 then
			scale = 25000
		end
	end
	return scale
end

local function computeDim(length,width,area)
	if length and width then
		return 0.5*math.max(length,width)
	end
	if length then return 0.5*length end
	if width then return 0.5*width end
	if area then return 0.977*math.sqrt(area) end
end

local function convertDim(args)
	for arg, _ in pairs({'length_mi','length_km','width_mi','width_km',
		'area_mi2','area_km2','area_acre','area_ha'}) do
		args[arg] = tonumber(args[arg])
	end
	local length = args.length_mi and 1.609*args.length_mi or args.length_km
	local width = args.width_mi and 1.609*args.width_mi or args.width_km
	local area = args.area_acre and 0.004047*args.area_acre or 
		args.area_ha and 0.01*args.area_ha or 
		args.area_mi2 and 2.59*args.area_mi2 or args.area_km2
	return computeDim(length, width, area)
end