
Temple Fay discovered this complicated curve in 1989. It can be defined either parametrically or as a polar equation; I did it the former way.
One application I thought of for this is object motion in games: I tried it out by writing this little Canvas game, where the comets follow the curve's trajectory. The differences in plot density along the curve create natural-looking comet tails.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{-# LANGUAGE NoMonomorphismRestriction #-} | |
import Data.Bits ((.|.), shiftL) | |
import Control.Arrow ((***), (&&&)) | |
import Graphics.UI.SDL as SDL | |
import Graphics.UI.SDL.Primitives (pixel) | |
(xres, yres, zz) = (1050, 1050, round *** round) | |
main = withInit [InitVideo] $ do | |
w <- setVideoMode xres yres 32 [NoFrame] | |
enableEvent SDLMouseMotion False | |
setCaption "Butterfly Curve" "Butterfly Curve" | |
fillRect w (Just $ Rect 0 0 xres yres) $ Pixel 0 | |
plot w $ center $ scale curve | |
loop w [] | |
where | |
scale = map ((150 *) *** (* 150)) | |
center = map (((xres / 2) +) *** (+ ((yres + 190) / 2))) | |
curve = map (f &&& (negate . g)) ts | |
where | |
ts = [-999, -998.99.. 999] | |
f t = sin t * (e ** cos t - 2 * cos (4*t) - h (t / 12)) | |
g t = cos t * (e ** cos t - 2 * cos (4*t) - h (t / 12)) | |
h = foldr1 (.) $ replicate 5 sin | |
e = exp 1 | |
plot w = mapM_ (f . zz) | |
where | |
f (x,y) = pixel w (fromIntegral x) (fromIntegral y) $ Pixel rgb | |
where | |
rgb = rgb' .|. shiftL (255 `div` (max x y `div` min x y)) 8 | |
rgb' = rgb'' .|. shiftL (255 `div` (xres `div` x)) 16 | |
rgb'' = 0xFF .|. shiftL (255 `div` (yres `div` y)) 24 | |
loop w ps = do | |
delay 128 | |
event <- pollEvent | |
case event of | |
KeyUp (Keysym SDLK_ESCAPE _ _) -> return () | |
_ -> loop w ps |