add perlin perls
This commit is contained in:
parent
ed10f4403d
commit
a8740b437e
10 changed files with 198 additions and 5 deletions
21
README.md
21
README.md
|
@ -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
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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
123
arts/perlinpearls.go
Normal 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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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)
|
||||||
|
}
|
||||||
|
|
19
docs/doc.md
19
docs/doc.md
|
@ -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)
|
|
@ -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)
|
||||||
|
|
|
@ -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")
|
||||||
}
|
}
|
||||||
|
|
21
example/example_perlinpearls.go
Normal file
21
example/example_perlinpearls.go
Normal 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
BIN
images/perlinperls.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 223 KiB |
Loading…
Reference in a new issue