Skip to content

Instantly share code, notes, and snippets.

@pigeonhill

pigeonhill/TILT.LUA

Last active May 10, 2020
Embed
What would you like to do?
Tilter Scripr
--[[
Tilter
Release 0.86
May 2020
Copyleft: Garry George 2020
photography.grayheron.net
--]]
require("config")
change_key = KEY.MENU
trigger_time = dryos.ms_clock
trigger_delay = 2000
toggle_screen = false
last_key = 0
infinity = 655241 -- trap ML reported infinity
tilt_angle = 0
f = lens.focal_length
fov = 0
tanal = 0
cot = 0
max_mag = 0.34
min_x = 210 -- in mm
fovang = 0
lens_t = (max_mag*min_x - f*(1+max_mag)*(1+max_mag))/max_mag -- lens 'thickness' based on a split thin lens model
x = lens.focus_distance
a = camera.aperture.value
H = lens.hyperfocal - f -- referenced to the lens front principal plane
angu = 0
angl = 0
ang = 0
jx = 0
ux = 0
J = 0
J_in = 0
rad = 100
H_scale = 3
text1 = " "
text2 = " "
text3 = " "
text4 = " "
text5 = " "
image_taken = false -- that is at least one has been taken
choices0 = {"OFF","ON"}
choices1 = {"Landscape","Portrait","L:Fully Shifted","P:Fully Shifted"}
choices2 = {"Text Only","Small","Medium","Large"}
switched_off = false
turned_off = false
function u(xx) -- focus distance from front lens principal plane
local u = xx - lens_t - (1+max_mag*min_x/xx)*f
return u
end
function my_display(text,time,x_pos,y_pos)
text = string.rep("\n",y_pos)..string.rep(" ",x_pos)..text
display.notify_box(text,time*1000)
end
function myround(nu,dp)
-- nu = a number, dp = decimal places required to show
-- returns number as a string
if dp == 0 then
nu = tostring(math.floor(nu))
else
nu = tostring(math.floor(nu)).."."..string.sub(tostring(math.floor(nu*10^dp)),-dp,-1)
end
return nu
end
function update()
tilt_angle = menu.get("Tilter","Hinge Angle",1)/10
f = lens.focal_length -- added to allow f to vary when not using a TS-E prime (albeit with a fixed lens thickness)
H = u(lens.hyperfocal) -- Split thin lens estimate H from front principal plane
x = lens.focus_distance -- sensor to focus distance as reported by Canon/ML
ux = u(x) -- estimate of focus distance from front 'principal' plane: assuming a split thin lens model
a = camera.aperture.value
J = f/math.sin(math.rad(menu.get("Tilter","Hinge Angle",1)/10))
jx = J*ux/H -- depth of field at ux, parallel to the sensor, based on the DoF at H being J parallel to the sensor
ang = math.atan(J/ux) -- angle of plane of sharp focus
angu = math.atan((J+jx)/ux) -- angle of upper (or near) DoF
angl = math.atan((J-jx)/ux) -- angle of lower (or far) DoF
if menu.get("Tilter","Orientation"," ") == "Landscape" then
fovang = 24
elseif menu.get("Tilter","Orientation"," ") == "Portrait" then
fovang = 36
elseif menu.get("Tilter","Orientation"," ") == "L:Fully Shifted" then
fovang = 48
elseif menu.get("Tilter","Orientation"," ") == "P:Fully Shifted" then
fovang = 60
end
fov = math.atan(fovang/(2*f)) -- in radians
local len = FONT.MED:width(text1)
display.print(text1,720 - len, 40, FONT.MED,COLOR.TRANSPARENT,COLOR.TRANSPARENT)
len = FONT.MED:width(text2)
display.print(text2,720 - len, 70, FONT.MED,COLOR.TRANSPARENT,COLOR.TRANSPARENT)
len = FONT.MED:width(text3)
display.print(text3,720 - len, 100, FONT.MED,COLOR.TRANSPARENT,COLOR.TRANSPARENT)
len = FONT.MED:width(text4)
display.print(text4,720 - len, 130, FONT.MED,COLOR.TRANSPARENT,COLOR.TRANSPARENT)
len = FONT.MED:width(text5)
display.print(text5,720 - len, 160, FONT.MED,COLOR.TRANSPARENT,COLOR.TRANSPARENT)
text1 = "(U):"..myround(math.deg(angu),0).."deg "
len = FONT.MED:width(text1)
display.print(text1,720 - len, 40, FONT.MED, COLOR.WHITE,COLOR.TRANSPARENT_BLACK)
text2 = "(F):"..myround(math.deg(ang),0).."deg "
len = FONT.MED:width(text2)
display.print(text2,720 - len, 70, FONT.MED, COLOR.WHITE,COLOR.TRANSPARENT_BLACK)
text3 = "(L):"..myround(math.deg(angl),0).."deg "
len = FONT.MED:width(text3)
display.print(text3,720 - len, 100, FONT.MED, COLOR.WHITE,COLOR.TRANSPARENT_BLACK)
if J == infinity then text4 = "(J): @ Inf" else text4 = "(J):"..myround(J/10,0).."cm " end
len = FONT.MED:width(text4)
display.print(text4,720 - len, 130, FONT.MED, COLOR.WHITE,COLOR.TRANSPARENT_BLACK)
text5 = "U-FoV:"..myround(math.deg(fov),0).."deg "
len = FONT.MED:width(text5)
display.print(text5,720 - len, 160, FONT.MED, COLOR.WHITE,COLOR.TRANSPARENT_BLACK)
if menu.get("Tilter","Scale"," ") ~= "Text Only" then -- draw graphics
if menu.get("Tilter","Scale"," ") == "Small" then
rad = 100
elseif menu.get("Tilter","Scale"," ") == "Medium" then
rad = 150
else
rad = 200
end
display.circle(rad,240,3,COLOR.TRANSPARENT,COLOR.TRANSPARENT)
display.circle(0,240,rad,COLOR.TRANSPARENT_BLACK,COLOR.TRANSPARENT_BLACK)
display.line(rad/H_scale,240-0.94*rad,rad/H_scale,240+math.sqrt((H_scale*H_scale - 1)/(H_scale*H_scale))*rad,COLOR.LIGHT_GRAY)
do -- display 15 degree tick marks
local var, limit, step = -75, 75, 15
while (var <= limit) do
local x1 = rad*math.cos(math.rad(var))
local y1 = 240-rad*math.sin(math.rad(var))
local x2 = (rad-10)*math.cos(math.rad(var))
local y2 = 240-(rad-10)*math.sin(math.rad(var))
display.line(x1,y1,x2,y2,COLOR.LIGHT_GRAY)
var = var + step
end
end
if tilt_angle ~=0 then
display.line(0,240,rad*math.cos(ang),240-rad*math.sin(ang),COLOR.YELLOW)
display.line(0,240,rad*math.cos(angu),240-rad*math.sin(angu),COLOR.YELLOW)
display.line(0,240,rad*math.cos(angl),240-rad*math.sin(angl),COLOR.YELLOW)
end
local minrad = 8
display.circle(0,240,minrad,COLOR.RED,COLOR.RED)
local temp = rad*J/(H*H_scale)
temp = math.sqrt(rad*rad - temp*temp)
display.circle(rad,240,5,COLOR.TRANSPARENT,COLOR.TRANSPARENT)
display.line(10,240,rad,240,COLOR.WHITE)
display.line(rad*2/H_scale,240-5,rad*2/H_scale,240+5,COLOR.WHITE)
if J < H_scale*H then
local sJ = rad*J/(H*H_scale)
display.line(0,(240 - sJ),math.sqrt(rad*rad - sJ*sJ),(240 - sJ),COLOR.ORANGE)
display.rect(0, (240 - sJ)-4, 5, 8, COLOR.ORANGE, COLOR.ORANGE)
if fovang ~= 0 then
cot = ((2*f)/fovang)*((2*f)/fovang)
local y1 = (sJ*cot + math.sqrt(rad*rad*(1+cot) - sJ*sJ*cot))/(1+cot)
local x1 = math.sqrt(rad*rad - y1*y1)
display.line(0,(240 - sJ),x1,(240 - y1),COLOR.ORANGE)
y1 = (sJ*cot - math.sqrt(rad*rad*(1+cot) - sJ*sJ*cot))/(1+cot)
x1 = math.sqrt(rad*rad - y1*y1)
display.line(0,(240 - sJ),x1,(240 - y1),COLOR.ORANGE)
end
end
if x > H_scale*H then
display.circle(rad,240 ,5,COLOR.RED,COLOR.RED)
elseif x >= H and x <= H_scale*H then
display.circle(rad*ux/(H*H_scale),240,5,COLOR.GREEN1,COLOR.GREEN1)
else
display.circle(rad*ux/(H*H_scale),240,5,COLOR.YELLOW,COLOR.YELLOW)
end
display.circle(0,240,rad,COLOR.WHITE)
display.circle(0,240,rad+1,COLOR.WHITE)
if menu.get("Tilter","Ground Focus"," ") == "ON" then
local xf24 = 2*f*J/24
local xf36 = 2*f*J/36
local xf48 = 2*f*J/48
local xf60 = 2*f*J/60
if ux < xf60 then display.circle(10,340,5,COLOR.WHITE,COLOR.RED) else display.circle(10,340,5,COLOR.WHITE,COLOR.GREEN1) end
if ux < xf48 then display.circle(30,340,5,COLOR.WHITE,COLOR.RED) else display.circle(30,340,5,COLOR.WHITE,COLOR.GREEN1) end
if ux < xf36 then display.circle(50,340,5,COLOR.WHITE,COLOR.RED) else display.circle(50,340,5,COLOR.WHITE,COLOR.GREEN1) end
if ux < xf24 then display.circle(70,340,5,COLOR.WHITE,COLOR.RED) else display.circle(70,340,5,COLOR.WHITE,COLOR.GREEN1) end
end
end
end
function check_stuff()
if (lv.running and (not menu.visible)) and toggle_screen == true then
if menu.get("Overlay","Global Draw",0) == 0 then
menu.set("Overlay","Global Draw",1)
else
menu.set("Overlay","Global Draw",0)
end
toggle_screen = false
return
end
if (lv.overlays == 2 and not menu.visible) then
if (not switched_off) and (string.find(lens.name,"TS") ~= nil) then
display.draw(update)
turned_off = false
elseif (not turned_off) then
display.clear()
turned_off = true
end
end
end
Tilter_Menu = menu.new
{
parent = "Focus",
name = "Tilter",
help = "Helps with TS-E focusing and bracketing",
depends_on = DEPENDS_ON.LIVEVIEW,
submenu =
{
{
name = "ON or Off?",
help = "Switches the script on & off",
choices = choices0,
update = function(this)
if this.value == "ON" then
switched_off = false
turned_off = false
else
switched_off = true
turned_off = false
end
end,
},
{
name = "Hinge Angle",
help = "In 1/10 degrees increments",
min = 3,
max = 85,
value = 6,
rinfo = function(this)
tilt_angle = this.value/10
J = f/math.sin(math.rad(tilt_angle)) -- hinge height in mm
if J >= infinity then
J = infinity
return "J @ Inf"
else
J_in = myround(J/(25.5*12),1)
return myround(J/10,0).."cm".."/"..J_in.."ft"
end
end,
},
{
name = "Orientation",
help = "Used to show FoV",
choices = choices1,
},
{
name = "Ground Focus",
help = "Used to show if Focus > FoV = Green",
help2 = "left to Right:shifted-Port, shifted-Lan,Port, ",
choices = choices0,
},
{
name = "Scale",
help = "Used to adjust the display scale",
choices = choices2,
value = "Text Only",
},
}
}
if (x==0 or a==0 or f==0) then
my_display("Can't use script",2,0,0)
ok_2_go = false
menu.set("Focus","Tilter","OFF")
return
end
event.shoot_task = check_stuff
config.create_from_menu(Tilter_Menu) -- keep a track of the script's menu state at camera close
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.