about summary refs log tree commit diff
diff options
context:
space:
mode:
authorhanemile <hanemile@protonmail.com>2018-12-14 16:01:49 +0100
committerhanemile <hanemile@protonmail.com>2018-12-14 16:01:49 +0100
commit5b07e06dcd837431ffc4e9ad0c2798029cf40a48 (patch)
tree37f84f89de66565604af2f07c9545cecb415f2e8
parent35c8993423f9240aefa0b4bd839fba85b8a3c944 (diff)
Updated some stuff, this is probably going to be the final commit in this monolithic application, because of the new microservices used in the rewrite.
-rw-r--r--.idea/inspectionProfiles/Project_Default.xml20
-rw-r--r--config.json2
-rw-r--r--csv/csv.go22
-rw-r--r--draw/draw.go10
-rw-r--r--main.go55
-rw-r--r--structs/boundingBox.go27
-rw-r--r--structs/quadtree.go84
-rw-r--r--structs/star.go56
8 files changed, 251 insertions, 25 deletions
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000..e62755d
--- /dev/null
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,20 @@
+<component name="InspectionProjectProfileManager">
+  <profile version="1.0">
+    <option name="myName" value="Project Default" />
+    <inspection_tool class="GoUnhandledErrorResult" enabled="true" level="WARNING" enabled_by_default="true">
+      <methods>
+        <method importPath="hash" receiver="Hash" name="Write" />
+        <method importPath="strings" receiver="*Builder" name="Write" />
+        <method importPath="strings" receiver="*Builder" name="WriteByte" />
+        <method importPath="bytes" receiver="*Buffer" name="WriteRune" />
+        <method importPath="bytes" receiver="*Buffer" name="Write" />
+        <method importPath="bytes" receiver="*Buffer" name="WriteString" />
+        <method importPath="strings" receiver="*Builder" name="WriteString" />
+        <method importPath="bytes" receiver="*Buffer" name="WriteByte" />
+        <method importPath="strings" receiver="*Builder" name="WriteRune" />
+        <method importPath="math/rand" receiver="*Rand" name="Read" />
+        <method importPath="os" receiver="*File" name="Close" />
+      </methods>
+    </inspection_tool>
+  </profile>
+</component>
\ No newline at end of file
diff --git a/config.json b/config.json
index 0fd8122..5b77619 100644
--- a/config.json
+++ b/config.json
@@ -2,7 +2,7 @@
   "Frames": 1,
   "Threads": 8,
   "RangeStart": 0,
-  "RangeEnd": 5000,
+  "RangeEnd": 50000,
   "LoadPath": "data/U_ALL.csv",
   "OutPath": "out_%d.csv"
 }
diff --git a/csv/csv.go b/csv/csv.go
index 1b3c0bc..01c3743 100644
--- a/csv/csv.go
+++ b/csv/csv.go
@@ -40,3 +40,25 @@ func Import(path string, start int, end int, slice []structs.Star2D) []structs.S
 
 	return slice
 }
+
+// Generate a homogeneous Grid
+func GenerateHomogeneousGrid(slice []structs.Star2D, left int, right int, step int) []structs.Star2D {
+
+	// Iterate over a grid
+	for i := left; i < right; i += step {
+		for j := left; j < right; j += step {
+
+			// generate a new star with the coordinates
+			tempStar := structs.Star2D{
+				C: structs.Vec2{X: float64(i) + float64(rand.Intn(step)), Y: float64(j) + float64(rand.Intn(step))},
+				M: float64(rand.Intn(500000)),
+			}
+
+			// add the star to the slice
+			slice = append(slice, tempStar)
+		}
+	}
+
+	// return the new slice containing a homogeneous grid of stars
+	return slice
+}
diff --git a/draw/draw.go b/draw/draw.go
index 8b66c90..de58191 100644
--- a/draw/draw.go
+++ b/draw/draw.go
@@ -1,7 +1,6 @@
 package draw
 
 import (
-	"fmt"
 	"git.darknebu.la/GalaxySimulator/Source/structs"
 	"github.com/fogleman/gg"
 	"math"
@@ -10,8 +9,8 @@ import (
 // initializePlot generates a new plot and returns the plot context
 func initializePlot() *gg.Context {
 	// Define the image size
-	const imageWidth = 8192
-	const imageHeight = 8192
+	const imageWidth = 8192 * 2
+	const imageHeight = 8192 * 2
 
 	// Initialize the new context
 	dc := gg.NewContext(imageWidth, imageHeight)
@@ -68,8 +67,7 @@ func drawVelocity(dc *gg.Context, star structs.Star2D) {
 
 	// Use a sigmoid function to generate useful values for coloring the vectors according to their
 	// strength
-	var val = 1.0 / (1.0 + math.Exp(-vecLength*scalingFactor/2 * 1e8))
-	fmt.Println(val)
+	var val = 1.0 / (1.0 + math.Exp(-vecLength*scalingFactor/2*1e8))
 
 	// Set the color to a blue / red
 	dc.SetRGB(val, 0, 1-val)
@@ -81,7 +79,7 @@ func drawVelocity(dc *gg.Context, star structs.Star2D) {
 	dc.LineTo(star.C.X/50+(FUnit.X*scalingFactor), star.C.Y/50+(FUnit.Y*scalingFactor))
 
 	// set line width
-	dc.SetLineWidth(3)
+	dc.SetLineWidth(5)
 
 	// And finally: DRAW (stroke) the vector
 	dc.Stroke()
diff --git a/main.go b/main.go
index 4a3dcad..1126af2 100644
--- a/main.go
+++ b/main.go
@@ -4,10 +4,7 @@ import (
 	"encoding/json"
 	"fmt"
 	"git.darknebu.la/GalaxySimulator/Source/csv"
-	"git.darknebu.la/GalaxySimulator/Source/draw"
-	"git.darknebu.la/GalaxySimulator/Source/forces"
 	"git.darknebu.la/GalaxySimulator/Source/structs"
-	"math"
 	"os"
 )
 
@@ -24,11 +21,11 @@ func main() {
 	// Load the config
 	var config Config = LoadConfiguration("config.json")
 
-	fmt.Printf("[+] Utilizing %d threads ", config.Threads)
+	fmt.Printf("[ ] Utilizing %d threads ", config.Threads)
 	fmt.Printf("for drawing %d Frames, ", config.Frames)
 	fmt.Printf("each containing %d Stars.\n", config.RangeEnd)
 
-	fmt.Printf("[+] Getting previously existing Stars from %s ", config.LoadPath)
+	fmt.Printf("[ ] Getting previously existing Stars from %s ", config.LoadPath)
 	fmt.Printf("and writing the results to %s.\n", config.OutPath)
 
 	// the slice starsSlice stores the star structures
@@ -67,23 +64,46 @@ func main() {
 			M: 1e10,
 		},
 	}
-	starsSlice = csv.Import(config.LoadPath, config.RangeStart, config.RangeEnd, starsSlice)
 
-	fmt.Println("Done loading the data")
+	// import existing stars from a csv
+	// generate new stars in a homogeneous grid
 
-	// Simulate frames
+	starsSlice = csv.GenerateHomogeneousGrid(starsSlice, -5e5, 5e5, 1e5)
+	fmt.Printf("Amount of Stars: %d\n", len(starsSlice))
+	//starsSlice = csv.Import(config.LoadPath, config.RangeStart, config.RangeEnd, starsSlice)
+
+	fmt.Println("[+] Done loading the data.")
+
+	// Iterate over all the frames
 	for i := 0; i < config.Frames; i++ {
-		fmt.Println("Calculating the frame")
+		fmt.Printf("[ ] Frame %d\n", i)
+
+		// Create a new quadtree
+		boundary := *structs.NewBoundingBox(structs.Vec2{0, 0}, 1e8)
+		starsQuadtree := *structs.NewQuadtree(boundary)
 
-		starsSlice = forces.NextTimestep(starsSlice, 25*math.Pow(10, 4+7))
-		starsSlice = forces.CalcAllAccelerations(starsSlice, config.Threads)
+		// Print all the elements in the stars Slice
+		for _, element := range starsSlice {
+			fmt.Println(element)
+		}
 
-		fmt.Println("Done Calculating")
+		// Insert all the stars from the starsSlice into the Quadtree
+		//starQuadtree := quadtree.InsertSlice(starsSlice)
+
+		//starsSlice = forces.NextTimestep(starsSlice, 25*math.Pow(10, 4+7))
+		//starsSlice = forces.CalcAllAccelerations(starsSlice, config.Threads)
+		//var starsQuadtree quadtree.Quadtree = quadtree.CreateWithSlice(starsSlice)
+		//quadtree.Print(&starsQuadtree)
+		//quadtree.Draw(&starsQuadtree)
+		//quadtree.DrawQuadtree(starsQuadtree)
+
+		fmt.Println("[+] Done Calculating the forces acting.")
 
 		// draw the galaxy
-		outputName := fmt.Sprintf("out_%d.png", i+4)
-		draw.Slice(starsSlice, outputName)
-		fmt.Println("Done drawing all the stars")
+		//fmt.Println("[ ] Drawing the Stars")
+		//outputName := fmt.Sprintf("out_%d.png", i+4)
+		//draw.Slice(starsSlice, outputName)
+		//fmt.Println("[+] Done drawing all the stars")
 	}
 }
 
@@ -106,7 +126,10 @@ func LoadConfiguration(file string) Config {
 
 	// Parsing the content and adding it to the config struct
 	jsonParser := json.NewDecoder(configFile)
-	jsonParser.Decode(&config)
+	err := jsonParser.Decode(&config)
+	if err != nil {
+		panic(err)
+	}
 
 	// Returning the config for further use
 	return config
diff --git a/structs/boundingBox.go b/structs/boundingBox.go
new file mode 100644
index 0000000..ad02eab
--- /dev/null
+++ b/structs/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/structs/quadtree.go b/structs/quadtree.go
new file mode 100644
index 0000000..7f82a2a
--- /dev/null
+++ b/structs/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/structs/star.go b/structs/star.go
index f495d99..d2bb124 100644
--- a/structs/star.go
+++ b/structs/star.go
@@ -1,7 +1,5 @@
 package structs
 
-import "C"
-
 // Define a struct storing essential star information such as it's coordinate, velocity and mass
 type Star2D struct {
 	C Vec2    // coordinates of the star
@@ -9,6 +7,60 @@ type Star2D struct {
 	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}