Module:Map

--[[   __  __           _       _        __  __              |  \/  | ___   __| |_   _| | ___ _|  \/  | __ _ _ __   | |\/| |/ _ \ / _` | | | | |/ _ (_) |\/| |/ _` | '_ \  | |  | | (_) | (_| | |_| | |  __/_| |  | | (_| | |_) | |_|  |_|\___/ \__,_|\__,_|_|\___(_)_|  |_|\__,_| .__/                                                 |_|                                                                                                This module is intended to be the engine behind "Template:Map.

Please do not modify this code without applying the changes first at "Module:Map/sandbox" and testing at "Module:Map/testcases".

Authors and maintainers: ]] -- ======================================= -- === Dependencies ====================== -- ======================================= require('strict') -- used for debugging purposes as it detects cases of unintended global variables local ISOdate =  require('Module:ISOdate')._ISOdate -- date localization local labels =   require("Module:I18n/map")                        -- internationalization of local core    =   require('Module:Core') local formatnum = require('Module:Formatnum')
 * User:Jarekt - original version

-- ================================================== -- === Internal functions =========================== -- ==================================================

--- local function getBareLabel(id, userLang) -- code equivalent to require("Module:Wikidata label")._getLabel with Wikidata=- option local label, link -- build language fallback list local langList = mw.language.getFallbacksFor(userLang) table.insert(langList, 1, userLang) for _, lang in ipairs(langList) do -- loop over language fallback list looking for label in the specific language label = mw.wikibase.getLabelByLang(id, lang) if label then break end                   -- label found and we are done end return label or id end

--- local function message(name, lang) return mw.message.new( 'wm-license-'..name ):inLanguage(lang):plain end

