generativeart/arts/circlenoise.go

88 lines
2.2 KiB
Go

package arts
import (
"github.com/fogleman/gg"
"github.com/jdxyw/generativeart"
"github.com/jdxyw/generativeart/common"
"math"
"math/rand"
)
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) {
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()
}
}
}
}