Mapdraw
- Initial BETA Module to draw circle
- See Module Talk page
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