1 ;; for i in `cat lens.lisp|grep "^(defun"|cut -d " " -f2`;do echo \#:$i ;done
4 (declaim (optimize (speed 2) (safety 3) (debug 3)))
6 (defgeneric intersect
(ray object
))
8 (defmethod intersect ((ray ray
) (plane plane
))
9 "Find the point where a ray intersects a plane."
10 (declare (values vec
&optional
))
11 (with-slots (center normal
) plane
12 (with-slots ((start vector
::start
) (dir vector
::direction
)) ray
13 (let* ((hess-dist (v. center normal
)) ;; distance of plane to origin
14 (div (v. normal dir
)))
15 (when (< (abs div
) 1d-12
) ;; plane and ray are parallel
17 (let ((eta (/ (- hess-dist
(v. normal start
))
18 ;; scaling along ray to hit exactly on plane
20 (v+ start
(v* dir eta
)))))))
24 (make-instance 'ray
:start
(v 0 1 -
1) :direction
(v 0 0 1))
25 (make-instance 'plane
:normal
(v 0 0 1) :center
(v)))
27 (defgeneric refract
(ray object
))
31 ;; | -----\ intersection
35 ;; | ----+/ r' | ----\
36 ;; f |--/ c | ----\ dir
42 ;; -------+----------<-------+-------------------------------------------
50 (defmethod refract ((ray ray
) (lens lens
))
51 "Return new ray after refraction on thin lens. In general you will
52 have to normalize its direction. The refraction on an objective needs
53 the non-normalized result. When the ray doesn't hit the lens the
54 condition RAY-LOST is signalled."
55 (declare (values ray
&optional
))
56 (check-direction-norm ray
)
57 (with-slots ((start vector
::start
)
58 (dir vector
::direction
)) ray
59 (with-slots ((c center
)
64 (let* ((i (intersect ray lens
))
66 (when (< r
(norm rho
)) ;; ray doesn't hit free aperture of lens
68 (let* ((cosphi (v. n dir
)))
71 :direction
(v- (v* dir
(/ f cosphi
))
75 (refract (make-instance 'ray
88 ;; --------------- s |
93 ;; / -----/ \ | \------
94 ;; / ----/ ru \ | \-------
98 ;; ------------------------------+-----------------------------------------
101 ;; +--------------------
104 ;; 2008 Hwang Simulation of an oil immersion objective lens...
105 (defmethod refract ((ray ray
) (objective objective
))
106 "Returns the refracted ray with the starting point on the principle
107 sphere of the objective. If the cap of the principal sphere (given by
108 NA) is missed then the condition LOST-RAY is signalled."
109 (declare (values ray
&optional
))
110 (check-direction-norm ray
)
111 (with-slots ((start vector
::start
)
112 (dir vector
::direction
)) ray
113 (with-slots ((c center
)
119 (na numerical-aperture
)) objective
121 ;; call refract for lens and refine the result
122 (let* ((lens-ray (call-next-method ray objective
))
123 (r (vector::direction lens-ray
))
124 (i (vector::start lens-ray
)) ;; intersection with lens plane
125 (a (v* n
(* f
(- ri
1))))
132 (when (<= rat
0d0
) ;; ray doesn't hit principal sphere
134 (let* ((s (v* dir
(- nf
(sqrt rat
))))
138 (sinu2 (- 1 (* cosu cosu
)))
139 (sinu-max (/ na ri
)))
140 (when (<= (* sinu-max sinu-max
) sinu2
) ;; angle to steep
144 :start
(v+ s i
)))))))
147 (refract (make-instance 'ray
148 :direction
(normalize (v 0 .001 1))
150 (make-objective :center
(v)
159 ;; -----+-------+------------o------------\------------------------
162 ;; 2005wolf p. 180 formula (8) sine condition for one image in infinity
163 (defmethod find-inverse-ray-angle ((objective objective
) point-x point-y
)
164 "Find the angle in the back focal plane for a ray that originates
165 from a POINT (coordinates in mm) in the focal plane in the object. The
166 coordinates of the point are given relative to the center of the front
168 (declare (double-float point-x point-y
)
169 (values double-float
&optional
))
170 (with-slots (focal-length)
172 (let* ((h (sqrt (+ (* point-x point-x
) (* point-y point-y
))))
173 (phi (asin (/ h focal-length
))))
177 (let* ((f (focal-length-from-magnification 63d0
))
179 (obj (make-objective :immersion-index ri
180 :normal
(v 0d0
0d0 -
1d0
)
181 :center
(make-vec 0d0
0d0
(- f
))))
182 (bfp-radius (back-focal-plane-radius obj
))
183 (field (make-vec .0d0
0d0
(- (+ f
(* ri f
)))))
184 (pupil (make-vec bfp-radius
0d0
0d0
)))
185 (find-inverse-ray-angle obj
0d0
.07d0
))