I am working on an a Ray Tracer for optical lens. Currently my code takes in a list of lens data:
{{'Number','Number', {'Number','Number'},'Number','Number'}, ... }
And a list of ray data:
{{'Number',{'Number','Number'}}, ... }
My problem is getting the data in this form for arbitrarily many rays and lenses. I can use the controls I learned from the documentation just fine for a predetermined number of rays and lens. However I would like this adjustable.
Ideally, the user would be able to select the number and then be able to input the specifications accordingly. The problem is that I can not figure out how to implement this.
Does anyone have any advice on which controls allow for more arbitrary inputs?
This is what I am working with. As you can see it is painfully long and limited.
Manipulate[Pause[1];Show[beamSysIter[{{a1,{x1,y1}},{a2,{x2,y2}},{a3,{x3,y3}},{a4,{x4,y4}},{a5,{x5,y5}},{a6,{x6,y6}},{a7,{x7,y7}},{a8,{x8,y8}},{a9,{x9,y9}}}, {{RL1,RR1,{Cx1,Cy1}, d1,h1},{RL2,RR2,{Cx2,Cy2}, d2,h2},{RL3,RR3,{Cx3,Cy3}, d3,h3},{RL4,RR4,{Cx4,Cy4}, d4,h4},{RL5,RR4,{Cx5,Cy5}, d5,h5}}, axl, axu, ayl, ayu, maxLens,maxRays]],OpenerView[{"Lens1", Column[{Control[{RL1,3}],Control[{RR1,-3}],Control[{Cx1,.0}],Control[{Cy1,.0}],{Control[{d1,.4}]},Control[{h1,3/2}]}]}] ,OpenerView[{"Lens2", Column[{Control[{RL2,3}],Control[{RR2,-3}],Control[{Cx2,2}],Control[{Cy2,.0}],{Control[{d2,.4}]},Control[{h2,3/2}]}]}] ,OpenerView[{"Lens3", Column[{Control[{RL3,3}],Control[{RR3,-3}],Control[{Cx3,4}],Control[{Cy3,.0}],{Control[{d3,.4}]},Control[{h3,3/2}]}]}] ,OpenerView[{"Lens4", Column[{Control[{RL4,3}],Control[{RR4,-3}],Control[{Cx4,6}],Control[{Cy4,.0}],Control[{C43,.0}],{Control[{d4,.4}]},Control[{h4,3/2}]}]}] ,OpenerView[{"Lens5", Column[{Control[{RL5,3}],Control[{RR5,-3}],Control[{Cx5,.0}],Control[{Cy5,.0}],Control[{d5,.4}],Control[{h5,3/2}]}]}] ,OpenerView[{"Graph", Column[{Control[{maxLens,3}],Control[{maxRays,3}],Control[{axl,-3}],Control[{axu,15}],Control[{ayl,-3}],Control[{ayu,3}]}]}],OpenerView[{"Ray1", Column[{Control[{a1,0}],Control[{x1,-1}],Control[{y1,.1}]}]}],OpenerView[{"Ray2", Column[{{Control[{a2,0}]},{Control[{x2,-1}]},Column[{Control[{y2,-.1}]}]}]}],OpenerView[{"Ray3", Column[{{Control[{a3,0}]},{Control[{x3,-1}]},Column[{Control[{y3,.5}]}]}]}],OpenerView[{"Ray4", Column[{{Control[{a4,0}]},{Control[{x4,-1}]},Column[{Control[{y4,-.5}]}]}]}],OpenerView[{"Ray5", Column[{{Control[{a5,0}]},{Control[{x5,-1}]},Column[{Control[{y5,-.5}]}]}]}],OpenerView[{"Ray6", Column[{{Control[{a6,0}]},{Control[{x6,-1}]},Column[{Control[{y6,-.5}]}]}]}],OpenerView[{"Ray7", Column[{{Control[{a7,0}]},{Control[{x7,-1}]},Column[{Control[{y7,-.5}]}]}]}],OpenerView[{"Ray8", Column[{{Control[{a8,0}]},{Control[{x8,-1}]},Column[{Control[{y8,-.5}]}]}]}],OpenerView[{"Ray9", Column[{{Control[{a9,0}]},{Control[{x9,-1}]},Column[{Control[{y9,-.5}]}]}]}],ControlPlacement -> Left, ContinuousAction -> False]
The updated GUI with Kuba's code.
gui[]:=DynamicModule[{lenses={},rays={}, axl,axu,ayl,ayu}, Panel@Grid[{{Panel@Dynamic[beamSysIter[Column@lenses,Column@rays,Column@{xl,axu,ayl,ayu}]],TabView[{"Lenses"->repeatedController[Dynamic@lenses,lensController{0{0,0}},"Lens"],"Rays">repeatedController[Dynamic@rays,rayController, {0,0,{0,0},0,0}, "Ray"],"Graph spec"->graphSpecController[Dynamic[{axl, axu, ayl, ayu}]]}]}},Alignment->{Left,Top}],Initialization:>{}
]
repeatedController[Dynamic[var_], controller_:Slider, def_:0,lbl_String:""]:= DynamicModule[{n = Length[var]},
Column[{
Button["+", AppendTo[var, def]; n++;],
Dynamic[
Delete[var, #]]}]
}, True] &@i, {i, n}]
, Alignment -> {Left, Center}],
TrackedSymbols :> {n}
]
}, BaseStyle ->
ButtonBoxOptions -> {ImageSize -> All, FrameMargins -> 5,
ContentPadding -> False}]
];
graphSpecController[spec:Dynamic[{__Symbol}]]:= Column[ Slider /@ Thread @ spec ]
lensController[Dynamic[var_]]:=DynamicModule[{temp=var}
,
Grid[{
{"a", "x", "y"},
InputField[Dynamic[temp[[##]],{Automatic, (var = temp)&}], ImageSize->50]& @@@ {{1},{2,1},{2,2}}
}, Alignment->{Center,Center},Spacings->{0,0}]
];
rayController[Dynamic[var_]]:=DynamicModule[{temp=var}
,
Grid[{
{"RL", "RR", "Cx","Cy","d1","h1"},
InputField[Dynamic[temp[[##]],{Automatic, (var = temp)&}], ImageSize->50]& @@@ {{1},{2},{3,1},{3,2},{4},{5}}
},Column[Table[OpenerView[{StringTemplate["`` ``"][lbl,#],
Row[{controller[Dynamic[var[[#]]]],Button["-", n--; var =Delete[var, #]]}]
}, True] &@i, {i, n}]
, Alignment -> {Left, Center}],
TrackedSymbols :> {n}
]
}, BaseStyle ->
ButtonBoxOptions -> {ImageSize -> All, FrameMargins -> 5,
ContentPadding -> False}]
];
graphSpecController[spec:Dynamic[{__Symbol}]]:= Column[ Slider /@ Thread @ spec ]
lensController[Dynamic[var_]]:=DynamicModule[{temp=var}
,
Grid[{
{"a", "x", "y"},
InputField[Dynamic[temp[[##]],{Automatic, (var = temp)&}], ImageSize->50]& @@@ {{1},{2,1},{2,2}}
}, Alignment->{Center,Center},Spacings->{0,0}]
];
rayController[Dynamic[var_]]:=DynamicModule[{temp=var}
,
Grid[{
{"RL", "RR", "Cx","Cy","d1","h1"},
InputField[Dynamic[temp[[##]],{Automatic, (var = temp)&}], ImageSize->50]& @@@ {{1},{2},{3,1},{3,2},{4},{5}}
},