-- ==================================================================== -- === This function is just responsible for producing HTML of the === -- === template. At this stage all the fields are already filed    === -- ==================================================================== local function build_html(args, cats) local lang = args.lang -- user's language local dir = mw.language.new( lang ):getDir    -- get text direction local desTag = mw.ustring.format(' %s ', args.pagename) local prmTag = mw.ustring.format(" (%s) ", message('information-permission-reusing-link', lang), 								 message('information-permission-reusing-text', lang)) -- files with no source will be flagged if (not args.source) and (args.strict==true) and (args.demo or (args.namespace==6)) then args.nosource = mw.getCurrentFrame:expandTemplate{ title = 'Source missing' } end -- boolean field controling if horizontal section bar will be added args.addGeotemporalBar  = args.demo or args.location or args.map_date or args.scale or args.zoom or args.projection or args.centroid or args.heading or args.latitude or (args.warp_status and not args.warp_status=="skip") or args.other_fields_2 args.addBibliographicBar = args.demo or args.set or args.sheet or args.book_title or args.book_author or args.volume or args.page or args.language or args.other_fields_3 or args.place_of_publication or args.publisher or args.printer or args.publication_date or args.authority args.addArchivalBar     = args.demo or args.institution or args.id or args.dimensions or args.scan_resolution or args.other_fields_4 or args.medium or args.inscriptions or args.notes or args.references or args.other_fields_5 args.addDigitalBar		 = args.demo local nCol = 2 if not args.image and args.demo then args.image = args.demo_image end if args.image then nCol = 3 end -- Top line local top, results = {}, {} if args.name then table.insert(top, string.format(' %s\n ', args.name ) ) end if args.linkback then -- Wikidata Link table.insert(top, string.format('', args.linkback, args.linkback) ) end if args.wikidata then -- Wikidata Link table.insert(top, string.format('', args.wikidata, args.wikidata) ) end if args.QS then -- quick_statement link to upload missing info to wikidata table.insert(top, string.format('%s', args.QS) ) end if #top>0 then local line = string.format('%s ', nCol, table.concat(top, ' ')) table.insert(results, string.format(' \n%s\n \n', line)) end -- add other fields local params = { -- field name                  machine readable tag                         field name i18n approach                     field value wrapper --		{field='representation'     , id='fileinfotpl_representation'            , tag='P6243'}, {field='title'              , id='fileinfotpl_art_title'                 , tag='P1476',              wrapper=' \n%s '}, {field='subtitle'           , id='fileinfotpl_art_subtitle'              , tag='P1680'}, {field='description'        , id='fileinfotpl_desc'                      , tag='Q1200750',    wrapper=' \n%s ', tag2=desTag}, {field='other_fields_1'}, {field='legend'			    , id='fileinfotpl_map_legend'				   , tag='legend'}, {field='adjacent_sheets'    , id='fileinfotpl_adjacent_sheets'		   , tag='adjacentsheets'}, {field='sheet_index'        , id='fileinfotpl_sheet_index'		       , tag='sheetindex'}, {field='other_fields'}, {field='date'               , id='fileinfotpl_date'                      , tag='wm-license-information-date'}, {field='source'             , id='fileinfotpl_src'                       , tag='wm-license-information-source'}, {field='nosource'           , id='fileinfotpl_nosrc'                     , tag='wm-license-information-source'}, {field='author'             , id='fileinfotpl_aut'                       , tag='P170',         wrapper=' \n%s '}, {field='contributor'        , id='fileinfotpl_contrib'                   , tag='Q20204892',    wrapper=' \n%s '}, {field='credit_line'        , id='fileinfotpl_art_credit_line'           , tag='wm-license-artwork-credit-line'}, {field='permission'         , id='fileinfotpl_perm'                      , tag='wm-license-information-permission', tag2=prmTag}, -- Geotemporal Data {field='addGeotemporalBar'                                               , tag='geotemporal_data'}, {field='map_date'           , id='fileinfotpl_map_date'                  , tag='P2913'}, {field='location'           , id='fileinfotpl_map_location'              , tag='maplocation'}, {field='type'               , id='fileinfotpl_type'                      , tag='type'}, {field='projection'         , id='fileinfotpl_map_projection'            , tag='P3037'}, {field='scale'              , id='fileinfotpl_map_scale'                 , tag='P1752'}, {field='zoom'	            , id='fileinfotpl_map_zoom'           	   , tag='P6592'}, {field='heading'            , id='fileinfotpl_map_heading'               , tag='heading'}, {field='bbox'               , id='fileinfotpl_map_bbox'		           , tag='limits'}, {field='centroid'           , id='fileinfotpl_map_centroid'              , tag='Q511093'}, {field='warp'               , id='fileinfotpl_map_warped'		           , tag='warper'}, {field='other_fields_2'}, -- Bibliographic Data {field='addBibliographicBar'                                             , tag='bibliographic_data'}, {field='set'                , id='fileinfotpl_map_parent'				   , tag='P179'}, {field='sheet'              , id='fileinfotpl_map_sheet'				   , tag='sheet'}, {field='book_title'         , id='fileinfotpl_book_title'                , tag='Q732577',              wrapper=' \n%s '}, {field='book_author'        , id='fileinfotpl_aut'                       , tag='wm-license-information-author',         wrapper=' \n%s '}, {field='volume'             , id='fileinfotpl_book_volume'               , tag='P478'}, {field='page'               , id='fileinfotpl_book_volume'               , tag='P304'}, {field='language'           , id='fileinfotpl_book_language'             , tag='Q34770'}, {field='other_fields_3'}, {field='publication_place'  , id='fileinfotpl_book_place-of-publication' , tag='wm-license-book-place-of-publication',  }, {field='publisher'          , id='fileinfotpl_book_publisher'            , tag='wm-license-book-publisher',             wrapper=' \n%s '}, {field='printer'            , id='fileinfotpl_book_printer'              , tag='P872',               wrapper=' \n%s '}, {field='publication_date'   , id='fileinfotpl_publication_date'          , tag='P577'}, {field='authority'          , id='fileinfotpl_art_authority'             , tag='Q36524'}, -- Archival Data {field='addArchivalBar'                                                  , tag='archival_data'}, {field='institution'        , id='fileinfotpl_art_gallery'               , tag='Q2668072'}, {field='id'                 , id='fileinfotpl_art_id'                    , tag='wm-license-artwork-id',                 wrapper=' \n%s '}, {field='dimensions'         , id='fileinfotpl_art_dimensions'            , tag='wm-license-artwork-dimensions'}, {field='other_fields_4'}, {field='medium'             , id='fileinfotpl_art_medium'                , tag='wm-license-artwork-medium'}, {field='inscriptions'       , id='fileinfotpl_art_inscriptions'          , tag='wm-license-artwork-inscriptions'}, {field='notes'              , id='fileinfotpl_art_notes'                 , tag='wm-license-artwork-notes'}, {field='references'         , id='fileinfotpl_art_references'            , tag='artwork-references'}, {field='other_fields_5'}, -- Data about the digital copy {field='addDigitalBar'                                             	  , tag='digital_data'}, {field='resolution'	        , id='fileinfotpl_map_scan_resolution'	   , tag='resolution'}, {field='other_versions'     , id='fileinfotpl_ver'                       , tag='wm-license-information-other-versions'}, {field='image'},       --  (former: imgen) -- unused extras: -- {field='imgen'},    --  deprecated 'image' alias -- {field='help_warp'}, -- ignore deprecated relict, but don't show param error -- {field='artist'             , id='fileinfotpl_aut'                       , tag='artwork-artist',             wrapper=' \n%s '}, -- {field='editor'             , id='fileinfotpl_book_editor'               , tag='book-editor',                wrapper=' \n%s '}, -- {field='translator'         , id='fileinfotpl_book_translator'           , tag='book-translator',            wrapper=' \n%s '}, -- {field='illustrator'        , id='fileinfotpl_book_illustrator'          , tag='book-illustrator',           wrapper=' \n%s '}, -- {field='architect'          , id='fileinfotpl_aut'                       , tag='Q42973',                                wrapper=' \n%s '}, -- {field='designer'           , id='fileinfotpl_aut'                       , tag='Q5322166',                              wrapper=' \n%s '}, -- {field='photographer'       , id='fileinfotpl_aut'                       , tag='Q33231',                                wrapper=' \n%s '}, -- {field='subtitle'           , id='fileinfotpl_book_subtitle'             , tag='book-subtitle'}, -- {field='series_title'       , id='fileinfotpl_book_series-title'         , tag='book-series-title'}, -- {field='edition'            , id='fileinfotpl_edition'                   , tag='book-edition'}, -- {field='object_type'        , id='fileinfotpl_art_object_type'           , tag='object_type'}, -- {field='genre'              , id='fileinfotpl_art_genre'                 , tag='Q483394'}, -- {field='original_description', id='fileinfotpl_desc'                     , tag='original_description',                  wrapper=' \n%s '}, -- {field='pageoverview'       , id='fileinfotpl_book-page-overview'        , tag='book-page-overview'}, -- {field='depicted_people'    , id='fileinfotpl_art_depicted_people'       , tag='depicted_people'}, -- {field='depicted_place'     , id='fileinfotpl_art_depicted_place'        , tag='depicted_place'}, -- {field='depicted_part'      , id='fileinfotpl_art_depicted_part'         , tag='P5961'}, -- {field='department'         , id='fileinfotpl_art_location'              , tag='artwork-current-location',   wrapper=' \n%s '}, -- {field='coordinates'        , id='fileinfo-paramfield'                   , tag='ObjectLocation'}, -- {field='place_of_creation'  , id='fileinfotpl_art_creation_place'        , tag='place_of_creation'}, -- {field='place_of_discovery' , id='fileinfotpl_art_discovery_place'       , tag='place_of_discovery'}, -- {field='object_history'     , id='fileinfotpl_art_object_history'        , tag='artwork-object-history'}, -- {field='exhibition_history' , id='fileinfotpl_art_exhibition_history'    , tag='exhibition_history'},

}	for _, param in ipairs(params) do		local field, tag, cell1, cell2, id		field = args[param.field] if param.id then -- skip "other fields" parameter id = mw.ustring.format('id="%s" ', param.id) if field or (args.demo and param.tag and (param.field ~= 'source')) then -- skip the row if  no field tag = param.tag or 'bad' if string.sub(tag,1,10) == 'wm-license' then -- translate using MediaWiki message tag = mw.message.new( tag ):inLanguage(lang):plain -- label message in args.lang language elseif string.match(tag, "^[QP]%d+$") then   -- translate based on Wikidata labels tag = mw.language.new(lang):ucfirst(getBareLabel(tag, lang)) elseif labels[tag] then                      -- translate using LangSwitch and Module:I18n/map tag = mw.language.new(lang):ucfirst(core.langSwitch(labels[tag], args.lang)) end field = (param.wrapper and mw.ustring.format(param.wrapper, field or '')) or field -- apply wrapper if provided cell1 = mw.ustring.format('%s%s \n', id or , lang, tag, param.tag2 or ) cell2 = mw.ustring.format(' \n%s ', field or '') field = mw.ustring.format('\n%s%s\n \n\n', cell1, cell2) end elseif field and param.tag then -- do horizontal bar tag  = mw.language.new(lang):ucfirst(core.langSwitch(labels[param.tag], args.lang)) cell1 = mw.ustring.format(' %s \n', tag) field = mw.ustring.format('\n%s\n \n\n', cell1) end table.insert(results, field) end -- add table and outer layers local style = string.format('class="fileinfotpl-type-artwork toccolours vevent mw-content-%s" dir="%s" style="width: 100%%" cellpadding="4"', dir, dir) results = string.format(' \n', style, table.concat(results)) -- combine "results", an array of strings into a single string results = string.format(' \n%s\n \n', results) return results end

