Advertisement
Guest User

Untitled

a guest
Nov 29th, 2014
241
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.40 KB | None | 0 0
  1. import System.Exit
  2. import Graphics.UI.GLUT
  3. import Control.Monad
  4. import Control.Concurrent
  5. import Graphics.Rendering.OpenGL
  6. import Data.IORef
  7. import Data.Function
  8. import Data.List
  9.  
  10. type R = GLdouble
  11.  
  12. data Kosha = (:=^.^=:) {koshaNapravlenie :: [R], koshaKoordinata :: [R]}
  13. data Misha = (:>^^<:) {mishaNapravlenie :: [R], mishaKoordinata :: [R]}
  14.  
  15. koshi = map ([sK,0] :=^.^=:) [[0,0.5],[0.5,0],[-0.5,0],[0,-0.5]]
  16. mishi = map ([0,sM] :>^^<:) (replicateM 2 [-0.7,-0.5..0.7])
  17. initial = (koshi,mishi)
  18. sK = 0.005; dtK = 0.08
  19. sM = 0.005
  20.  
  21. main = initialWindowSize $= Size 987 987 >>
  22. initialWindowPosition $= Position 0 0 >>
  23. initialDisplayMode $= [DoubleBuffered] >>
  24. createWindow "ursula" >>
  25. newIORef initial >>= \ior ->
  26. keyboardMouseCallback $= Just (\_ _ _ _ -> exitWith ExitSuccess) >>
  27. displayCallback $= dlay ior >>
  28. idleCallback $= Just (anime ior) >>
  29. mainLoop
  30.  
  31. dlay ior = clearColor $= Color4 0 0 0 0 >>
  32. clear [ColorBuffer] >>
  33. readIORef ior >>= drawDoxyq >>
  34. swapBuffers
  35.  
  36. anime ior = modifyIORef' ior shag >>
  37. threadDelay 20000 >>
  38. postRedisplay Nothing
  39.  
  40. drawDoxyq (koshi,mishi) =
  41. currentColor $= Color4 1 1 1 1 >>
  42. drawCircle (1 :: R) [0,0] >>
  43. currentColor $= Color4 0 0 0 0 >>
  44. mapM_ drawKosha koshi >>
  45. mapM_ drawMisha mishi
  46.  
  47. drawKosha (_ :=^.^=: c) = drawCircle 0.04 c >>
  48. currentColor $= Color4 0.5 0.5 0.3 0.8 >>
  49. mapM_ (drawCircle 0.01) [c .+. [-0.02,0.01],c .+. [0.02,0.01]] >>
  50. mapM_ (drawCircle 0.015) [c .+. [-0.01,-0.015],c .+. [0.01,-0.015]] >>
  51. currentColor $= Color4 0 0 0 0 >>
  52. mapM_ (drawCircle 0.012) [c .+. [-0.009,-0.007],c .+. [0.009,-0.007]]
  53.  
  54. drawMisha (_ :>^^<: c) = currentColor $= Color4 0.6 0.6 0.6 0.6 >> drawCircle 0.02 c
  55.  
  56. drawCircle r [x,y] = renderPrimitive TriangleFan (mapM_ vertex [Vertex2 (x+r*cos t) (y+r*sin t) | t <- [0,0.1..2*pi]])
  57.  
  58. (.+.) = zipWith (+)
  59. (.-.) = zipWith (-)
  60. v .*. u = sum (zipWith (*) v u)
  61. [a,b] .<>. [c,d] = a*d - b*c
  62. v .<. u = atan2 (v .<>. u) (v .*. u)
  63. norm = sqrt . sum . map (^2)
  64. dist a b = norm (a .-. b)
  65. t *. v = map (*t) v
  66. arg [x,y] = atan2 y x
  67. neg = map negate
  68. povernut [x,y] t = [x*cos t-y*sin t,y*cos t+x*sin t]
  69.  
  70. shag (koshi,mishi) = (koshi',mishi') where
  71. koshi' = map obrabotatKoshu koshi
  72. mishi' = mishi >>= obrabotatMishu
  73.  
  74. obrabotatKoshu (v :=^.^=: c) = v' :=^.^=: c' where
  75. v' = povernut v (dtK * (v .<. (cm .-. c)))
  76. c' = c .+. v'
  77. blizhajshajaMisha@(_ :>^^<: cm) = minimumBy (compare `on` dist c . mishaKoordinata) mishi
  78.  
  79. obrabotatMishu (v :>^^<: c) = [v' :>^^<: c' | 0.04 < dist c ck] where
  80. c' = c .+. v'
  81. v' | vperediKosha = povernut v (if norm (c .+. (100 *. povernut v (pi/2))) < 1 then pi/2 else -pi/2)
  82. | stenaRjadom = head [v' | tt <- [0,0.01..], t <- [tt,-tt], let v' = povernut v t, 0.4 < rasstojanieDoSteni v']
  83. | otherwise = v
  84. vperediKosha = or [dist c ck < 0.3 && abs (v .<. (ck .-. c)) < (pi/4) | _ :=^.^=: ck <- koshi]
  85. stenaRjadom = rasstojanieDoSteni v < 0.2
  86. rasstojanieDoSteni v = norm (t *. v) where
  87. t = reshitKvUr [norm v^2,2*(c .*. v),norm c^2 - 1]
  88. reshitKvUr [a,b,c] = maximum [(-b - sqrt d)/2/a,(-b + sqrt d)/2/a] where
  89. d = b^2 - 4*a*c
  90. blizhajshajaKosha@(_ :=^.^=: ck) = minimumBy (compare `on` dist c . koshaKoordinata) koshi
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement