local p = {}
local redvalue = 0
local greenvalue = 0
local bluevalue = 0
local function nm2RGB(wavelength, IFcorrect)
-- code based on an algorithm from Dan Bruton's Color Science Page: http://www.physics.sfasu.edu/astro/color/spectra.html
-- calculating RGB color components
if (wavelength >= 380) and (wavelength < 440) then
redvalue = (440 - wavelength) / 90
greenvalue = 0
bluevalue = 1
elseif (wavelength >= 440) and (wavelength < 490) then
redvalue = 0
greenvalue = (wavelength - 440) / 50
bluevalue = 1
elseif (wavelength >= 490) and (wavelength < 510) then
redvalue = 0
greenvalue = 1
bluevalue = (510 - wavelength) / 20
elseif (wavelength >= 510) and (wavelength < 580) then
redvalue = (wavelength - 510) / 70
greenvalue = 1
bluevalue = 0
elseif (wavelength >= 580) and (wavelength < 645) then
redvalue = 1
greenvalue = (645 - wavelength) / 65
bluevalue = 0
elseif (wavelength >= 645) and (wavelength < 780) then
redvalue = 1
greenvalue = 0
bluevalue = 0
end
-- calculating intensity correction factor
if IFcorrect then
local intensityfactor = 0
if (wavelength >= 380) and (wavelength < 420) then
intensityfactor = 0.3 + 0.7*(wavelength - 350) / 70
elseif (wavelength >= 420) and (wavelength <= 700) then
intensityfactor = 1
elseif (wavelength > 700) and (wavelength <= 780) then
intensityfactor = 0.3 + 0.7*(780 - wavelength) / 80
end
redvalue = redvalue * intensityfactor
greenvalue = greenvalue * intensityfactor
bluevalue = bluevalue * intensityfactor
end
end
function p.emission(frame)
-- this function returns the string "#RRGGBB" with approximate RGB value for a wavelength passed as a first argument
local wavelength = tonumber(frame.args[1])
nm2RGB(wavelength, true)
local result='#' .. string.format("%.2X%.2X%.2X", 255*redvalue, 255*greenvalue, 255*bluevalue)
return result
end
local function absorption_to_visible(wavelength_abs)
-- code based on a color wheel drawn at: http://www2.chemistry.msu.edu/faculty/reusch/virttxtjml/spectrpy/uv-vis/spectrum.htm
local wavelength_vis
local minVioletIndigo = 400
local maxVioletIndigo = 430
local widthVioletIndigo = maxVioletIndigo - minVioletIndigo
local minBlue = 430
local maxBlue = 490
local widthBlue = maxBlue - minBlue
local minGreen = 490
local maxGreen = 560
local widthGreen = maxGreen - minGreen
local minYellow = 560
local maxYellow = 580
local widthYellow = maxYellow - minYellow
local minOrange = 580
local maxOrange = 620
local widthOrange = maxOrange - minOrange
local minRed = 620
local maxRed = 800
local widthRed = maxRed - minRed
if (wavelength_abs>minVioletIndigo) and (wavelength_abs<=maxVioletIndigo) then
wavelength_vis = (wavelength_abs - minVioletIndigo)*widthYellow/widthVioletIndigo + minYellow
elseif (wavelength_abs>minBlue) and (wavelength_abs<=maxBlue) then
wavelength_vis = (wavelength_abs - minBlue)*widthOrange/widthBlue + minOrange
elseif (wavelength_abs>minGreen) and (wavelength_abs<=maxGreen) then
wavelength_vis = (wavelength_abs - minGreen)*widthRed/widthGreen + minRed
elseif (wavelength_abs>minYellow) and (wavelength_abs<=maxYellow) then
wavelength_vis = (wavelength_abs - minYellow)*widthVioletIndigo/widthYellow + minVioletIndigo
elseif (wavelength_abs>minOrange) and (wavelength_abs<=maxOrange) then
wavelength_vis = (wavelength_abs - minOrange)*widthBlue/widthOrange + minBlue
elseif (wavelength_abs>minRed) and (wavelength_abs<=maxRed) then
wavelength_vis = (wavelength_abs - minRed)*widthGreen/widthRed + minGreen
end
return wavelength_vis
end
function p.absorption(frame)
-- this function returns the string "#RRGGBB" with approximate RGB value for a complementary color (reflection) to a color, defined as a wavelength passed as a first argument
local wavelength = tonumber(frame.args[1])
nm2RGB(absorption_to_visible(wavelength), false)
local result='#' .. string.format("%.2X%.2X%.2X", 255*redvalue, 255*greenvalue, 255*bluevalue)
return result
end
function p.absorption_old(frame)
-- this function returns the string "#RRGGBB" with approximate RGB value for a complementary color (reflection) to a color, defined as a wavelength passed as a first argument
-- The following formula is used for the complimentary color: {0xFF - RR, 0xFF - (RR + BB)/2, 0xFF - BB}
-- local wavelength = tonumber(frame.args[1])
-- nm2RGB(wavelength)
-- local result='#' .. string.format("%.2X%.2X%.2X", 255*(1-redvalue), 255*(1-greenvalue), 255*(1-bluevalue))
local wavelength = tonumber(frame.args[1])
local redsum = 0
local greensum = 0
local bluesum = 0
local intensityfactor = 0
local numofitems = 400
-- for wlcycle = 380,780,1 do
-- nm2RGB(wlcycle, false)
-- if wlcycle < wavelength then
-- intensityfactor = (wlcycle - 380) / (wavelength - 380)
-- else
-- intensityfactor = (wlcycle - wavelength) / (380 - wavelength) + 1
-- end
-- if intensityfactor < 0 then
-- intensityfactor = 0
-- numofitems = numofitems - 1
-- end
-- redsum = redsum + redvalue*intensityfactor*1.8
-- greensum = greensum + greenvalue*intensityfactor*1.5
-- bluesum = bluesum + bluevalue*intensityfactor*1
-- end
-- local result='#' .. string.format("%.2X%.2X%.2X", 255*(redsum/numofitems), 255*(greensum/numofitems), 255*(bluesum/numofitems))
nm2RGB(1160-wavelength, true)
local result='#' .. string.format("%.2X%.2X%.2X", 255*redvalue, 255*bluevalue, 255*greenvalue)
return result
end
return p