Module:Boundaries
More actions
This is a documentation subpage for Boundaries. It contains usage information, categories, and other content that is not part of the original template.
This module stores boundary polygons for geographic entities on the wiki. Growing regions, growing areas, appellations and admin subdivisions all read their polygon from a single keyed entry, replacing the inline boundary= parameters that previously lived on each page.
The entries themselves are kept on data subpages, one per tier and longitude band (see below). This page holds only the code that finds a key on them, so every call below works whichever subpage holds the entry.
Schema
Each entry is a Lua table with five fields:
| Field | Type | Description |
|---|---|---|
polygon |
string | Vertex string in lat,lng;lat,lng format. See format below.
|
style |
string | Provenance signal: editorial, admin, or derived.
|
source |
string | Human-readable note on origin, e.g. "Freehand trace, geojson.io" or "OSM relation 18547452". |
vertices |
number | Vertex count. |
area_km2 |
number | Computed area in square kilometres. |
Functions
All functions are called via {{#invoke:Boundaries|function}}. Each looks up an entry using the lookup priority described below.
| Function | Returns |
|---|---|
get |
Polygon string. Empty if no entry. |
getStyle |
Style value (editorial, admin, or derived). Empty if no entry.
|
getSource |
Provenance string. |
getMeta |
Formatted summary: Source: X · N vertices · ~Y km². Useful on talk pages.
|
has |
"yes" if entry exists, empty otherwise.
|
listKeys |
Bulleted list of all registered keys, sorted alphabetically. |
Lua modules can also call it directly: require('Module:Boundaries').get(frame), with the key as the frame's first argument.
Lookup priority
The key used to look up an entry is resolved in this order:
- Explicit positional argument:
{{#invoke:Boundaries|get|Some Name}}(pass it as1=when the value might contain an equals sign) - Parent template's
boundary_keyparameter, when invoked from inside a template that exposes one {{PAGENAME}}as fallback
Most page-level usage works without arguments. An infobox calls {{#invoke:Boundaries|get}} and the page name resolves the lookup automatically.
Data subpages
The entries are split by tier and by longitude band so that no page comes near the wiki's page-size limit. Each subpage returns a plain table of entries and is read with mw.loadData, which loads it once per page render however many calls the page makes. A key is on one subpage only.
| Tier | Americas | West | Central | Central-East | East | East-95 | East-100 |
|---|---|---|---|---|---|---|---|
| Appellations | Americas | West | Central | Central-East | East | (in East) | East-100 |
| Growing areas | Americas | West | Central | Central-East | East | (in East) | East-100 |
| Growing regions | Americas | West | Central | Central-East | East | East-95 | East-100 |
| Admin subdivisions | Module:Boundaries/Admin | ||||||
The band of a new entry is the mean longitude of all its vertices:
| Band | Mean longitude | Covers |
|---|---|---|
| Americas | west of 25°W | the Americas and the eastern Pacific |
| West | 25°W to 60°E | Europe, Africa and West Asia |
| Central | 60°E to 77°E | Central Asia, Afghanistan, Pakistan, Kashmir and western India |
| Central-East | 77°E to 90°E | the Himalaya from Kullu east, eastern Kyrgyzstan, Xinjiang east of Kashgar, the rest of India, Nepal and Sri Lanka |
| East | 90°E to 100°E (growing regions: 90°E to 95°E) | Tibet, Bhutan, Myanmar and Thailand; for growing regions, Bhutan, Northeast India, Bangladesh and southern Siberia |
| East-95 | 95°E to 100°E, growing regions only | eastern Tibet, Myanmar, Thailand and northern Sumatra |
| East-100 | 100°E and east | Yunnan, Laos, Vietnam, Cambodia, the rest of China, Japan, Southeast Asia and Oceania |
An entry stays on its subpage when its polygon is redrawn, even if the redraw moves its mean longitude across a band edge. An entry moved to another tier goes to its new tier's subpage for its band. Each subpage is kept under 450,000 bytes; a band that outgrows that is split in two, and the new subpage is added to the DATA list in this module in the same edit.
Polygon string format
Polygons are stored as flat strings rather than nested tables for compatibility with SMW Text properties and direct embedding in HTML data- attributes:
lat,lngper vertex, comma-separated;separates vertices within one polygon:separates polygons in a multipolygon- No closing repeat: the rendering layer closes the ring implicitly
Single polygon:
32.07413,77.27155;32.07296,77.27128;...;32.07156,77.27403
Multipolygon (used for entities with disconnected lobes, e.g. The Dooars):
26.57477,89.14644;...;26.56641,89.15261:26.33025,88.72855;...;26.29716,88.73344
Style values
The style field signals provenance and is read by the JS renderer to apply visual styling.
| Style | Meaning |
|---|---|
editorial |
Hand-traced polygon, typically via geojson.io. Default rendering: slate-blue fill, palette-by-neighbour on the multi-polygon home map view. |
admin |
Fetched from OSM administrative relations. Solid grey, thin stroke, minimal fill. |
derived |
Computed by derive_boundaries.py as the morphological union of child entries (e.g. a growing region derived from its growing areas, or a valley derived from its appellations). Rendered identically to editorial.
|
Adding or modifying entries
Add or change an entry on the data subpage that holds it (or, for a new entry, the subpage of its tier and band); this page needs no edit. Entries use the same block format on every subpage:
["Some Name"] = {
polygon = "lat,lng;lat,lng;...",
style = "editorial",
source = "...",
vertices = 123,
area_km2 = 456.78,
},
Derived entries (regions, valleys) regenerate via the local derive_boundaries.py pipeline, which reads all the subpages together and writes the whole table as one file; the changed entries are then copied to their subpages. After a change, null-edit the affected pages so SMW reindexes the new boundary.
Used by
{{Infobox Growing Region}}{{Infobox Growing Area}}{{Infobox Appellation}}{{Infobox Admin Subdivision}}(whenboundary_keyis set){{Infobox accession}}(the border of the accession's appellation on its map)- Module:Population (the border of a population's appellation or growing area, through
require) {{Home/ConservationPanel}}(indirectly, via SMWHas boundaryqueries)
Semantic properties
Each infobox that reads from this module also writes the polygon to Has boundary (type Text), enabling tier-specific queries from the home map and other contexts:
[[Category:Growing Areas]][[Has boundary::+]]|?Has boundary|?Has area name
See also
- Property:Has boundary
- MediaWiki:Common.js
- Template:Infobox Growing Area
- Template:Infobox Appellation
-- Module:Boundaries
-- Border polygons of growing regions, growing areas, appellations and admin subdivisions.
-- The entries are kept on data subpages, one per tier and longitude band (listed in DATA below), so that no page
-- nears the wiki's page-size limit. This module finds a key on them; its functions and arguments are unchanged.
-- Schema, the band rule and the subpages: Module:Boundaries/doc.
local p = {}
-- Searched in this order. A key is on one subpage only.
local DATA = {
"Module:Boundaries/Appellations/Americas",
"Module:Boundaries/Appellations/West",
"Module:Boundaries/Appellations/Central",
"Module:Boundaries/Appellations/Central-East",
"Module:Boundaries/Appellations/East",
"Module:Boundaries/Appellations/East-100",
"Module:Boundaries/Areas/Americas",
"Module:Boundaries/Areas/West",
"Module:Boundaries/Areas/Central",
"Module:Boundaries/Areas/Central-East",
"Module:Boundaries/Areas/East",
"Module:Boundaries/Areas/East-100",
"Module:Boundaries/Regions/Americas",
"Module:Boundaries/Regions/West",
"Module:Boundaries/Regions/Central",
"Module:Boundaries/Regions/Central-East",
"Module:Boundaries/Regions/East",
"Module:Boundaries/Regions/East-95",
"Module:Boundaries/Regions/East-100",
"Module:Boundaries/Admin",
}
-- mw.loadData reads each subpage once per page render, however many times it is called.
local function findEntry(key)
for _, page in ipairs(DATA) do
local e = mw.loadData(page)[key]
if e then return e end
end
return nil
end
local function getKey(frame)
local args = frame.args
if args[1] and args[1] ~= "" then return args[1] end
local pframe = frame:getParent()
if pframe and pframe.args and pframe.args.boundary_key and pframe.args.boundary_key ~= "" then
return pframe.args.boundary_key
end
return mw.title.getCurrentTitle().text
end
local function getEntry(frame)
return findEntry(getKey(frame))
end
function p.get(frame)
local e = getEntry(frame); return e and e.polygon or ""
end
function p.getStyle(frame)
local e = getEntry(frame); return e and e.style or ""
end
function p.getSource(frame)
local e = getEntry(frame); return e and e.source or ""
end
function p.getMeta(frame)
local e = getEntry(frame)
if not e then return "" end
return string.format("Source: %s · %d vertices · ~%.1f km²", e.source, e.vertices, e.area_km2)
end
function p.has(frame)
return getEntry(frame) and "yes" or ""
end
function p.listKeys(frame)
local keys, seen = {}, {}
for _, page in ipairs(DATA) do
for k in pairs(mw.loadData(page)) do
if not seen[k] then seen[k] = true; table.insert(keys, k) end
end
end
table.sort(keys)
local out = {}
for _, k in ipairs(keys) do table.insert(out, "* [[" .. k .. "]]") end
return table.concat(out, "\n")
end
return p