-
Notifications
You must be signed in to change notification settings - Fork 0
/
bodyGravityForces.hs
107 lines (61 loc) · 3.66 KB
/
bodyGravityForces.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
{-# LANGUAGE ViewPatterns #-}
{-# LANGUAGE BangPatterns #-}
module BodyGravityForces where
import Physics
import Numeric.Units.Dimensional.Prelude as D hiding (concat, foldl)
import Numeric.Units.Dimensional.NonSI
import qualified Prelude hiding (concat, foldl)
import Graphics.Rendering.OpenGL as GL
import DataStructures as DS
import Data.List as List hiding (concat, foldl)
import qualified Data.Sequence as Seq
import Data.Foldable
--import Data.Functor
--optimized
optimizedCalculateAccelerationsFromGravity objects = Seq.zipWith (addForceAsAcceleration) objects (forceVectors)
where forceVectors = optSumForceVectorsByObjectID . optGetTotalGravityForces $ (objectsWithIndex)
objectsWithIndex = Seq.zipWith (\(!x) (!y) -> (x,y)) (Seq.fromList [1..(Seq.length objects)]) objects
optGetGravityForceVector :: Mass GLdouble -> Mass GLdouble -> Vector3 (D.Length GLdouble) -> Vector3 (D.Length GLdouble) -> (Vector3 (Force GLdouble) , Vector3 (Force GLdouble))
optGetGravityForceVector m1 m2 p1 p2 = (vectorTimesScalar normalizedDVec (negate force), vectorTimesScalar normalizedDVec force)
where force = bigG * m1 * m2 / (vecMag * vecMag)
vecMag = vectorMagnitude dVec
normalizedDVec = vectorNormalize dVec
dVec = vectorSubstract p1 p2
optSumForceVectorsByObjectID (Seq.viewl -> Seq.EmptyL) = Seq.empty
optSumForceVectorsByObjectID (Seq.viewl -> (i,vec) Seq.:< xs) = foldl (\acc (j,x) -> vectorAdd acc x) vec sameObj Seq.<| optSumForceVectorsByObjectID remlist
where sameObj = Seq.takeWhileL (\(j,_) -> j == i) xs
remlist = Seq.drop (Seq.length sameObj) xs
optGetTotalGravityForces objects = Seq.sortBy (sortObj) . asum . optFoo (f) $ objects
where f (i,(Object p1 _ _ _ m1)) xs = asum . fmap (g i p1 m1) $ xs
g i p1 m1 = (\(j,(Object p2 _ _ _ m2)) -> let (!f1,!f2) = optGetGravityForceVector m1 m2 p1 p2 in ((i,f1) Seq.<| (j,f2) Seq.<| Seq.empty ))
optFoo _ (Seq.viewl -> Seq.EmptyL) = Seq.empty
optFoo f (Seq.viewl -> x Seq.:< xs) = f x xs Seq.<| optFoo f xs
--non optimized
calculateAccelerationsFromGravity objects = zipWith (addForceAsAcceleration) objects forceVectors
where forceVectors = sumForceVectorsByObjectID . getTotalGravityForces $ objectsWithIndex
objectsWithIndex = zipWith (\x y -> (x,y)) [1..] objects
--acceleration calculation, first: 2 bodies
getGravityForceVector :: Mass GLdouble -> Mass GLdouble -> Vector3 (D.Length GLdouble) -> Vector3 (D.Length GLdouble) -> (Vector3 (Force GLdouble) , Vector3 (Force GLdouble))
getGravityForceVector m1 m2 p1 p2 = (vectorTimesScalar normalizedDVec (negate force), vectorTimesScalar normalizedDVec force)
where force = bigG * m1 * m2 / (vecMag * vecMag)
vecMag = vectorMagnitude dVec
normalizedDVec = vectorNormalize dVec
dVec = vectorSubstract p1 p2
sumForceVectorsByObjectID [] = []
sumForceVectorsByObjectID ((i,vec):xs) = foldl (\acc (j,x) -> vectorAdd acc x) vec sameObj : sumForceVectorsByObjectID remlist
where sameObj = takeWhile (\(j,_) -> j == i) xs
remlist = List.drop (List.length sameObj) xs
getTotalGravityForces objects = sortBy (sortObj) . concat . foo' (f) $! objects
where f (i,(Object p1 _ _ _ m1)) xs = concat . map (g i p1 m1) $ xs
g i p1 m1 = (\(j,(Object p2 _ _ _ m2)) -> let (f1,f2) = getGravityForceVector m1 m2 p1 p2 in [(i,f1),(j,f2)])
foo _ [] = [[]]
foo f (x:xs) = f x xs : foo f xs
foo' f (x:xs) = (f x xs) : (foo f xs)
--shared
--sortObj :: Num a => (a,Vector3 b) -> (a,Vector3 b) -> Ordering
sortObj (i,_) (j,_)
| i < j = LT
| i > j = GT
| i == j = EQ
addAcceleration (Object p o v a m) aVec = (Object p o v (vectorAdd a aVec) m)
addForceAsAcceleration obj@(Object _ _ _ _ m) fVec = addAcceleration obj (vectorTimesScalar fVec ((num 1)/m))