Modul:Coordinate
Utseende
--local math = require('Module:Math');
local labels = {
['en'] = { north = 'N', south = 'S', west = 'W', east = 'E' },
['nb'] = { north = 'N', south = 'S', west = 'V', east = 'Ø' }
}
local localLanguage = 'nb'
local titleTemplate = '<span style="font-size: small;">' ..
' <span id="coordinates">[[Geografiske koordinater|Koordinater]]: ' ..
' <span class="plainlinks nourlexpansion">' ..
' [//tools.wmflabs.org/geohack/geohack.php?language=no&pagename=%{pageName}s¶ms=%{geohackParams}s <span class="geo-dms" title="Kart, flyfoto og andre ressurser for dette stedet">' ..
' <span class="latitude">%{dmsLatitude}</span>' ..
' <span class="longitude">%{dmsLongitude}</span>' ..
' </span>]' ..
' </span>' ..
' </span>' ..
'</span>';
-------------------------------------------------------------------------------
-- interp
-- Example: interp("${key}s is %{val}7.2f%", {key = "concentration", val = 56.2795} )
-- Source: http://lua-users.org/wiki/StringInterpolation
function interp(s, tab)
return (s:gsub('($%b{})', function(w) return tab[w:sub(3, -2)] or w end))
end
-------------------------------------------------------------------------------
-- Coordinate class
-- Stores a geographic coordinate internally as DMS
-------------------------------------------------------------------------------
local Coordinate = {}
-------------------------------------------------------------------------------
-- Creates a new coordinate object.
-- @param o
--
function Coordinate:new(frame)
local o = {} -- create object
meta = {__index = self} --
setmetatable(o, meta) --
o:init(frame) -- do some initialization
--[[
o.fromWikidata = function(latitude, longitude, precision)
return self:fromWikidata(latitude, longitude, precision)
end
o.formatForTitle = function(frame)
return self:formatForTitle()
end
o.formatForInline = function(frame)
return self:formatForInline()
end
]]
return o
end
-------------------------------------------------------------------------------
-- Initialize the coordinate object
--
function Coordinate:init( frame )
-- store the frame
self.frame = frame
-- We use DMS for internal storage
self.lat = { deg = nil, min = nil, sec = nil, sign = nil }
self.long = { deg = nil, min = nil, sec = nil, sign = nil }
end
function Coordinate:parseDecimal( value, uncertainty )
local o = {}
o.sign = (value < 0 and -1 or 1)
value = math.abs(value)
value = math.floor(value/uncertainty + 1/2) * uncertainty
o.deg = math.floor(value) -- degrees
value = (value - o.deg) * 60
o.min = math.floor(value) -- arcminutes
o.sec = (value - o.min) * 60 -- arcseconds
-- Round off arcseconds
local factor = 1
if (uncertainty < 1/3600.001) then
factor = (1/3600) / uncertainty
end
o.factor = factor -- for debug
o.sec = math.floor(o.sec * factor + 1/2) / factor
if (o.sec >= 60) then
o.sec = o.sec - 60
o.min = o.min + 1
end
if (o.min == 60) then
o.min = 0
o.deg = o.deg + 1
end
-- if uncertainty < 1/60 => format = dms
-- if uncertainty is between 1/3600 and 1/60 => format = dm
-- if uncertainty >= 1, => format = d
-- If uncertainty >= 1/60
if (uncertainty > 1/60.001) then
o.sec = nil
end
-- If uncertainty >= 1
if (uncertainty > 1/1.001) then
o.min = nil
end
return o
end
function Coordinate:fromDecimal( latitude, longitude, precision )
if (precision == nil) then
precision = 1/3600 -- set default precision to one arcsecond (1/3600 degree)
end
self.lat = Coordinate:parseDecimal(latitude, precision)
self.long = Coordinate:parseDecimal(longitude, precision)
--[[
local antal_decimaler = 3
if (prec >= 1e-8) then antal_decimaler = math.max(0,math.floor(-math.log(prec*3600)/math.log(10)+0.5)) end
local format = coordinates.wdprec2dms(frame)
if (format == 'd') then frame.args = {latd .. "", latNS, longd .. "", longEW, display=disp, 'region:'..reg..'_type:'..type..'_source:Wikidata'} end
if (format == 'dm') then frame.args = {latd .. "", latm .. "", latNS, longd .. "", longm .. "", longEW, display=disp, 'region:'..reg..'_type:'..type..'_source:Wikidata'} end
if (format == 'dms') then frame.args = {latd .. "", latm .. "", string.format('%2.'..antal_decimaler..'f',lats) .. "",latNS, longd .. "", longm .. "",string.format('%2.'..antal_decimaler..'f',longs) .. "",longEW, display=disp, 'region:'..reg..'_type:'..type..'_source:Wikidata'} end
return coordinates.local_coord(frame)
]]
end
-------------------------------------------------------------------------------
-- Returns a single coordinate direction formatted as DMS
--
function Coordinate:formatAsDms(value, direction)
return value.deg .. '°' ..
(value.min and value.min .. '′' or '') ..
(value.sec and value.sec .. '″' or '') ..
(direction == 'latitude'
and (value.sign < 0 and labels[localLanguage].south or labels[localLanguage].north)
or (value.sign < 0 and labels[localLanguage].west or labels[localLanguage].east)
)
end
-------------------------------------------------------------------------------
-- Returns the geohack URL params
--
function Coordinate:geohackParams(lat, long)
return lat.deg ..
(lat.min and '_' .. lat.min or '') ..
(lat.sec and '_' .. lat.sec or '') ..
'_' .. (lat.sign < 0 and labels.en.south or labels.en.north) ..
'_' .. long.deg ..
(long.min and '_' .. long.min or '') ..
(long.sec and '_' .. long.sec or '') ..
'_' .. (long.sign < 0 and labels.en.west or labels.en.east)
end
-------------------------------------------------------------------------------
-- Returns the coordinate formatted for 'title' use
--
function Coordinate:formatForTitle()
return interp(titleTemplate, {
pageName = 'dummy',
geohackParams = self:geohackParams(self.lat, self.long),
dmsLatitude = self:formatAsDms(self.lat, 'latitude'),
dmsLongitude = self:formatAsDms(self.long, 'longitude')
})
end
return Coordinate