Motion/Pursuit Law in 2D (Visual Depth Perception 3)

Manipulate[
nORM[vector_?VectorQ]:=(Sqrt[vector.vector]);
degrees[q_]:=q*180/π;
arcMinutes[q_]:=q*60*180/π;

aimψ[headAimVector_?VectorQ,base_?VectorQ]:=ArcTan[headAimVector[[1]],headAimVector[[2]]];

midPoint[headAimVector_?VectorQ,base_?VectorQ]:=base-aimOffset*interOcular*{headAimVector[[2]],-headAimVector[[1]]};

rightEyeCenter[headAimVector_?VectorQ,base_?VectorQ]:=base+((1/2)-aimOffset)*interOcular*{headAimVector[[2]],-headAimVector[[1]]};

leftEyeCenter[headAimVector_?VectorQ,base_?VectorQ]:=base-((1/2)+aimOffset)*interOcular*{headAimVector[[2]],-headAimVector[[1]]};


rightViewVector[headAimVector_?VectorQ,fixate_?VectorQ,base_?VectorQ]:=fixate-rightEyeCenter[headAimVector, base];

rightφ[headAimVector_?VectorQ,fixate_?VectorQ,base_?VectorQ]:=ArcTan[rightViewVector[headAimVector, fixate, base][[1]],rightViewVector[headAimVector, fixate, base][[2]]];

rightEyeNode[headAimVector_?VectorQ,fixate_?VectorQ,base_?VectorQ]:=rightEyeCenter[headAimVector, base]+nodePercent*eyeRadius*rightViewVector[headAimVector,fixate, base]/nORM[rightViewVector[headAimVector, fixate, base]];

leftViewVector[headAimVector_?VectorQ,fixate_?VectorQ,base_?VectorQ]:=fixate-leftEyeCenter[headAimVector, base];

leftφ[headAimVector_?VectorQ,fixate_?VectorQ,base_?VectorQ]:=ArcTan[leftViewVector[headAimVector, fixate, base][[1]],leftViewVector[headAimVector, fixate, base][[2]]];

leftEyeNode[headAimVector_?VectorQ,fixate_?VectorQ,base_?VectorQ]:=leftEyeCenter[headAimVector, base]+nodePercent*eyeRadius*leftViewVector[headAimVector, fixate, base]/nORM[leftViewVector[headAimVector, fixate, base]];

fixateConvergence[headAimVector_?VectorQ,fixate_?VectorQ,base_?VectorQ]:=(rightφ[headAimVector,fixate,base]-leftφ[headAimVector,fixate,base]);

leftα[headAimVector_?VectorQ,fixate_?VectorQ,base_?VectorQ]:=leftφ[headAimVector,fixate,base]-aimψ[headAimVector,base];
rightα[headAimVector_?VectorQ,fixate_?VectorQ,base_?VectorQ]:=rightφ[headAimVector,fixate,base]-aimψ[headAimVector,base];

rightDistractVector[headAimVector_?VectorQ,fixate_?VectorQ,distraction_?VectorQ,base_?VectorQ]:=distraction-rightEyeNode[headAimVector,fixate, base];

rightδ[headAimVector_?VectorQ,fixate_?VectorQ,distraction_?VectorQ,base_?VectorQ]:=ArcTan[rightDistractVector[headAimVector,fixate,distraction,base][[1]],rightDistractVector[headAimVector,fixate,distraction,base][[2]]];

leftDistractVector[headAimVector_?VectorQ,fixate_?VectorQ,distraction_?VectorQ,base_?VectorQ]:=distraction-leftEyeNode[headAimVector,fixate, base];

leftδ[headAimVector_?VectorQ,fixate_?VectorQ,distraction_?VectorQ,base_?VectorQ]:=ArcTan[leftDistractVector[headAimVector,fixate,distraction,base][[1]],leftDistractVector[headAimVector,fixate,distraction,base][[2]]];

convergenceDistraction[headAimVector_?VectorQ,fixate_?VectorQ,distraction_?VectorQ,base_?VectorQ]:=If[Or[Abs[leftφ[headAimVector,fixate, base]-leftδ[headAimVector,fixate, distraction,base]]>π/3.,Abs[rightφ[headAimVector,fixate, base]-rightδ[headAimVector,fixate, distraction,base]]>π/3.],0.0,(rightδ[headAimVector,fixate, distraction,base]-leftδ[headAimVector,fixate, distraction,base])];

rightθ[headAimVector_?VectorQ,fixate_?VectorQ,distraction_?VectorQ,base_?VectorQ]:=(rightφ[headAimVector,fixate, base]-rightδ[headAimVector,fixate,distraction,base]);

leftθ[headAimVector_?VectorQ,fixate_?VectorQ,distraction_?VectorQ,base_?VectorQ]:=(leftφ[headAimVector,fixate, base]-leftδ[headAimVector,fixate,distraction,base]);

binocularDisparity[headAimVector_?VectorQ,fixate_?VectorQ,distraction_?VectorQ,base_?VectorQ]:=If[Or[leftθ[headAimVector,fixate,distraction,base]<-π/2.,leftθ[headAimVector,fixate,distraction,base]>π/3.,rightθ[headAimVector,fixate,distraction,base]<-π/3.,rightθ[headAimVector,fixate,distraction,base]>π/2.],0,(rightθ[headAimVector,fixate,distraction,base]-leftθ[headAimVector,fixate,distraction,base])];

rightθinside[headAimVector_?VectorQ,fixate_?VectorQ,distraction_?VectorQ,base_?VectorQ]:=rightθ[headAimVector,fixate,distraction,base]+ArcSin[nodePercent*Sin[rightθ[headAimVector,fixate,distraction,base]]];

leftθinside[headAimVector_?VectorQ,fixate_?VectorQ,distraction_?VectorQ,base_?VectorQ]:=leftθ[headAimVector,fixate,distraction,base]+ArcSin[nodePercent*Sin[leftθ[headAimVector,fixate,distraction,base]]];

retinalDisparity[headAimVector_?VectorQ,fixate_?VectorQ,distraction_?VectorQ,base_?VectorQ]:=If[Or[leftθ[headAimVector,fixate,distraction,base]<-π/2.,leftθ[headAimVector,fixate,distraction,base]>π/3.,rightθ[headAimVector,fixate,distraction,base]<-π/3.,rightθ[headAimVector,fixate,distraction,base]>π/2.],0,(rightθinside[headAimVector,fixate,distraction,base]-leftθinside[headAimVector,fixate,distraction,base])];


eyePict[eyeCenter_?VectorQ,fixate_?VectorQ]:=Module[{λ,viewVector},viewVector=fixate-eyeCenter;
λ=ArcTan[viewVector[[1]],viewVector[[2]]];
viewVector=viewVector/nORM[viewVector];
Show[{Graphics[{AbsoluteThickness[2],Gray,Circle[eyeCenter,eyeRadius,{λ+.4,2π+λ-.4}]}],Graphics[{Gray,
Circle[eyeCenter+ .8eyeRadius viewVector,.5eyeRadius,{λ-1.5,λ+1.5}]}],
Graphics[{Black,
Disk[eyeCenter+eyeRadius*nodePercent*viewVector,eyeRadius/10]
}]
},AspectRatio->Automatic]];

movingEyePict[eyeCenter_?VectorQ,fixate_?VectorQ]:=Module[{λ,viewVector},viewVector=fixate-eyeCenter;
λ=ArcTan[viewVector[[1]],viewVector[[2]]];
viewVector=viewVector/nORM[viewVector];
Show[{Graphics[{AbsoluteThickness[2],Dashing[.01],Gray,{Line[{eyeCenter-{1.eyeRadius,1.5eyeRadius},eyeCenter+{ 1.eyeRadius,-1.5eyeRadius},eyeCenter+{ .7eyeRadius,-1.6eyeRadius}}],Circle[eyeCenter,eyeRadius,{λ+.4,2π+λ-.4}]}}],Graphics[{Gray,
Circle[eyeCenter+ .8eyeRadius viewVector,.5eyeRadius,{λ-1.5,λ+1.5}]}],
Graphics[{Black,
Disk[eyeCenter+eyeRadius*nodePercent*viewVector,eyeRadius/10]
}]
},AspectRatio->Automatic]];

eyeEdge[θ_]:=eyeRadius*{Cos[θ],Sin[θ]};

eyeEdge[θ_]:=eyeRadius*{Cos[θ],Sin[θ]};

inRays[headAimVector_?VectorQ,fixate_?VectorQ,distraction_?VectorQ,base_?VectorQ]:=Show[{eyePict[leftEyeCenter[headAimVector, base],fixate],eyePict[rightEyeCenter[headAimVector,base],fixate],Graphics[{Red,{Line[{rightEyeNode[headAimVector,fixate,base],rightEyeCenter[headAimVector,base]-eyeRadius*rightViewVector[headAimVector,fixate,base]/nORM[rightViewVector[headAimVector,fixate,base]]}]}}],Graphics[{Red,{Line[{leftEyeNode[headAimVector,fixate,base],leftEyeCenter[headAimVector, base]-eyeRadius*leftViewVector[headAimVector,fixate,base]/nORM[leftViewVector[headAimVector,fixate,base]]}]}}],Graphics[{Blue,{Line[{rightEyeNode[headAimVector,fixate,base],rightEyeCenter[headAimVector,base]+eyeEdge[rightφ[headAimVector,fixate,base]-π-rightθinside[headAimVector,fixate,distraction,base]]}]}}],
Graphics[{Blue,{Line[{leftEyeNode[headAimVector,fixate,base],leftEyeCenter[headAimVector,base]+eyeEdge[leftφ[headAimVector,fixate,base]-π-leftθinside[headAimVector,fixate,distraction,base]]}]}}],
Graphics[{Purple,{Line[{rightEyeCenter[headAimVector,base],rightEyeCenter[headAimVector,base]+eyeEdge[rightφ[headAimVector,fixate,base]-π-rightθinside[headAimVector,fixate,distraction,base]]}]}}],
Graphics[{Purple,{Line[{leftEyeCenter[headAimVector,base],leftEyeCenter[headAimVector,base]+eyeEdge[leftφ[headAimVector,fixate,base]-π-leftθinside[headAimVector,fixate,distraction,base]]}]}}],
Graphics[{Green,{Line[N[{leftEyeCenter[headAimVector, base],rightEyeCenter[headAimVector, base]}]]}}],
min=Min[{leftφ[headAimVector,fixate,base]-π-leftθinside[headAimVector,fixate,distraction,base]-retinalDisparity[headAimVector,fixate,distraction,base],leftφ[headAimVector,fixate,base]-π-leftθinside[headAimVector,fixate,distraction,base]}];
MAX=Max[{leftφ[headAimVector,fixate,base]-π-leftθinside[headAimVector,fixate,distraction,base]-retinalDisparity[headAimVector,fixate,distraction,base],leftφ[headAimVector,fixate,base]-π-leftθinside[headAimVector,fixate,distraction,base]}];
Graphics[{Brown,AbsoluteThickness[3],{Circle[leftEyeCenter[headAimVector, base],eyeRadius,{min,MAX}]}}]
},AspectRatio->Automatic,PlotRange->{{midPoint[headAimVector,base][[1]]-interOcular,midPoint[headAimVector,base][[1]]+interOcular},{midPoint[headAimVector,base][[2]]-interOcular,midPoint[headAimVector,base][[2]]+interOcular}}];


outRays[headAimVector_?VectorQ,fixate_?VectorQ,distraction_?VectorQ,base_?VectorQ]:=Show[{Graphics[{Black,AbsolutePointSize[4],{Point[N[fixate]]}}],Graphics[{Black,AbsolutePointSize[4],{Point[N[distraction]]}}],Graphics[{Black,{Line[N[{fixate,rightEyeNode[headAimVector,fixate, base]}]]}}],Graphics[{Black,{Line[N[{fixate,leftEyeNode[headAimVector,fixate, base]}]]}}],Graphics[{Black,{Line[N[{distraction,rightEyeNode[headAimVector,fixate, base]}]]}}],Graphics[{Black,{Line[N[{distraction,leftEyeNode[headAimVector,fixate, base]}]]}}]
},AspectRatio->Automatic];

rightβRatio[f_,d1_,d2_,t_]:=((f(d1(d1+f)+(d2^2)-2d2 i t)-d1 (i^2) (t^2))/((d1+f) ((f^2)+(i^2) (t^2))));
t1[f_,d1_,d2_]:=(((d1^2) +(d2^2) +2 d1 f +(Sqrt[(d1^2)+(d2^2)]) (Sqrt[(d1^2)+(d2^2)+4 d1 f+4 (f^2)]) )/(2 d2 i));
t2[f_,d1_,d2_]:=(((d1^2) +(d2^2) +2 d1 f -(Sqrt[(d1^2)+(d2^2)]) (Sqrt[(d1^2)+(d2^2)+4 d1 f+4 (f^2)]) )/(2 d2 i));
tC[f_,d1_,d2_]:=If[Abs[d2]>.01,If[d1≥0,t2[f,d1,d2],t1[f,d1,d2]],0];

rightPeakβRatio[f_,d1_,d2_]:=rightβRatio[f,d1,d2,tC[f,d1,d2]];

r=eyeRadius=1.3;
n=nodePercent=0;
i=interOcular=6.5;
aimOffset=0;

f=fixate[[2]];
(*fixate={0,f};*)
d1:=distractor[[2]]-f;
d2:=distractor[[1]];


headAimVector={0,1};
base[tt_]={interOcular*(tt),0};

Show[{
Graphics[{Blue,AbsolutePointSize[5],{Point[distractor],Text["D",1.05distractor]
}}],
Graphics[{AbsolutePointSize[4],Point[midPoint[headAimVector,base[0]]]}]
,
Graphics[{Black,AbsolutePointSize[4],{Point[base[0]]
}}]
,
Graphics[{Red,AbsolutePointSize[4],{Point[fixate],Text["F",1.05fixate]}}]
,
Graphics[{Black,{Line[{{0,0},fixate}]}}]
,
Graphics[{Black,AbsolutePointSize[5],Dashing[.01],{Line[{{0,nodePercent*13/10},distractor}],Circle[{0,n*r+((d1+f)/2)(1+((((d2/(d1+f))))^2))},((d1+f)/2)(1+((((d2/(d1+f))))^2))]}}]
,
movingEyePict[base[0],fixate]
,
Graphics[{Gray,{Text[Row[{Style["t",Italic]," = ",0}],{0,-.23 scale}],
Text[Row[{HoldForm[((dθ)/(dβ))]," = ",Round[rightβRatio[f,d1,d2,0],.001]}],{0,-.1 scale}]}}]
,
movingEyePict[base[t],fixate]
,
movingEyePict[base[tC[f,d1,d2]],fixate]
,
Graphics[{Magenta,{Line[{distractor,base[t],fixate}],Text[Row[{Style["t",Italic]," = ",Round[t,.1]}],{t i,-.2 scale}],
Text[Row[{HoldForm[((dθ)/(dβ))]," = ",Round[rightβRatio[f,d1,d2,t],.001]}],{t i,-.05 scale}]}}]
,
Graphics[{Brown,{Line[{distractor,base[tC[f,d1,d2]],fixate}],Text[Row[{Style["t",Italic]," ",C," = ",Round[tC[f,d1,d2],.1]}],{tC[f,d1,d2] i,-.25 scale}],
Text[Row[{HoldForm[((dθ)/(dβ))]," = ",Round[rightPeakβRatio[f,d1,d2],.001]}],{tC[f,d1,d2] i,-.15 scale}]}}],
Graphics[{Blue,{Line[{fixate,distractor}],Text[Row[{"|","D","-","F","|","/",Style["f",Italic]," = ",Round[Sign[d1]nORM[{d1,d2}]/f,.001]}],scale{-.3,.4}]}}]
,
Graphics[{Blue,{Text[Row[{"|","D","-","F","|"," = ",Round[Sign[d1]nORM[{d1,d2}],.001]}],scale{-.3,.6}]}}],
Graphics[{Red,{Text[Row[{Style["f",Italic]," = ",Round[f,.001]}],scale{-.3,.5}]}}],
Graphics[{Red,{Text[Row[{"F"," = (0,",Round[f,.001],")"}],scale{.3,.5}]}}],
Graphics[{Blue,{Text[Row[{"D"," = (",Round[distractor[[1]],.001],",",Round[distractor[[2]],.001],")"}],scale{.3,.6}]}}]

},PlotRange->scale{{-.6,.6},{-.3,1.1}},AspectRatio->Automatic,ImageSize->{400,400}]

,
{{t,-5,"time t"},-10,10,Appearance->"Labeled"},
{{scale,125},50,1000,Appearance->"Labeled"},
{{fixate,{0,100}},{0,15},{0,1000},Locator},
{{distractor,{10,110}},{-500,10},{500,1100},Locator},TrackedSymbols->Manipulate]

