Logo Voyage

Module:Mapdraw Voyage Tips and guide

You can check the original Wikivoyage article Here
[view] [edit] [history] [purge] Documentation

Mapdraw

[edit]
  1. Initial BETA Module to draw circle
Function Arguments Argument Description
p.circle (maplink or mapframe output can be very large) - built from a circle center point
lat Required latitude (see id below) - ie. lat=27.0
long Required longitude (see id below) - ie. long=28.0
id Wikidata ID to look up coordinates instead of using lat and long parameters
type "line" or "poly" default is "line"
group group name to be used as "show" argument in <mapframe> - default is "circle"
title title to be used in <maplink> -- default is "A circle"
desc description default is ""
radius radius of a circle. - default is .5, MAX set at 10 -- and can not be less than or equal to 0 -- .00010 is about 40 meters, 3 is about 50 km
fill default set to #ccef64 if missing
stroke default set to #0000ff
mapframe To create a mapframe insted of a maplink - use mapframe=y or mapframe=yes
marker y or yes - create a marker - at input lat long
{{safesubst:#invoke:Mapdraw|circle|lat=22.35|long=70.07|type=poly|radius=10|fill=#000000|stroke=#0000cc}}

    -- keeping original shape for a circle -- Matroc
    -- other shapes etc. moved to a Sandbox
    
    local p = {}
    
    local function newlat(a)
    -- newlat = math.log(math.tan((90 + a) * math.pi / 360)) / (math.pi / 180) -- worked this code elsewhere in function can remove
       newlatitude = 180/math.pi * (2 * math.atan(math.exp( a * math.pi/180)) - math.pi/2 )
      if newlatitude > 89.5 then point = 89.5 end -- END if       -- straight line at top of map
      if newlatitude < -89.5 then point = -89.5 end -- END if     -- straight line at bottom of map
      return newlatitude
    end
    
    local function checkhex(fill,stroke)
             if string.len(fill) ~= 7 then error("Incorrect length for argument fill!") end
             if string.gsub(fill,"#[0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f]","") ~= "" then
                error("Incorrect hexidecimal format for argument fill!") end
             if string.len(stroke) ~= 7 then error("Incorrect length for argument stroke!") end
             if string.gsub(stroke,"#[0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f]","") ~= "" then
                error("Incorrect hexidecimal format for argument stroke!") end
    end
    
    local function checkid(id)
           id = string.gsub(id,"q","Q")
           id = string.gsub(id,"%s+","")	    	
           if string.gsub(id,"^[Q]%d+$","") ~= "" then error("Bad format for parameter id!") end
       return id
    end
    -- GET LATITUDE
    
    local function latitude(wikidata)
    	local latitude = ""
    	    local entity = mw.wikibase.getEntityObject(wikidata)	
    	if entity == nil then error("Wikidata ID " .. wikidata .. " not found!") end
    	local claims = entity.claims
    	if claims == nil then error("Wikidata ID found No Data!") end	
    	if claims.P625 ~= nil then
    		latitude = entity.claims.P625[1].mainsnak.datavalue.value.latitude
    		return latitude
    	end
    	if latitude == "" then error("Latitude not found in Wikidata!") end
    		return latitude
    	end
    
    --  GET LONGITUDE -- P625
    
    local function longitude(wikidata)
    	local longitude = ""
    	    local entity = mw.wikibase.getEntityObject(wikidata)	
    	if entity == nil then error("Wikidata ID " .. wikidata .. " not found!") end	
    	local claims = entity.claims
    	if claims == nil then error("Wikidata ID found No Data!") end	
    	if claims.P625 ~= nil then
    		longitude = entity.claims.P625[1].mainsnak.datavalue.value.longitude
    		return longitude
    	end
    	if longitude == "" then error("Longitude not found in Wikidata!") end
    		return longitude
    end
    
    
    local function parts(lat,long,group,title,description,fill,stroke)
            local part1a = '<maplink class="no-icon" text="" latitude="' .. lat .. '" longitude="' .. long .. '" '
            local part1a = part1a .. 'zoom="5" group="' .. group .. '">\n{"type": "Feature","geometry":\t{"coordinates":\n'
    
            local part2a = '\n\t\t"type":"LineString"},\n\t"properties":{\n\t\t"title": "' .. title .. '",\n'
            local part2a = part2a .. '\t\t"description": "' .. description .. '",\n'
            local part2a = part2a .. '\t\t"stroke":"' .. stroke .. '",\n\t\t"stroke-width":1\n}}\n</maplink>\n'
    
            local part1b = '<maplink class="no-icon" text="" latitude="' .. lat .. '" longitude="' .. long .. '" '
            local part1b = part1b .. 'zoom="5" group="' .. group .. '">\n{"type": "Feature","geometry":\t{"coordinates":\n'
    
            local part2b = '\n\t\t"type":"Polygon"},\n\t"properties":{\n\t\t"title": "' .. title .. '",\n'
            local part2b = part2b .. '\t\t"description": "' .. description .. '",\n\t\t"fill": "' .. fill .. '",\n'
            local part2b = part2b .. '\t\t"stroke":"' .. stroke .. '",\n\t\t"stroke-width":1\n}}\n</maplink>\n'
    
            local part1c = '<mapframe text="" latitude="' .. lat .. '" longitude="' .. long .. '" '
            local part1c = part1c .. 'zoom="5" group="' .. group .. '" width="600" height="400" >\n{"type": "FeatureCollection",\n\t"features": [\n\t\t{\n\t\t"type": "Feature",\n\t\t"geometry": {"coordinates":\n'
    
            local part2ca = '\n\t\t"type":"LineString"},\n\t"properties":{\n\t\t"title": "' .. title .. '",\n'
            local part2ca = part2ca .. '\t\t"description": "' .. description .. '",\n\t\t"fill": "' .. fill .. '",\n'
            local part2ca = part2ca .. '\t\t"stroke":"' .. stroke .. '",\n\t\t"stroke-width":1\n}\n}]}\n</mapframe>\n'
            
            local part2cb = '\n\t\t"type":"Polygon"},\n\t"properties":{\n\t\t"title": "' .. title .. '",\n'
            local part2cb = part2cb .. '\t\t"description": "' .. description .. '",\n\t\t"fill": "' .. fill .. '",\n'
            local part2cb = part2cb .. '\t\t"stroke":"' .. stroke .. '",\n\t\t"stroke-width":1\n}\n}]}\n</mapframe>\n' 
    
            return part1a,part2a,part1b,part2b,part1c,part2ca,part2cb
    end
    
    -- CIRCLE
    
    function p.circle(frame)
    	   local shape = "circle"
    	   local id = frame.args['id']	or ""
    	   local lat,long = "",""
    	   local x,y = 0,0
    	   if id == nil or id == "" then
                  if frame.args['lat'] == nil then error("Missing argument lat!") end
                  if frame.args['long'] == nil then error("Missing argument long!") end
                  lat = frame.args['lat']
                  long = frame.args['long']
                  if tonumber(frame.args['lat']) > 90 or tonumber(frame.args['lat']) < -90 then
               	   error("Latitude must be between 90 and -90!") end
                  if tonumber(frame.args['long']) > 180 or tonumber(frame.args['long']) < -180 then
               	   error("Longitude must be between 180 and -180!") end
    	    else
                  id = checkid(id)
                  lat = latitude(id)
                  long = longitude(id)	
    	   end        
               x = string.format("%.6f",lat)
               y = string.format("%.6f",long)                   
            
            local marker = frame.args['marker'] or "no"
                  if marker == nil or marker == "" then marker = "no" end
            local mapframe = frame.args['mapframe'] or "no"
                  if mapframe == nill or mapframe == "" then mapframe = "no" end -- FUTURE USE              
            if tonumber(lat) > 85.35 or tonumber(lat) < -85.35 then
            	error("Latitude must be between 85.35 and -85.35!") end -- END if
    -- I set this as a default - function will not handle the polar circles yet will still handle areas within the majority of a map
            if tonumber(long) > 180 or tonumber(long) < -180 then
            	error("Longitude must be between 180 and -180!") end -- END if
    -- this will draw a full circle at 0 lat and 180 long
            local group = frame.args['group'] or 'circle'
            local title = frame.args['title'] or 'A circle'
            local description = frame.args['desc'] or ''
            local r = frame.args['radius'] or ".5"   -- default
            -- radius of 10 is approx. 500 km - futz with sizes - below 3 would probably be adequate
            -- .1 is about 20km - .0001 is about 30 m
                    r = tonumber(r)
                    if r > 10 then error("10 for radius is MAX") end   -- END if - my default
                    if r <= 0 then error("radius has to be greater than 0") end -- END if
            local fill = frame.args['fill'] or "#ccef64"
            local stroke = frame.args['stroke'] or "#0000ff"
            checkhex(fill,stroke)
            local data = {}
            local coordinates = ""
            local ptx,pty,angle = 0,0,0
            local type = frame.args['type'] or "line" -- default line for LineString
            if type ~= "line" then
                    type = "poly"
            end -- END if
    
            local part1a,part2a,part1b,part2b,part1c,part2ca,part2cb = parts(lat,long,group,title,description,fill,stroke)
    
            if tonumber(x) >= 10.5 then
                x = math.log(math.tan((90 + x) * math.pi/360)) / (math.pi/180)
            elseif tonumber(x) <= -10.5 then
                x = math.log(math.tan((90 + x) * math.pi/360)) / (math.pi/180)
            end -- END if ELSEIF
    
            for i = 1, 360 do
               angle = i * math.pi / 180
               ptx = x + r * math.cos( angle )
               pty = y + r * math.sin( angle )
    --         ptx, pty = x + r * math.cos( angle ), y + r * math.sin( angle ) -- original code split for readability above
    
            if tonumber(x) >= 10.5 then
             ptx = newlat(ptx) -- makes correction to make circle show up on map - upper latitudes
            end -- END if
    
            if tonumber(x) <= -10.5 then
              ptx = newlat(ptx) -- makes correction to make circle show up on map - lower latitudes
            end -- END if
    
              data[i] = '[' .. string.format("%.6f",pty) .. "," .. string.format("%.6f",ptx) .. ']'
            end -- END for
    
            for i = 5,359, 5 do
                    data[i] = data[i] .. "@@@@@"
            end -- END for
    
    -- cycle through array and build single string of all coordinates to be output
    
            for i = 1,360, 1 do
                   coordinates = coordinates .. data[i]
            end -- END for
    
            coordinates = coordinates.gsub(coordinates,'%]%[','],[')
            coordinates = coordinates.gsub(coordinates,'%]@@@@@%[','],\n[')
            coordinates = "[" .. coordinates .. ',' .. data[1] .. "],"          -- close the circle extra precautionary measure
    
            if mapframe == "y" or mapframe == "yes" then
    			if type == "poly" then
                    coordinates  = string.gsub(coordinates,'%]%,$',']],')
                    coordinates = part1c .. string.gsub(coordinates,'^%[','[[') .. part2cb
    			else
                    coordinates = part1c .. coordinates .. part2ca
    			end -- END if
    		else
    			if type == "poly" then
                    coordinates  = string.gsub(coordinates,'%]%,$',']],')
                    coordinates = part1b .. string.gsub(coordinates,'^%[','[[') .. part2b
    			else
                    coordinates = part1a .. coordinates .. part2a
    			end -- END if		
    		
    		end
            if marker == "yes" or marker == "y" then
                  coordinates = coordinates .. '\n* {{marker|type=vicinity|name=Center Circle|lat=' .. lat .. "|long=" .. long .. '}}\n'
            end
            return coordinates
    
    end
    
    
    
    -- END MODULE
    
    
    return p
    


    Discover



    Powered by GetYourGuide