-
Notifications
You must be signed in to change notification settings - Fork 2
/
arrows.go
102 lines (84 loc) · 2.09 KB
/
arrows.go
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
package draw
import (
"github.com/mumax/3/data"
"github.com/mumax/3/freetype/raster"
"image"
"image/color"
"math"
)
func drawArrows(img *image.RGBA, arr [3][][][]float32, sub int) {
c := NewCanvas(img)
Na := data.SizeOf(arr[0]) // number of arrows
h := Na[Y] // orignal image height
Na[X] = imax(Na[X]/sub, 1)
Na[Y] = imax(Na[Y]/sub, 1)
Na[Z] = 1
small := data.Downsample(arr[:], Na)
S := float32(sub)
for iy := 0; iy < Na[Y]; iy++ {
Ay := float32(h) - (float32(iy)+0.5)*S
for ix := 0; ix < Na[X]; ix++ {
Ax := (float32(ix) + 0.5) * S
mx := small[X][0][iy][ix]
my := small[Y][0][iy][ix]
mz := small[Z][0][iy][ix]
c.Arrow(Ax, Ay, mx, my, mz, float32(sub))
}
}
c.rasterizer.Rasterize(c.RGBAPainter)
c.rasterizer.Clear()
}
// A Canvas is used to draw on.
type Canvas struct {
*image.RGBA
*raster.RGBAPainter
rasterizer *raster.Rasterizer
}
// Make a new canvas of size w x h.
func NewCanvas(img *image.RGBA) *Canvas {
c := new(Canvas)
c.RGBA = img
c.RGBAPainter = raster.NewRGBAPainter(c.RGBA)
c.rasterizer = raster.NewRasterizer(img.Bounds().Max.X, img.Bounds().Max.Y)
c.rasterizer.UseNonZeroWinding = true
c.SetColor(color.RGBA{0, 0, 0, 100})
return c
}
func (c *Canvas) Arrow(x, y, mx, my, mz, size float32) {
arrlen := 0.4 * size
arrw := 0.2 * size
norm := float32(math.Sqrt(float64(mx*mx + my*my + mz*mz)))
if norm == 0 {
return
}
if norm > 1 {
norm = 1
}
theta := math.Atan2(float64(my), float64(mx))
cos := float32(math.Cos(theta))
sin := float32(math.Sin(theta))
r1 := arrlen * norm * float32(math.Cos(math.Asin(float64(mz))))
r2 := arrw * norm
pt1 := pt((r1*cos)+x, -(r1*sin)+y)
pt2 := pt((r2*sin-r1*cos)+x, -(-r2*cos-r1*sin)+y)
pt3 := pt((-r2*sin-r1*cos)+x, -(r2*cos-r1*sin)+y)
var path raster.Path
path.Start(pt1)
path.Add1(pt2)
path.Add1(pt3)
path.Add1(pt1)
c.rasterizer.AddPath(path)
}
func pt(x, y float32) raster.Point {
return raster.Point{fix32(x), fix32(y)}
}
func fix32(x float32) raster.Fix32 {
return raster.Fix32(int(x * (1 << 8)))
}
func imax(a, b int) int {
if a > b {
return a
} else {
return b
}
}