Files
OpenSpace/modules/globebrowsing/scripts/layer_support.lua
Emma Broman 1fbd5e827d Utilize new docs functionality in API scripts that are defined in Lua files (#3505)
* Fix a reference to a deprecated and renamed function in navigationstate docs

* Review documentation for scripts defined in .lua files

And utilize new markdown functionality

* Update renderable box grid size specs

So that it can have a size less than 1, and throws a specification error when the size is given as negative

* Fix some issues with the gaia filtering scripts

* Try adding param documentation to the lua script documentation

It works!

* Utiliize mroe markdown features in the updated documentations

* Add function parameter info and make small updated to gaia filtering functions

* Replace a long parameter info in description with `param` description

* Update usage examples

* Add example of how to create debug axes for the current SGN
2025-02-11 08:59:33 +01:00

457 lines
13 KiB
Lua

openspace.globebrowsing.documentation = {
{
Name = "createTemporalGibsGdalXml",
Arguments = {
{ "layerName", "String" },
{ "resolution", "String" },
{ "format", "String" }
},
Return = "String",
Documentation = [[
Creates an XML configuration for a temporal GIBS dataset to be used in a
TemporalTileprovider.
]]
},
{
Name = "createGibsGdalXml",
Arguments = {
{ "layerName", "String" },
{ "date", "String" },
{ "resolution", "String" },
{ "format", "String" }
},
Return = "String",
Documentation = [[
Creates an XML configuration for a GIBS dataset.
For all specifications, see
[this page](https://wiki.earthdata.nasa.gov/display/GIBS/GIBS+Available+Imagery+Products).
Usage:
```lua
openspace.globebrowsing.addLayer(
"Earth",
"ColorLayers",
{
Name = "MODIS_Terra_Chlorophyll_A",
FilePath = openspace.globebrowsing.createGibsGdalXml(
"MODIS_Terra_Chlorophyll_A",
"2013-07-02",
"1km",
"png"
)
}
)
```
]]
},
{
Name = "addGibsLayer",
Arguments = {
{ "layer", "String" },
{ "resolution", "String" },
{ "format", "String" },
{ "startDate", "String" },
{ "endDate", "String" }
},
Documentation = [[
Adds a new layer from NASA GIBS to the Earth globe.
For all specifications, see
[this page](https://wiki.earthdata.nasa.gov/display/GIBS/GIBS+Available+Imagery+Products).
Usage:
```lua
openspace.globebrowsing.addGibsLayer(
"AIRS_Temperature_850hPa_Night", "2km", "2013-07-15", "Present", "png"
)
```
]]
},
{
Name = "parseInfoFile",
Arguments = {
{ "file", "String" }
},
Return = "Table",
Documentation = [[
Parses the passed info file and return the table with the information provided in
the info file.
The return table contains the optional keys: `Color`, `Height`, `Node`, `Location`,
`Identifier`.
Usage:
```lua
local t = openspace.globebrowsing.parseInfoFile(file)
openspace.globebrowsing.addLayer("Earth", "ColorLayers", t.color)
openspace.globebrowsing.addLayer("Earth", "HeightLayers", t.height)
```
]]
},
{
Name = "addBlendingLayersFromDirectory",
Arguments = {
{ "directory", "String" },
{ "nodeName", "String" }
},
Documentation = [[
Retrieves all info files recursively in the directory passed as the first argument
to this function. The color and height tables retrieved from these info files are
then added to the RenderableGlobe identified by name passed to the second argument.
Usage:
```lua
openspace.globebrowsing.addBlendingLayersFromDirectory(directory, "Earth")
```
]]
},
{
Name = "addFocusNodesFromDirectory",
Arguments = {
{ "directory", "String" },
{ "nodeName", "String" }
},
Documentation = [[
Retrieves all info files recursively in the directory passed as the first argument
to this function. The name and location retrieved from these info files are then
used to create new SceneGraphNodes that can be used as focus nodes.
Usage:
```lua
openspace.globebrowsing.addFocusNodesFromDirectory(directory, "Mars")
```
]]
},
{
Name = "addFocusNodeFromLatLong",
Arguments = {
{ "name", "String" },
{ "globeIdentifier", "String" },
{ "latitude", "Number" },
{ "longitude", "Number" },
{ "altitude", "Number?" }
},
Documentation = [[
Creates a new SceneGraphNode that can be used as focus node for a specific point on
a globe. If no altitude is specified, an altitude of 0 will be used.
Usage:
```lua
openspace.globebrowsing.addFocusNodeFromLatLong(
"Olympus Mons", "Mars", -18.65, 226.2, optionalAltitude
)
```
]]
},
{
Name = "loadWMSServersFromFile",
Arguments = {
{ "filePath", "String" }
},
Documentation = [[
Loads all WMS servers from the provided file and passes them to the
'openspace.globebrowsing.loadWMSCapabilities' file.
]]
}
}
openspace.globebrowsing.addGibsLayer = function(layerName, resolution, format, startDate, endDate)
if endDate == "Present" then
endDate = "Today"
end
local layer = {
Identifier = layerName,
Type = "TemporalTileProvider",
Mode = "Prototyped",
Prototyped = {
Time = {
Start = startDate,
End = endDate
},
TemporalResolution = "1d",
TimeFormat = "YYYY-MM-DD",
Prototype = openspace.globebrowsing.createTemporalGibsGdalXml(layerName, resolution, format)
}
}
openspace.globebrowsing.addLayer("Earth", "ColorLayers", layer)
end
openspace.globebrowsing.createGibsGdalXml = function (layerName, date, resolution, format)
local tileLevel = 5
-- These resolutions are defined by GIBS: https://wiki.earthdata.nasa.gov/display/GIBS/GIBS+API+for+Developers#GIBSAPIforDevelopers-Script-levelAccessviaGDAL
if resolution == "2km" then
tileLevel = 5
elseif resolution == "1km" then
tileLevel = 6
elseif resolution == "500m" then
tileLevel = 7
elseif resolution == "250m" then
tileLevel = 8
elseif resolution == "125m" then
tileLevel = 9
elseif resolution == "62.5m" then
tileLevel = 10
elseif resolution == "31.25m" then
tileLevel = 11
elseif resolution == "15.625m" then
tileLevel = 12
else
openspace.printError("Unknown resolution: " .. resolution)
return ""
end
local rasterCount = 3
if format == "jpg" then
if layerName == "ASTER_GDEM_Greyscale_Shaded_Relief" then
rasterCount = 1
else
rasterCount = 3
end
elseif format == "png" then
rasterCount = 4
else
openspace.printError("Unknown format \"" .. format .. "\". Use 'jpg' or 'png'")
return ""
end
local gdalWmsTemplate =
"<GDAL_WMS>" ..
"<Service name=\"TMS\">" ..
"<ServerUrl>https://gibs.earthdata.nasa.gov/wmts/epsg4326/best/" ..
layerName .. "/default/" .. date .. "/" .. resolution ..
"/${z}/${y}/${x}." .. format .. "</ServerUrl>" ..
"</Service>" ..
"<DataWindow>" ..
"<UpperLeftX>-180.0</UpperLeftX>" ..
"<UpperLeftY>90</UpperLeftY>" ..
"<LowerRightX>396.0</LowerRightX>" ..
"<LowerRightY>-198</LowerRightY>" ..
"<TileLevel>" .. tileLevel .. "</TileLevel>" ..
"<TileCountX>2</TileCountX>" ..
"<TileCountY>1</TileCountY>" ..
"<YOrigin>top</YOrigin>" ..
"</DataWindow>" ..
"<Projection>EPSG:4326</Projection>" ..
"<BlockSizeX>512</BlockSizeX>" ..
"<BlockSizeY>512</BlockSizeY>" ..
"<BandsCount>" .. rasterCount .. "</BandsCount>" ..
"<UnsafeSSL>true</UnsafeSSL>" ..
"<ZeroBlockHttpCodes>400,204,404</ZeroBlockHttpCodes>" ..
"<ZeroBlockOnServerException>true</ZeroBlockOnServerException>" ..
"<Timeout>5</Timeout>" ..
"</GDAL_WMS>"
return gdalWmsTemplate
end
openspace.globebrowsing.createTemporalGibsGdalXml = function (layerName, resolution, format)
return openspace.globebrowsing.createGibsGdalXml(layerName, "${OpenSpaceTimeId}", resolution, format)
end
openspace.globebrowsing.parseInfoFile = function (file)
-- We are loading these values from an external info file and since we are switching
-- to a strict Lua, we need to predefine these global variables
local function declare(name)
rawset(_G, name, "")
end
declare("Name")
declare("Identifier")
declare("Description")
declare("ColorFile")
declare("HeightFile")
declare("Location")
declare("ZIndex")
declare("BlendMode")
local dir = openspace.directoryForPath(file)
local file_func, error = loadfile(file)
if file_func then
file_func()
else
openspace.printError('Error loading file "' .. file .. '": '.. error)
return nil
end
-- Hoist the global variables into local space
local Name = rawget(_G, "Name")
local Identifier = rawget(_G, "Identifier")
local Description = rawget(_G, "Description")
local ColorFile = rawget(_G, "ColorFile")
local HeightFile = rawget(_G, "HeightFile")
local Location = rawget(_G, "Location")
local ZIndex = rawget(_G, "ZIndex")
local BlendMode = rawget(_G, "BlendMode")
-- Now we can start
local name = Name or Identifier
local identifier = Identifier
local zIndex = ZIndex
local blendMode = BlendMode
if zIndex == "" then
zIndex = nil
end
if blendMode == "" then
-- Color blending is the default for .info files if nothing else is specified
blendMode = "Color"
end
if identifier == "" then
openspace.printError('Error loading file "' .. file .. '": No "Identifier" found')
return nil
end
local color = nil
if ColorFile and ColorFile ~= "" then
color = {
Identifier = identifier,
Name = name,
Description = Description or "",
FilePath = dir .. "/" .. ColorFile,
BlendMode = blendMode,
ZIndex = zIndex
}
end
local height = nil
if HeightFile and HeightFile ~= "" then
height = {
Identifier = identifier,
Name = name,
Description = Description or "",
FilePath = dir .. "/" .. HeightFile,
TilePixelSize = 65,
ZIndex = zIndex
}
end
local location = nil
if Location then
location = Location
end
return {
Color = color,
Height = height,
Name = name,
Location = location,
Identifier = identifier
}
end
openspace.globebrowsing.addBlendingLayersFromDirectory = function (dir, node_name)
local function ends_with(str, ending)
return ending == "" or str:sub(-#ending) == ending
end
-- Walking the directory with an empty string will cause the current working directory
-- to be walked recursively. This is probably not what the users expects (and it is
-- also one of the default values in the globebrowsing customization script), so we
-- ignore the empty string here
if dir == nil or dir == "" then
openspace.printError("No directory specified")
return
end
if node_name == nil or node_name == "" then
openspace.printError("No node name specified")
return
end
local files = openspace.walkDirectoryFiles(dir, true, true)
for _, file in pairs(files) do
if file and file:find(".info") and ends_with(file, ".info") then
local t = openspace.globebrowsing.parseInfoFile(file)
if t and t.Color then
openspace.printInfo("Adding color layer '" .. t.Color["Identifier"] .. "'")
openspace.globebrowsing.addLayer(node_name, "ColorLayers", t.Color)
end
if t and t.Height then
openspace.printInfo("Adding height layer '" .. t.Height["Identifier"] .. "'")
openspace.globebrowsing.addLayer(node_name, "HeightLayers", t.Height)
end
end
end
end
openspace.globebrowsing.addFocusNodesFromDirectory = function (dir, node_name)
local files = openspace.walkDirectoryFiles(dir, true, true)
for _, file in pairs(files) do
if file and file:find(".info") then
local t = openspace.globebrowsing.parseInfoFile(file)
if node_name and t and t.Location then
openspace.printInfo("Creating focus node for '" .. node_name .. "'")
local lat = t.Location.Center[1]
local long = t.Location.Center[2]
local identifier = node_name .. " - " .. t.Identifier
local name = node_name .. " - " .. t.Name
openspace.addSceneGraphNode({
Identifier = identifier,
Parent = node_name,
Transform = {
Translation = {
Type = "GlobeTranslation",
Globe = node_name,
Latitude = lat,
Longitude = long,
UseHeightmap = true
}
},
GUI = {
Path = "/Other/Bookmarks",
Name = name
}
})
end
end
end
end
openspace.globebrowsing.addFocusNodeFromLatLong = function (name, globe_identifier, lat, long, altitude)
altitude = altitude or 0;
local identifier = globe_identifier .. "-" .. name
openspace.addSceneGraphNode({
Identifier = identifier,
Parent = globe_identifier,
Transform = {
Translation = {
Type = "GlobeTranslation",
Globe = globe_identifier,
Latitude = lat,
Longitude = long,
FixedAltitude = altitude
}
},
GUI = {
Path = "/Other/Bookmarks",
Name = identifier
}
})
return identifier
end
openspace.globebrowsing.loadWMSServersFromFile = function (file_path)
local servers = dofile(file_path)
for key, value in pairs(servers) do
local globe = key
for _,val in pairs(value) do
openspace.globebrowsing.loadWMSCapabilities(val["Name"], globe, val["URL"] )
end
end
end