Added hexapolar and spiral ray patterns
This commit is contained in:
@@ -8,6 +8,9 @@ module Petzval.Trace
|
|||||||
, HitRecord(..)
|
, HitRecord(..)
|
||||||
, TraceError(..)
|
, TraceError(..)
|
||||||
, raytrace
|
, raytrace
|
||||||
|
-- * Ray patterns
|
||||||
|
, hexapolarPattern
|
||||||
|
, spiralPattern
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Linear
|
import Linear
|
||||||
@@ -46,14 +49,14 @@ createRay :: (RealFloat a, Mode a, Epsilon a)
|
|||||||
=> Maybe a -- ^ The image plane position. If `Nothing`, the object is at infinity
|
=> Maybe a -- ^ The image plane position. If `Nothing`, the object is at infinity
|
||||||
-> Pupil a -- ^ The entrance pupil to aim at
|
-> Pupil a -- ^ The entrance pupil to aim at
|
||||||
-> a -- ^ Field angle
|
-> a -- ^ Field angle
|
||||||
-> (a,a) -- ^ Normalized pupil coordinates (in the range \([-1,1]\))
|
-> V2 a -- ^ Normalized pupil coordinates (in the range \([-1,1]\))
|
||||||
-> Ray a
|
-> Ray a
|
||||||
createRay (Just objectPlane) Pupil{position=pz,radius=pr} h (px, py) =
|
createRay (Just objectPlane) Pupil{position=pz,radius=pr} h (V2 px py) =
|
||||||
Ray source (normalize $ target ^-^ source)
|
Ray source (normalize $ target ^-^ source)
|
||||||
where dz = pz - objectPlane
|
where dz = pz - objectPlane
|
||||||
source = V3 0 (dz * tan h) objectPlane
|
source = V3 0 (dz * tan h) objectPlane
|
||||||
target = V3 (px * pr) (py * pr) pz
|
target = V3 (px * pr) (py * pr) pz
|
||||||
createRay Nothing Pupil{position=pz,radius=pr} h (px, py) = Ray source (normalize $ target ^-^ source)
|
createRay Nothing Pupil{position=pz,radius=pr} h (V2 px py) = Ray source (normalize $ target ^-^ source)
|
||||||
where h' = (pi * (-abs h) / 180) -- field angle in rad
|
where h' = (pi * (-abs h) / 180) -- field angle in rad
|
||||||
dy = (V3 0 (cos h') (-sin h')) `project` (V3 0 (py * pr) 0)
|
dy = (V3 0 (cos h') (-sin h')) `project` (V3 0 (py * pr) 0)
|
||||||
dz = V3 0 (pz * tan h') (pz * cos h')
|
dz = V3 0 (pz * tan h') (pz * cos h')
|
||||||
@@ -124,3 +127,17 @@ raytrace system ray = trace' 1 ray system
|
|||||||
(fray, rest) <- trace' n2 (nray'&_pos._z -~ element ^. thickness) elements
|
(fray, rest) <- trace' n2 (nray'&_pos._z -~ element ^. thickness) elements
|
||||||
|
|
||||||
return (fray & _pos._z +~ element ^. thickness, HitRecord { pos=(nray' ^. _pos), opl} : rest)
|
return (fray & _pos._z +~ element ^. thickness, HitRecord { pos=(nray' ^. _pos), opl} : rest)
|
||||||
|
|
||||||
|
-- | Spiral pattern. This is somewhat more irregular than the hexapolar pattern. The argument is the number of points
|
||||||
|
spiralPattern :: Floating a => Int -> [V2 a]
|
||||||
|
spiralPattern n = map (point . fromIntegral) [0..n-1]
|
||||||
|
where npoints = fromIntegral n - 1
|
||||||
|
point n = let r = sqrt (n / npoints)
|
||||||
|
theta = 2.3999632297286531 * n
|
||||||
|
in r *^ V2 (sin theta) (cos theta)
|
||||||
|
-- | A hexapolar pattern. This is rather optimally distributed; the argument is the number of rings
|
||||||
|
hexapolarPattern :: Floating a => Integer -> [V2 a]
|
||||||
|
hexapolarPattern nRings = (V2 0 0) : ( mconcat . map ring $ [0..nRings-1])
|
||||||
|
where ring n = let point t = r *^ V2 (sin t) (cos t)
|
||||||
|
r = (fromIntegral n) / (fromIntegral nRings)
|
||||||
|
in map (point . (\x -> x / (fromIntegral) n * 3 * pi) . fromIntegral) [0 .. n-1]
|
||||||
|
|||||||
Reference in New Issue
Block a user