about summary refs log tree commit diff
path: root/draw/draw.go
blob: a5d5f0de01a27494ffe7de6a9af8677d76513ff5 (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
package draw

import (
	"../structs"
	"github.com/fogleman/gg"
	"math"
)

// initializePlot generates a new plot and returns the plot context
func initializePlot() *gg.Context {
	// Define the image size
	const imageWidth = 8192
	const imageHeight = 8192

	// Initialize the new context
	dc := gg.NewContext(imageWidth, imageHeight)

	// Set the background black
	dc.SetRGB(0, 0, 0)
	dc.Clear()

	// Invert the Y axis (positive values are on the top and right)
	dc.InvertY()

	// Set the coordinate midpoint to the middle of the image
	dc.Translate(imageWidth/2, imageHeight/2)

	return dc
}

// saveImages saves the given context to a png at the given path
func saveImage(dc *gg.Context, path string) {
	dc.SavePNG(path)
}

// drawStar draws the given stars to the given context
func drawStar(dc *gg.Context, star structs.Star2D) {

	// set radius of the star to 2
	R := 2.0

	// if the star has a greater mass than the default 5E4, it's radius is increased to 5
	if star.M > 5E4 {
		R = 5
	}

	// draw the star / point
	dc.DrawPoint(star.C.X/50, star.C.Y/50, R)
	dc.Fill()
	dc.Stroke()
}

func drawVelocity(dc *gg.Context, star structs.Star2D) {
	// scaling factor for a better view of the velocity difference
	var scalingFactor float64 = 15

	// Move the "cursor" to the start position of the vector
	dc.MoveTo(star.C.X/50, star.C.Y/50)

	// calculate the length of the vector
	vecLength := star.V.GetLength()

	// 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))

	// Set the color to a blue / red
	dc.SetRGB(val, 0, 1-val)

	// calculate the direction vector
	FUnit := (&star.V).Divide(vecLength)

	// set end-position of the vector line
	dc.LineTo(star.C.X/50+(FUnit.X*scalingFactor), star.C.Y/50+(FUnit.Y*scalingFactor))

	// set line width
	dc.SetLineWidth(3)

	// And finally: DRAW (stroke) the vector
	dc.Stroke()
}

// drawStars draws all the stars in the given slice to the given context
func drawStars(dc *gg.Context, slice []structs.Star2D) {
	// draw all the velocity in the given slice
	for _, star := range slice {
		drawVelocity(dc, star)
	}

	dc.SetRGB(1, 1, 1)

	// draw all the stars in the given slice
	for _, star := range slice {
		drawStar(dc, star)
	}
}

// Slice draws the stars and the forces acting on them and saves the result to the given path
func Slice(slice []structs.Star2D, path string) {

	// initialize the plot
	dc := initializePlot()

	// draw all the stars in the given slice
	drawStars(dc, slice)

	dc.SetRGB(1, 1, 1)

	// drawing the 4 big stars as bigger white dots
	//dc.DrawCircle(600, 600, 5)
	//dc.DrawCircle(-600, 600, 5)
	//dc.DrawCircle(-600, 0, 5)
	//dc.DrawCircle(600, -600, 5)

	dc.Fill()

	// save the plot to the given path
	saveImage(dc, path)
}