diff --git a/README.md b/README.md index e949688..45c55b3 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,8 @@ For these kinds of art, the package provides as many as parameters to control th ## Install +The go version I used is go 1.16. + ```bash go get github.com/jdxyw/generativeart ``` @@ -27,15 +29,32 @@ go get github.com/jdxyw/generativeart ## Art Type ```go -NewCircleLine(step float64, lineNum int, radius float64) +NewCircleLine(step float64, lineNum int, radius, xaixs, yaixs float64) NewCircleLoop(radius float64) -NewMaze() +NewMaze(step int) NewRandCicle(mc, msp int, minStep, maxStep, minr, maxr float64, isRandColor bool) NewSilkSky(circleNum int, sunRadius float64) NewSilkSmoke(mc, msp int, minStep, maxStep, minRadius, maxRadius float64, isRandColor bool) NewSpiralSquare(squareNum int, rectSide, decay float64, randColor bool) ``` +## General Options + +```go +type Options struct { + background color.RGBA + foreground color.RGBA + lineColor color.RGBA + lineWidth float64 + colorSchema []color.RGBA + nIters int + alpha int +} +``` + +The `Options` is a global option for the whole `canva`. It includes those general parameters used by different kinds of types, such as `background`, `lineColor`, and `colorScheme`. + +For those parameters specified for different kinds of art type, they have their own `struct`. ## Usage and example ### Silk Smoke @@ -43,7 +62,7 @@ NewSpiralSquare(squareNum int, rectSide, decay float64, randColor bool) ```go func main() { rand.Seed(time.Now().Unix()) - c := generativeart.NewCanva(500, 500, 2, 2) + c := generativeart.NewCanva(500, 500) c.SetBackground(generativeart.Black) c.SetLineWidth(1.0) c.SetLineColor(generativeart.MediumAquamarine) @@ -63,11 +82,11 @@ func main() { ```go func main() { rand.Seed(time.Now().Unix()) - c := generativeart.NewCanva(500, 500, 2, 2) + c := generativeart.NewCanva(500, 500) c.SetBackground(generativeart.MistyRose) c.SetLineWidth(10) c.SetLineColor(generativeart.Orange) - c.SetColorSchema(generativeart.Viridis) + c.SetColorSchema(generativeart.Plasma) c.SetForeground(generativeart.Tomato) c.FillBackground() c.Draw(generativeart.NewSpiralSquare(40, 400, 0.05, true)) @@ -82,7 +101,7 @@ func main() { ```go func main() { rand.Seed(time.Now().Unix()) - c := generativeart.NewCanva(500, 500, 2, 2) + c := generativeart.NewCanva(500, 500) c.SetBackground(generativeart.Black) c.SetLineWidth(1) c.SetLineColor(generativeart.Orange) @@ -101,7 +120,6 @@ func main() { ```go func julia1(z complex128) complex128 { c := complex(-0.1, 0.651) - z = z*z + c return z @@ -109,11 +127,11 @@ func julia1(z complex128) complex128 { func main() { rand.Seed(time.Now().Unix()) - c := generativeart.NewCanva(500, 500, 1.5, 1.5) + c := generativeart.NewCanva(500, 500) c.SetIterations(800) c.SetColorSchema(generativeart.Viridis) c.FillBackground() - c.Draw(generativeart.NewJulia(julia1, 40)) + c.Draw(generativeart.NewJulia(julia1, 40, 1.5, 1.5)) c.ToPNG("julia.png") } ``` @@ -125,12 +143,12 @@ func main() { ```go func main() { rand.Seed(time.Now().Unix()) - c := generativeart.NewCanva(600, 600, 2, 2) + c := generativeart.NewCanva(600, 600) c.SetBackground(generativeart.Tan) c.SetLineWidth(1.0) c.SetLineColor(generativeart.LightPink) c.FillBackground() - c.Draw(generativeart.NewCircleLine(0.02, 600, 1.5)) + c.Draw(generativeart.NewCircleLine(0.02, 600, 1.5, 2, 2)) c.ToPNG("circleline.png") } ``` @@ -142,7 +160,7 @@ func main() { ```go func main() { rand.Seed(time.Now().Unix()) - c := generativeart.NewCanva(600, 600, 1, 1) + c := generativeart.NewCanva(600, 600) c.SetAlpha(10) c.Draw(generativeart.NewSilkSky(15, 5)) c.ToPNG("silksky.png") @@ -156,12 +174,12 @@ func main() { ```go func main() { rand.Seed(time.Now().Unix()) - c := generativeart.NewCanva(600, 600, 2, 2) + c := generativeart.NewCanva(600, 600) c.SetBackground(generativeart.Azure) c.SetLineWidth(3) c.SetLineColor(generativeart.Orange) c.FillBackground() - c.Draw(generativeart.NewMaze()) + c.Draw(generativeart.NewMaze(20)) c.ToPNG("maze.png") } ``` @@ -173,7 +191,7 @@ func main() { ```go func main() { rand.Seed(time.Now().Unix()) - c := generativeart.NewCanva(500, 500, 2, 2) + c := generativeart.NewCanva(500, 500) c.SetBackground(generativeart.MistyRose) c.SetLineWidth(1.0) c.SetLineColor(color.RGBA{ diff --git a/circleline.go b/circleline.go index 5561e8d..88ffc10 100644 --- a/circleline.go +++ b/circleline.go @@ -11,17 +11,20 @@ type point struct { } type circleLine struct { - step float64 - lineNum int - radius float64 + step float64 + lineNum int + radius float64 + xaixs, yaixs float64 } // NewCircleLine returns a circleLine object. -func NewCircleLine(step float64, lineNum int, radius float64) *circleLine { +func NewCircleLine(step float64, lineNum int, radius, xaixs, yaixs float64) *circleLine { return &circleLine{ step: step, lineNum: lineNum, radius: radius, + xaixs: xaixs, + yaixs: yaixs, } } @@ -34,7 +37,7 @@ func (cl *circleLine) Generative(c *canva) { for theta := -math.Pi; theta <= math.Pi; theta += cl.step { x := cl.radius * math.Cos(theta) y := cl.radius * math.Sin(theta) - xi, yi := ConvertCartesianToPixel(x, y, c.xaixs, c.yaixs, c.width, c.height) + xi, yi := ConvertCartesianToPixel(x, y, cl.xaixs, cl.yaixs, c.width, c.height) points = append(points, point{ x: float64(xi), y: float64(yi), diff --git a/example/example_circleline.go b/example/example_circleline.go index 76fe32f..40065ad 100644 --- a/example/example_circleline.go +++ b/example/example_circleline.go @@ -8,11 +8,11 @@ import ( func main() { rand.Seed(time.Now().Unix()) - c := generativeart.NewCanva(600, 600, 2, 2) + c := generativeart.NewCanva(600, 600) c.SetBackground(generativeart.Tan) c.SetLineWidth(1.0) c.SetLineColor(generativeart.LightPink) c.FillBackground() - c.Draw(generativeart.NewCircleLine(0.02, 600, 1.5)) + c.Draw(generativeart.NewCircleLine(0.02, 600, 1.5, 2, 2)) c.ToPNG("circleline.png") } diff --git a/example/example_circleloop.go b/example/example_circleloop.go index cc48725..c9ea2ca 100644 --- a/example/example_circleloop.go +++ b/example/example_circleloop.go @@ -8,7 +8,7 @@ import ( func main() { rand.Seed(time.Now().Unix()) - c := generativeart.NewCanva(500, 500, 2, 2) + c := generativeart.NewCanva(500, 500) c.SetBackground(generativeart.Black) c.SetLineWidth(1) c.SetLineColor(generativeart.Orange) diff --git a/example/example_gridsquare.go b/example/example_gridsquare.go index a2aee99..2b41fd0 100644 --- a/example/example_gridsquare.go +++ b/example/example_gridsquare.go @@ -8,9 +8,9 @@ import ( func main() { rand.Seed(time.Now().Unix()) - c := generativeart.NewCanva(600, 600, 1, 1) + c := generativeart.NewCanva(600, 600) c.SetBackground(generativeart.DarkPink[rand.Intn(5)]) c.SetColorSchema(generativeart.DarkPink) - c.Draw(generativeart.NewGirdSquares()) + c.Draw(generativeart.NewGirdSquares(24, 10, 0.2)) c.ToPNG("gsquare.png") } diff --git a/example/example_julia.go b/example/example_julia.go index 0585638..7454e7f 100644 --- a/example/example_julia.go +++ b/example/example_julia.go @@ -16,10 +16,10 @@ func julia1(z complex128) complex128 { func main() { rand.Seed(time.Now().Unix()) - c := generativeart.NewCanva(500, 500, 1.5, 1.5) + c := generativeart.NewCanva(500, 500) c.SetIterations(800) c.SetColorSchema(generativeart.Viridis) c.FillBackground() - c.Draw(generativeart.NewJulia(julia1, 40)) + c.Draw(generativeart.NewJulia(julia1, 40, 1.5, 1.5)) c.ToPNG("julia.png") } diff --git a/example/example_maze.go b/example/example_maze.go index f73ae61..2e11b74 100644 --- a/example/example_maze.go +++ b/example/example_maze.go @@ -8,11 +8,11 @@ import ( func main() { rand.Seed(time.Now().Unix()) - c := generativeart.NewCanva(600, 600, 2, 2) + c := generativeart.NewCanva(600, 600) c.SetBackground(generativeart.Azure) c.SetLineWidth(3) c.SetLineColor(generativeart.Orange) c.FillBackground() - c.Draw(generativeart.NewMaze()) + c.Draw(generativeart.NewMaze(20)) c.ToPNG("maze.png") } diff --git a/example/example_randcircle.go b/example/example_randcircle.go index 69fc6c3..45b4217 100644 --- a/example/example_randcircle.go +++ b/example/example_randcircle.go @@ -9,7 +9,7 @@ import ( func main() { rand.Seed(time.Now().Unix()) - c := generativeart.NewCanva(500, 500, 2, 2) + c := generativeart.NewCanva(500, 500) c.SetBackground(generativeart.MistyRose) c.SetLineWidth(1.0) c.SetLineColor(color.RGBA{ diff --git a/example/example_silksky.go b/example/example_silksky.go index 8ddffb3..16f98bf 100644 --- a/example/example_silksky.go +++ b/example/example_silksky.go @@ -8,7 +8,7 @@ import ( func main() { rand.Seed(time.Now().Unix()) - c := generativeart.NewCanva(600, 600, 1, 1) + c := generativeart.NewCanva(600, 600) c.SetAlpha(10) c.Draw(generativeart.NewSilkSky(15, 5)) c.ToPNG("silksky.png") diff --git a/example/example_silksmoke.go b/example/example_silksmoke.go index 77717ed..13200c9 100644 --- a/example/example_silksmoke.go +++ b/example/example_silksmoke.go @@ -8,7 +8,7 @@ import ( func main() { rand.Seed(time.Now().Unix()) - c := generativeart.NewCanva(500, 500, 2, 2) + c := generativeart.NewCanva(500, 500) c.SetBackground(generativeart.Black) c.SetLineWidth(1.0) c.SetLineColor(generativeart.MediumAquamarine) diff --git a/example/example_spiralsquare.go b/example/example_spiralsquare.go index 98cc91f..44f9e4d 100644 --- a/example/example_spiralsquare.go +++ b/example/example_spiralsquare.go @@ -8,7 +8,7 @@ import ( func main() { rand.Seed(time.Now().Unix()) - c := generativeart.NewCanva(500, 500, 2, 2) + c := generativeart.NewCanva(500, 500) c.SetBackground(generativeart.MistyRose) c.SetLineWidth(10) c.SetLineColor(generativeart.Orange) diff --git a/generativeart.go b/generativeart.go index 8998c19..4074a6d 100644 --- a/generativeart.go +++ b/generativeart.go @@ -15,48 +15,35 @@ type Engine interface { type canva struct { height, width int - xaixs, yaixs float64 img *image.RGBA opts Options } type Options struct { - background color.RGBA - foreground color.RGBA - lineColor color.RGBA - lineWidth float64 - colorSchema []color.RGBA - isPolarCoodinate bool - step int - nIters int - alpha int - rectLenSide int - radius float64 - decay float64 + background color.RGBA + foreground color.RGBA + lineColor color.RGBA + lineWidth float64 + colorSchema []color.RGBA + nIters int + alpha int } // NewCanva returns a canva. -func NewCanva(h, w int, x, y float64) *canva { +func NewCanva(h, w int) *canva { return &canva{ height: h, width: w, - xaixs: x, - yaixs: y, img: image.NewRGBA(image.Rect(0, 0, h, w)), // Set some defaults value opts: Options{ - background: Azure, - foreground: MistyRose, - lineColor: Tomato, - lineWidth: 3, - colorSchema: Plasma, - isPolarCoodinate: false, - step: 24, - nIters: 20, - alpha: 30, - rectLenSide: 10, - radius: 1.0, - decay: 0.2, + background: Azure, + foreground: MistyRose, + lineColor: Tomato, + lineWidth: 3, + colorSchema: Plasma, + nIters: 20, + alpha: 255, }, } } @@ -85,14 +72,6 @@ func (c *canva) SetLineWidth(lw float64) { c.opts.lineWidth = lw } -func (c *canva) SetPolarCoodinate() { - c.opts.isPolarCoodinate = true -} - -func (c *canva) SetStep(step int) { - c.opts.step = step -} - func (c *canva) SetIterations(nIters int) { c.opts.nIters = nIters } @@ -101,18 +80,6 @@ func (c *canva) SetAlpha(alpha int) { c.opts.alpha = alpha } -func (c *canva) SetRectLenSide(l int) { - c.opts.rectLenSide = l -} - -func (c *canva) SetRadius(r float64) { - c.opts.radius = r -} - -func (c *canva) SetDecay(d float64) { - c.opts.decay = d -} - func (c *canva) Draw(e Engine) { e.Generative(c) } diff --git a/julia.go b/julia.go index 433dafb..6a6fc0c 100644 --- a/julia.go +++ b/julia.go @@ -6,14 +6,17 @@ import "math/cmplx" type GenFunc func(complex128) complex128 type julia struct { - fn GenFunc - maxz float64 + fn GenFunc + maxz float64 + xaixs, yaixs float64 } -func NewJulia(formula GenFunc, maxz float64) *julia { +func NewJulia(formula GenFunc, maxz, xaixs, yaixs float64) *julia { return &julia{ - fn: formula, - maxz: maxz, + fn: formula, + maxz: maxz, + xaixs: xaixs, + yaixs: yaixs, } } @@ -27,7 +30,7 @@ func (j *julia) Generative(c *canva) { for i := 0; i <= c.width; i++ { for k := 0; k <= c.height; k++ { nit := 0 - z := complex(float64(i)/float64(c.width)*2.0*c.yaixs-c.yaixs, float64(k)/float64(c.height)*2.0*c.yaixs-c.yaixs) + z := complex(float64(i)/float64(c.width)*2.0*j.yaixs-j.yaixs, float64(k)/float64(c.height)*2.0*j.yaixs-j.yaixs) for cmplx.Abs(z) <= j.maxz && nit < c.opts.nIters { z = j.fn(z) diff --git a/maze.go b/maze.go index 0fa5156..f2177c0 100644 --- a/maze.go +++ b/maze.go @@ -6,11 +6,15 @@ import ( "github.com/fogleman/gg" ) -type maze struct{} +type maze struct { + step int +} // NewMaze returns a maze generator. -func NewMaze() *maze { - return &maze{} +func NewMaze(step int) *maze { + return &maze{ + step: step, + } } // Generative draws a random maze image. @@ -18,13 +22,12 @@ func (m *maze) Generative(c *canva) { ctex := gg.NewContextForRGBA(c.img) ctex.SetColor(c.opts.lineColor) ctex.SetLineWidth(c.opts.lineWidth) - step := c.opts.step - for x := 0; x < c.width; x += step { - for y := 0; y < c.height; y += step { + for x := 0; x < c.width; x += m.step { + for y := 0; y < c.height; y += m.step { if rand.Float32() > 0.5 { - ctex.DrawLine(float64(x), float64(y), float64(x+step), float64(y+step)) + ctex.DrawLine(float64(x), float64(y), float64(x+m.step), float64(y+m.step)) } else { - ctex.DrawLine(float64(x+step), float64(y), float64(x), float64(y+step)) + ctex.DrawLine(float64(x+m.step), float64(y), float64(x), float64(y+m.step)) } ctex.Stroke() } diff --git a/squaregrid.go b/squaregrid.go index ce14bb8..5bfa2e3 100644 --- a/squaregrid.go +++ b/squaregrid.go @@ -5,32 +5,37 @@ import ( "math/rand" ) -type girdSquares struct{} +type girdSquares struct { + step, rectSize int + decay float64 +} // NewGirdSquares returns a grid squares generator. -func NewGirdSquares() *girdSquares { - return &girdSquares{} +func NewGirdSquares(step, rectSize int, decay float64) *girdSquares { + return &girdSquares{ + step: step, + rectSize: rectSize, + decay: decay, + } } // Generative draws a grid squares image. func (g *girdSquares) Generative(c *canva) { ctex := gg.NewContextForRGBA(c.img) - step := c.opts.step - rectSize := c.opts.rectLenSide - for x := 0; x < c.width; x += step { - for y := 0; y < c.height; y += step { - cl := c.opts.colorSchema[rand.Intn(255)] + for x := 0; x < c.width; x += g.step { + for y := 0; y < c.height; y += g.step { + cl := c.opts.colorSchema[rand.Intn(len(c.opts.colorSchema))] x0 := float64(x) y0 := float64(y) - s := float64(rectSize) + s := float64(g.rectSize) theta := rand.Intn(360) + 1 for i := 0; i < c.opts.nIters; i++ { ctex.Push() - ctex.Translate(x0+float64(step/2), y0+float64(step/2)) + ctex.Translate(x0+float64(g.step/2), y0+float64(g.step/2)) ctex.Rotate(gg.Radians(float64(theta * i))) ctex.Scale(s, s) @@ -47,7 +52,7 @@ func (g *girdSquares) Generative(c *canva) { ctex.SetRGBA255(int(cl.R), int(cl.G), int(cl.B), c.opts.alpha) ctex.Fill() ctex.Pop() - s = s - c.opts.decay*float64(rectSize) + s = s - g.decay*float64(g.rectSize) } } }