add perlin perls

This commit is contained in:
Yongwei Xing 2021-04-07 17:22:53 +08:00
parent ed10f4403d
commit a8740b437e
10 changed files with 198 additions and 5 deletions

View file

@ -33,6 +33,7 @@
- [Circle Loop](#circle-loop) - [Circle Loop](#circle-loop)
- [Domain Warp](#domain-warp) - [Domain Warp](#domain-warp)
- [Circle Noise](#circle-noise) - [Circle Noise](#circle-noise)
- [Perlin Perls](#perlin-perls)
- [Color Canva](#color-canva) - [Color Canva](#color-canva)
- [Julia Set](#julia-set) - [Julia Set](#julia-set)
- [Black Hole](#black-hole) - [Black Hole](#black-hole)
@ -83,6 +84,7 @@ This package is still working in progress. More types would be added. Welcome an
- Black Hole - Black Hole
- Color Canva - Color Canva
- Domain Warp - Domain Warp
- Perlin Perls
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.
@ -123,6 +125,7 @@ NewYarn(n int)
NewBlackHole(circleN int, density, circleGap float64) NewBlackHole(circleN int, density, circleGap float64)
NewColorCanve(seg float64) NewColorCanve(seg float64)
NewDomainWrap(scale, scale2, xOffset, yOffset float64, cmap ColorMapping) NewDomainWrap(scale, scale2, xOffset, yOffset float64, cmap ColorMapping)
NewPerlinPerls(circleN, dotsN, colorMin, colorMax int)
``` ```
## Docs ## Docs
@ -460,6 +463,24 @@ func main() {
![](images/circlenoise.png) ![](images/circlenoise.png)
### Perlin Perls
```go
func main() {
rand.Seed(time.Now().Unix())
c := generativeart.NewCanva(500, 500)
c.SetBackground(common.White)
c.SetAlpha(120)
c.SetLineWidth(0.3)
c.FillBackground()
c.SetIterations(200)
c.Draw(arts.NewPerlinPerls(10, 200, 40, 80))
c.ToPNG("perlinperls.png")
}
```
![](../images/perlinperls.png)
### Color Canva ### Color Canva
```go ```go

View file

@ -18,6 +18,7 @@ type dot struct {
prevx, prevy float64 prevx, prevy float64
theta float64 theta float64
count int count int
cx, cy float64
} }
func NewCircleNoise(dotsN, colorMin, colorMax int) *circleNoise { func NewCircleNoise(dotsN, colorMin, colorMax int) *circleNoise {

View file

@ -12,7 +12,7 @@ type ColorMapping func(float64, float64, float64) color.RGBA
type domainWrap struct { type domainWrap struct {
noise *common.PerlinNoise noise *common.PerlinNoise
scale float64 scale float64
scale2 float64 scale2 float64
xOffset, yOffset float64 xOffset, yOffset float64
fn ColorMapping fn ColorMapping
} }
@ -21,7 +21,7 @@ type domainWrap struct {
func NewDomainWrap(scale, scale2, xOffset, yOffset float64, cmap ColorMapping) *domainWrap { func NewDomainWrap(scale, scale2, xOffset, yOffset float64, cmap ColorMapping) *domainWrap {
return &domainWrap{ return &domainWrap{
scale: scale, scale: scale,
scale2: scale2, scale2: scale2,
xOffset: xOffset, xOffset: xOffset,
yOffset: yOffset, yOffset: yOffset,
noise: common.NewPerlinNoise(), noise: common.NewPerlinNoise(),

123
arts/perlinpearls.go Normal file
View file

@ -0,0 +1,123 @@
package arts
import (
"github.com/fogleman/gg"
"github.com/jdxyw/generativeart"
"github.com/jdxyw/generativeart/common"
"math"
"math/rand"
)
type perlinPearls struct {
circleN int
dotsN int
colorMin, colorMax int
}
type circles struct {
x, y float64
radius float64
colorMin, colorMax int
}
func NewPerlinPerls(circleN, dotsN, colorMin, colorMax int) *perlinPearls {
return &perlinPearls{
circleN: circleN,
dotsN: dotsN,
colorMin: colorMin,
colorMax: colorMax,
}
}
// Generative draws a circle with perlin noise.
func (pp *perlinPearls) Generative(c *generativeart.Canva) {
ctex := gg.NewContextForRGBA(c.Img())
ctex.SetLineWidth(0.5)
ctex.SetColor(common.Black)
cs := make([]circles, 0)
for len(cs) < pp.circleN {
c := circles{
x: common.RandomRangeFloat64(100, float64(c.Width())-50),
y: common.RandomRangeFloat64(100, float64(c.Height())-50),
radius: common.RandomRangeFloat64(20, 100),
colorMin: pp.colorMin,
colorMax: pp.colorMax,
}
var overlapping bool
for _, cl := range cs {
d := common.Distance(c.x, c.y, cl.x, cl.y)
if d < c.radius+cl.radius {
overlapping = true
break
}
}
if overlapping == false {
cs = append(cs, c)
}
}
ds := make([][]dot, 0)
for i := 0; i < pp.circleN; i++ {
dots := make([]dot, 0)
for j := 0; j < pp.dotsN; j++ {
theta := rand.Float64() * math.Pi * 2
//x, y := float64(c.Width())/2+math.Sin(theta)*radius, float64(c.Height())/2+math.Cos(theta)*radius
dots = append(dots, dot{
theta: theta,
cx: cs[i].x,
cy: cs[i].y,
x: cs[i].x + math.Sin(theta)*cs[i].radius,
y: cs[i].y + math.Cos(theta)*cs[i].radius,
prevx: cs[i].x + math.Sin(theta)*cs[i].radius,
prevy: cs[i].y + math.Cos(theta)*cs[i].radius,
count: 0,
})
}
ds = append(ds, dots)
}
noise := common.NewPerlinNoise()
for i := 0; i < pp.circleN; i++ {
ctex.SetLineWidth(0.5)
ctex.SetColor(common.Black)
ctex.DrawCircle(cs[i].x, cs[i].y, cs[i].radius)
ctex.Stroke()
var factor = 0.008
for j := 0; j < c.Opts().NIters(); j++ {
for k := range ds[i] {
n := noise.Noise2D(ds[i][k].x*factor, ds[i][k].y*factor)
nx, ny := math.Cos(n*math.Pi*2+float64(ds[i][k].count)*math.Pi)*2, math.Sin(n*math.Pi*2+float64(ds[i][k].count)*math.Pi)*2
ds[i][k].prevx, ds[i][k].prevy = ds[i][k].x, ds[i][k].y
ds[i][k].x, ds[i][k].y = ds[i][k].x+nx, ds[i][k].y+ny
hsv := common.HSV{
H: int(common.Remap(n, 0, 1, float64(cs[i].colorMin), float64(cs[i].colorMax))),
S: 100,
V: 20,
}
if common.Distance(cs[i].x, cs[i].y, ds[i][k].x, ds[i][k].y) > cs[i].radius+1 {
ds[i][k].count += 1
}
if common.Distance(cs[i].x, cs[i].y, ds[i][k].x, ds[i][k].y) < cs[i].radius &&
common.Distance(cs[i].x, cs[i].y, ds[i][k].prevx, ds[i][k].prevy) < cs[i].radius {
ctex.SetLineWidth(c.Opts().LineWidth())
rgb := hsv.ToRGB(100, 100, 100)
rgb.A = uint8(c.Opts().Alpha())
ctex.SetColor(rgb)
ctex.DrawLine(ds[i][k].prevx, ds[i][k].prevy, ds[i][k].x, ds[i][k].y)
ctex.Stroke()
}
}
}
}
}

View file

@ -15,3 +15,13 @@ func (v *Vector) Multiple(z float64) {
v.X = v.X * z v.X = v.X * z
v.Y = v.Y * z v.Y = v.Y * z
} }
func (v *Vector) Normalize() {
l := Magnitude(v.X, v.Y)
v.Multiple(1 / l)
}
func (v *Vector) SetMag(m float64) {
v.Normalize()
v.Multiple(m)
}

View file

@ -38,6 +38,8 @@
- [parameters](#parameters-16) - [parameters](#parameters-16)
- [Domain Warping](#domain-warping) - [Domain Warping](#domain-warping)
- [parameters](#parameters-17) - [parameters](#parameters-17)
- [Perlin Perls](#perlin-perls)
- [parameters](#parameters-18)
## Color Circle 2 ## Color Circle 2
@ -281,4 +283,19 @@ Warping, or domain distortion is a very common technique in computer graphics fo
d := arts.NewDomainWrap(0.01, 4, 8, cmap) d := arts.NewDomainWrap(0.01, 4, 8, cmap)
``` ```
![](../images/domainwarp.png) ![](../images/domainwarp.png)
## Perlin Perls
### parameters
- circleN: The number of circle on this image.
- dotsN: The number of dots in each circle.
- colorMin: The minimum color.
- colorMax: The maximum color.
```go
pp := arts.NewPerlinPerls(10, 200, 40, 80
```
![](../images/perlinperls.png)

View file

@ -12,7 +12,7 @@ func main() {
rand.Seed(time.Now().Unix()) rand.Seed(time.Now().Unix())
c := generativeart.NewCanva(500, 500) c := generativeart.NewCanva(500, 500)
c.SetBackground(common.White) c.SetBackground(common.White)
c.SetAlpha(80) c.SetAlpha(5)
c.SetLineWidth(0.3) c.SetLineWidth(0.3)
c.FillBackground() c.FillBackground()
c.SetIterations(400) c.SetIterations(400)

View file

@ -24,6 +24,6 @@ func main() {
c := generativeart.NewCanva(500, 500) c := generativeart.NewCanva(500, 500)
c.SetBackground(common.Black) c.SetBackground(common.Black)
c.FillBackground() c.FillBackground()
c.Draw(arts.NewDomainWrap(0.01, 4,4, 20, cmap)) c.Draw(arts.NewDomainWrap(0.01, 4, 4, 20, cmap))
c.ToPNG("domainwarp.png") c.ToPNG("domainwarp.png")
} }

View file

@ -0,0 +1,21 @@
package main
import (
"github.com/jdxyw/generativeart"
"github.com/jdxyw/generativeart/arts"
"github.com/jdxyw/generativeart/common"
"math/rand"
"time"
)
func main() {
rand.Seed(time.Now().Unix())
c := generativeart.NewCanva(500, 500)
c.SetBackground(common.White)
c.SetAlpha(120)
c.SetLineWidth(0.3)
c.FillBackground()
c.SetIterations(200)
c.Draw(arts.NewPerlinPerls(10, 200, 40, 80))
c.ToPNG("perlinperls.png")
}

BIN
images/perlinperls.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 223 KiB