વિભાગ:Coordinates: આવૃત્તિઓ વચ્ચેનો તફાવત

Content deleted Content added
નાનુંNo edit summary
major update to add support for new OSM maps and maintenance categories for comparing coordinates to Wikidata (attempt #2)
લીટી ૧૨:
 
Functions:
*function coordinatesp.LocationTemplateCore(frame)
**function coordinatesp.GeoHack_link(frame)
***function coordinatesp.lat_lon(frame)
****function coordinatesp._deg2dms(deg,lang)
***function coordinatesp.externalLink(frame)
****function coordinatesp._externalLink(site, globe, latStr, lonStr, lang, attributes)
**function coordinatesp._getHeading(attributes)
**function coordinatesp.externalLinksSection(frame)
***function coordinatesp._externalLink(site, globe, latStr, lonStr, lang, attributes)
*function coordinatesp.getHeading(frame)
*function coordinatesp.deg2dms(frame)
 
]]
 
coordinates = {};
 
-- =======================================
Line ૩૨ ⟶ ૩૦:
-- =======================================
local i18n = require('Module:I18n/coordinates') -- get localized translations of site names
local Fallback = require('Module:Fallback') -- get fallback functions
local yesno = require('Module:Yesno')
 
Line ૭૩ ⟶ ૭૦:
NNW = 337.5,
NBW = 348.75,
}
 
-- files to use for different headings
local heading_icon = {
[ 1] = 'File:Compass-icon bb N.svg',
[ 2] = 'File:Compass-icon bb NbE.svg',
[ 3] = 'File:Compass-icon bb NNE.svg',
[ 4] = 'File:Compass-icon bb NEbN.svg',
[ 5] = 'File:Compass-icon bb NE.svg',
[ 6] = 'File:Compass-icon bb NEbE.svg',
[ 7] = 'File:Compass-icon bb ENE.svg',
[ 8] = 'File:Compass-icon bb EbN.svg',
[ 9] = 'File:Compass-icon bb E.svg',
[10] = 'File:Compass-icon bb EbS.svg',
[11] = 'File:Compass-icon bb ESE.svg',
[12] = 'File:Compass-icon bb SEbE.svg',
[13] = 'File:Compass-icon bb SE.svg',
[14] = 'File:Compass-icon bb SEbS.svg',
[15] = 'File:Compass-icon bb SSE.svg',
[16] = 'File:Compass-icon bb SbE.svg',
[17] = 'File:Compass-icon bb S.svg',
[18] = 'File:Compass-icon bb SbW.svg',
[19] = 'File:Compass-icon bb SSW.svg',
[20] = 'File:Compass-icon bb SWbS.svg',
[21] = 'File:Compass-icon bb SW.svg',
[22] = 'File:Compass-icon bb SWbW.svg',
[23] = 'File:Compass-icon bb WSW.svg',
[24] = 'File:Compass-icon bb WbS.svg',
[25] = 'File:Compass-icon bb W.svg',
[26] = 'File:Compass-icon bb WbN.svg',
[27] = 'File:Compass-icon bb WNW.svg',
[28] = 'File:Compass-icon bb NWbW.svg',
[29] = 'File:Compass-icon bb NW.svg',
[30] = 'File:Compass-icon bb NWbN.svg',
[31] = 'File:Compass-icon bb NNW.svg',
[32] = 'File:Compass-icon bb NbW.svg'
}
 
