Last active
May 10, 2020 20:00
-
-
Save pigeonhill/2c799711e1a774b4ebe1ef09d2d95749 to your computer and use it in GitHub Desktop.
Tilter Scripr
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--[[ | |
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