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)
- [Domain Warp](#domain-warp)
- [Circle Noise](#circle-noise)
- [Perlin Perls](#perlin-perls)
- [Color Canva](#color-canva)
- [Julia Set](#julia-set)
- [Black Hole](#black-hole)
@ -83,6 +84,7 @@ This package is still working in progress. More types would be added. Welcome an
- Black Hole
- Color Canva
- Domain Warp
- Perlin Perls
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)
NewColorCanve(seg float64)
NewDomainWrap(scale, scale2, xOffset, yOffset float64, cmap ColorMapping)
NewPerlinPerls(circleN, dotsN, colorMin, colorMax int)
```
## Docs
@ -460,6 +463,24 @@ func main() {
![](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
```go

View File

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

View File

@ -12,7 +12,7 @@ type ColorMapping func(float64, float64, float64) color.RGBA
type domainWrap struct {
noise *common.PerlinNoise
scale float64
scale2 float64
scale2 float64
xOffset, yOffset float64
fn ColorMapping
}
@ -21,7 +21,7 @@ type domainWrap struct {
func NewDomainWrap(scale, scale2, xOffset, yOffset float64, cmap ColorMapping) *domainWrap {
return &domainWrap{
scale: scale,
scale2: scale2,
scale2: scale2,
xOffset: xOffset,
yOffset: yOffset,
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.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)
- [Domain Warping](#domain-warping)
- [parameters](#parameters-17)
- [Perlin Perls](#perlin-perls)
- [parameters](#parameters-18)
## 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)
```
![](../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())
c := generativeart.NewCanva(500, 500)
c.SetBackground(common.White)
c.SetAlpha(80)
c.SetAlpha(5)
c.SetLineWidth(0.3)
c.FillBackground()
c.SetIterations(400)

View File

@ -24,6 +24,6 @@ func main() {
c := generativeart.NewCanva(500, 500)
c.SetBackground(common.Black)
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")
}

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