add rand circles
This commit is contained in:
parent
ca593e6a6e
commit
664f27d421
4 changed files with 163 additions and 3 deletions
26
example/example_randcircle.go
Normal file
26
example/example_randcircle.go
Normal file
|
@ -0,0 +1,26 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"generativeart"
|
||||
"image/color"
|
||||
"math/rand"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
rand.Seed(time.Now().Unix())
|
||||
c := generativeart.NewCanva(500, 500, 2, 2)
|
||||
c.SetBackground(generativeart.MistyRose)
|
||||
c.SetLineWidth(1.0)
|
||||
c.SetLineColor(color.RGBA{
|
||||
R: 122,
|
||||
G: 122,
|
||||
B: 122,
|
||||
A: 30,
|
||||
})
|
||||
c.SetColorSchema(generativeart.Plasma)
|
||||
c.SetIterations(4)
|
||||
c.FillBackground()
|
||||
c.Draw(generativeart.NewRandCicle(30, 80, 0.2, 2, 10, 30, true))
|
||||
c.ToPNG("randcircle.png")
|
||||
}
|
6
julia.go
6
julia.go
|
@ -12,13 +12,13 @@ type julia struct {
|
|||
|
||||
func NewJulia(formula GenFunc, maxz float64) *julia {
|
||||
return &julia{
|
||||
fn: formula,
|
||||
fn: formula,
|
||||
maxz: maxz,
|
||||
}
|
||||
}
|
||||
|
||||
// Generative draws a julia set.
|
||||
func (j *julia)Generative(c *canva) {
|
||||
func (j *julia) Generative(c *canva) {
|
||||
n := len(c.opts.colorSchema)
|
||||
if n > 255 {
|
||||
n = 255
|
||||
|
@ -37,4 +37,4 @@ func (j *julia)Generative(c *canva) {
|
|||
c.img.Set(i, k, c.opts.colorSchema[idx])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
130
randcircle.go
Normal file
130
randcircle.go
Normal file
|
@ -0,0 +1,130 @@
|
|||
package generativeart
|
||||
|
||||
import (
|
||||
"github.com/fogleman/gg"
|
||||
"math"
|
||||
"math/rand"
|
||||
)
|
||||
|
||||
type circle struct {
|
||||
x, y float64
|
||||
radius float64
|
||||
dx, dy float64
|
||||
}
|
||||
|
||||
type randCircle struct {
|
||||
maxCircle int
|
||||
maxStepsPerCircle int
|
||||
minSteps float64
|
||||
maxSteps float64
|
||||
minRadius float64
|
||||
maxRadius float64
|
||||
isRandColor bool
|
||||
}
|
||||
|
||||
func NewRandCicle(mc, msp int, minStep, maxStep, minr, maxr float64, isRandColor bool) *randCircle {
|
||||
return &randCircle{
|
||||
maxCircle: mc,
|
||||
maxStepsPerCircle: msp,
|
||||
minSteps: minStep,
|
||||
maxSteps: maxStep,
|
||||
minRadius: minr,
|
||||
maxRadius: maxr,
|
||||
isRandColor: isRandColor,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *randCircle) newCircleSlice(cn, w, h int) []circle {
|
||||
var circles []circle
|
||||
|
||||
for i := 0; i < cn; i++ {
|
||||
x := rand.Intn(w) + 1
|
||||
y := rand.Intn(h) + 1
|
||||
radius := float64(rand.Intn(int(r.minRadius))) + r.maxRadius - r.minRadius
|
||||
angle := rand.Float64() * math.Pi * 2.0
|
||||
step := r.minSteps + rand.Float64()*(r.maxSteps-r.minSteps)
|
||||
circles = append(circles, circle{
|
||||
x: float64(x),
|
||||
y: float64(y),
|
||||
radius: radius,
|
||||
dx: step * math.Cos(angle),
|
||||
dy: step * math.Sin(angle),
|
||||
})
|
||||
}
|
||||
|
||||
return circles
|
||||
}
|
||||
|
||||
func (r *randCircle) circleSliceUpdate(cs []circle, w, h int) []circle {
|
||||
var circles []circle
|
||||
|
||||
for _, c := range cs {
|
||||
c.x += c.dx
|
||||
c.y += c.dy
|
||||
|
||||
if c.x <= 0 {
|
||||
c.x = 0
|
||||
c.dx *= -1
|
||||
}
|
||||
|
||||
if c.y <= 0 {
|
||||
c.y = 0
|
||||
c.dy *= -1
|
||||
}
|
||||
|
||||
if c.x > float64(w) {
|
||||
c.x = float64(w)
|
||||
c.dx *= -1
|
||||
}
|
||||
|
||||
if c.y > float64(h) {
|
||||
c.y = float64(h)
|
||||
c.dy *= -1
|
||||
}
|
||||
|
||||
circles = append(circles, c)
|
||||
}
|
||||
|
||||
return circles
|
||||
}
|
||||
|
||||
// Generative draws a random circles image.
|
||||
func (r *randCircle) Generative(c *canva) {
|
||||
ctex := gg.NewContextForRGBA(c.img)
|
||||
|
||||
|
||||
for j := 0; j<c.opts.nIters; j++ {
|
||||
cn := rand.Intn(r.maxCircle) + int(r.maxCircle/3)
|
||||
circles := r.newCircleSlice(cn, c.width, c.height)
|
||||
|
||||
for i := 0; i < r.maxStepsPerCircle; i++ {
|
||||
for _, c1 := range circles {
|
||||
for _, c2 := range circles {
|
||||
|
||||
cl := c.opts.lineColor
|
||||
if r.isRandColor {
|
||||
cl = c.opts.colorSchema[rand.Intn(len(c.opts.colorSchema))]
|
||||
}
|
||||
|
||||
if c1 == c2 {
|
||||
continue
|
||||
}
|
||||
|
||||
distance := Distance(c1.x, c1.y, c2.x, c2.y)
|
||||
|
||||
if distance <= c1.radius+c2.radius {
|
||||
cx := (c1.x + c2.x) / 2
|
||||
cy := (c1.y + c2.y) / 2
|
||||
|
||||
ctex.SetRGBA255(int(cl.R), int(cl.G), int(cl.B), 30)
|
||||
ctex.SetLineWidth(c.opts.lineWidth)
|
||||
ctex.DrawEllipse(cx, cy, distance/2, distance/2)
|
||||
ctex.Stroke()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
circles = r.circleSliceUpdate(circles, c.width, c.height)
|
||||
}
|
||||
}
|
||||
}
|
4
utils.go
4
utils.go
|
@ -33,3 +33,7 @@ func ConvertPolarToPixel(r, theta, xaixs, yaixs float64, h, w int) (int, int) {
|
|||
|
||||
return i, j
|
||||
}
|
||||
|
||||
func Distance(x1, y1, x2, y2 float64) float64 {
|
||||
return math.Sqrt(math.Pow(x1-x2, 2.0) + math.Pow(y1-y2, 2.0))
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue