add silk smoke
This commit is contained in:
parent
8a8688f56a
commit
05f31aca8e
3 changed files with 107 additions and 6 deletions
26
example/example_silksmoke.go
Normal file
26
example/example_silksmoke.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.Black)
|
||||||
|
c.SetLineWidth(1.0)
|
||||||
|
c.SetLineColor(color.RGBA{
|
||||||
|
R: 255,
|
||||||
|
G: 255,
|
||||||
|
B: 255,
|
||||||
|
A: 30,
|
||||||
|
})
|
||||||
|
c.SetColorSchema(generativeart.Plasma)
|
||||||
|
c.SetIterations(4)
|
||||||
|
c.FillBackground()
|
||||||
|
c.Draw(generativeart.NewSilkSmoke(400, 20, 0.2, 2, 10, 30, false))
|
||||||
|
c.ToPNG("silksmoke.png")
|
||||||
|
}
|
|
@ -34,15 +34,15 @@ func NewRandCicle(mc, msp int, minStep, maxStep, minr, maxr float64, isRandColor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *randCircle) newCircleSlice(cn, w, h int) []circle {
|
func newCircleSlice(cn, w, h int, minStep, maxStep, minRadius, maxRadius float64) []circle {
|
||||||
var circles []circle
|
var circles []circle
|
||||||
|
|
||||||
for i := 0; i < cn; i++ {
|
for i := 0; i < cn; i++ {
|
||||||
x := rand.Intn(w) + 1
|
x := rand.Intn(w) + 1
|
||||||
y := rand.Intn(h) + 1
|
y := rand.Intn(h) + 1
|
||||||
radius := float64(rand.Intn(int(r.minRadius))) + r.maxRadius - r.minRadius
|
radius := float64(rand.Intn(int(minRadius))) + maxRadius - minRadius
|
||||||
angle := rand.Float64() * math.Pi * 2.0
|
angle := rand.Float64() * math.Pi * 2.0
|
||||||
step := r.minSteps + rand.Float64()*(r.maxSteps-r.minSteps)
|
step := minStep + rand.Float64()*(maxStep-minStep)
|
||||||
circles = append(circles, circle{
|
circles = append(circles, circle{
|
||||||
x: float64(x),
|
x: float64(x),
|
||||||
y: float64(y),
|
y: float64(y),
|
||||||
|
@ -55,7 +55,7 @@ func (r *randCircle) newCircleSlice(cn, w, h int) []circle {
|
||||||
return circles
|
return circles
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *randCircle) circleSliceUpdate(cs []circle, w, h int) []circle {
|
func circleSliceUpdate(cs []circle, w, h int) []circle {
|
||||||
var circles []circle
|
var circles []circle
|
||||||
|
|
||||||
for _, c := range cs {
|
for _, c := range cs {
|
||||||
|
@ -94,7 +94,7 @@ func (r *randCircle) Generative(c *canva) {
|
||||||
|
|
||||||
for j := 0; j < c.opts.nIters; j++ {
|
for j := 0; j < c.opts.nIters; j++ {
|
||||||
cn := rand.Intn(r.maxCircle) + int(r.maxCircle/3)
|
cn := rand.Intn(r.maxCircle) + int(r.maxCircle/3)
|
||||||
circles := r.newCircleSlice(cn, c.width, c.height)
|
circles := newCircleSlice(cn, c.width, c.height, r.minSteps, r.maxSteps, r.minRadius, r.maxRadius)
|
||||||
|
|
||||||
for i := 0; i < r.maxStepsPerCircle; i++ {
|
for i := 0; i < r.maxStepsPerCircle; i++ {
|
||||||
for _, c1 := range circles {
|
for _, c1 := range circles {
|
||||||
|
@ -123,7 +123,7 @@ func (r *randCircle) Generative(c *canva) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
circles = r.circleSliceUpdate(circles, c.width, c.height)
|
circles = circleSliceUpdate(circles, c.width, c.height)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
75
silksmoke.go
Normal file
75
silksmoke.go
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
package generativeart
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/fogleman/gg"
|
||||||
|
"math/rand"
|
||||||
|
)
|
||||||
|
|
||||||
|
type sileSmoke struct {
|
||||||
|
maxCircle int
|
||||||
|
maxStepsPerCircle int
|
||||||
|
minSteps float64
|
||||||
|
maxSteps float64
|
||||||
|
minRadius float64
|
||||||
|
maxRadius float64
|
||||||
|
isRandColor bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSilkSmoke(mc, msp int, minStep, maxStep, minRadius, maxRadius float64, isRandColor bool) *sileSmoke {
|
||||||
|
return &sileSmoke{
|
||||||
|
maxCircle: mc,
|
||||||
|
maxStepsPerCircle: msp,
|
||||||
|
minSteps: minStep,
|
||||||
|
maxSteps: maxStep,
|
||||||
|
minRadius: minRadius,
|
||||||
|
maxRadius: maxRadius,
|
||||||
|
isRandColor: isRandColor,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generative draws a silk smoke image.
|
||||||
|
func (s *sileSmoke) Generative(c *canva) {
|
||||||
|
ctex := gg.NewContextForRGBA(c.img)
|
||||||
|
|
||||||
|
cn := rand.Intn(s.maxCircle) + int(s.maxCircle/3)
|
||||||
|
circles := newCircleSlice(cn, c.width, c.height, s.minSteps, s.maxSteps, s.minRadius, s.maxRadius)
|
||||||
|
|
||||||
|
for i :=0; i<s.maxStepsPerCircle; i++ {
|
||||||
|
ctex.SetRGBA255(0, 0, 0, 5)
|
||||||
|
ctex.DrawRectangle(0, 0, float64(c.width), float64(c.height))
|
||||||
|
ctex.Fill()
|
||||||
|
|
||||||
|
for _, c1 := range circles {
|
||||||
|
for _, c2 := range circles {
|
||||||
|
|
||||||
|
cl := c.opts.lineColor
|
||||||
|
if s.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.LineTo(c1.x, c1.y)
|
||||||
|
ctex.LineTo(c2.x, c2.y)
|
||||||
|
ctex.LineTo(cx, cy)
|
||||||
|
ctex.LineTo(c1.x, c1.y)
|
||||||
|
|
||||||
|
ctex.Stroke()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
circles = circleSliceUpdate(circles, c.width, c.height)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue