about summary refs log tree commit diff
path: root/draw.go
blob: 277a8d252e425672f07e3cd15fd89a0ceced6c4f (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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
package structs

import (
	"fmt"
	"log"

	"github.com/fogleman/gg"
)

func initializePlot(imageWidth int, imageHeight int) *gg.Context {

	// define an new context using the given image width and height
	context := gg.NewContext(imageWidth, imageHeight)

	// set the background color to black
	context.SetRGB(0, 0, 0)
	context.Clear()
	context.SetRGB(1, 1, 1)

	// translate the coordinate origin to the midpoint of the image
	context.Translate(float64(imageWidth/2), float64(imageHeight/2))

	return context
}

// drawQuadtree draws a given quadtree and the stars in it recursively to the given canvas
func drawQuadtree(context *gg.Context, q Quadtree) {

	// find out if the node is a leaf find out if the node is a leaf find out if the node is a leaf find out if the node is a leaf
	var draw bool = false
	for i := 0; i < 4; i++ {
		if q.Quadrants[i] == nil {
			draw = true
		}
	}

	// draw the bounding box and the star if the node is a leaf
	if draw == true {

		// Don't draw nonexistent stars
		if q.Star != (Star2D{}) {

			// define the current star
			x := q.Star.C.X
			y := q.Star.C.Y
			starsize := 2

			// set the color of the stars to green
			context.SetRGB(0, 1, 1)
			context.DrawPoint(x, y, float64(starsize))
			context.Fill()
			// context.DrawString(fmt.Sprintf("(%f, %f)", x, y), x, y)
			context.Stroke()
			log.Printf("[***] Drawing Star (%f, %f)", x, y)
		}

		// define the bounding box
		boundingx := q.Boundary.Center.X
		boundingy := q.Boundary.Center.Y
		boundingw := q.Boundary.Width

		// bottom left corner
		contextx := boundingx - (boundingw / 2)
		contexty := boundingy - (boundingw / 2)

		// draw the rectangle
		context.SetRGB(1, 1, 1)
		context.DrawRectangle(contextx, contexty, boundingw, boundingw)
		context.Stroke()

		log.Printf("[***] Drawing Box ((%f, %f), %f)", contextx, contexty, boundingw)
	}

	// draw all the other trees recursively...
	for i := 0; i < 4; i++ {
		// ... but only if they exist
		if q.Quadrants[i] != nil {
			drawQuadtree(context, *q.Quadrants[i])
		}
	}
}

// saveImage saves the given context to the given path as a png
func saveImage(context *gg.Context, outpath string) {
	savePngError := context.SavePNG(outpath)
	if savePngError != nil {
		panic(savePngError)
	}
}

// DrawGalaxy draws the given quadtree to the given output path
func (q Quadtree) DrawGalaxy(outpath string) {
	log.Printf("Drawing the quadtree to %s", outpath)

	// define the image dimensions
	imageWidth := 1024 * 8
	imageHeight := 1024 * 8

	// define a new context to draw on
	context := initializePlot(imageWidth, imageHeight)

	// first recursive call of drawQuadtree
	drawQuadtree(context, q)

	// save the context to the given output path
	saveImage(context, outpath)
}

// GeneratePrintTree generates forest code for drawing a tree
func (q Quadtree) GeneratePrintTree(depth int) string {
	returnString := ""
	if q.Star != (Star2D{}) {
		returnString += "[a"
		fmt.Printf("[a")
	} else {
		returnString += "["
		fmt.Printf("[")
	}

	for i := 0; i < 4; i++ {
		if q.Quadrants[i] != nil {
			returnString += fmt.Sprintf("[%d]", depth)
			returnString += q.Quadrants[i].GeneratePrintTree(depth + 1)
		}
	}

	// ok, the reason the final image will only show the nodes in the leaf is, that in the latex
	// forest package that I use, trees must be drawn like this: [a[b]] and not like this: [[b]a].
	// [[b]a] == [[b]]. So there might be a lot of zeros, but that's ok!
	if q.Star != (Star2D{}) {
		returnString += "a]"
		fmt.Printf("a]")
	} else {
		returnString += "]"
		fmt.Printf("]")
	}

	return returnString
}

// DrawTree returns a valid LaTeX Document as a string drawing the quadtree it is called on using the forest package
func (q Quadtree) DrawTree() string {
	s1 := `\documentclass{article}
\usepackage{tikz}
\usepackage{forest}
\begin{document}
\begin{forest}
for tree={circle,draw, s sep+=0.25em}`

	s2 := q.GeneratePrintTree(0)

	s3 := `\end{forest}
\end{document}`

	return fmt.Sprintf("%s\n%s\n%s\n", s1, s2, s3)
}