88 lines
2.2 KiB
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()
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
}
|