about summary refs log tree commit diff
path: root/backend/calc.go
blob: 4ad9ce63105ea477e082f5066bbe018558e84c3b (plain)
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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
package backend

import (
	"database/sql"
	"git.darknebu.la/GalaxySimulator/structs"
	"log"
	"math"
)

// CalcAllForces calculates all the forces acting on the given star.
// The theta value it receives is used by the Barnes-Hut algorithm to determine what
// stars to include into the calculations
func CalcAllForces(database *sql.DB, star structs.Star2D, galaxyIndex int64, theta float64) structs.Vec2 {
	db = database

	// calculate all the forces and add them to the list of all forces
	// this is done recursively
	// first of all, get the root id
	log.Println("[db_actions] Getting the root ID")
	rootID := getRootNodeID(galaxyIndex)
	log.Println("[db_actions] Done getting the root ID")

	log.Printf("[db_actions] Calculating the forces acting on the star %v", star)
	force := CalcAllForcesNode(star, rootID, theta)
	log.Printf("[db_actions] Done calculating the forces acting on the star %v", star)
	log.Printf("[db_actions] Force: %v", force)

	return force
}

// calcAllForces nodes calculates the forces in between a sta	log.Printf("Calculating the forces acting on the star %v", star)r and a node and returns the overall force
// TODO: implement the calcForce(star, centerOfMass) {...} function
// TODO: implement the getSubtreeIDs(nodeID) []int64 {...} function
func CalcAllForcesNode(star structs.Star2D, nodeID int64, theta float64) structs.Vec2 {
	log.Println("---------------------------------------")
	log.Printf("NodeID: %d \t star: %v \t theta: %f \t nodeboxwidth: %f", nodeID, star, theta, getBoxWidth(nodeID))
	var forceX float64
	var forceY float64
	var localTheta float64

	nodeWidth := getBoxWidth(nodeID)

	if nodeID != 0 {
		log.Println("[theta] Calculating localtheta(star, node)")
		log.Printf("[theta] node with: %f", nodeWidth)
		localTheta = calcTheta(star, nodeID)
		log.Printf("[theta] Done calculating localtheta: %v", localTheta)
	}

	// recurse deeper into the tree
	if localTheta < theta {
		log.Println("[   ] localtheta < theta")

	} else {
		log.Println("[   ] localtheta > theta")

		log.Printf("[   ] Iterating over subtrees")
		var subtreeIDs [4]int64
		subtreeIDs = getSubtreeIDs(nodeID)
		for i, subtreeID := range subtreeIDs {
			log.Printf("Subtree: %d\t ID: %d", i, subtreeID)

			if subtreeID != 0 {
				subtreeStarId := getStarID(subtreeID)
				if subtreeStarId != 0 {
					var localStar = GetStar(subtreeStarId)
					log.Printf("subtree %d star: %v", i, localStar)
					if localStar != star {
						log.Println("Not even the original star, calculating forces...")
						var force = calcForce(localStar, star)
						forceX += force.X
						forceY += force.Y
					}
				}
				var force = CalcAllForcesNode(star, subtreeID, theta)
				log.Printf("force: %v", force)
				forceX += force.X
				forceY += force.Y
			}
		}

	}

	//// dont't recurse deeper into the tree
	//if localTheta < theta {
	//	log.Printf("localTheta < theta")
	//	var force structs.Vec2
	//
	//	// if the nodeID is not zero, use the center of mass as the other star
	//	if nodeID != 0 {
	//		pseudoStarCoodinates := getCenterOfMass(nodeID)
	//		PseudoStar := structs.Star2D{
	//			C: structs.Vec2{
	//				X: pseudoStarCoodinates.X,
	//				Y: pseudoStarCoodinates.Y,
	//			},
	//			V: structs.Vec2{
	//				X: 0,
	//				Y: 0,
	//			},
	//			M: 1000,
	//		}
	//		log.Printf("PseudoStar: %v", PseudoStar)
	//		force = calcForce(star, PseudoStar)
	//
	//		// else, use the star in the node as the other star
	//	} else {
	//		if getStarID(nodeID) != 0 {
	//			var pseudoStar = GetStar(getStarID(nodeID))
	//			force = calcForce(star, pseudoStar)
	//		}
	//	}
	//
	//	forceX = force.X
	//	forceY = force.X
	//
	//// recurse deeper into the tree
	//} else {
	//	log.Printf("localTheta > theta")
	//	// iterate over all subtrees and add the forces acting through them
	//	var subtreeIDs [4]int64
	//	subtreeIDs = getSubtreeIDs(nodeID)
	//	for i, subtreeID := range subtreeIDs {
	//		fmt.Printf("Subtree: %d", i)
	//
	//		// don't recurse into
	//		if subtreeID != 0 {
	//			var force = CalcAllForcesNode(star, subtreeID, theta)
	//			log.Printf("force: %v", force)
	//			forceX += force.X
	//			forceY += force.Y
	//		}
	//	}
	//}
	log.Println("---------------------------------------")
	return structs.Vec2{forceX, forceY}
}

// calcTheta calculates the theat for a given star and a node
func calcTheta(star structs.Star2D, nodeID int64) float64 {
	d := getBoxWidth(nodeID)
	r := distance(star, nodeID)
	theta := d / r
	return theta
}

// calculate the distance in between the star and the node with the given ID
func distance(star structs.Star2D, nodeID int64) float64 {
	var starX float64 = star.C.X
	var starY float64 = star.C.Y
	var node structs.Vec2 = getNodeCenterOfMass(nodeID)
	var nodeX float64 = node.X
	var nodeY float64 = node.Y

	var tmpX = math.Pow(starX-nodeX, 2)
	var tmpY = math.Pow(starY-nodeY, 2)

	var distance float64 = math.Sqrt(tmpX + tmpY)
	return distance
}

// calcForce calculates the force the star s1 is acting on s2.
// The force acting is returned in Newtons.
func calcForce(s1 structs.Star2D, s2 structs.Star2D) structs.Vec2 {
	log.Println("+++++++++++++++++++++++++")
	log.Printf("s1: %v", s1)
	log.Printf("s2: %v", s2)
	G := 6.6726 * math.Pow(10, -11)

	// calculate the force acting
	var combinedMass float64 = s1.M * s2.M
	var distance float64 = math.Sqrt(math.Pow(math.Abs(s1.C.X-s2.C.X), 2) + math.Pow(math.Abs(s1.C.Y-s2.C.Y), 2))
	log.Printf("combined mass: %f", combinedMass)
	log.Printf("distance: %f", distance)

	var scalar float64 = G * ((combinedMass) / math.Pow(distance, 2))
	log.Printf("scalar: %f", scalar)

	// define a unit vector pointing from s1 to s2
	var vector structs.Vec2 = structs.Vec2{s2.C.X - s1.C.X, s2.C.Y - s1.C.Y}
	var UnitVector structs.Vec2 = structs.Vec2{vector.X / distance, vector.Y / distance}

	// multiply the vector with the force to get a vector representing the force acting
	var force structs.Vec2 = UnitVector.Multiply(scalar)
	log.Println("+++++++++++++++++++++++++")

	// return the force exerted on s1 by s2
	return force
}