Here is another variation of grain2. It's like the "flower" program, but it includes stems, and a porportion of "lean" (0 - full lean to the left, 100 - full lean to the right) is programmed in.
The variations were produced with this script:
for i in 0 25 50 75 100
do
./grain -n 150 -w 900 -h 200 -l 175 -nl $i > grain$i.svg
done
Grain 100
Here's the Go program
// grain -- flowers with programmable lean
package main
import (
svglib "./svg"
"time"
"rand"
"os"
"flag"
"fmt"
"math"
)
var (
width = flag.Int("w", 500, "width")
height = flag.Int("h", 500, "height")
ninter = flag.Int("n", 75, "interations")
stemlen = flag.Int("l", 450, "stem length")
stemwidth = flag.Int("st", 4, "stem thickness")
numleft = flag.Int("nl", 50, "percentage of left-leaning stems")
thickness = flag.Int("t", 10, "max petal thinkness")
np = flag.Int("p", 15, "max number of petals")
psize = flag.Int("s", 30, "max length of petals")
opacity = flag.Int("o", 50, "max opacity (10-100)")
svg = svglib.New(os.Stdout)
)
const (
flowerfmt = `stroke:rgb(%d,%d,%d); stroke-opacity:%.2f; stroke-width:%d`
stemfmt = `stroke:green;stroke-opacity:0.3;stroke-width:%d`
)
func radial(xp int, yp int, n int, l int, style ...string) {
var x, y, r, t, limit float64
limit = 2.0 * math.Pi
r = float64(l)
svg.Gstyle(style[0])
for t = 0.0; t < limit; t += limit / float64(n) {
x = r * math.Cos(t)
y = r * math.Sin(t)
svg.Line(xp, yp, xp+int(x), yp+int(y))
}
svg.Gend()
}
func background(v int) { svg.Rect(0, 0, *width, *height, svg.RGB(v, v, v)) }
func random(howsmall, howbig int) int {
if howsmall >= howbig {
return howsmall
}
return rand.Intn(howbig-howsmall) + howsmall
}
func randrad(x, y int) {
var r, g, b, o, s, t, p int
r = rand.Intn(255)
g = rand.Intn(255)
b = rand.Intn(255)
o = random(10, *opacity)
s = random(10, *psize)
t = random(2, *thickness)
p = random(10, *np)
radial(x, y, p, s, fmt.Sprintf(flowerfmt, r, g, b, float64(o)/100.0, t))
}
func init() {
flag.Parse()
rand.Seed(time.Nanoseconds() % 1e9)
}
func main() {
svg.Start(*width, *height)
background(255)
svg.Gstyle(fmt.Sprintf(stemfmt, *stemwidth))
var x, l, xe, offset int
for i := 0; i < *ninter; i++ {
x = rand.Intn(*width)
l = rand.Intn(*stemlen)
offset = rand.Intn(*width / 10)
if rand.Intn(100) > *numleft {
xe = x - offset
} else {
xe = x + offset
}
svg.Line(x, *height, xe, *height-l)
randrad(xe, *height-l)
}
svg.Gend()
svg.End()
}