diff options
-rw-r--r-- | .idea/inspectionProfiles/Project_Default.xml | 20 | ||||
-rw-r--r-- | config.json | 2 | ||||
-rw-r--r-- | csv/csv.go | 22 | ||||
-rw-r--r-- | draw/draw.go | 10 | ||||
-rw-r--r-- | main.go | 55 | ||||
-rw-r--r-- | structs/boundingBox.go | 27 | ||||
-rw-r--r-- | structs/quadtree.go | 84 | ||||
-rw-r--r-- | structs/star.go | 56 |
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} |