3ba2149533750bee68d90592a993cf7edd377ff2
1 {-# LANGUAGE BangPatterns #-}
3 -- | Massful bodies in the simulation.
4 module Body
5 ( Velocity
6 , Accel
7 , MassPoint
8 , Body
10 , unitBody
11 , massPointOfBody
12 , setMassOfBody
13 , setAccelOfBody
14 , setStartVelOfBody
16 where
17 import Util
20 -- Types ----------------------------------------------------------------------
21 -- We're using tuples instead of ADTs so we can put them in unboxed vectors.
23 -- | The velocity of a point.
24 type Velocity = (Double, Double)
26 -- | The acceleration of a point.
27 type Accel = (Double, Double)
29 -- | A point in 2D space with its mass.
30 type MassPoint = (Double, Double, Double)
32 -- | Bodies consist of a MassPoint, but also carry their velocity
33 -- and acceleration between steps of the simulation.
34 type Body = (MassPoint, Velocity, Accel)
37 -- Body -----------------------------------------------------------------------
38 -- | Make a body with unit mass and zero vel and acc.
39 unitBody :: Double -> Double -> Body
40 unitBody x y
41 = ((x, y, 1), (0, 0), (0, 0))
44 -- | Take the MassPoint of a body.
45 massPointOfBody :: Body -> MassPoint
46 massPointOfBody (mp, vel, acc)
47 = mp
50 -- | Set the mass of a body.
51 setMassOfBody :: Double -> Body -> Body
52 setMassOfBody mass ((x, y, _), vel, acc)
53 = ((x, y, mass), vel, acc)
56 -- | Set the acceleration of a body.
57 setAccelOfBody :: Accel -> Body -> Body
58 setAccelOfBody acc' (mp, vel, _)
59 = (mp, vel, acc')
62 -- | Set the starting velocity of a body.
63 -- It is set to rotate around the origin, with the speed proportional
64 -- to the sqrt of the distance from it. This seems to make nice simulations.
65 setStartVelOfBody :: Double -> Body -> Body
66 setStartVelOfBody startVel (mp@(x, y, mass), vel, acc)
67 = let pos = (x, y)
68 (x', y') = normaliseV (x, y)
69 vel' = (y', -x')
70 vel'' = mulSV (sqrt (magV pos) * startVel) vel'
72 in (mp, vel'', acc)
75 -- | Advance a body forwards in time.
76 advanceBody :: Double -> Body -> Body