-- ================================================================= -- === Construct output fields from the input arguments -- =================================================================

local function create_infobox(args)

local cats = '' local frame = mw.getCurrentFrame

if args.demo then args.scale = '100000' args.heading = 'N'               args.latitude = '0.0/0.0/0.0/0.0' args.longitude = '0.0/0.0/0.0/0.0'

end

-- add formatting to the scale in accordance with current language preference if args.scale and tonumber(args.scale) then args.scale = string.format('1:%s', formatnum.formatNum(args.scale, args.lang)) end

-- compass image for heading if args.heading then                  -- note : no input validation currently done local img_link = frame:expandTemplate{ title = 'Compass rose file', args = { args.heading, style = 'north' } } args.heading = string.format('50px', img_link) end -- bounding box if args.latitude and args.longitude then args.bbox = frame:expandTemplate{ title = 'Map/bbox', args = { latitude = args.latitude, longitude = args.longitude } } end -- button with link for Map Warper or external georeferencing local title = mw.title.getCurrentTitle local page_id_for_warper = '' if 6 == title.namespace then page_id_for_warper = title.id        -- set pageID ready for warper link, but only if we are in the File: namespace end if ('warped' == args.warp_status) or ('1' == args.warp_status) then local warp_msg = mw.language.new(args.lang):ucfirst(core.langSwitch(labels['view_warp'], args.lang)) -- msg from I18n/map args.warp = frame:expandTemplate{ title = 'Clickable button', args = { target='//warper.wmflabs.org/wikimaps/new?pageid=' .. page_id_for_warper, text= warp_msg, external='yes', class='mw-ui-progressive mw-ui-button ui-button-blue' }		}               cats = cats .. '\n' elseif 'external' == args.warp_status then local warp_msg = mw.language.new(args.lang):ucfirst(core.langSwitch(labels['external_warp'], args.lang)) -- msg from I18n/map args.warp = frame:expandTemplate{ title = 'Clickable button 2', args = { link=args.warp_url, text= warp_msg, color='blue2', }		}	elseif 'skip' == args.warp_status then -- nothing else local warp_msg = mw.language.new(args.lang):ucfirst(core.langSwitch(labels['help_warp'], args.lang))  -- msg from I18n/map args.warp = frame:expandTemplate{ title = 'Clickable button', args = { target='//warper.wmflabs.org/wikimaps/new?pageid=' .. page_id_for_warper, text= warp_msg, external='yes', class='mw-ui-progressive mw-ui-button ui-button-blue' }		}	   if not ('unwarped' == args.warp_status) then args.warp = mw.ustring.format('%s %s ', args.warp, mw.language.new(args.lang):ucfirst(core.langSwitch(labels['skip_warp'], args.lang))) end end -- try to internationalise language code if args.language then local language_i18n = mw.language.fetchLanguageName( args.language, args.lang ) if not ('' == language_i18n) then args.language = language_i18n end end

-- internationalise ISO dates if args.date then -- apply ISODate to function to date string to convert date in ISO format to translated date string args.date = ISOdate(args.date, args.lang, '', 'dtstart', '100-999') end

if args.map_date then -- apply ISODate to function to date string to convert date in ISO format to translated date string args.map_date = ISOdate(args.map_date, args.lang, '', 'dtstart', '100-999') end

if args.print_date then -- apply ISODate to function to date string to convert date in ISO format to translated date string args.print_date = ISOdate(args.print_date, args.lang, '', 'dtstart', '100-999') end

if args.wikidata_title then args.title = string.format('%s ', args.title or '', args.wikidata_title, args.wikidata_title) end

local results = build_html(args) return results .. cats end

-- ================================================== -- === External functions =========================== -- ================================================== local p = {}

-- =========================================================================== -- === Version of the function to be called from other LUA codes -- ===========================================================================

--- -- _map function creates a wikicode for template based on -- passed arguments (through "args") and data extracted from SDC. --- -- Dependencies: p._SDC_Description, p._SDC_Source, p._SDC_Author, p._SDC_Date, --   Build_html, Module:ISOdate (_date) --- function p._map(args) local cats = '' -- ============================================================================================	-- === add if needed === -- ============================================================================================	local page = mw.title.getCurrentTitle local lang = args.lang local namespace = page.namespace  -- get page namespace if namespace==6 or namespace==10 then -- TODO add all allowed fields local allowedFields = {'title', 'wikidata_title', 'description', 'legend', 'adjacent_sheets', 'sheet_index', 'author', 'contributor', 'image', 'date', 'source', 'permission', 'map_date', 'location', 'wikidata_location', 'type', 'projection', 'centroid', 'scale', 'zoom', 'heading', 'latitude', 'longitude', 'warp_status', 'warp_url', 'set', 'wikidata_set', 'sheet', 'book_author', 'wd_book_author', 'book_title', 'wikidata_book', 'volume', 'page', 'language', 'publication_place', 'publisher', 'printer', 'print_date', 'ISBN', 'LCCN', 'OCLC', 'institution', 'id', 'dimensions', 'scan_resolution', 'medium', 'credit_line', 'inscriptions', 'notes', 'other_versions', 'references', 'other_fields', 'other_fields_1', 'other_fields_2', 'other_fields_3', 'other_fields_4', 'other_fields_5', 'demo', 'lang', 'resolution', 'other-versions', 'subtitle', 'strict' } local set, badField = {}, {} for _, field in ipairs(allowedFields) do set[field] = true end for field, _ in pairs( args ) do 			if not set[field] then table.insert(badField, field) end end if #badField>0 then cats = mw.ustring.format('\n; Error in '..				' template: unknown parameter "%s". ', table.concat(badField,'", "')) cats = cats .. '\n' end end

