<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-GB">
	<id>https://stockhub.co/index.php?action=history&amp;feed=atom&amp;title=Module%3ASandbox%2FWnt%2FFindFeatures</id>
	<title>Module:Sandbox/Wnt/FindFeatures - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://stockhub.co/index.php?action=history&amp;feed=atom&amp;title=Module%3ASandbox%2FWnt%2FFindFeatures"/>
	<link rel="alternate" type="text/html" href="https://stockhub.co/index.php?title=Module:Sandbox/Wnt/FindFeatures&amp;action=history"/>
	<updated>2026-04-12T05:52:30Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.43.5</generator>
	<entry>
		<id>https://stockhub.co/index.php?title=Module:Sandbox/Wnt/FindFeatures&amp;diff=146407&amp;oldid=prev</id>
		<title>imported&gt;Pppery: Update for module move</title>
		<link rel="alternate" type="text/html" href="https://stockhub.co/index.php?title=Module:Sandbox/Wnt/FindFeatures&amp;diff=146407&amp;oldid=prev"/>
		<updated>2020-02-11T20:54:39Z</updated>

		<summary type="html">&lt;p&gt;Update for module move&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt; -- This module finds features with coordinates in a certain area on a globe.&lt;br /&gt;
 -- It uses other modules containing database files, which can be generated by Module:FindFeatures/displayDatabase&lt;br /&gt;
 -- These files can be edited manually, so for brevity they use simple indexes:&lt;br /&gt;
 -- * recordname = dataitem[1]&lt;br /&gt;
 -- * latitude = dataitem[2][1]&lt;br /&gt;
 -- * longitude = dataitem[2][2]&lt;br /&gt;
 &lt;br /&gt;
local getArgs = require(&amp;#039;Module:Arguments&amp;#039;).getArgs&lt;br /&gt;
local p = {}&lt;br /&gt;
local DEFAULTHITS = 5&lt;br /&gt;
local DEFAULTSHOWDIST = 1&lt;br /&gt;
local GLOBES = mw.loadData(&amp;#039;Module:Sandbox/Wnt/FindFeatures/globes&amp;#039;) or {}&lt;br /&gt;
local GLOBEDATA = {}&lt;br /&gt;
local i = 1&lt;br /&gt;
while GLOBES[i] do&lt;br /&gt;
    local fcn = GLOBES[i][1]&lt;br /&gt;
    GLOBEDATA[fcn] = {GLOBES[i][2], GLOBES[i][3], GLOBES[i][4], &amp;quot;Module:Sandbox/Wnt/FindFeatures/&amp;quot;..fcn}&lt;br /&gt;
    p[fcn] = function (frame)&lt;br /&gt;
    return p.main(frame, unpack(GLOBEDATA[fcn]))&lt;br /&gt;
    end&lt;br /&gt;
    p[mw.ustring.gsub(fcn, &amp;quot;(.)&amp;quot;, mw.ustring.lower, 1)] = p[fcn]&lt;br /&gt;
    i = i + 1&lt;br /&gt;
end&lt;br /&gt;
local DEBUGLOG = &amp;quot;&amp;quot;&lt;br /&gt;
local WARNCATEGORIES = {}&lt;br /&gt;
&lt;br /&gt;
function selfLink(link, current, distance)&lt;br /&gt;
    -- link may contain &amp;quot;|&amp;quot; piping but should otherwise be ready to go in [[ ]]&lt;br /&gt;
    local link = mw.ustring.gsub(link, &amp;quot;%s*|.*$&amp;quot;, &amp;quot;&amp;quot;) or link&lt;br /&gt;
    if (link == current) then&lt;br /&gt;
        if (distance and distance &amp;gt; 0.0001) then&lt;br /&gt;
            table.insert(WARNCATEGORIES, &amp;quot;position&amp;quot;)&lt;br /&gt;
        end&lt;br /&gt;
        return true&lt;br /&gt;
    else&lt;br /&gt;
        return nil&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function warnings()&lt;br /&gt;
    local messages = &amp;quot;&amp;quot;&lt;br /&gt;
    local i = 1&lt;br /&gt;
    while WARNCATEGORIES[i] do&lt;br /&gt;
        messages = messages .. &amp;quot;[[Category: Errors reported by Module:FindFeatures/&amp;quot; .. WARNCATEGORIES[i] .. &amp;quot;]]&amp;quot;&lt;br /&gt;
        i = i + 1&lt;br /&gt;
    end&lt;br /&gt;
    return messages&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function parseBounds(args)&lt;br /&gt;
    local i&lt;br /&gt;
    local norths = {}&lt;br /&gt;
    local easts = {}&lt;br /&gt;
    for i = 1, 4 do&lt;br /&gt;
        if args[i] then&lt;br /&gt;
            local value, direction = parseBound(args[i])&lt;br /&gt;
            if (direction == &amp;quot;S&amp;quot;) or (direction == &amp;quot;W&amp;quot;) then value = 0 - value end&lt;br /&gt;
            if direction == &amp;quot;N&amp;quot; or direction == &amp;quot;S&amp;quot; then&lt;br /&gt;
                table.insert(norths, value)&lt;br /&gt;
            elseif direction == &amp;quot;E&amp;quot; or direction == &amp;quot;W&amp;quot; then&lt;br /&gt;
                table.insert(easts, value)&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    if (#norths == 2 and #easts == 2) then&lt;br /&gt;
        local bound = {}&lt;br /&gt;
        if norths[1] &amp;gt; norths[2] then&lt;br /&gt;
            bound.N, bound.S = norths[1], norths[2]&lt;br /&gt;
        else&lt;br /&gt;
            bound.N, bound.S = norths[2], norths[1]&lt;br /&gt;
        end&lt;br /&gt;
        -- screw the wrap.  I don&amp;#039;t even care anymore.  Let the user think about it.&lt;br /&gt;
        if easts[1] &amp;gt; easts[2] then&lt;br /&gt;
            bound.E, bound.W = easts[1], easts[2]&lt;br /&gt;
        else&lt;br /&gt;
            bound.E, bound.W = easts[2], easts[1]&lt;br /&gt;
        end			&lt;br /&gt;
        return bound&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function tidyNum(text)&lt;br /&gt;
    text = mw.ustring.gsub(text, &amp;quot; &amp;quot;, &amp;quot;&amp;quot;)&lt;br /&gt;
    text = mw.ustring.gsub(text, &amp;quot;,&amp;quot;, &amp;quot;.&amp;quot;)&lt;br /&gt;
    return tonumber(text)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function parseValue(text)&lt;br /&gt;
    -- extract 3 or 2 or 1 values from the string.  Can contain . or , as a decimal, no spaces allowed.&lt;br /&gt;
    local d, m, s = mw.ustring.match(text,&amp;quot;(%-?%d+[%.,]?%d*)[%a%c%s%z!@#$%%^&amp;amp;%*%(%)%=|\~&amp;#039;]+(%-?%d+[%.,]?%d*)[%a%c%s%z!@#$%%^&amp;amp;%*%(%)%=|\~&amp;#039;]+(%-?%d+[%.,]?%d*)&amp;quot;)&lt;br /&gt;
    if not d then d, m = mw.ustring.match(text,&amp;quot;(%-?%d+[%.,]?%d*)[%a%c%s%z!@#$%%^&amp;amp;%*%(%)%=|\~&amp;#039;]+(%-?%d+[%.,]?%d*)&amp;quot;) end&lt;br /&gt;
    if not d then d = mw.ustring.match(text,&amp;quot;(%-?%d+[%.,]?%d*)&amp;quot;) end&lt;br /&gt;
    if d then&lt;br /&gt;
    	d = tidyNum(d or &amp;quot;0&amp;quot;) + tidyNum(m or &amp;quot;0&amp;quot;)/60 + tidyNum(s or &amp;quot;0&amp;quot;)/3600&lt;br /&gt;
    end&lt;br /&gt;
    return d&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function parseDirection(text)&lt;br /&gt;
    local direction = mw.ustring.match(text,&amp;quot;%A([NSEWnsew])%A&amp;quot;) or mw.ustring.match(text,&amp;quot;^([NSEWnsew])%A&amp;quot;) or mw.ustring.match(text,&amp;quot;%A([NSEWnsew])$&amp;quot;)&lt;br /&gt;
    if (not direction) then&lt;br /&gt;
        direction = mw.ustring.match(text,&amp;quot;([Nn])[Oo][Rr][Tt][Hh]&amp;quot;) or mw.ustring.match(text,&amp;quot;([Ss])[Oo][Uu][Tt][Hh]&amp;quot;) or mw.ustring.match(text,&amp;quot;([Ee])[Aa][Ss][Tt]&amp;quot;) or mw.ustring.match(text,&amp;quot;([Ww])[Ee][Ss][Tt]&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    if direction then direction = mw.ustring.upper(direction) end&lt;br /&gt;
    return direction&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function parseBound(text)&lt;br /&gt;
    -- note: currently does NOT hunt for deg, min, sec variations.  ASSuMEs that order.&lt;br /&gt;
    -- analogous to parseCoord, but we just want one number and direction.  But direction is mandatory.&lt;br /&gt;
    -- What to do when presented with &amp;quot;47 40 N&amp;quot;: assume degree and minute&lt;br /&gt;
    -- &amp;quot;47,40 N&amp;quot;: assume European decimal&lt;br /&gt;
    -- &amp;quot;47, 40 N&amp;quot; : assume degree and minute, I guess&lt;br /&gt;
    -- &amp;quot;47. 40 N&amp;quot; : assume US-style decimal, I guess&lt;br /&gt;
    -- this logic may be contested, esp. as it gives different results for different decimal types.&lt;br /&gt;
    -- therefore, for both &amp;quot;guess&amp;quot; issues and even 47,40 N, the alternate way is: if there are ONLY the two &lt;br /&gt;
    -- numbers separated by space both are considered one, but if there are more, consider them two.&lt;br /&gt;
    local value = parseValue(text)&lt;br /&gt;
    -- single letter, can be NSEWnsew, could be beginning or end&lt;br /&gt;
    local direction = parseDirection(text)&lt;br /&gt;
    return value, direction&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function parseCoord(text)&lt;br /&gt;
    local text = mw.ustring.upper(text) -- we&amp;#039;re only getting direction letters and numbers here&lt;br /&gt;
    local coord = {}&lt;br /&gt;
    -- maybe it&amp;#039;s a Coord call like &amp;quot;{{Coord|37.3|N|259.0|E|globe:Mars_type:mountain}}&amp;quot; - then only search the template&lt;br /&gt;
    text = mw.ustring.match(text,&amp;quot;{{COORD(.-)}}&amp;quot;) or text&lt;br /&gt;
    -- maybe it&amp;#039;s a simple coordinate like 37N,33E?&lt;br /&gt;
    -- note: currently does NOT hunt for deg, min, sec variations.  ASSuMEs that order.&lt;br /&gt;
    -- In this case, parsing what to do based on three numbers starts to fall apart (what if there are five?)&lt;br /&gt;
    -- Instead, look for the direction markers first, then split into two bound parsing problems&lt;br /&gt;
    local first, second = mw.ustring.match(text,&amp;quot;^(.-%A)[NSEW](%A.-)$&amp;quot;)&lt;br /&gt;
    if first and second and mw.ustring.match(first,&amp;quot;%d&amp;quot;) then&lt;br /&gt;
    coord[1] = parseValue(first)&lt;br /&gt;
    second = mw.ustring.match(second, &amp;quot;^(.-%A)[NSEW]%A.-$&amp;quot;) or mw.ustring.match(second, &amp;quot;^(.-%A)[NSEW]$&amp;quot;) or second&lt;br /&gt;
    coord[2] = parseValue(second)&lt;br /&gt;
    if not (coord[1] and coord[2]) then return nil end&lt;br /&gt;
    else&lt;br /&gt;
        -- last ditch effort: take the first two numbers in the section, WHATEVER they are.  Can be signed.&lt;br /&gt;
        coord[1], coord[2] = mw.ustring.match(text,&amp;quot;(%-?%d+[%.,]?%d*)[%a%c%s%z!@#$%%^&amp;amp;%*%(%)%=]+(%-?%d+[%.,]?%d*)&amp;quot;)&lt;br /&gt;
        if not (coord[1] and coord[2]) then return nil end&lt;br /&gt;
        coord[1] = tidyNum(coord[1])&lt;br /&gt;
        coord[2] = tidyNum(coord[2])&lt;br /&gt;
    end&lt;br /&gt;
    -- at this point the amounts of coord[1] (lat) and coord[2] (lon) are set, but what directions?&lt;br /&gt;
    local firstdir = parseDirection(text)&lt;br /&gt;
    local seconddir = firstdir&lt;br /&gt;
    if firstdir then&lt;br /&gt;
        frag = text&lt;br /&gt;
        repeat -- I just keep the first letter of the direction, not the context, so need to run forward to it&lt;br /&gt;
            frag = mw.ustring.match(frag, firstdir .. &amp;quot;(.*)$&amp;quot;)&lt;br /&gt;
            seconddir = parseDirection(frag)&lt;br /&gt;
        until seconddir ~= firstdir&lt;br /&gt;
    end&lt;br /&gt;
    -- invert signs for west, south positions&lt;br /&gt;
    if (firstdir == &amp;quot;W&amp;quot; or firstdir == &amp;quot;S&amp;quot;) then&lt;br /&gt;
        coord[1] = 0 - coord[1]&lt;br /&gt;
    end&lt;br /&gt;
    if (seconddir == &amp;quot;W&amp;quot; or seconddir == &amp;quot;S&amp;quot;) then&lt;br /&gt;
        coord[2] = 0 - coord[2]&lt;br /&gt;
    end&lt;br /&gt;
    -- if first is E/W, put it second&lt;br /&gt;
    if (firstdir == &amp;quot;W&amp;quot; or firstdir == &amp;quot;E&amp;quot;) then&lt;br /&gt;
        coord[1], coord[2] = coord[2], coord[1]&lt;br /&gt;
    end&lt;br /&gt;
    -- default without directions specified: first = latitude, no sign reversal&lt;br /&gt;
    if (not firstdir) then&lt;br /&gt;
        firstdir = &amp;quot;N&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
    if (not seconddir) then&lt;br /&gt;
        seconddir = &amp;quot;E&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
    if (seconddir == &amp;quot;N&amp;quot; or seconddir == &amp;quot;S&amp;quot; or firstdir == &amp;quot;E&amp;quot; or firstdir == &amp;quot;W&amp;quot;) then&lt;br /&gt;
        table.insert(WARNCATEGORIES, &amp;quot;coordinates&amp;quot;)&lt;br /&gt;
        return nil&lt;br /&gt;
    end&lt;br /&gt;
    coord[2] = (coord[2] + 180) % 360 - 180&lt;br /&gt;
    -- at this point firstdir and seconddir no longer mean anything - direction is in the + or - and first or second position&lt;br /&gt;
    return coord&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function display(dataitem, globe, distance)&lt;br /&gt;
    local recordname, coord1, coord2 = dataitem[1], dataitem[2][1], dataitem[2][2]&lt;br /&gt;
    local dir1, dir2&lt;br /&gt;
    -- distance comes as a prerounded number of km, leaves as a string&lt;br /&gt;
    distance = (distance ~= nil) and (&amp;quot;: &amp;quot; .. tostring(distance) .. &amp;quot; km&amp;quot;)  or &amp;quot;&amp;quot;&lt;br /&gt;
    -- The Coord template is absolutely up on its hind legs demanding this for non-Earth globes - see&lt;br /&gt;
    -- https://en.wikipedia.org/wiki/Template_talk:Infobox_mill_building.  Needs fixing.&lt;br /&gt;
    if coord1&amp;lt;0 then &lt;br /&gt;
        dir1 = &amp;quot;S&amp;quot;&lt;br /&gt;
        coord1 = 0 - coord1&lt;br /&gt;
    else &lt;br /&gt;
        dir1 = &amp;quot;N&amp;quot; &lt;br /&gt;
    end&lt;br /&gt;
    if coord2&amp;lt;0 then &lt;br /&gt;
        dir2 = &amp;quot;W&amp;quot;&lt;br /&gt;
        coord2 = 0 - coord2&lt;br /&gt;
    else dir2 = &amp;quot;E&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
    return &amp;#039;[[&amp;#039;..recordname..&amp;#039;]] ({{Coord|&amp;#039; .. coord1 .. &amp;quot;|&amp;quot; .. dir1 .. &amp;quot;|&amp;quot; .. coord2 .. &amp;quot;|&amp;quot; .. dir2 .. &amp;quot;|globe:&amp;quot; .. globe .. &amp;quot;}}&amp;quot; .. distance .. &amp;quot;)&amp;quot;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function inBounds(datapoint, region)&lt;br /&gt;
    return (datapoint[2][1] &amp;lt; region.N and datapoint[2][1] &amp;gt; region.S and datapoint[2][2] &amp;gt; region.W and datapoint[2][2] &amp;lt; region.E)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function haversine(radians)&lt;br /&gt;
    return (1 - math.cos(radians))/2&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function inverseHaversine(number)&lt;br /&gt;
    if number &amp;gt; 1 then number = 1 end&lt;br /&gt;
    if number &amp;lt; -1 then number = -1 end&lt;br /&gt;
    return 2 * math.asin(number ^ 0.5)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function haversineFunction(lat1, lon1, lat2, lon2)&lt;br /&gt;
    local rLat1 = lat1 * math.pi / 180&lt;br /&gt;
    local rLat2 = lat2 * math.pi / 180&lt;br /&gt;
    local rLon1 = lon1 * math.pi / 180&lt;br /&gt;
    local rLon2 = lon2 * math.pi / 180&lt;br /&gt;
    -- returns d/r; must be multiplied by planetary radius to get a distance&lt;br /&gt;
    return inverseHaversine(haversine(rLat2 - rLat1) + math.cos(rLat1)*math.cos(rLat2)*haversine(rLon2 - rLon1))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function inRadius(datapoint, region)&lt;br /&gt;
    local lat = datapoint[2][1]&lt;br /&gt;
    local lon = datapoint[2][2]&lt;br /&gt;
    local clat = region.center[1]&lt;br /&gt;
    local clon = region.center[2]&lt;br /&gt;
    local distance = haversineFunction(lat, lon, clat, clon)&lt;br /&gt;
    return ((not region.threshold) or distance &amp;lt; region.threshold) and distance&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p._main(region, pRadius, eRadius, database, globe, suppress, current)&lt;br /&gt;
    -- default list style; others not implemented&lt;br /&gt;
    local outprefix = &amp;quot;&amp;quot;&lt;br /&gt;
    local delimiter = &amp;quot;, &amp;quot;&lt;br /&gt;
    local outsuffix = &amp;quot;&amp;quot;&lt;br /&gt;
    local outarray = {}&lt;br /&gt;
    local criterion&lt;br /&gt;
    -- ndatabase = &amp;quot;#database&amp;quot;; it&amp;#039;s a pseudo table.  If there&amp;#039;s a dumber way to do this let me know.&lt;br /&gt;
    local ndatabase = 1&lt;br /&gt;
    while database[ndatabase] do&lt;br /&gt;
        ndatabase = ndatabase + 1&lt;br /&gt;
    end&lt;br /&gt;
    ndatabase = ndatabase - 1&lt;br /&gt;
    if region.type == &amp;quot;circle&amp;quot; then&lt;br /&gt;
        local localRadius = ((pRadius * math.sin(region.center[1]*math.pi/180))^2 + (eRadius * math.cos(region.center[1]*math.pi/180))^2)^0.5&lt;br /&gt;
        if region.radius then region.threshold = region.radius / localRadius end&lt;br /&gt;
        if region.hits then&lt;br /&gt;
            local hits = {}&lt;br /&gt;
            for i = 1, ndatabase do&lt;br /&gt;
                -- presently this isn&amp;#039;t the real distance; it&amp;#039;s relative to radius/threshold&lt;br /&gt;
                local distance = inRadius(database[i], region) * localRadius&lt;br /&gt;
                -- if radius isn&amp;#039;t defined, everything is inRadius&lt;br /&gt;
                if distance then&lt;br /&gt;
                    -- table is ranked from 1 to hits.  Insert hit at the lowest position where there&lt;br /&gt;
                    -- is either a vacancy or the distance is currently greater.&lt;br /&gt;
                    -- Table entries are 1.. hits containing {distance, database[i]}&lt;br /&gt;
                    local p = region.hits&lt;br /&gt;
                    while (p &amp;gt; 0) and ((hits[p] == nil) or (hits[p][1] &amp;gt; distance)) do&lt;br /&gt;
                        p = p - 1&lt;br /&gt;
                    end&lt;br /&gt;
                    if (p &amp;lt; region.hits) then&lt;br /&gt;
                    	if not (suppress and selfLink(database[i][1], current, distance)) then&lt;br /&gt;
                            table.insert(hits, p + 1, {distance, database[i]})&lt;br /&gt;
                            table[region.hits + 1] = nil -- scrap most distant entry&lt;br /&gt;
                        end&lt;br /&gt;
                    end&lt;br /&gt;
                end&lt;br /&gt;
            end&lt;br /&gt;
            for i = 1, region.hits do&lt;br /&gt;
                table.insert(outarray, display(hits[i][2], globe, region.showdist and math.floor(hits[i][1]/region.showdist)*region.showdist))&lt;br /&gt;
            end&lt;br /&gt;
        else&lt;br /&gt;
            criterion = inRadius&lt;br /&gt;
        end&lt;br /&gt;
    else&lt;br /&gt;
    	criterion = inBounds&lt;br /&gt;
    end&lt;br /&gt;
    if criterion then&lt;br /&gt;
        for i = 1, ndatabase do&lt;br /&gt;
            if (criterion(database[i], region)) and not (suppress and selfLink(database[i][1], current, distance)) then&lt;br /&gt;
                table.insert(outarray, display(database[i], globe, nil))&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return outprefix .. table.concat(outarray, delimiter) .. outsuffix&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.main(frame, globe, pRadius, eRadius, datafile)&lt;br /&gt;
	 -- no presets - look up polar, equator, datafile from parameters&lt;br /&gt;
     -- begin processing args here:&lt;br /&gt;
    local args = getArgs(frame)&lt;br /&gt;
    globe = args.globe or globe&lt;br /&gt;
    pRadius = args.polar or pRadius&lt;br /&gt;
    eRadius = args.equator or eRadius&lt;br /&gt;
    datafile = args.datafile or datafile -- these values override the presets&lt;br /&gt;
    if not (globe and pRadius and eRadius and datafile) then&lt;br /&gt;
        table.insert(WARNCATEGORIES, &amp;quot;parameters&amp;quot;)&lt;br /&gt;
        return warnings()..DEBUGLOG&lt;br /&gt;
    end&lt;br /&gt;
    local region = {}&lt;br /&gt;
    if args.center then&lt;br /&gt;
        region.type = &amp;quot;circle&amp;quot;&lt;br /&gt;
        region.center = parseCoord(args.center)&lt;br /&gt;
        region.radius = args.radius&lt;br /&gt;
        region.showdist = args.showdist and (tonumber(args.showdist) or DEFAULTSHOWDIST)&lt;br /&gt;
        region.hits = args.hits and tidyNum(args.hits)&lt;br /&gt;
        if (not region.hits) and (not region.radius) then region.hits = DEFAULTHITS end&lt;br /&gt;
    else&lt;br /&gt;
        region = parseBounds(args)&lt;br /&gt;
        if (not region) then&lt;br /&gt;
            table.insert(WARNCATEGORIES, &amp;quot;bounds&amp;quot;)&lt;br /&gt;
            return warnings() .. DEBUGLOG end&lt;br /&gt;
        region.type = &amp;quot;square&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
    database = mw.loadData(datafile)&lt;br /&gt;
    -- may write more generally; for now parameter &amp;#039;suppress&amp;#039; means don&amp;#039;t show link to the current article&lt;br /&gt;
    if args.suppress then args.suppress = {self = true} end&lt;br /&gt;
    current = mw.title.getCurrentTitle().fullText&lt;br /&gt;
    if args.nowiki then&lt;br /&gt;
        return frame:preprocess(&amp;quot;&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&amp;quot;..tostring(p._main(region, pRadius, eRadius, database, globe, args.suppress, current))..&amp;quot;&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&amp;quot;) .. warnings() .. DEBUGLOG&lt;br /&gt;
    else&lt;br /&gt;
        return frame:preprocess(tostring(p._main(region, pRadius, eRadius, database, globe, args.suppress, current))) .. warnings() .. DEBUGLOG&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>imported&gt;Pppery</name></author>
	</entry>
</feed>