CAPTION

This Demonstration computes the motion/pursuit law in the two-dimensional horizontal fixation plane of the eyes. The observer is looking mainly at F on the vertical axis, but also sees D as he translates to the right at speed equal to the interocular distance per second.

We do not know a theoretical explanation for the rough approximation of the peak motion pursuit law by the 2D relative distance, but this Demonstration compares ((dθ)/(dβ))(0), ((dθ)/(dβ))((Subscript[t, c])), and the 2D signed relative distance, ± ((|D-F|)/f). It also lets you vary time and compare the motion/pursuit law at other times. You can drag the distractor point and the fixate distance is variable.

DETAILS

See the details in "Motion/Pursuit Law in 1D (Visual Depth Perception 1)" for the basic set-up.

The relative depth formula extends to the two-dimensional distractor as:

((d θ)/(dα-dθ))(t)=((dθ)/(dβ))(t)=f((((((f n r-((Subscript[d, 1])+f) (Sqrt[(f^2)+(s^2) (t^2)])))^2)+(((n r s t+((Subscript[d, 2])-s t) (Sqrt[(f^2)+(s^2) (t^2)])))^2))/(f n r s t (n r s t+((Subscript[d, 2])-s t) (Sqrt[(f^2)+(s^2) (t^2)]))+(f n r-((Subscript[d, 1])+f) (Sqrt[(f^2)+(s^2) (t^2)])) ((f^2) n r-((((f^2)+(s^2) (t^2)))^(3/2))))))-1