Line ૭૯ ⟶ ૧૧૨:
local SiteURL = {
GeoHack = '//tools.wmflabs.org/geohack/geohack.php?pagename=$page&params=$lat_N_$lon_E_$attr&language=$lang',
GoogleEarth = '{{fullurl:toollabs://tools.wmflabs.org/geocommons/earth.kml|?latdegdec=$lat&londegdec=$lon&scale=10000&commons=1}}',
Proximityrama = '{{fullurl:toollabs://tools.wmflabs.org/geocommons/proximityrama|?latlon=$lat,$lon}}',
OpenStreetMap = '{{fullurl:toollabs://tools.wmflabs.org/wiwosm/osm-on-ol/commons-on-osm.php|?zoom=16&lat=$lat&lon=$lon}}',
GoogleMaps = {
Mars = '//www.google.com/mars/#lat=$lat&lon=$lon&zoom=8',
Moon = '//www.google.com/moon/#lat=$lat&lon=$lon&zoom=8',
Earth = 'https://maps.google.com/maps?ll=$lat,$lon&spn=0.01,0.01&t=k&q=http://tools.wmflabs.org/geocommons/web.kml&hl=$lang'
}
}
Line ૯૪ ⟶ ૧૨૭:
Gallery = '[[Category:Galleries with coordinates]]',
Category = '[[Category:Categories with coordinates]]',
wikidata1 = '[[Category:Pages with local coordinates and matching wikidata coordinates]]',
wikidata2 = '[[Category:Pages with local coordinates and similar wikidata coordinates]]',
wikidata3 = '[[Category:Pages with local coordinates and mismatching wikidata coordinates]]',
wikidata4 = '[[Category:Pages with local coordinates and missing wikidata coordinates]]',
globe = '[[Category:Media with %s locations]]',
default = '[[Category:Media with default locations]]',
Line ૧૦૧ ⟶ ૧૩૮:
 
local NoLatLonString = 'latitude, longitude'
 
local function langSwitch(list,lang)
local langList = mw.language.getFallbacksFor(lang)
table.insert(langList,1,lang)
for i,language in ipairs(langList) do
if list[language] then
return list[language]
end
end
end
 
local function add_maplink(lat, lon, marker, text)
local tstr = ''
if text then
tstr = string.format('text="%s" ', text)
end
return string.format('<maplink %szoom="13" latitude="%f" longitude="%f">{'..
' "type": "Feature",'..
' "geometry": { "type":"Point", "coordinates":[%f, %f] },'..
' "properties": { "marker-symbol":"%s", "marker-size": "large", "marker-color": "0050d0" }'..
'}</maplink>', tstr, lat, lon, lon, lat, marker)
end
 
local function info_box(text)
return string.format('<table class="messagebox plainlinks layouttemplate" style="border-collapse:collapse; border-width:2px; border-style:solid; width:100%%; clear: both; '..
'border-color:#f28500; background:#ffe;direction:ltr; border-left-width: 8px; ">'..
'<tr>'..
'<td class="mbox-image" style="padding-left:.9em;">'..
' [[File:Commons-emblem-issue.svg|class=noviewer|45px]]</td>'..
'<td class="mbox-text" style="">%s</td>'..
'</tr></table>', text)
end
 
local function mergeWithWikidata(q, lat1, lon1)
-- we are given wikidata q-code so look up the coordinates
local dist_str=''
-- Wikiata coordinates
if q:match( '^[Qq]%d+$' ) then
entity = mw.wikibase.getEntity(q)
else
entity = q
end
q = entity.id
local v, lat2, lon2, precision
if entity and q:match( '^[Qq]%d+$' ) then
local s = entity:getBestStatements( 'P625' )
if s[1] and s[1].mainsnak.datavalue.value.latitude then
v = s[1].mainsnak.datavalue.value
if v.globe == 'http://www.wikidata.org/entity/Q2' then
lat2 = v.latitude
lon2 = v.longitude
precision = math.floor(v.precision*111000) -- convert precision from degrees to meters and round
precision = math.max(math.min(precision,111000),5) -- bound precision to a number between 5 meters and 1 degree
end
end
end
-- compare coordinates
local cat = ''
if not lat1 or not lon1 then -- wikidata coordinates only
lat1 = lat2
lon1 = lon2
elseif lat1 and lon1 and not lat2 and not lon2 then
cat = string.format("The above coordinates are missing from linked Wikidata item [[d:%s|%s]]. Please copy them. "..
"You can use [http://tools.wmflabs.org/wikidata-todo/quick_statements.php QuickStatements] tool with string <code>%s P625 @%09.5f/%09.5f S143 Q565</code> after replacing spaces with tabs in a text editor. ",
q, q, q, lat1, lon1)
cat = CoorCat.wikidata4 .. info_box(cat)
elseif lat1 and lon1 and lat2 and lon2 then
-- calculate distance
local dLat = math.rad(lat1-lat2)
local dLon = math.rad(lon1-lon2)
local d = math.pow(math.sin(dLat/2),2) + math.pow(math.sin(dLon/2),2) * math.cos(math.rad(lat1)) * math.cos(math.rad(lat2))
d = 2 * math.atan2(math.sqrt(d), math.sqrt(1-d)) -- angular distance in radians
d = 6371000 * d -- radians to meters conversion
local frame = mw.getCurrentFrame()
local info = frame:preprocess(add_maplink(lat2, lon2, 'marker')) -- fancy link to OSM
info = string.format("There is a discrepancy of %i meters between the above coordinates and the ones stored at linked Wikidata item [[d:%s|%s]] (%s, precision: %i m). Please reconcile them. "..
"To copy Commons coordinates to Wikidata, you can use [http://tools.wmflabs.org/wikidata-todo/quick_statements.php QuickStatements] tool with string "..
"<code>%s P625 @%09.5f/%09.5f S143 Q565</code> after replacing spaces with tabs in a text editor. ",
math.floor(d+0.5), q, q, info, precision, q, lat1, lon1)
 
if d<20 or d<precision then -- will consider location within 20 meters or precisi0on distance as the same
cat = CoorCat.wikidata1
dist_str = string.format(' (discrepancy of %i meters between the above coordinates and the ones stored on Wikidata)', d) -- will be displayed when hovering a mouse above wikidata icon
elseif d>1000 and d>5*precision then -- locations 1 km off and 5 precision distances away are likely wrong
cat = CoorCat.wikidata3 .. info_box(info)
else
cat = CoorCat.wikidata2 .. info_box(info)
end
end
return lat1, lon1, q, cat, dist_str
end
 
-- =======================================
-- === Functions =========================
-- =======================================
p = {}
 
-- parse attribute variable returning desired field
function coordinatesp.parseAttribute(frame)
return string.match(mw.text.decode(frame.args[1]), mw.text.decode(frame.args[2]) .. ':' .. '([^_]*)') or ''
end
Line ૧૧૫ ⟶ ૨૪૫:
try to convert it to an angle
==============================================================================]]
function coordinatesp.getHeading(frame)
local attributes
if frame.args[1] then
Line ૧૨૪ ⟶ ૨૫૪:
return ''
end
local hNum = coordinatesp._getHeading(attributes)
if hNum == nil then
return ''
Line ૧૩૧ ⟶ ૨૬૧:
end
-- Helper core function for getHeading.
function coordinatesp._getHeading(attributes)
if attributes == nil then
return nil
Line ૧૫૮ ⟶ ૨૮૮:
3) language used in formating of the number
==============================================================================]]
function coordinatesp.deg2dms(frame)
local deg = tonumber(frame.args[1])
local degPrec = tonumber(frame.args[2]) or 0-- precision in degrees
local lang = frame.args.lang
if frame.args.not (lang and mw.language.isSupportedLanguage(frame.args.lang)) then
lang = frame.args.:callParserFunction("int","lang") -- get user's chosen language
else -- get user's chosen language
lang = mw.message.new( "lang" ):plain()
end
if deg==nil then
return frame.args[1];
else
return coordinatesp._deg2dms(deg, degPrec, lang)
end
end
Line ૧૮૨ ⟶ ૩૧૦:
* lang - language to used when formating the number
==============================================================================]]
function coordinatesp._deg2dms(deg, degPrec, lang)
local dNum, mNum, sNum, dStr, mStr, sStr, formatStr, secPrec, c, k
local Lang = mw.language.new(lang)
Line ૨૩૨ ⟶ ૩૬૦:
* prec = geolocation precission in meters
==============================================================================]]
function coordinatesp.lat_lon(frame)
local lat = tonumber(frame.args.lat)
local lon = tonumber(frame.args.lon)
Line ૨૪૨ ⟶ ૩૭૦:
end
end
local lang = frame.args.lang
if frame.args.not (lang and mw.language.isSupportedLanguage(frame.args.lang)) then
lang = frame.args.:callParserFunction("int","lang") -- get user's chosen language
else -- get user's chosen language
lang = mw.message.new( "lang" ):plain()
end
if lat==nil or lon==nil then
return NoLatLonString
else
local nsew = Fallback._langSwitchlangSwitch(i18n.NSEW, lang) -- find set of localized translation of N, S, W and E in the desired language
local SN, EW, latStr, lonStr, lon2m, lat2m, phi
if lat<0 then SN = nsew.S else SN = nsew.N end -- choose S or N depending on latitude degree sign
Line ૨૬૨ ⟶ ૩૮૮:
lat2m = 111000 -- average latitude degree size in meters
end
latStr = coordinatesp._deg2dms(math.abs(lat), prec/lat2m, lang) -- Convert latitude degrees to degrees/minutes/seconds
lonStr = coordinatesp._deg2dms(math.abs(lon), prec/lon2m, lang) -- Convert longitude degrees to degrees/minutes/seconds
return string.format('%s&nbsp;%s, %s&nbsp;%s', latStr, SN, lonStr, EW)
--return string.format('<span class="latitude">%s %s</span>, <span class="longitude">%s %s</span>', latStr, SN, lonStr, EW)
Line ૨૮૧ ⟶ ૪૦૭:
* attributes = attributes to be passed to GeoHack
==============================================================================]]
function coordinatesp.externalLink(frame)
args = frame.args
iflocal lang = frame.args.lang
if not (lang and mw.language.isSupportedLanguage(args.lang)) then
lang = frame:callParserFunction("int","lang") -- get user's chosen language
lang = args.lang
else -- get user's chosen language
lang = mw.message.new( "lang" ):plain()
end
localreturn str = coordinatesp._externalLink(args.site or 'GeoHack', args.globe or 'Earth', args.lat, args.lon, lang, args.attributes or '')
return frame:preprocess(str)
end
Line ૩૦૪ ⟶ ૪૨૮:
* attributes = attributes to be passed to GeoHack
==============================================================================]]
function coordinatesp._externalLink(site, globe, latStr, lonStr, lang, attributes)
local URLstr = SiteURL[site];
if site == 'GoogleMaps' then
Line ૩૨૯ ⟶ ૪૫૩:
* mode = set by each calling template
==============================================================================]]
function coordinatesp.alterAttributes(attributes, mode)
-- indicate which template called it
if mode=='camera' then -- Used by {{Location}} and {{Location dec}}
Line ૩૬૦ ⟶ ૪૮૪:
* attributes = attributes to be passed to GeoHack
==============================================================================]]
function coordinatesp.GeoHack_link(frame)
-- create link and coordintate string
local latlon = coordinatesp.lat_lon(frame)
if latlon==NoLatLonString then
return latlon
else
frame.args.site = 'GeoHack'
local url = coordinatesp.externalLink(frame)
return string.format('<span class="plainlinksneverexpand">[%s %s]</span>', url, latlon) --<span class="plainlinks nourlexpansion">
end
Line ૩૮૫ ⟶ ૫૦૯:
* namespace = namespace name: File, Category, (Gallery)
==============================================================================]]
function coordinatesp.externalLinksSection(frame)
local args = frame.args
iflocal lang = frame.args.lang
if not (lang and mw.language.isSupportedLanguage(args.lang)) then
lang = frame:callParserFunction("int","lang") -- get user's chosen language
lang = args.lang
else -- get user's chosen language
lang = mw.message.new( "lang" ):plain()
end
if not args.namespace then
Line ૩૯૬ ⟶ ૫૧૯:
end
local str, link1, link2
if args.globe=='Earth' then -- Earth locations will have 3 or 4 links
link1 = p._externalLink('OpenStreetMap', 'Earth', args.lat, args.lon, lang, '')
str = string.format('[%s %s] - [%s %s]', -- - [%s %s]',
coordinateslink2 = p._externalLink('OpenStreetMapGoogleEarth' , 'Earth', args.lat, args.lon, lang, ''),
-- GoogleMap link no longer works due to changes in the website software
Fallback._langSwitch(i18n.OpenStreetMaps, lang),
-- link3 = p._externalLink('GoogleMaps' , 'Earth', args.lat, args.lon, lang, '') %langSwitch(i18n.GoogleMaps, lang)
-- GoogleMap link no longer works due to changes in the website software
str = string.format('[%s %s] - [%s %s]',
--coordinates._externalLink('GoogleMaps' , 'Earth', args.lat, args.lon, lang, ''),
--Fallback._langSwitchlink1, langSwitch(i18n.GoogleMapsOpenStreetMaps, lang),
link2, langSwitch(i18n.GoogleEarth, lang))
coordinates._externalLink('GoogleEarth' , 'Earth', args.lat, args.lon, lang, ''),
Fallback._langSwitch(i18n.GoogleEarth, lang))
if args.namespace=="Category" then
link1 = p._externalLink('Proximityrama', 'Earth', args.lat, args.lon, lang, '')
str = string.format('%s - [%s %s]', str,
str = string.format('%s - [%s %s]', str, link1, langSwitch(i18n.Proximityrama, lang))
coordinates._externalLink('Proximityrama', 'Earth', args.lat, args.lon, lang, ''),
Fallback._langSwitch(i18n.Proximityrama, lang))
end
elseif args.globe=='Mars' or args.globe=='Moon' then
link1 = p._externalLink('GoogleMaps', args.globe, args.lat, args.lon, lang, '')
str = string.format('[%s %s]',
str = string.format('[%s %s]', link1, langSwitch(i18n.GoogleMaps, lang))
coordinates._externalLink('GoogleMaps', args.globe, args.lat, args.lon, lang, ''),
Fallback._langSwitch(i18n.GoogleMaps, lang))
end
return str
return frame:preprocess(str) -- use preprocess to expand {{#fullurl}}
--return str
end
 
Line ૪૩૬ ⟶ ૫૫૫:
* prec = geolocation precission in meters
==============================================================================]]
function coordinatesp.LocationTemplateCore(frame)
-- prepare arguments
args = frame.args
Line ૪૪૩ ⟶ ૫૬૨:
end
if not (args.lang and mw.language.isSupportedLanguage(args.lang)) then
args.lang = mw.message.newframe:callParserFunction( "int","lang" ):plain() -- get user's chosen language
end
if not (args.namespace) then -- if namespace not provided than look it up
Line ૪૫૬ ⟶ ૫૭૫:
Status = 'secondary'
end
args.attributes = coordinatesp.alterAttributes(args.attributes or '', args.mode)
-- Convert coordinates from string to numbers
-- check for errors and add Geo (microformat) code for machine readability.
local lat = tonumber(args.lat)
local lon = tonumber(args.lon)
if args.wikidata and args.wikidata~='' and (not lat or not lon) then
-- if lat/lon is not provided but we are given wikidata q-code than look up the coordinates
local data = require('Module:Wikidata')
local args2 = {}
args2.property='P625'
args2.item=args.wikidata
args2.numval = 1
args2.link = '-'
args2.displayformat='latitude'
lat = data.formatStatements(args2)
args2.displayformat='longitude'
lon = data.formatStatements(args2)
end
if lon then -- get longitude to be in -180 to 180 range
lon=lon%360
Line ૪૮૦ ⟶ ૫૮૬:
end
end
-- If wikidata link provided than compare coordinates
local Categories, geoMicroFormat, coorTag, wikidata_link = '', '', '', ''
if args.wikidata and args.wikidata~='' then
local dist_str
-- if lat/lon is not provided but we are given wikidata q-code than look up the coordinates
lat, lon, q, Categories, dist_str = mergeWithWikidata(args.wikidata, lat, lon)
wikidata_link = string.format("\n[[File:Wikidata-logo.svg|20px|Edit coordinates on Wikidata%s|link=wikidata:%s]]", dist_str, q);
end
 
args.lat = string.format('%010.6f', lat or 0)
args.lon = string.format('%011.6f', lon or 0)
frame.args = args
local Categories, geoMicroFormat, coorTag = '', '', ''
 
-- Categories, {{#coordinates}} and geoMicroFormat will be only added to File, Category and Gallery pages
Line ૪૮૯ ⟶ ૬૦૪:
if lat and lon then -- if lat and lon are numbers...
if lat==0 and lon==0 then -- lat=0 and lon=0 is a common issue when copying from flickr and other sources
Categories = Categories .. CoorCat.default
end
if frame.args.attributes and string.find(frame.args.attributes, '=') then
Line ૫૧૦ ⟶ ૬૨૫:
if args.namespace == 'File' and Status == 'primary' and args.mode=='camera' then
coorTag = string.format('{{#coordinates:primary|%10.6f|%11.6f|%s}}', lat, lon, args.attributes)
coorTag = frame:preprocess(coorTag)
end
else -- if lat and lon are not numbers then add error category
Line ૫૧૮ ⟶ ૬૩૪:
 
-- Call helper functions to render different parts of the template
local str1coor, str2, str3, str4info_link, inner_table, heading, OSM = '','','','','','',''
str1coor = coordinatesp.GeoHack_link(frame) -- the coordinatesp and link to GeoHack
heading = coordinatesp._getHeading(frame.args.attributes) -- get heading arrow section
if heading then
local k = math.fmod(math.floor(0.5+math.fmod(heading+360,360)/11.25),32)+1
--str1 = string.format('%s&nbsp;&nbsp;<span style="{{Transform-rotate|%f}}">[[File:North Pointer.svg|20px|link=|alt=]]</span>', str1, 360-heading)
local fname = heading_icon[k]
local fname = string.format('{{Compass rose file|%f|style=heading}}', heading)
str1coor = string.format('%s&nbsp;&nbsp;<span title="%s°">[[%s|25px|link=|alt=Heading=%s°]]</span>', str1coor, heading, fname, heading)
end
if args.globe=='Earth' then
str2 = Fallback._langSwitch(i18n.LocationTemplateLinkLabel, args.lang) -- header of the link section
local icon = 'marker'
str3 = coordinates.externalLinksSection(frame) or '' -- external link section
if args.mode=='camera' then
str4 = string.format('[[File:Circle-information.svg|18x18px|alt=info|link=%s]]', Fallback._langSwitch(i18n.COM_GEO, args.lang) )
icon = 'camera'
inner_table = string.format('<td style="border:none;">%s</td><td style="border:none;">%s %s</td><td style="border:none;">%s%s</td>', str1, str2, str3, str4, geoMicroFormat)
end
OSM = frame:preprocess(add_maplink(args.lat, args.lon, icon, '[[File:Openstreetmap logo.svg|20px|link=]]')) -- fancy link to OSM
end
external_link = p.externalLinksSection(frame) -- external link section
if external_link then
external_link = langSwitch(i18n.LocationTemplateLinkLabel, args.lang) .. ' ' .. external_link -- header of the link section
end
info_link = string.format('[[File:Circle-information.svg|18x18px|alt=info|link=%s]]', langSwitch(i18n.COM_GEO, args.lang) )
inner_table = string.format('<td style="border:none;">%s&nbsp;%s</td><td style="border:none;">%s</td><td style="border:none;">%s%s%s</td>',
coor, OSM, external_link or '', info_link, wikidata_link, geoMicroFormat)
-- combine strings into a table
Line ૫૩૯ ⟶ ૬૬૫:
local field_name = 'Location'
if args.mode=='camera' then
field_name = Fallback._langSwitchlangSwitch(i18n.CameraLocation, args.lang)
elseif args.mode=='object' then
field_name = Fallback._langSwitchlangSwitch(i18n.ObjectLocation, args.lang)
elseif args.mode=='globe' then
field_list = Fallback._langSwitchlangSwitch(i18n.GlobeLocation, args.lang)
if args.globe and i18n.GlobeLocation['en'][args.globe] then -- verify globe is provided and is recognized
field_name = field_list[args.globe]
end
end
--Create HTML text
local style = frame:expandTemplate{ title="Infobar-Layout", args={ ["lang"] = lang, ["class"] = 'commons-file-information-table' } }
local dir, text_align
templateText = string.format('<table lang="%s" %s><tr><th class="type fileinfo-paramfield">%s</th>%s</tr></table>', lang, style, field_name, inner_table)
if mw.language.new( args.lang ):isRTL() then
dir = 'rtl'
text_align = 'right'
else
dir = 'ltr'
text_align = 'left'
end
local style = string.format('class="toccolours mw-content-%s layouttemplate commons-file-information-table" cellpadding="2" style="width: 100%%; direction:%s;" lang="%s"',
args.lang, dir, text_align, args.lang)
templateText = string.format('<table lang="%s" %s><tr><th class="type fileinfo-paramfield">%s</th>%s</tr></table>', args.lang, style, field_name, inner_table)
end
return frame:preprocess(templateText .. Categories .. coorTag)
end
 
return coordinatesp