forked from jdxyw/generativeart
/
circlenoise.go
89 lines (77 loc) · 2.27 KB
/
circlenoise.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
package arts
import (
"math"
"math/rand"
"github.com/andrewwatson/generativeart"
"github.com/andrewwatson/generativeart/common"
"github.com/fogleman/gg"
)
type circleNoise struct {
dotsN int
colorMin, colorMax int
}
type dot struct {
x, y float64
prevx, prevy float64
theta float64
count int
cx, cy float64
}
func NewCircleNoise(dotsN, colorMin, colorMax int) *circleNoise {
return &circleNoise{
dotsN: dotsN,
colorMin: colorMin,
colorMax: colorMax,
}
}
// Generative draws a circle with perlin noise.
func (cn *circleNoise) Generative(c *generativeart.Canva) string {
ctex := gg.NewContextForRGBA(c.Img())
ctex.SetLineWidth(2.0)
ctex.SetColor(common.Black)
radius := float64(c.Width()) * 0.8 / 2
ctex.DrawCircle(float64(c.Width()/2), float64(c.Height()/2), radius)
ctex.Stroke()
//ctex.Clip()
var factor = 0.008
noise := common.NewPerlinNoise()
dots := make([]dot, 0)
for i := 0; i < cn.dotsN; i++ {
theta := rand.Float64() * math.Pi * 2
x, y := float64(c.Width())/2+math.Sin(theta)*radius, float64(c.Height())/2+math.Cos(theta)*radius
dots = append(dots, dot{
theta: theta,
x: x,
y: y,
prevx: x,
prevy: y,
count: 0,
})
}
for j := 0; j < c.Opts().NIters(); j++ {
for i, _ := range dots {
n := noise.Noise2D(dots[i].x*factor, dots[i].y*factor)
nx, ny := math.Cos(n*math.Pi*2+float64(dots[i].count)*math.Pi)*2, math.Sin(n*math.Pi*2+float64(dots[i].count)*math.Pi)*2
dots[i].prevx, dots[i].prevy = dots[i].x, dots[i].y
dots[i].x, dots[i].y = dots[i].x+nx, dots[i].y+ny
hsv := common.HSV{
H: int(common.Remap(n, 0, 1, float64(cn.colorMin), float64(cn.colorMax))),
S: 100,
V: 20,
}
if common.Distance(float64(c.Width())/2, float64(c.Height())/2, dots[i].x, dots[i].y) > radius+2 {
dots[i].count += 1
}
if common.Distance(float64(c.Width())/2, float64(c.Height())/2, dots[i].x, dots[i].y) < radius &&
common.Distance(float64(c.Width())/2, float64(c.Height())/2, dots[i].prevx, dots[i].prevy) < radius {
ctex.SetLineWidth(c.Opts().LineWidth())
rgb := hsv.ToRGB(100, 100, 100)
rgb.A = uint8(c.Opts().Alpha())
ctex.SetColor(rgb)
ctex.DrawLine(dots[i].prevx, dots[i].prevy, dots[i].x, dots[i].y)
ctex.Stroke()
}
}
}
return ""
}