-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathRetina.m
More file actions
131 lines (121 loc) · 4.42 KB
/
Retina.m
File metadata and controls
131 lines (121 loc) · 4.42 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
classdef Retina < Surface
% RETINA implements a spherical/ellipsoidal screen
%
% Member functions:
%
% p = Retina( r, R, k ) - object constructor
% INPUT:
% r - 1x3 position vector
% R - tangent sphere radius
% k - conic coefficient for the surface
% OUTPUT:
% p - retina object
%
% p.display() - displays the retina p information
%
% p.draw() - draws the retina p in the current axes
%
% p.rotate( rot_axis, rot_angle ) - rotate the retina
% INPUT:
% rot_axis - 1x3 vector defining the rotation axis
% rot_angle - rotation angle (radians)
%
% Copyright: Yury Petrov, 2016
%
properties
D = 1; % retina diameter
ang = pi/2; % aperture angle
azbins = 512; % number of azimuth bins
elbins = 512; % number of elevation bins
image = [];
end
properties ( SetAccess = private )
end
methods
function self = Retina( ar, aR, ak, aang, aazbins, aelbins )
if nargin == 0
return;
end
if nargin < 6
aelbins = 512;
end
if nargin < 5
aazbins = 512;
end
if nargin < 4
aang = 0.69 * pi/2; % to fit the lens
end
if nargin < 3
ak = 0;
end
if nargin < 2
error( 'At least position and radius Retina parameters must be specified!' );
end
self.r = ar;
self.R = aR;
self.k = ak;
self.ang = aang;
self.azbins = aazbins;
self.elbins = aelbins;
if ak <= -1 % not a sphere or ellipsoid
error( 'Aspheric parameter has to be larger than -1 for Retina' );
end
self.D = 2 * abs( self.R ) ./ sqrt( 1 + self.k );
end
function display( self )
fprintf( 'Position:\t [%.3f %.3f %.3f]\n', self.r );
fprintf( 'Orientation:\t [%.3f %.3f %.3f]\n', self.n );
fprintf( 'Diameter:\t %.3f\n', self.D );
fprintf( 'Curv. radius:\t %.3f\n', self.R );
fprintf( 'Asphericity:\t %.3f\n', self.k );
end
function h = draw( self, color, plot_type )
% DISPLAY the spherical surface
if nargin < 2
color = [ 0.2 0.2 0.2 1 ]; % dull gray opaque color
end
switch plot_type
case 'wireframe'
nrad = 10;
nang = 10;
otherwise
nrad = self.azbins;
nang = self.elbins;
end
theta = linspace( -pi, pi, nang ); % azimuth
phi = linspace( -pi/2, self.ang, nrad )'; % elevation
cosphi = cos( phi ); cosphi(1) = 0;
sintheta = sin( theta ); sintheta(1) = 0; sintheta( end ) = 0;
y = cosphi * cos( theta );
z = cosphi * sintheta;
x = sin( phi ) * ones( 1, length( theta ) );
S = self.R * [ ( x(:) + 1 ) / ( 1 + self.k ), y(:) / sqrt( 1 + self.k ), z(:) / sqrt( 1 + self.k ) ]; % apex at the orgin
% rotate and shift
if self.rotang ~= 0
S = rodrigues_rot( S, self.rotax, self.rotang );
end
x(:) = S( :, 1 ) + self.r( 1 );
y(:) = S( :, 2 ) + self.r( 2 );
z(:) = S( :, 3 ) + self.r( 3 );
c = repmat( reshape( color( 1:3 ), [ 1 1 3 ] ), size( x, 1 ), size( x, 2 ), 1 );
switch plot_type
case '3D'
h = mesh( x, y, z, c, ...
'EdgeColor', 'none', 'FaceLighting','phong', 'FaceColor', 'interp', 'FaceAlpha', color(4), ...
'AmbientStrength', 1, 'SpecularStrength', 0 );
case 'wireframe'
[ x, y, z ] = triangulate( x, y, z );
h = patch( x', y', z', 'red', 'FaceAlpha', 0.0 );
case 'XY'
[ ~, h ] = contour( x, y, z, [ 0.1 0.1 ] );
h.LineWidth = 2.0;
h.LineColor = 'k';
case 'XZ'
[ ~, h ] = contour( x, z, y, [ 0.1 0.1 ] );
h.LineWidth = 2.0;
h.LineColor = 'k';
end
colormap summer;
end
end
end