Skip to content

Commit 1ff8143

Browse files
committed
add seeded randomness
1 parent fc5b939 commit 1ff8143

File tree

5 files changed

+52
-20
lines changed

5 files changed

+52
-20
lines changed

README.md

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1 @@
11
# blobs
2-
3-
<!--
4-
5-
TODO
6-
- seeded randomness
7-
8-
-->

blob.svg

Lines changed: 1 addition & 1 deletion
Loading

index.ts

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
11
// https://www.blobmaker.app/
22
// https://math.stackexchange.com/questions/873224/calculate-control-points-of-cubic-bezier-curve-approximating-a-part-of-a-circle
33

4-
import {rad, smooth} from "./util";
4+
import {rad, smooth, rand} from "./util";
55
import {render} from "./render";
66
import {Point, BlobOptions} from "./types";
77

88
export {BlobOptions} from "./types";
99

1010
// Generates a random rounded shape.
1111
export const blob = (opt: BlobOptions): string => {
12-
opt = Object.assign({}, opt);
12+
// Random number generator.
13+
const rgen = rand(opt.seed || String(Date.now()));
1314

1415
if (!opt.stroke && !opt.color) {
15-
throw new Error("no color or stroke specified")
16+
throw new Error("no color or stroke specified");
1617
}
1718

1819
if (opt.complexity <= 0 || opt.complexity > 1) {
@@ -29,7 +30,7 @@ export const blob = (opt: BlobOptions): string => {
2930

3031
const points: Point[] = [];
3132
for (let i = 0; i < count; i++) {
32-
const rand = 1 - 0.8 * opt.contrast * Math.random();
33+
const rand = 1 - 0.8 * opt.contrast * rgen();
3334

3435
points.push({
3536
x: Math.sin(rad(i * angle)) * radius * rand + opt.size / 2,
@@ -39,31 +40,32 @@ export const blob = (opt: BlobOptions): string => {
3940

4041
const smoothed = smooth(points, {
4142
closed: true,
42-
strength: (4/3) * Math.tan(rad(angle/4)) / Math.sin(rad(angle/2)),
43+
strength: ((4 / 3) * Math.tan(rad(angle / 4))) / Math.sin(rad(angle / 2)),
4344
});
4445

4546
return render(smoothed, {
4647
closed: true,
4748
width: opt.size,
4849
height: opt.size,
4950
fill: opt.color,
50-
transform: `rotate(${Math.random() * angle},${opt.size / 2},${opt.size / 2})`,
51-
stroke: (opt.stroke && opt.stroke.color),
52-
strokeWidth: (opt.stroke && opt.stroke.width),
51+
transform: `rotate(${rgen() * angle},${opt.size / 2},${opt.size / 2})`,
52+
stroke: opt.stroke && opt.stroke.color,
53+
strokeWidth: opt.stroke && opt.stroke.width,
5354
guides: opt.guides,
5455
});
5556
};
5657

5758
console.log(
5859
blob({
5960
color: "pink",
60-
complexity: 0.2,
61-
contrast: 1,
62-
size: 600,
61+
complexity: 0.4,
62+
seed: "16",
63+
contrast: 0.4,
64+
size: 400,
6365
guides: true,
6466
stroke: {
6567
color: "red",
66-
width: 1.8,
68+
width: 1,
6769
},
6870
}),
6971
);

types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ export interface SVGPoint {
3434

3535
export interface BlobOptions {
3636
size: number;
37+
seed?: string;
3738
color?: string;
3839
stroke?: {
3940
color: string;

util.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,3 +61,39 @@ export const smooth = (points: Point[], opt: SmoothingOptions): Point[] => {
6161

6262
return out;
6363
};
64+
65+
// Seeded random number generator.
66+
// https://stackoverflow.com/a/47593316/3053361
67+
export const rand = (seed: string) => {
68+
const xfnv1a = (str: string) => {
69+
let h = 2166136261 >>> 0;
70+
for (let i = 0; i < str.length; i++) {
71+
h = Math.imul(h ^ str.charCodeAt(i), 16777619);
72+
}
73+
return () => {
74+
h += h << 13;
75+
h ^= h >>> 7;
76+
h += h << 3;
77+
h ^= h >>> 17;
78+
return (h += h << 5) >>> 0;
79+
};
80+
};
81+
82+
const sfc32 = (a: number, b: number, c: number, d: number) => () => {
83+
a >>>= 0;
84+
b >>>= 0;
85+
c >>>= 0;
86+
d >>>= 0;
87+
var t = (a + b) | 0;
88+
a = b ^ (b >>> 9);
89+
b = (c + (c << 3)) | 0;
90+
c = (c << 21) | (c >>> 11);
91+
d = (d + 1) | 0;
92+
t = (t + d) | 0;
93+
c = (c + t) | 0;
94+
return (t >>> 0) / 4294967296;
95+
};
96+
97+
const seedGenerator = xfnv1a(seed);
98+
return sfc32(seedGenerator(), seedGenerator(), seedGenerator(), seedGenerator());
99+
};

0 commit comments

Comments
 (0)