refactor perline noise; add circle loop2
This commit is contained in:
parent
a1f1c00a3a
commit
3328f24db7
9 changed files with 186 additions and 10 deletions
30
README.md
30
README.md
|
@ -35,6 +35,7 @@ This package is still working in progress. More types would be added. Welcome an
|
||||||
- Contour Line
|
- Contour Line
|
||||||
- Noise Line
|
- Noise Line
|
||||||
- Ocean Fish
|
- Ocean Fish
|
||||||
|
- Circle Loop2
|
||||||
|
|
||||||
For these kinds of art, the package provides as many parameters to control the appearance.
|
For these kinds of art, the package provides as many parameters to control the appearance.
|
||||||
|
|
||||||
|
@ -66,6 +67,7 @@ NewColorCircle2(circleNum int)
|
||||||
NewCircleGrid(circleNumMin, circleNumMax int)
|
NewCircleGrid(circleNumMin, circleNumMax int)
|
||||||
NewContourLine(lineNum int)
|
NewContourLine(lineNum int)
|
||||||
NewNoiseLine(n int)
|
NewNoiseLine(n int)
|
||||||
|
NewCircleLoop2(depth int)
|
||||||
```
|
```
|
||||||
|
|
||||||
## Docs
|
## Docs
|
||||||
|
@ -181,6 +183,29 @@ func main() {
|
||||||
|
|
||||||
![](images/circlegrid.png)
|
![](images/circlegrid.png)
|
||||||
|
|
||||||
|
## Circle Composes Circle
|
||||||
|
|
||||||
|
```go
|
||||||
|
func main() {
|
||||||
|
rand.Seed(time.Now().Unix())
|
||||||
|
colors := []color.RGBA{
|
||||||
|
{0xF9, 0xC8, 0x0E, 0xFF},
|
||||||
|
{0xF8, 0x66, 0x24, 0xFF},
|
||||||
|
{0xEA, 0x35, 0x46, 0xFF},
|
||||||
|
{0x66, 0x2E, 0x9B, 0xFF},
|
||||||
|
{0x43, 0xBC, 0xCD, 0xFF},
|
||||||
|
}
|
||||||
|
c := generativeart.NewCanva(500, 500)
|
||||||
|
c.SetBackground(color.RGBA{8, 10, 20, 255})
|
||||||
|
c.FillBackground()
|
||||||
|
c.SetColorSchema(colors)
|
||||||
|
c.Draw(generativeart.NewCircleLoop2(7))
|
||||||
|
c.ToPNG("colorloop2.png")
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
![](images/colorloop2.png)
|
||||||
|
|
||||||
### Silk Smoke
|
### Silk Smoke
|
||||||
|
|
||||||
```go
|
```go
|
||||||
|
@ -390,7 +415,7 @@ func main() {
|
||||||
|
|
||||||
## Contribution
|
## Contribution
|
||||||
|
|
||||||
Thanks for the following sites and repos, I got lots of ideas, inspiration, code and tricks from them. The list would be very long, sorry for forgetting some of them.
|
Thanks for the following sites and repos, I got lots of ideas, inspiration, code, and tricks from them. The list would be very long; sorry for forgetting some of them.
|
||||||
|
|
||||||
- https://inconvergent.net/
|
- https://inconvergent.net/
|
||||||
- https://fronkonstin.com/
|
- https://fronkonstin.com/
|
||||||
|
@ -406,4 +431,5 @@ Thanks for the following sites and repos, I got lots of ideas, inspiration, code
|
||||||
- https://openprocessing.org/sketch/1071233
|
- https://openprocessing.org/sketch/1071233
|
||||||
- https://twitter.com/okazz_
|
- https://twitter.com/okazz_
|
||||||
- https://openprocessing.org/sketch/738638
|
- https://openprocessing.org/sketch/738638
|
||||||
- https://openprocessing.org/sketch/1102157
|
- https://openprocessing.org/sketch/1102157
|
||||||
|
- https://openprocessing.org/sketch/1071233
|
80
circleloop2.go
Normal file
80
circleloop2.go
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
package generativeart
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/fogleman/gg"
|
||||||
|
"github.com/jdxyw/generativeart/common"
|
||||||
|
"math"
|
||||||
|
"math/rand"
|
||||||
|
)
|
||||||
|
|
||||||
|
type circleLoop2 struct {
|
||||||
|
depth int
|
||||||
|
noise *common.PerlinNoise
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewCircleLoop2(depth int) *circleLoop2 {
|
||||||
|
return &circleLoop2{
|
||||||
|
depth: depth,
|
||||||
|
noise: common.NewPerlinNoise(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generative draws a circle composed by many colored circles.
|
||||||
|
func (cl *circleLoop2) Generative(c *canva) {
|
||||||
|
ctex := gg.NewContextForRGBA(c.img)
|
||||||
|
ctex.Translate(float64(c.width)/2, float64(c.height)/2)
|
||||||
|
cl.recursionDraw(ctex, c, float64(c.width), cl.depth)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cl *circleLoop2) recursionDraw(ctex *gg.Context, c *canva, x float64, depth int) {
|
||||||
|
if depth <= 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
cl.draw(ctex, c, x)
|
||||||
|
cl.recursionDraw(ctex, c, 1*x/4.0, depth-1)
|
||||||
|
cl.recursionDraw(ctex, c, 2*x/4.0, depth-1)
|
||||||
|
cl.recursionDraw(ctex, c, 3*x/4.0, depth-1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cl *circleLoop2) draw(ctex *gg.Context, c *canva, x float64) {
|
||||||
|
var lw float64
|
||||||
|
if rand.Float64() < 0.8 {
|
||||||
|
lw = 1
|
||||||
|
} else {
|
||||||
|
lw = common.RandomRangeFloat64(1.0, common.RandomRangeFloat64(1, 3))
|
||||||
|
}
|
||||||
|
ctex.SetLineWidth(lw)
|
||||||
|
|
||||||
|
noise := cl.noise.Noise3D(x*0.02+123.234, (1-x)*0.02, 345.4123)
|
||||||
|
noise = math.Pow(noise, 0.5)
|
||||||
|
a2 := common.Remap(noise, 0.15, 0.85, 0.1, 0.6)
|
||||||
|
|
||||||
|
px := math.Pow(x/float64(c.height), a2) * float64(c.height)
|
||||||
|
py := math.Pow(1-x/float64(c.height), a2)*float64(c.height) -
|
||||||
|
common.RandomRangeFloat64(0, common.RandomRangeFloat64(float64(c.height)*0.18, common.RandomRangeFloat64(float64(c.height)*0.18, float64(c.height)*0.7)))
|
||||||
|
|
||||||
|
cls := c.opts.colorSchema[rand.Intn(len(c.opts.colorSchema))]
|
||||||
|
ctex.SetColor(cls)
|
||||||
|
nCircles := common.RandomRangeInt(1, 6)
|
||||||
|
if rand.Float64() < 0.03 {
|
||||||
|
nCircles = common.RandomRangeInt(8, 10)
|
||||||
|
}
|
||||||
|
|
||||||
|
r := math.Pow(rand.Float64(), 2) * 50
|
||||||
|
|
||||||
|
var flag bool
|
||||||
|
if rand.Float64() < 0.7 {
|
||||||
|
flag = true
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < nCircles; i++ {
|
||||||
|
if flag {
|
||||||
|
ctex.DrawCircle(px*0.39, py*0.39, rand.Float64()*float64(i)*r/float64(nCircles))
|
||||||
|
} else {
|
||||||
|
ctex.DrawCircle(px*0.39, py*0.39, float64(i)*r/float64(nCircles))
|
||||||
|
}
|
||||||
|
ctex.Stroke()
|
||||||
|
}
|
||||||
|
ctex.Rotate(x / float64(c.height) * 0.2)
|
||||||
|
}
|
19
common/calculation.go
Normal file
19
common/calculation.go
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
package common
|
||||||
|
|
||||||
|
import "math"
|
||||||
|
|
||||||
|
// Constrain returns a value between a minimum and maximum value.
|
||||||
|
func Constrain(val, low, high float64) float64 {
|
||||||
|
return math.Max(math.Min(val, high), low)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remap re-maps a number from one range to another.
|
||||||
|
func Remap(n, start1, stop1, start2, stop2 float64) float64 {
|
||||||
|
newval := (n-start1)/(stop1-start1)*(stop2-start2) + start2
|
||||||
|
|
||||||
|
if start2 < stop2 {
|
||||||
|
return Constrain(newval, start2, stop2)
|
||||||
|
} else {
|
||||||
|
return Constrain(newval, stop2, start2)
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,12 +15,12 @@ const (
|
||||||
perlinAmpFalloff = 0.5
|
perlinAmpFalloff = 0.5
|
||||||
)
|
)
|
||||||
|
|
||||||
type perlinNoise struct {
|
type PerlinNoise struct {
|
||||||
perlin []float64
|
perlin []float64
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewPerlinNoise() *perlinNoise {
|
func NewPerlinNoise() *PerlinNoise {
|
||||||
perlin := &perlinNoise{perlin: nil}
|
perlin := &PerlinNoise{perlin: nil}
|
||||||
perlin.perlin = make([]float64, perlinSize+1)
|
perlin.perlin = make([]float64, perlinSize+1)
|
||||||
|
|
||||||
for i, _ := range perlin.perlin {
|
for i, _ := range perlin.perlin {
|
||||||
|
@ -29,7 +29,19 @@ func NewPerlinNoise() *perlinNoise {
|
||||||
return perlin
|
return perlin
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *perlinNoise) Noise(x, y, z float64) float64 {
|
func (p *PerlinNoise) Noise1D(x float64) float64 {
|
||||||
|
return p.noise(x, 0, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PerlinNoise) Noise2D(x, y float64) float64 {
|
||||||
|
return p.noise(x, y, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PerlinNoise) Noise3D(x, y, z float64) float64 {
|
||||||
|
return p.noise(x, y, z)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PerlinNoise) noise(x, y, z float64) float64 {
|
||||||
if x < 0 {
|
if x < 0 {
|
||||||
x = -x
|
x = -x
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ func (cl *contourLine) Generative(c *canva) {
|
||||||
|
|
||||||
for j := 0; j < 1500; j++ {
|
for j := 0; j < 1500; j++ {
|
||||||
|
|
||||||
theta := noise.Noise(x/800.0, y/800.0, 0) * math.Pi * 2 * 800
|
theta := noise.Noise2D(x/800.0, y/800.0) * math.Pi * 2 * 800
|
||||||
x += math.Cos(theta) * 0.4
|
x += math.Cos(theta) * 0.4
|
||||||
y += math.Sin(theta) * 0.4
|
y += math.Sin(theta) * 0.4
|
||||||
|
|
||||||
|
|
18
docs/doc.md
18
docs/doc.md
|
@ -111,7 +111,7 @@ nl := generativeart.NewNoiseLine(1000)
|
||||||
|
|
||||||
## Ocean Fish
|
## Ocean Fish
|
||||||
|
|
||||||
`Ocean Fish` draws a ocean and some fishes in the center.
|
`Ocean Fish` draws an ocean and some fishes in the center.
|
||||||
|
|
||||||
### parameters
|
### parameters
|
||||||
|
|
||||||
|
@ -122,4 +122,18 @@ nl := generativeart.NewNoiseLine(1000)
|
||||||
o := generativeart.NewOceanFish(100, 8)
|
o := generativeart.NewOceanFish(100, 8)
|
||||||
```
|
```
|
||||||
|
|
||||||
![](../images/oceanfish.png)
|
![](../images/oceanfish.png)
|
||||||
|
|
||||||
|
## Circle Loop2
|
||||||
|
|
||||||
|
`Circle loop2` draws a circle composed by colored circles.
|
||||||
|
|
||||||
|
### parameters
|
||||||
|
|
||||||
|
- depth: Control the number of circles.
|
||||||
|
|
||||||
|
```go
|
||||||
|
cl := generativeart.NewCircleLoop2(7)
|
||||||
|
```
|
||||||
|
|
||||||
|
![](../images/colorloop2.png)
|
25
example/example_circleloop2.go
Normal file
25
example/example_circleloop2.go
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/jdxyw/generativeart"
|
||||||
|
"image/color"
|
||||||
|
"math/rand"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
rand.Seed(time.Now().Unix())
|
||||||
|
colors := []color.RGBA{
|
||||||
|
{0xF9, 0xC8, 0x0E, 0xFF},
|
||||||
|
{0xF8, 0x66, 0x24, 0xFF},
|
||||||
|
{0xEA, 0x35, 0x46, 0xFF},
|
||||||
|
{0x66, 0x2E, 0x9B, 0xFF},
|
||||||
|
{0x43, 0xBC, 0xCD, 0xFF},
|
||||||
|
}
|
||||||
|
c := generativeart.NewCanva(500, 500)
|
||||||
|
c.SetBackground(color.RGBA{8, 10, 20, 255})
|
||||||
|
c.FillBackground()
|
||||||
|
c.SetColorSchema(colors)
|
||||||
|
c.Draw(generativeart.NewCircleLoop2(7))
|
||||||
|
c.ToPNG("colorloop2.png")
|
||||||
|
}
|
BIN
images/colorloop2.png
Normal file
BIN
images/colorloop2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 230 KiB |
|
@ -45,7 +45,7 @@ func (nl *noiseLine) Generative(c *canva) {
|
||||||
for j := 0; j < l; j++ {
|
for j := 0; j < l; j++ {
|
||||||
var ns = 0.0005
|
var ns = 0.0005
|
||||||
w := math.Sin(math.Pi*float64(j)/float64(l-1)) * 5
|
w := math.Sin(math.Pi*float64(j)/float64(l-1)) * 5
|
||||||
theta := noise.Noise(x*ns, y*ns, t) * 100
|
theta := noise.Noise3D(x*ns, y*ns, t) * 100
|
||||||
ctex.SetColor(cl)
|
ctex.SetColor(cl)
|
||||||
ctex.DrawCircle(x, y, w)
|
ctex.DrawCircle(x, y, w)
|
||||||
ctex.Fill()
|
ctex.Fill()
|
||||||
|
|
Loading…
Reference in a new issue