args.pagename = page.text

return create_infobox(args) .. cats end

-- =========================================================================== -- === Version of the functions to be called from template namespace -- ===========================================================================

--- -- information function creates a wikicode for template based on -- passed arguments (through "frame") and data extracted from SDC. All inputs do not -- depend on capitalization and all "_" can be replaced with spaces. --- -- Dependencies: p._information --- function p.map(frame) local args = core.getArgs(frame) -- map aliases to a single variable (all parameters converted to lowercase with _ instead of spaces	args.id = args.id or args.accession_number	args.medium = args.medium or args.technique	args.dimensions = args.dimensions or args.size	args.permission = args.permission or args.license	args.location = args.depicted_place or args.location	args.resolution = args.scan or args.scan_resolution or args.resolution       args.warp_status = args.warp_status or args.warper or args.warped	if args.imgen then		if not args.image then			args.image = args.imgen 			args.imgen = nil		end	end	if  args.image and string.sub(args.image, 1, 1 ) ~= '{' then		args.image = frame:expandTemplate{ title = 'Igen/map', args = { args.image } }	end

-- remove aliases args.accession_number = nil args.technique = nil args.size = nil args.license = nil args.help_warp = nil args.depicted_place = nil args.scan_resolution,  args.scan = nil, nil args.warper, args.warped = nil, nil

-- ensure the right format args.strict      = core.yesno(args.strict, true)

return p._map(args) end

--- -- List of exported functions --- -- map -- Calculate coordinates of 4 corners of the map based on 3 georeferenced anchor points and image dimensions. INPUTS: * anchorX - x map coordinate (pixel column) of 3 anchor points on the map * anchorY - y map coordinate (pixel row  ) of 3 anchor points on the map * anchorDeg - latitude or longitude of 3 anchor points on the map * nx - image width  in pixels * ny - image height in pixels 	X   = {7772, 330, 6679}         -- x map coordinate of 4 cities on the map    Y   = {553, 4122, 5248}         -- y map coordinate of 4 cities on the map    lat = {52.516, 48.857, 48.133} -- latitude of 4 cities on the map    lon = {13.383, 2.351, 11.567}   -- longitude of 4 cities on the map    nx   = 8150                            -- image width    ny   = 6978                            --image height function p.CalculateCornerLocations(frame) -- process inputs local anchorX  = mw.text.split(frame.args.anchorX, '/') local anchorY  = mw.text.split(frame.args.anchorY, '/') local anchorDeg = mw.text.split(frame.args.anchorDeg, '/') local nx       = tonumber(frame.args.nx) local ny       = tonumber(frame.args.ny) local formatstr = tonumber(frame.args.formatstr) or '%8.6f' if (#anchorX~=3 or #anchorY~=3 or #anchorDeg~=3) then

end

-- do matrix algebra local matrix = require('Module:Matrix') -- Calculate transformation matrix -- MATLAB: M = [X, Y, ones(length(X),1)] \ anchorDeg; C = matrix{{ anchorX[1], anchorY[1], 1, anchorDeg[1]}, { anchorX[2], anchorY[2], 1, anchorDeg[2]}, { anchorX[3], anchorY[3], 1, anchorDeg[3]}} local done = matrix.dogauss( C ) if done then M = matrix.subm( C, 1,4,3,4) -- remove identity matrix from first 3 columns -- MATLAB: cornerDeg = [ 1, ny, 1; nx, ny, 1; nx, 1, 1; 1, 1, 1] * M		cornerPix = matrix{{ 1, ny, 1},{nx, ny, 1},{nx, 1, 1},{1, 1, 1}} -- corner points in pixels cornerDeg = cornerPix * M		-- convert to a string local tstr = {} for i = 1,#cornerDeg do			tstr[i] = string.format(formatstr, cornerDeg[i][1]) end str =table.concat(tstr,'/') else str = '0/0/0/0' end return str end

return p