diff options
-rw-r--r-- | boundingBox.go | 27 | ||||
-rw-r--r-- | quadtree.go | 84 | ||||
-rw-r--r-- | star.go | 86 | ||||
-rw-r--r-- | vector2D.go | 71 |
4 files changed, 268 insertions, 0 deletions
diff --git a/boundingBox.go b/boundingBox.go new file mode 100644 index 0000000..ad02eab --- /dev/null +++ b/boundingBox.go @@ -0,0 +1,27 @@ +package structs + +// BoundingBox is a struct defining the spatial outreach of a box +type BoundingBox struct { + center Vec2 // Center of the box + width float64 // width of the box +} + +func (b *BoundingBox) Width() float64 { + return b.width +} + +func (b *BoundingBox) SetWidth(width float64) { + b.width = width +} + +func (b *BoundingBox) Center() Vec2 { + return b.center +} + +func (b *BoundingBox) SetCenter(center Vec2) { + b.center = center +} + +func NewBoundingBox(center Vec2, halfDim float64) *BoundingBox { + return &BoundingBox{center: center, width: halfDim} +} diff --git a/quadtree.go b/quadtree.go new file mode 100644 index 0000000..103a666 --- /dev/null +++ b/quadtree.go @@ -0,0 +1,84 @@ +package structs + +// Definition of a quadtree and it's nodes recursively +type Quadtree struct { + boundary BoundingBox // Spatial outreach of the quadtree + centerOfMass Vec2 // Center of mass of the cell + totalMass float64 // Total mass of the cell + depth int // Depth of the cell in the quadtree + star Star2D // Star inside the cell + + // NW, NE, SW, SE + quadrants []*Quadtree // List of quadtrees representing individual quadrants + + // Quadrants + //northWest *Quadtree + //northEast *Quadtree + //southWest *Quadtree + //southEast *Quadtree +} + +// CenterOfMass is a getter method for quadtrees. +// It returns the Center of mass of the quadtree it is applied on +func (q *Quadtree) CenterOfMass() Vec2 { + return q.centerOfMass +} + +// SetCenterOfMass is a setter method for quadtrees. +// It sets the centerOfMass of the quadtree to the given value +func (q *Quadtree) SetCenterOfMass(centerOfMass Vec2) { + q.centerOfMass = centerOfMass +} + +// CalcCenterOfMass is a calculator method for quadtrees. +// It recursively walks through the quadtree and calculates it's center of mass. +// The calculated center of mass is then inserted into the centerOfMass variable. +func (q *Quadtree) CalcCenterOfMass() (Vec2, float64) { + var totalMass float64 = 0 + var x float64 = 0 + var y float64 = 0 + + // If the Node is a leaf + if q.IsLeaf() == true { + + // update the values needed to calculate the center of mass + totalMass += q.star.M + x += q.star.C.X * q.star.M + y += q.star.C.X * q.star.M + + return Vec2{x, y}, totalMass + + } else { + + // Iterate over all the quadrants + for _, element := range q.quadrants { + + // Calculate the center of mass for each quadrant + centerOfMass, totalMass := element.CalcCenterOfMass() + + // Update the overall centerOfMass for the individual quadtree + q.centerOfMass.X += centerOfMass.X + q.centerOfMass.Y += centerOfMass.Y + q.totalMass += totalMass + } + } + + // Return the original centerOfMass and totalMass + return q.centerOfMass, q.totalMass +} + +// IsLeaf is a method for quadtrees returning true if the node is a leaf (has no children) +// or returning false if the node is nor a leaf (has children). +func (q *Quadtree) IsLeaf() bool { + for _, element := range q.quadrants { + if element == nil { + return true + } + } + return false +} + +// NewQuadtree generates a new root node. +//func NewQuadtree(boundary BoundingBox) *Quadtree { +// return &Quadtree{boundary: boundary} +//} diff --git a/star.go b/star.go new file mode 100644 index 0000000..d2bb124 --- /dev/null +++ b/star.go @@ -0,0 +1,86 @@ +package structs + +// Define a struct storing essential star information such as it's coordinate, velocity and mass +type Star2D struct { + C Vec2 // coordinates of the star + V Vec2 // velocity of the star + M float64 // mass of the star +} + +// InsideOf is a method that tests if the star it is applied on is in or outside of the given +// BoundingBox. It returns true if the star is inside of the BoundingBox and false if it isn't. +func (s Star2D) InsideOf(boundary BoundingBox) bool { + + // Test if the star is inside or outside of the bounding box. + // Abort testing if one of the conditions is not met + if s.C.X < boundary.center.X+boundary.width/2 { + if s.C.X > boundary.center.X-boundary.width/2 { + if s.C.Y < boundary.center.Y+boundary.width/2 { + if s.C.Y > boundary.center.Y-boundary.width/2 { + return true + } else { + return false + } + } else { + return false + } + } else { + return false + } + } else { + return false + } +} + +// Quadrant returns a string indicating in which quadrant of the given quadtree the point the method +// is applied on is. +// This methods presumes that the point is inside of the boundingBox +func (s Star2D) Quadrant(starsQuadtree *Quadtree) string { + centerX := starsQuadtree.boundary.center.X + centerY := starsQuadtree.boundary.center.Y + + // test if the point is left the the center or not + if s.C.X < centerX { + + // Test if the point is above or below of the center + if s.C.Y > centerY { + return "northwest" + } else { + return "southwest" + } + + // The point is right of the center + } else { + + // Test if the point is above or below of the center + if s.C.Y > centerY { + return "northeast" + } else { + return "southeast" + } + } +} + +// Return a copy of the star by returning a star struct with the same values. +func (s *Star2D) Copy() Star2D { + return Star2D{s.C.Copy(), s.V.Copy(), s.M} +} + +// Accelerate the star with the acceleration a for the time t. +// This changes the velocity of the star. +func (s *Star2D) AccelerateVelocity(a Vec2, t float64) { + s.V = s.V.Add(a.Multiply(t)) +} + +// Move the star with it's velocity for the time t. +// This changes the Position of the star. +func (s *Star2D) Move(t float64) { + s.C = s.C.Add(s.V.Multiply(t)) +} + +// Accelerate and move the star with it's velocity and the acceleration a for the time t +// This changes the position and the velocity of the star. +func (s *Star2D) Accelerate(a Vec2, t float64) { + s.AccelerateVelocity(a, t) + s.Move(t) +} diff --git a/vector2D.go b/vector2D.go new file mode 100644 index 0000000..6beedb2 --- /dev/null +++ b/vector2D.go @@ -0,0 +1,71 @@ +package structs + +import ( + "math" +) + +type Vec2 struct { + X, Y float64 +} + +// newVec2 returns a new Vec2 using the given coordinates +func newVec2(x float64, y float64) *Vec2 { + return &Vec2{ + X: x, + Y: y, + } +} + +// creates a copy of the vector +func (v *Vec2) Copy() Vec2 { + return Vec2{v.X, v.Y} +} + +func (v *Vec2) Split() (x float64, y float64) { + return v.X, v.Y +} + +// changes the length of the vector to the length l +func (v *Vec2) SetLength(l float64) { + var k = l / v.GetLength() + var newV = v.Multiply(k) + // v = newV + v.X, v.Y = newV.Split() +} + +// changes the length of the vector to the length 1 +func (v *Vec2) SetLengthOne() { + v.SetLength(1) +} + +// returns the direction Vector of this vector. This means a copy of this vector with a length of 1 +func (v *Vec2) GetDirVector() Vec2 { + var dirV = v.Copy() + dirV.SetLengthOne() + return dirV +} + +// returns the length of the vector +func (v *Vec2) GetLength() float64 { + return math.Sqrt(math.Pow(v.X, 2) + math.Pow(v.Y, 2)) +} + +// returns the product of the vector and a scalar s +func (v *Vec2) Multiply(s float64) Vec2 { + return Vec2{v.X * s, v.Y * s} +} + +// returns the quotient of the vector and a scalar s +func (v *Vec2) Divide(s float64) Vec2 { + return Vec2{v.X / s, v.Y / s} +} + +// returns the sum of this vector and the vector v2 +func (v1 *Vec2) Add(v2 Vec2) Vec2 { + return Vec2{v1.X + v2.X, v1.Y + v2.Y} +} + +// returns the difference of this vector minus the vector v2 +func (v1 *Vec2) Subtract(v2 Vec2) Vec2 { + return Vec2{v1.X - v2.X, v1.Y - v2.Y} +} |