about summary refs log tree commit diff
path: root/backend/calc.go
blob: a1363011ef8fcd92a22127f2c7b268bfe5d3dd97 (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
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
			}
		}

	}

	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
}