When n=0 this is somewhat simpler:

((d θ)/(d β))[t]=((f((Subscript[d, 1])((Subscript[d, 1])+f)+((Subscript[d, 2])^2)-2(Subscript[d, 2]) s t)-(Subscript[d, 1]) (s^2) (t^2))/(((Subscript[d, 1])+f) ((f^2)+(s^2) (t^2))))

This simplifies greatly at the time, t=0, when the eye crosses the (Subscript[d, 1]) axis:

((dθ)/(dβ))(0)=(((Subscript[d, 1])((Subscript[d, 1])+f)+((Subscript[d, 2])^2))/(f((Subscript[d, 1]) +f))).

The motion/pursuit ratio dθ/dα at t=0 is constant on circles passing through the eye node at time zero and distractor (f+(Subscript[d, 1]),(Subscript[d, 2])) with diameter on the (Subscript[d, 1]) axis. (These circles are similar to the invariant circles for binocular disparity, but slightly different.)

This means that the time zero motion/pursuit law is NOT an especially good indicator of the relative distance between the two-dimensional distractor and fixate, |D-F|/f, because you can move quite far from F on this circle with no change in the quantity dθ/dβ(0). If we take the translation of the observer into account, we can show that the peak value of the motion/pursuit law is a good indicator of the relative distance in two dimensions. (It is also likely that the changing value of the motion/pursuit ratio is a cue that the brain could use.)

