109 lines
2.6 KiB
Go
109 lines
2.6 KiB
Go
package arts
|
|
|
|
import (
|
|
"github.com/fogleman/gg"
|
|
"github.com/jdxyw/generativeart"
|
|
"github.com/jdxyw/generativeart/common"
|
|
"image/color"
|
|
"math"
|
|
"math/rand"
|
|
)
|
|
|
|
type circleGrid struct {
|
|
circleNumMin, circleNumMax int
|
|
}
|
|
|
|
// NewCircleGrid returns a circleGrid object.
|
|
func NewCircleGrid(circleNumMin, circleNumMax int) *circleGrid {
|
|
return &circleGrid{
|
|
circleNumMin: circleNumMin,
|
|
circleNumMax: circleNumMax,
|
|
}
|
|
}
|
|
|
|
// Generative draws a circle grid image.
|
|
func (cg *circleGrid) Generative(c *generativeart.Canva) {
|
|
ctex := gg.NewContextForRGBA(c.Img())
|
|
cg.grid(ctex, c)
|
|
ctex.Translate(float64(c.Width())/2, float64(c.Height())/2)
|
|
ctex.Scale(0.9, 0.9)
|
|
ctex.Translate(-float64(c.Width())/2, -float64(c.Height())/2)
|
|
|
|
seg := common.RandomRangeInt(cg.circleNumMin, cg.circleNumMax)
|
|
w := float64(c.Width()) / float64(seg)
|
|
|
|
for i := 0; i < seg; i++ {
|
|
for j := 0; j < seg; j++ {
|
|
x := float64(i)*w + w/2
|
|
y := float64(j)*w + w/2
|
|
ctex.SetColor(c.Opts().ColorSchema()[rand.Intn(len(c.Opts().ColorSchema()))])
|
|
ctex.DrawCircle(x, y, w/2*common.RandomRangeFloat64(0.1, 0.5))
|
|
ctex.Fill()
|
|
cg.draw(ctex, c, x, y, w/2*common.RandomRangeFloat64(0.6, 0.95))
|
|
}
|
|
}
|
|
}
|
|
|
|
func (cg *circleGrid) draw(ctex *gg.Context, c *generativeart.Canva, x, y, r float64) {
|
|
rnd := rand.Intn(4)
|
|
col := c.Opts().ColorSchema()[rand.Intn(len(c.Opts().ColorSchema()))]
|
|
ctex.Push()
|
|
ctex.Translate(x, y)
|
|
ctex.Rotate(float64(rand.Intn(10)))
|
|
ctex.SetColor(col)
|
|
ctex.SetLineWidth(c.Opts().LineWidth())
|
|
|
|
switch rnd {
|
|
case 0:
|
|
ctex.DrawCircle(0, 0, r)
|
|
ctex.Stroke()
|
|
case 1:
|
|
n := common.RandomRangeInt(1, 4) * 2
|
|
ctex.DrawCircle(0, 0, r)
|
|
ctex.Stroke()
|
|
for i := 0; i < n; i++ {
|
|
ctex.Rotate(math.Pi * 2 / float64(n))
|
|
ctex.DrawCircle(r, 0, r*0.1)
|
|
ctex.Fill()
|
|
}
|
|
case 2:
|
|
n := common.RandomRangeInt(8, 20)
|
|
theta := math.Pi * 0.5 * float64(common.RandomRangeInt(1, 5))
|
|
for i := 0; i < n; i++ {
|
|
d := float64(i) / float64(n)
|
|
if d > r*0.1 {
|
|
d = r * 0.1
|
|
}
|
|
ctex.Rotate(theta / float64(n))
|
|
ctex.DrawCircle(r/2, 0, d*2)
|
|
ctex.Fill()
|
|
}
|
|
case 3:
|
|
n := common.RandomRangeInt(5, 20)
|
|
for i := 0; i < n; i++ {
|
|
ctex.Rotate(math.Pi * 2 / float64(n))
|
|
ctex.DrawLine(r/2, 0, (r*2/3)-(r*0.05), 0)
|
|
ctex.Stroke()
|
|
}
|
|
|
|
}
|
|
ctex.Pop()
|
|
}
|
|
|
|
func (cg *circleGrid) grid(ctex *gg.Context, c *generativeart.Canva) {
|
|
var segment int = 100
|
|
w := float64(c.Width()) / float64(segment)
|
|
|
|
ctex.SetColor(color.RGBA{255, 255, 255, 255})
|
|
ctex.SetLineWidth(0.6)
|
|
for i := 0; i < segment; i++ {
|
|
ctex.DrawLine(0, float64(i)*w, float64(c.Width()), float64(i)*w)
|
|
ctex.Stroke()
|
|
}
|
|
|
|
for j := 0; j < segment; j++ {
|
|
ctex.DrawLine(float64(j)*w, 0, float64(j)*w, float64(c.Height()))
|
|
ctex.Stroke()
|
|
}
|
|
}
|