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
|
||||
- Noise Line
|
||||
- Ocean Fish
|
||||
- Circle Loop2
|
||||
|
||||
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)
|
||||
NewContourLine(lineNum int)
|
||||
NewNoiseLine(n int)
|
||||
NewCircleLoop2(depth int)
|
||||
```
|
||||
|
||||
## Docs
|
||||
|
@ -181,6 +183,29 @@ func main() {
|
|||
|
||||
![](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
|
||||
|
||||
```go
|
||||
|
@ -390,7 +415,7 @@ func main() {
|
|||
|
||||
## 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://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://twitter.com/okazz_
|
||||
- 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
|
||||
)
|
||||
|
||||
type perlinNoise struct {
|
||||
type PerlinNoise struct {
|
||||
perlin []float64
|
||||
}
|
||||
|
||||
func NewPerlinNoise() *perlinNoise {
|
||||
perlin := &perlinNoise{perlin: nil}
|
||||
func NewPerlinNoise() *PerlinNoise {
|
||||
perlin := &PerlinNoise{perlin: nil}
|
||||
perlin.perlin = make([]float64, perlinSize+1)
|
||||
|
||||
for i, _ := range perlin.perlin {
|
||||
|
@ -29,7 +29,19 @@ func NewPerlinNoise() *perlinNoise {
|
|||
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 {
|
||||
x = -x
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ func (cl *contourLine) Generative(c *canva) {
|
|||
|
||||
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
|
||||
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` draws a ocean and some fishes in the center.
|
||||
`Ocean Fish` draws an ocean and some fishes in the center.
|
||||
|
||||
### parameters
|
||||
|
||||
|
@ -122,4 +122,18 @@ nl := generativeart.NewNoiseLine(1000)
|
|||
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++ {
|
||||
var ns = 0.0005
|
||||
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.DrawCircle(x, y, w)
|
||||
ctex.Fill()
|
||||
|
|
Loading…
Reference in a new issue