The figure above on the left shows the peak values of the motion/pursuit law in color and the time zero M/PL in gray. On the right the dark gray graph is the two-dimensional relative depth.

When (Subscript[d, 2])=0 the motion dθ/dt, the motion pursuit ratio dθ/dα, and dθ/dβ all peak at t=0 and this peak value satisfies

((dθ)/(dβ))(0)=((Subscript[d, 1])/f).

When (Subscript[d, 2])≠0 and the eye node is at the center of the eye, n=0, the motion/pursuit ratio and dθ/dβ have critical points at the times

(Subscript[t, 1])=((-((Subscript[d, 1])^2) -((Subscript[d, 2])^2) -2 (Subscript[d, 1]) f -(Sqrt[((Subscript[d, 1])^2)+((Subscript[d, 2])^2)]) (Sqrt[((Subscript[d, 1])^2)+((Subscript[d, 2])^2)+4 (Subscript[d, 1]) f+4 (f^2)]) )/(2 (Subscript[d, 2]) i)),

(Subscript[t, 2])=((-((Subscript[d, 1])^2) -((Subscript[d, 2])^2) -2 (Subscript[d, 1]) f +(Sqrt[((Subscript[d, 1])^2)+((Subscript[d, 2])^2)]) (Sqrt[((Subscript[d, 1])^2)+((Subscript[d, 2])^2)+4 (Subscript[d, 1]) f+4 (f^2)]) )/(2 (Subscript[d, 2]) i)).

