Module:Sandbox/Matroc/Inapoly

From Wikivoyage
Jump to navigation Jump to search
[view] [edit] [history] [purge] Documentation

  • Inapoly is a test module to see if a position is located within a polygon (shape). This was presented to me as an issue by a fellow user on hewikivoyage that has list of positions and needed to select those that fit within a polygon area -- Matroc
  • After researching and looking at Python, MatLab, Lua, C++ and Math examples to determine if a point is located within a polygon. I resorted to convertng them (most are very similar) in order to create this Module. As this is experimental and not fully vetted user beware.
  • Not for production use - Should only be used in a Sandbox as a tool or aid...

  • Functions
    1. function pointinpoly - main entry point when invoking module inapoly
    2. internal local function inapoly - function to compare positions and shape provided
    3. internal local function grabmaskinpoly - attempts to retrieve a Mapmask from a page
    4. internal local function grabmarkerpoly - attempts to retrieve markers and see listing from a page
    5. internal local function getwdcoords - attempts to retrieve latitude/longitude via Wikidata if need be
    6. internal local function t1_load - loads table Regions which contains formatted polygons (shapes)
    7. internal local function newlat - reworks latitude for map
    8. internal local function box - creates a box polygon (shape)
  • Parameters
    1. poly --- Minimum of 3 decimal combinations of latitude and longitude in the form 'lat:long" -- each set separated by a comma.
      • 32.932:35.097, 32.909:35.653, 33.293:35.572,32.932:35.097 -- note the first and last are the same... Much larger polygon (shapes) can be entered and used.
      • or enter GeoJSON format such as "[[[-140.000000,53.435182],[-150.392305,62.866762],[-129.607695,62.866762],[-140.000000,53.435182]]],". Module will check to see if it begins with a "[" it will be processed and lat/long positions will be reversed.
    2. table -- Can be used instead of poly and mapmaskpage (below). Preformatted olygons (shapes) in Module:Sanbox/Matroc/Regions table... table=Negev... the table itself is fixed/set and table in this case means which array member to get.
      • note: -- This may change to allow for loading other tables and a lukfor parameter to be introduced...
    3. mapmaskpage -- Can be used instead of poly and table. This will attempt to take a page and extract and use the Mapmask template for the polygon shape. ie.mapmask=Brooklyn/South.
      • Be aware -- The time allocated for running scripts has expired. error message may appear. Let me know if you get any of this type of error and I will examine. (One case I experienced was resolved by replacing {{ and }} around a mapmask - these characters may have been entered with a different style keyboard.
    4. makebox -- Can be use instead of poly,table and mapmaskpage just for fun... Consists of a latitude and longitude separated by a comma ie. makebox=42.81958,-74.73999 will create a mapmask in the shape of a box in (New York (state) (width and height of approx. 35 kms.
      • Notes: -- Order of precedence -- poly, table, mapmaskpage then makebox - other wise an error may possibly occur...
    • Following can be used for a single check against a polygon (shape) only
    1. name --- name of place optional ie. name=Baram Synagogue
    2. lat ---- decimal latitude ie. latitude=30.932
    3. long --- decimal latitude ie. longitude=35.932
    4. wikidata - wikidata id ie. wikidata=Qnnnn
    • Example: {{#invoke:Sandbox/Matroc/Inapoly|pointinpoly|poly=32.932:35.097, 32.909:35.653, 33.293:35.572,32.932:35.097|lat=32.989 | long=35.389 | wikidata=Q668}}
    • Following can be used to perform multiple checks - multiple checks override any single check (name,lat,long,wikidata combo),,,
    1. multi -- Container parameter for multiple checks only - contains 4 subfields for name, latitude, longitude and wikidata -- these can be entered by hand and have to be in the following order: @nname@alatitude@blongitude@wwikidata ID - groupings are separated by a :.
      • @n --- name -------- @nName
      • @a --- latitude----- @a32.98
      • @b --- longitude --- @b34.23
      • @w --- wikidata ID - @wQnnnnn
    • Example: multi=@nSomewhere@a33.04290@b35.41458@wQ000110 (can be used for one) -- multi=@nMontfort Castle@a33.0443627@b35.2266088@wQnnnn:@nBaram synagogue@a33.04290@b35.41458@wnnn:@nBeit Shemesh@a31.751389@b34.988611@wQnnnn -- if latitude and longitude will attempt to retrieve using the wikidata ID -- Remember too many can be expensive and cause issues.
    1. markerpage - Can be used instead of multi to grab markers and optional listings from an article page and create multiple checks markerpage=Jerusalem. These will be used to create simple markers as output.
      • types -- parameter to use with markerpage - enter types separated by a , ie. types=see,buy,go - an attempt to include these listings for checking against a polygon (shape) will be made.
    • Parameters controlling output
    1. mapframe' ----- defaul is no - to output a mapframe and a mapmask with markers if marker=yes and takes markermatch parameter into consideration - especially if you only want to see matches, non-matches or both on a map.
      • If you already have a mapframe and mapmask on your test page then I would opt out of using mapframe=yes and add show=listing,vicinity,mask to your existing mapframe -- if using oporigtype then you may have to add other types to the show parameter...
    2. marker ------- yes or no -- to output simple markers - default is yes ...
    3. markermatch -- yes or no or both - output (simple markers) matches, non-matches or both if marker=yes and markermatch parameter is set ... - default is both.
    4. text --------- default is no .. textual explanation of matches and non-matches - if marker=yes and text=yes and markermatch=yes, no or both then markers and text will be output accordingly. If marker=no and text=yes then text will be output.
    5. sort ---------- default is no - rudimentary sort (English) of shortened markers being created ..
    6. oporigtype ---- default is no - options are yes,no or both - This should retain the original type for display on the mapframe ..
  • Examples:
    1. Single check: {{#invoke:Sandbox/Matroc/Inapoly|pointinpoly|poly=32.932:35.097, 32.909:35.653, 33.293:35.572,32.932:35.097|lat=32.989 | long=35.389}}
    2. Multiple check {{#invoke:Sandbox/Matroc/Inapoly|pointinpoly|poly=33.293:35.567,33.244:35.699,32.887:35.630,32.925:35.105,33.094:35.126,33.096:35.457,33.293:35.567| multi=@nMontfort Castle@a33.0443627@b35.2266088:@nBaram synagogue@a33.04290@b35.41458:@n[[Beit Shemesh]]@a31.751389@b34.988611}}
      • {{safesubst:#invoke:Sandbox/Matroc/Inapoly|pointinpoly|marker=yes|mapframe=yes|markermatch=both|markerpage=Israel|mapmaskpage=Judaean Desert|sort=yes}}
  • Notes:
    1. The use of safesubst: while using the wiki editor you can preview the output and work with parameters to change/reuse it. Once you save/publish - results are finalized and the call to the Module will disappear. safesubst allows the module to do its job prior to processing templates and other processes first. If you do not use safesubst you will see the textual output and if saved or published you will only see textual output. Be sure and copy the module template call to #invoke a module in case you need it again!
    2. At times it may be necessary to actually save/publish the Sandbox page and purge the page. You can then reenter wiki editor and experiment some more reusing a copy of the module template call.
    3. Simple markers are output as 2 types - listing and vicinity (listing=green=match / vicinity=maroon=non-match)
    4. Issues may arise due to the difficulty of text-processing a page to get markers/listings and mapmask. There are multiple variations of how and what templates etc. do and the many oddities that were input by editors not following any standard method of entering them.
    5. This is designed as a tool and not really for production. Play safe and use in a Sandbox! -- Have fun! -- Matroc (talk) 04:55, 26 September 2018 (UTC)

local p = {}



-- Having worked further on similar processes - the code here can be dropped by at least 30% in size and further simplified
-- Methods used though sound and working are clumsy -- furture work project
-- Examole
-- {{#invoke:Inpoly|pointinpoly|poly=32.932:35.097, 32.909:35.653, 33.293:35.572, 32.932:35.097|lat=42.989 | long=35.389}}

-- function needed to correct lat positioning

local function newlat(a)
    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
    if newlatitude < -89.5 then point = -89.5 end -- END if
    return newlatitude
end

-- Makes a box as a marker for inclusion on a map

local function box(makebox)
       local makebox = makebox
	   if makebox == nil or makebox == "" then
	      return "" end
	   makebox = string.gsub(makebox,"%s*","")
	   local lat = string.gsub(makebox,",.*","")
	   local long = string.gsub(makebox,".*,","")
	   if lat == nil or lat == "" then return "" end
	   if long == nil or long == "" then return "" end
       local coordinates = "" 
       local r = ".25"  	   
	   
	   if tonumber(lat) > 90 or tonumber(lat) < -90 then
           	   return "" end
       if tonumber(long) > 180 or tonumber(long) < -180 then
           	    return "" end

        r = tonumber(r)
 
        lat = math.log(math.tan((90 + lat) * math.pi/360)) / (math.pi/180)

        local angle1,angle2,angle3,angle4 = 0,0,0,0
        local ptx,ptx2,ptx3,ptx4 = 0,0,0,0
        local pty,pty2,pty3,pty4 = 0,0,0,0
        local a = 45
        local b = 135
        local c = 225
        local d = 315
        
        angle1 = a * math.pi / 180
        ptx = lat + r * math.cos( angle1 )
        pty = long + r * math.sin( angle1 )

        angle2 = b * math.pi /180
        ptx2 = lat + r * math.cos( angle2 )
        pty2 = long + r * math.sin( angle2 )

        angle3 = c * math.pi /180
        ptx3 = lat + r * math.cos( angle3 )
        pty3 = long + r * math.sin( angle3 )
        
        angle4 = d * math.pi /180
        ptx4 = lat + r * math.cos( angle4 )
        pty4 = long + r * math.sin( angle4 )
        
        ptx,pty = string.format("%.6f",newlat(ptx)),string.format("%.6f",pty)
        ptx2,pty2 = string.format("%.6f",newlat(ptx2)),string.format("%.6f",pty2)
        ptx3,pty3 = string.format("%.6f",newlat(ptx3)),string.format("%.6f",pty3)
        ptx4,pty4 = string.format("%.6f",newlat(ptx4)),string.format("%.6f",pty4)


        coordinates = "[[[" .. pty .. "," .. ptx .. "],[" .. pty2 .. "," .. ptx2 .. "],[" .. pty3 .. "," .. ptx3 .. "],[".. pty4 .. "," .. ptx4 .. "],[" .. pty .. "," .. ptx .. "],[" .. pty .. "," .. ptx .. "]]]"
        return coordinates
end

--  grab a mapmask if possible from a wv article page and convert to a poly if asked for
function grabmapmaskinpoly(mapmaskpage)
		local page = mapmaskpage or ""
		local xoutput = ""
        local title = mw.title.new(page)
        local newdata = ""
        if title == nil then return end
        if title.id == 0 then
            return error(mapmaskpage .. "No such page for '''mapmaskpage''' exists!")
        end
        newdata = title:getContent()
		if newdata == nil or newdata == "" or not newdata == true then
			return ""
		end
		if string.find(newdata,"{{%s*[Mm]apmask") == nil then
			return error("'''No MAPMASK''' found on page " .. mapmaskpage .."!")
			end

		
		newdata = string.gsub(newdata,"^.*%{%{%s*[Mm]apmask","")

		newdata = string.gsub(newdata,"%s*}}.*","")
		
		newdata = string.gsub(newdata,"%s*=%s*","=")
		newdata = string.gsub(newdata,"|%s*%a+=","@D")
--		beginit,endit = string.find(newdata,"|")
		newdata = string.gsub(newdata, "%s*|%s*", "@x", 1)
        newdata = string.gsub(newdata,"@D.*@x","@x")
        newdata = string.gsub(newdata,"@D.*$","")
        newdata = string.gsub(newdata,"^@x","")        
        newdata = string.gsub(newdata,",",":")
        newdata = string.gsub(newdata,"|",",")
        newdata = string.gsub(newdata,"%s*","")

        return newdata     -- becomes poly for searching if available
end

-- read in a page with title:getcontent() and try and get markers - can be expensive processing wise
-- included are not only '''markers''' but '''See''' listings
function grabmarkerinpoly(markerpage,types)
--	    local copytype = ""
        local separator = ","
		local page = markerpage or ""
		local types = types or ""
		local xoutput = ""
        local title = mw.title.new(page)
        local newdata = ""
        if title == nil then return end
        if title.id == 0 then
            return error("'''" .. markerpage .. "''' does not exist")
        end
        newdata = title:getContent()
		if newdata == nil or newdata == "" or not newdata == true then
			return ""
		end
		newdata = string.gsub(newdata,"\n"," ")
		newdata = string.gsub(newdata,"%{%{%s*[Ss]ee[Dd]istricts%s*%}%}","{{JUNK")
		newdata = string.gsub(newdata,"%{%{%s*[Ss]ee%s*[Aa]lso%s*%}%}","JUNK")
		newdata = string.gsub(newdata,"%{%{%s*[Ss]leeppricerange","{{JUNK")
		newdata = string.gsub(newdata,"%{%{%s*[Ee]atpricerange","{{JUNK")		
        newdata = string.gsub(newdata,"\n","")
        newdata = string.gsub(newdata,"\r","")		
		newdata = string.gsub(newdata,"@","BULLET")
        newdata = string.gsub(newdata,"%{%{%{","BEGINTRIPLE")
        newdata = string.gsub(newdata,"}}}","ENDTRIPLE")
        newdata = string.gsub(newdata,"%{%{dead link%|%a+ %d+%s*%}%}","")          -- problem with this (internal curly brackets)
        newdata = string.gsub(newdata,"%{%{dead link%|%a+ %d+|%a+ %d+%s*%}%}","")  -- problem with this - see above
--        newdata = string.gsub(newdata,"%{%{%s*[Ss]eealso","{{other")
--        newdata = string.gsub(newdata,"%{%{%s*[Ss]ee also","{{other")			
--        newdata = string.gsub(newdata,"%{%{%s*[Ss]ee","{{marker")
--        newdata = string.gsub(newdata,"(%{%{%s*listing%s*|%s*type%s*=%s*[sS]ee","{{marker|type=see")


        if types ~= nil and types ~= "" then
           types = string.gsub(types,"%s*","") -- listing,see,do,buy,eat,drink,sleep,go etc.
           types = "," .. types
           types = string.lower(types)

           for zip in string.gmatch(types,"([^"..separator.."]+)") do
           	  if zip == "listing" then
           	  	newdata = string.gsub(newdata,"%{%{%s*[Ll]isting%s*|%s*name=","{{marker|type=listing|name=")
           	  else
   	            copytype = zip
                zip = "[" .. string.upper(string.sub(zip,1,1)) .. string.lower(string.sub(zip,1,1)) .. "]" .. string.sub(zip,2,15)
--                newdata = string.gsub(newdata,"%{%{%s*listing%s*|%s*type%s*=%s*" .. zip ,"{{marker|type=" .. copytype)
--                newdata = string.gsub(newdata,"%{%{%s*" .. zip,"{{marker|type=" .. copytype)

                  newdata = string.gsub(newdata,"%{%{%s*listing%s*|%s*type%s*=%s*" .. zip ,"{{marker|type=" .. copytype)
                  newdata = string.gsub(newdata,"%{%{%s*" .. zip .. "%s*|","{{marker|type=" .. copytype .. "|")                
              end
           end
        end
--if string.match(types,"@[Dd]o") ~= nil then
--      newdata = string.gsub(newdata,"%{%{%s*listing%s*|%s*type%s*=%s*[Dd]o","{{marker|type=do")
--      newdata = string.gsub(newdata,"%{%{%s*[Dd]o","{{marker|type=do")
--end

        newdata = string.gsub(newdata,"/","SLASH")
        newdata = string.gsub(newdata,":","COLON")
        newdata = string.gsub(newdata,"%{%{%s*[Mm]arker","@@{{marker") -- add separator @@
        newdata = string.gsub(newdata,"\n"," ")
		
		if string.find(newdata,"{{%s*marker") == nil then
--		if string.find(newdata,"{{marker") == nil then			
			return error("No '''Markers''' found on page " .. markerpage)
			end
			
		local separator = "@@"

		newdata = string.gsub(newdata,"@@@@","@@")

		for str in string.gmatch(newdata,"([^"..separator.."]+)") do
            if string.find(str,"^%{%{marker") ~= nil then
               str = string.gsub(str,"(%{%{)(%s*IATA%s*)(|)(%s*%u+%s*)(}})","%2--%4")
           str = string.gsub(str,"=%{%{","=opencurlyopencurly")         -- internal template inside template
           str = string.gsub(str,"}}%s*|","closecurlyclosecurly|")
           str = string.gsub(str,"}}%s*}}","closecurlyclosecurly}}")               
			   str = str.gsub(str,"}}.*","")                   -- short cut to chop off end might not work as expected
			   str = "@" .. str .. "@"
			   str = str.gsub(str,"= ","=")
			   str = str.gsub(str," =","=")			   
			   str = str.gsub(str,"name=","@n")
			   str = str.gsub(str,"lat=","@a")
			   str = str.gsub(str,"long=","@b")
			   str = str.gsub(str,"wikidata=","@w")
			   str = str.gsub(str,"wikipedia=","@D")			   
			   str = str.gsub(str,"zoom=","@D")
			   str = str.gsub(str,"type=","@t")
			   str = str.gsub(str,"url=","@D")
			   str = str.gsub(str,"lastedit=","@D")
			   str = str.gsub(str,"image=","@i")
			   str = str.gsub(str,"^@{{marker","@xmarker")
               str = str.gsub(str,"phone=","@D")
               str = str.gsub(str,"tollfree=","@D")
               str = str.gsub(str,"price=","@D")
               str = str.gsub(str,"fax=","@D")
               str = str.gsub(str,"directions=","@D")
               str = str.gsub(str,"alt=","@D")
               str = str.gsub(str,"address=","@D")
               str = str.gsub(str,"content","@D")
               str = str.gsub(str,"hours=","@D")

			   str = str.gsub(str,"%s%s+"," ")
			   str = str.gsub(str,"%s@","@")
			   str = string.gsub(str,"%s*|%s*@","@")
			   str = string.gsub(str,"@$","")

               if string.find(str,"@a") == nil then
        	      str = str .. "@a1"
               end
               if string.find(str,"@b") == nil then
                  str = str .. "@b1"
               end
               if string.find(str,"@n") == nil then
                  str = string.gsub(str,"@a","@nMissing Name@a")
               end

               str = string.gsub(str,"@D%d+@","@")
               str = string.gsub(str,"opencrly","{")
               str = string.gsub(str,"closecurly","}")
        
               xoutput = xoutput .. str .. ":"       
             end				   
		end

        xoutput = string.gsub(xoutput,":$","")

return xoutput

end

-- Work in Wikidata IDs for lat/long only if id present and no lat/long available
-- can be expensive if too many markers present 
local function getwdcoords(a,b,c)

    local a = a
    local b = b
    local id = c

	id = string.gsub(id,"%s+","")
	if string.match(id,"^[Qq]%d+$") == nil then return a,b,c end  -- wrong format don't even try

    if tostring(a) ~= "1" and tostring(b) ~= "1" then -- use lat long given rather than lookup Wikidata ID
		return a,b,c
		end
    if id ~= nil and id ~= '' then
       entity = mw.wikibase.getEntityObject(id)
       end
    if entity == nil then
		a = a
	    b = b
	    end
	local claims = entity.claims
	if claims == nil then
		a = a
	    b = b
	    end	
    if pcall(function () t =claims.P625 end ) then
 		if pcall(function () t =entity.claims.P625[1].mainsnak.datavalue.value.latitude end ) then		
		   a = entity.claims.P625[1].mainsnak.datavalue.value.latitude
		else a = a end
 		if pcall(function () t =entity.claims.P625[1].mainsnak.datavalue.value.longitude end ) then		
		   b = entity.claims.P625[1].mainsnak.datavalue.value.longitude
		else b = b end
     end
 return a,b,c
end

-- Load a table of mapshapes for tblukup if used -- already formatted
-- Table is Sandbox/Matroc/Regions - contains mostly shapes for Israel at this time
-- Can be cleaned or added to...

local function load_t1(t1,table2load)
	if pcall(function()t1 = mw.loadData(table2load) end) then
		return t1
	else
		error ("Unable to load table!")
	end
end

-- Main Processing center for finding if a position is within or not within a polygon
local function inapoly(polyx,polyy,ptx,pty)

    local answer = false
    local polyx = polyx
    local polyy = polyy
    local j = #polyx
    local ptx = ptx
    local pty = pty
    for i = 1, #polyx do
        if (polyy[i] < pty and polyy[j] >= pty or polyy[j] < pty and polyy[i] >= pty) then
            if (polyx[i] + ( pty - polyy[i] ) / (polyy[j] - polyy[i]) * (polyx[j] - polyx[i]) < ptx) then
                answer = not answer
            end
        end
        j = i;
    end
    return answer 
end

-- Main entrance to Inapoly module -- Starts here 
function p.pointinpoly(frame)
	 local sortit = {}
	 local sort = frame.args['sort'] or "no"
	 local oporigtype = frame.args['oporigtype'] or "none"
	 local keeptype = {}
	 keeptype[1] = "red"
     local t1 = {}           ---- local array for table1
     local t1_loaded = 0     ---- NO TABLE 1 is NOT LOADED!
     local table2load = "Module:Sandbox/Matroc/Regions"  -- only table to use
     local lukfor = frame.args['table'] or ""
     
	 local a,b,c = ""
	 local work = ""
	 local output = ""
     local index = 1
     local separator = ","
     local separator2 = ":"
     local separator3 = "@-@"
     local mapframe = frame.args['mapframe'] or "no"
     local map = ""
     local shape = ""
     local name = {}
     name[1] = frame.args['name'] or "Missing Name Parameter"     
     local wikidata = {} -- addon
     wikidata[1] = frame.args['wikidata'] or "" 
     
--   local type = {}       -- Future if different type output wanted in short marker
     local images = {}      -- Future if image to be output in short marker
     local image = frame.args['image'] or ""
     images[1] = image
--     local markertxt = "\n"
     local markertxtyes = "\n"
     local markertxtno = "\n"
     local marker = frame.args['marker'] or "yes"        -- Default to not output markers
     local markermatch = frame.args['markermatch'] or "both"
     local markerpage = frame.args['markerpage'] or ""
     local types = frame.args['types'] or "" -- comma separated lis of listing types to treat as markers - listing,see,do,buy,eat,drink,sleep,go
     local mapmaskpage = frame.args['mapmaskpage'] or ""
     local text = frame.args['text'] or 'yes'           -- Default to output textual output
     local ptx = {}        -- latitude
     local pty = {}        -- longitude
     local polyx = {}
     local polyy = {}
     local result = false
     local reverse = "no"
     local poly = frame.args['poly'] or ""
     local makebox = frame.args['makebox'] or ""
     local dummy = "{{mapmask|group=mask|"

     if poly == "" or poly == nil then
       t1 = load_t1(t1,table2load)
       if t1[lukfor] ~= nil then
      	 poly = t1[lukfor]
      	 shape = string.gsub(poly,",","|")
      	 shape = string.gsub(shape,":",",")
      	 shape = "{{mapmask|group=mask|" .. shape .. "}}"
       else
       		 poly = poly
        	 reverse = "no"
      end
      if poly == "" or poly == nil then
      	if mapmaskpage ~= nil and mapmaskpage ~= "" then
      	    	poly = grabmapmaskinpoly(mapmaskpage)
      		    shape = string.gsub(poly,",","|")
      		    shape = string.gsub(shape,":",",")
      		    shape = "{{mapmask|group=mask|" .. shape .. "}}"
      		else
      		     poly = poly
      		     reverse = "no"
      		end
       end
    end

    if poly == nil or poly == "" then
       if makebox ~= nil and makebox ~= "" then
       	   poly = box(makebox)
       else
       	   poly = poly
       end
    end
    
    poly = string.gsub(poly,"%s+","") or ""
    poly = string.gsub(poly,"\n","")

     if poly == nil or poly == "" then output = output .. "Empty parameter '''poly''' for marker comparison missing - use poly, table, mapmaskpage or makebox!\n"
         return output
         end 
    
-- Check to see if polygon is in the form [[[-140.000000,53.435182],[-150.392305,62.866762],[-129.607695,62.866762],[-140.000000,53.435182]]]
-- Assumption the parameter begins with a "[" as trigger that it is from Mapframe or Maplink. - If so reverse is automatically set to "yes"
-- Modify string to match original format of parameter

   if string.match(poly,"^%[.*$") ~= nil then
      poly = string.gsub(poly,"(%d)(,)(%d)","%1:%3")
      poly = string.gsub(poly,"%],%[",",")
      poly = string.gsub(poly,"%[+","")
      poly = string.gsub(poly,"%]+","")
      poly = string.gsub(poly,",$","")

      reverse = "yes"

   end

     for str in string.gmatch(poly,"([^"..separator.."]+)") do
     	if reverse == "yes" then
     		  a = str.gsub(str,"%:.*$","")
              polyy[index] = tonumber(a)
              b = str.gsub(str,"^.*%:","")
              polyx[index] = tonumber(b)
              dummy = dummy .. b .. "," .. a .. "|"
 		else
     		 a = str.gsub(str,"%:.*$","")
             polyx[index] = tonumber(a)
             b = str.gsub(str,"^.*%:","")
             polyy[index] = tonumber(b)              
          end
        index = index + 1 
        end
        
if reverse == "yes" then       
        dummy = string.gsub(dummy,"|$","}}")
        shape = dummy
end

if shape == "" or shape == nil then
      		    shape = string.gsub(poly,",","|")
      		    shape = string.gsub(shape,":",",")
      		    shape = "{{mapmask|group=mask|" .. shape .. "}}"	
end
 
       if index <= 2 then output = output .. "Not enough '''coordinates''' for polygon '''" .. name[1] .. "'''\n"
           return output
           end     

     local multi = frame.args['multi'] or ""
     if multi == nil or multi == "" then
        if markerpage ~= nil and markerpage ~= "" then
     	        multi = grabmarkerinpoly(markerpage,types)
     	    else
     	    	multi = ""
        	end
      end
     	
     multi = string.gsub(multi,"\n","")
     multi = string.gsub(multi,"%s%s+"," ")

   if multi == "" or multi == nil then
	 
     if frame.args['lat'] == nil or frame.args['lat'] == "" then
     	output = output .. "----Missing latitude for '''" .. name[1] .. "'''- Provide name,lat,long parameters for single comparison. or multi or markerpage parameters for multiple comparisons\n"
     	return output end
     if frame.args['long'] == nil or frame.args['long'] == "" then
     	output = output .. "----Missing longitude for '''" .. name[1] .. "'''- Provide name,lat,long parameters for single comparison. or multi or markerpage parameters for multiple comaparisons\n"
     	return output end
  
     ptx[1] = tonumber(frame.args['lat']) or 1
     pty[1] = tonumber(frame.args['long']) or 1
  else
     index = 1

     for str in string.gmatch(multi,"([^"..separator2.."]+)") do
        str = string.gsub(str," @","@")    	

        if string.find(str,"@n") == nil then    -- Missing name created
           str = "@nMissingname" .. str
        end
        if string.find(str,"@a") == nil then
        	str = str .. "@a1"
        end
        if string.find(str,"@b") == nil then
        	str = str .. "@b1"
        end

        str = str.gsub(str,"@a@","@a1@")
        str = str.gsub(str,"@b@","@b1@")
        str = str.gsub(str,"@b$","@b1")

        if string.find(str,"@i") == nil then
        		str = str .. "@i "
            end

         if string.find(str,"@t") == nil then
         	    str = str .. "@t "
         	end
         if string.find(str,"@w") == nil then
        	str = str .. "@wWikidata ID"
        end
        
-- build arrays for name, type, lat, lat, image and wikidata

        work = str
        work = string.gsub(work,"^.*@i","")
        work = string.gsub(work,"@.*","")
        work = string.gsub(work,"SLASH","/")
        work = string.gsub(work,"COLON",":")
        images[index] = work
        
        work = str
        work = string.gsub(work,"^.*@n","")
        work = string.gsub(work,"@.*","")
        work = string.gsub(work,"SLASH","/")
        name[index] = work
        
        work = str
        work = string.gsub(work,"^.*@t","")
        work = string.gsub(work,"@.*","")
        keeptype[index] = work
        
        work = str
        work = string.gsub(work,"@b.*","")
        work = string.gsub(work,"^.*@a","")
        work = tonumber(work)
        ptx[index] = work

        work = str
        work = string.gsub(work,"^.*@b","")
        work = string.gsub(work,"@.*","")
        work = tonumber(work)
        pty[index] = work
        
        work = str
        work = string.gsub(work,"^.*@w","")
        work = string.gsub(work,"@.*","")
        wikidata[index] = work
        
-- call getwdcoords - if Wikidata check if lat/long missing - try to get it from Wikidata
        ptx[index],pty[index],wikidata[index] = getwdcoords(ptx[index],pty[index],wikidata[index])
        if sort == "yes" then
	       sortit[index] = string.gsub(string.gsub(name[index],"%[%[",""),"]]","")
	       sortit[index] = sortit[index] .. "@n" .. name[index] .. "@a" .. ptx[index] .. "@b" .. pty[index] .. "@i" .. images[index] .."@w" .. wikidata[index] .. "@t" .. keeptype[index]
            table.sort(sortit)
        end
        index = index + 1
      end
  end
      if sort == "yes" then
          for i = 1, #sortit do	
             name[i] = string.gsub(string.gsub(sortit[i],"^.*@n",""),"@.*","")
             ptx[i] = string.gsub(string.gsub(sortit[i],"^.*@a",""),"@.*","")
             ptx[i] = tonumber(ptx[i])
             pty[i] = string.gsub(string.gsub(sortit[i],"^.*@b",""),"@.*","")
             pty[i] = tonumber(pty[i])
             images[i] = string.gsub(string.gsub(sortit[i],"^.*@i",""),"@.*","")
             wikidata[i] = string.gsub(string.gsub(sortit[i],"^.*@w",""),"@.*","")
             keeptype[i] = string.gsub(string.gsub(keeptype[i],"^.*@t",""),"@.*","")
          end
    end
    for i = 1, #ptx do
       result = inapoly(polyx,polyy,ptx[i],pty[i])
       if ptx[i] == 1  or ptx[i] == nil then ptx[i] = "None" end
       if pty[i] == 1 or pty[i] == nil then pty[i] = "None" end
       if keeptype[i] == nil or keeptype[i] == "" or keeptype[i] == " " then keeptype[i] = "listing" end
	if result == true then
	   if name[i] ~= nil or name[i] ~= "" then
           output = output .. "* latitude: " .. ptx[i] .. " longitude: " .. ptx[i]  .. " for '''" .. name[i] .. "'''... appears to be within the polygon...\n"
           if marker == "yes" then
--	           markertxt = markertxt .. "\*".. i .. ". {{marker | type=listing | name=" .. name[i]  .. " | lat=" .. string.gsub(ptx[i],"None"," ") .. " | long=" ..string.gsub(pty[i],"None"," ") .. " | image=" .. images[i] .. " | wikidata=" .. string.gsub(wikidata[i],"Wikidata ID","") .. "}}\n"
               if oporigtype == "yes" or oporigtype == "both" then
	              markertxtyes = markertxtyes .. "\*".. i .. ". {{marker | type=" .. keeptype[i] .. "| name=" .. name[i]  .. " | lat=" .. string.gsub(ptx[i],"None"," ") .. " | long=" ..string.gsub(pty[i],"None"," ") .. " | image=" .. images[i] .. " | wikidata=" .. string.gsub(wikidata[i],"Wikidata ID","") .. "}}\n"
               elseif oporigtype == "no"and oporigtype == "yes" then
	              markertxtyes = markertxtyes .. "\*".. i .. ". {{marker | type=" .. keeptype[i] .. "| name=" .. name[i]  .. " | lat=" .. string.gsub(ptx[i],"None"," ") .. " | long=" ..string.gsub(pty[i],"None"," ") .. " | image=" .. images[i] .. " | wikidata=" .. string.gsub(wikidata[i],"Wikidata ID","") .. "}}\n"
               	else
	              markertxtyes = markertxtyes .. "\*".. i .. ". {{marker | type=listing | name=" .. name[i]  .. " | lat=" .. string.gsub(ptx[i],"None"," ") .. " | long=" ..string.gsub(pty[i],"None"," ") .. " | image=" .. images[i] .. " | wikidata=" .. string.gsub(wikidata[i],"Wikidata ID","") .. "}}\n"
               end
        	end
         else
            if marker == "yes" then
--	            markertxt = markertxt .. "\*".. i .. ". {{marker | type=listing | name=NoName"  .. " | lat=" .. string.gsub(ptx[i],"None"," ") .. " | long=" .. string.gsub(pty[i],"None"," ") .. " | image=" .. images[i] .. " | wikidata=" .. string.gsub(wikidata[i],"Wikidata ID","") .. "}}\n"
                if oporigtype == "yes" or oporigtype == "both" then
	                 markertxtyes = markertxtyes .. "\*".. i .. ". {{marker | type=" .. keeptype[i] .. " | name=" .. name[i]  .. " | lat=" .. string.gsub(ptx[i],"None"," ") .. " | long=" ..string.gsub(pty[i],"None"," ") .. " | image=" .. images[i] .. " | wikidata=" .. string.gsub(wikidata[i],"Wikidata ID","") .. "}}\n"
                elseif oporigtype == "no" or oporigtype == "both" then
	                 markertxtyes = markertxtyes .. "\*".. i .. ". {{marker | type=" .. keeptype[i] .. " | name=" .. name[i]  .. " | lat=" .. string.gsub(ptx[i],"None"," ") .. " | long=" ..string.gsub(pty[i],"None"," ") .. " | image=" .. images[i] .. " | wikidata=" .. string.gsub(wikidata[i],"Wikidata ID","") .. "}}\n"
                else
	                 markertxtyes = markertxtyes .. "\*".. i .. ". {{marker | type=listing | name=" .. name[i]  .. " | lat=" .. string.gsub(ptx[i],"None"," ") .. " | long=" ..string.gsub(pty[i],"None"," ") .. " | image=" .. images[i] .. " | wikidata=" .. string.gsub(wikidata[i],"Wikidata ID","") .. "}}\n"
                end
         	end       	
            output = output .. "* latitude: " .. pty[i] .. " longitude: " .. pty[i]  .. " ... appears to be within the polygon...\n"
           end
	 else
	   if name[i] ~= nil or name[i] ~= "" then	   	
              output = output .. "* latitude: " .. ptx[i] .. " longitude: " .. pty[i]  .. " for '''" .. name[i] .. "'''... appears '''not''' to be within the polygon...\n"
              if marker == "yes" then
--                markertxt = markertxt .. "\*".. i .. ". {{marker | type=vicinity | name=" .. name[i]  .. " | lat=" .. string.gsub(ptx[i],"None"," ") .. " | long=" .. string.gsub(pty[i],"None"," ") .. " | image=" .. images[i] .. " | wikidata=" .. string.gsub(wikidata[i],"Wikidata ID","") .. "}}\n"
                  if oporigtype == "yes" or oporigtype == "both" then
	                    markertxtno = markertxtno .. "\*".. i .. ". {{marker |  type=" .. keeptype[i] .. " | name=" .. name[i]  .. " | lat=" .. string.gsub(ptx[i],"None"," ") .. " | long=" .. string.gsub(pty[i],"None"," ") .. " | image=" .. images[i] .. " | wikidata=" .. string.gsub(wikidata[i],"Wikidata ID","") .. "}}\n"
                      elseif oporigtype == "no" or oporigtype == "both" then
	                    markertxtno = markertxtno .. "\*".. i .. ". {{marker |  type=" .. keeptype[i] .. " | name=" .. name[i]  .. " | lat=" .. string.gsub(ptx[i],"None"," ") .. " | long=" .. string.gsub(pty[i],"None"," ") .. " | image=" .. images[i] .. " | wikidata=" .. string.gsub(wikidata[i],"Wikidata ID","") .. "}}\n"
                      else
	                 markertxtno = markertxtno .. "\*".. i .. ". {{marker | type=vicinity | name=" .. name[i]  .. " | lat=" .. string.gsub(ptx[i],"None"," ") .. " | long=" ..string.gsub(pty[i],"None"," ") .. " | image=" .. images[i] .. " | wikidata=" .. string.gsub(wikidata[i],"Wikidata ID","") .. "}}\n"

                    end
            	end
             else
               output = output ..  "* latitude: " .. ptx[i] .. " longitude: " .. pty[i]  .. "... appears '''not''' to be within the polygon...\n"          
              if marker == "yes" then
--              	markertxt = markertxt .. "\*".. i .. ". {{marker | type=listing | name=NoName"  .. " | lat=" .. string.gsub(ptx[i],"None"," ") .. " | long=" .. string.gsub(pty[i],"None"," ") .. " | image=" .. images[i] .. " | wikidata=" .. string.gsub(wikidata[i],"Wikidata ID","") .."}}\n"
                    if oporigtype == "yes" or oporigtype == "both" then
	                    markertxtno = markertxtno .. "\*".. i .. ". {{marker |  type=" .. keeptype[i] .. " | name=NoName"  .. " | lat=" .. string.gsub(ptx[i],"None"," ") .. " | long=" .. string.gsub(pty[i],"None"," ") .. " | image=" .. images[i] .. " | wikidata=" .. string.gsub(wikidata[i],"Wikidata ID","") .. "}}\n"
                     elseif oporigtype == "no" or oporigtype == "yes" then
	                    markertxtno = markertxtno .. "\*".. i .. ". {{marker |  type=" .. keeptype[i] .. " | name=NoName"  .. " | lat=" .. string.gsub(ptx[i],"None"," ") .. " | long=" .. string.gsub(pty[i],"None"," ") .. " | image=" .. images[i] .. " | wikidata=" .. string.gsub(wikidata[i],"Wikidata ID","") .. "}}\n"
                        else
	                    markertxtno = markertxtno .. "\*".. i .. ". {{marker | type=vicinity | name=NoName"  .. " | lat=" .. string.gsub(ptx[i],"None"," ") .. " | long=" .. string.gsub(pty[i],"None"," ") .. " | image=" .. images[i] .. " | wikidata=" .. string.gsub(wikidata[i],"Wikidata ID","") .. "}}\n"
                     end
	          end       	
          end	  
       end
end -- ENDFor Loop

--       markertxt,_ = string.gsub(markertxt," - $","")
       markertxtyes,_ = string.gsub(markertxtyes," - $","")       
       markertxtno,_ = string.gsub(markertxtno," - $","")
       map = "" 
       if mapframe == "yes" then
           if ptx[1] ~= "None" and pty[1] ~= "None" then
 	         map = '{{mapframe|align=center|height="500"|width="850"|' .. ptx[1] .. '|' .. pty[1] .. '|layer=MS|zoom=7|show=listing,see,do,buy,eat,drink,sleep,around,city,view,site,other,go,vicinity,mask,gold,lime,magenta,mediumaquamarine,orange,plum,red,silver,unknown|name=Inapoly Test}}' .. "\n" .. shape
           elseif makebox ~= nil and makebox ~= "" then
	         local latx = string.gsub(makebox,",.*$","")
	         local longy = string.gsub(makebox,"^.*,","")
 	         map = '{{mapframe|align=center|height="500"|width="850" | ' .. latx .. '|' .. longy .. '| layer=MS|zoom=7|show=listing,see,do,buy,eat,drink,sleep,around,city,view,site,other,go,vicinity,mask,gold,lime,magenta,mediumaquamarine,orange,plum,red,silver,unknown|name=Inapoly Test}}' .. "\n" .. shape
           else	
 	          map = '{{mapframe|align=center|height="500"|width="850"|' .. polyx[1] .. '|' .. polyy[1] .. '|layer=MS|zoom=7|show=listing,see,do,buy,eat,drink,sleep,around,city,view,site,other,go,vicinity,mask,gold,lime,magenta,mediumaquamarine,orange,plum,red,silver,unknown|name=Inapoly Test}}' .. "\n" .. shape
           end
       else
       	   map = ""
       end     -- END MAKE A MAPFRAME WITH MAPMASK
       
       if marker == "no" and text == "yes" then
       	  return map .. "\n----\n" .. output
       end
       if marker == "no" and text == "no" then
       	  return map
       end
 	   if marker == "yes" and text == "no" then
 	   	  if markermatch == "yes" then
             return map .. "\n----\n" .. markertxtyes .. "\n"
           end
           if markermatch == "no" then
              return map .. "\n----\n" .. markertxtno .. "\n"
            end
           if markermatch == "both" then
              return map .. "\n----\n" .. markertxtyes .. "\n----\n" .. markertxtno 
           end
       end
  	   
  	   if marker == "yes" then
  	      if markermatch == "yes" then
  	         if text == "yes" then
  	    	    return map .. "\n----\n" .. markertxtyes .. "\n----\n" .. output
  	  	  	 else
                return map .. "\n----\n" .. markertxtyes
              end
           end
           if markermatch == "no" then
          	  if text == "yes" then
  	  	         return map .. "\n----\n" .. markertxtno .. "\n----\n" .. output
  	  	  	  else
  	  	    	 return  map .. "\n----\n" .. markertxtno
  	  	  	  end
  	       end
  	       if markermatch == "both" then
  	       	  if text == "yes" then
                 return  map .. "\n----\n" .. markertxtyes .. "\n----\n" .. markertxtno .. "\n----\n" .. output
              else              
                  return  map .. "\n----\n" .. markertxtyes .. "\n----\n" .. markertxtno 
              end
           end
        else
           return  map .. "\n----\n" .. markertxtyes .. "\n----\n" .. markertxtno .. output
 	   end

end

return p