The peak time motion/pursuit formula gives a value close to the relative distance ±|D-F|/f:

((dθ)/(dβ))((Subscript[t, 2])(f,(Subscript[d, 1]),(Subscript[d, 2])))≃((|D-F|)/f), when (Subscript[d, 2])>0, ((dθ)/(dβ))((Subscript[t, 1])(f,(Subscript[d, 1]),(Subscript[d, 2])))≃-((|D-F|)/f), when (Subscript[d, 2])<0, and ((dθ)/(dβ))(0)=((|D-F|)/f), when (Subscript[d, 2])=0.

We do not know a theoretical explanation for the rough approximation of the peak motion/pursuit law by the 2D relative distance, but this Demonstration compares ((dθ)/(dβ))(0), ((dθ)/(dβ))((Subscript[t, c])), and the 2D signed relative distance, ±((|D-F|)/f). It also lets you vary time and compare the motion/pursuit law at other times. You can drag the distractor in two dimensions.

The Demonstration "Motion/Pursuit Law on Invariant Circles (Visual Depth Perception 4)" (see Related Links) lets you vary the distractor on the time zero invariant circles.

THIS NOTEBOOK IS THE SOURCE CODE FROM

"Motion/Pursuit Law in 2D (Visual Depth Perception 3)" from the Wolfram Demonstrations Project
 http://demonstrations.wolfram.com/MotionPursuitLawIn2DVisualDepthPerception3/

Contributed by: Keith Stroyan

A full-function Wolfram Mathematica system (Version 6 or higher) is required to edit this notebook.
GET WOLFRAM MATHEMATICA »

© Wolfram Demonstrations Project & Contributors   |   Terms of Use   |   Make a new version of this Demonstration »