primitive 1.0.1 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +89 -0
- package/bin/run.js +16 -0
- package/dist/cli-config-B5hrwe8q.js +1330 -0
- package/dist/oclif/index.js +23833 -0
- package/dist/oclif/proxy-auto-detect.js +71 -0
- package/dist/oclif/root-signup-hint.js +136 -0
- package/man/primitive.1 +111 -0
- package/package.json +137 -68
- package/.babelrc +0 -12
- package/.editorconfig +0 -9
- package/.eslintrc +0 -5
- package/.travis.yml +0 -5
- package/browser.js +0 -109
- package/dist/browser.js +0 -6791
- package/lib/browser-context.js +0 -98
- package/lib/color.js +0 -6
- package/lib/context.js +0 -101
- package/lib/context.test.js +0 -31
- package/lib/core.js +0 -199
- package/lib/core.test.js +0 -70
- package/lib/model.js +0 -168
- package/lib/optimize.js +0 -53
- package/lib/primitive.js +0 -76
- package/lib/random.js +0 -4
- package/lib/rasterize.js +0 -101
- package/lib/scanline.js +0 -25
- package/lib/shapes/ellipse.js +0 -111
- package/lib/shapes/factory.js +0 -52
- package/lib/shapes/rectangle.js +0 -92
- package/lib/shapes/rotated-ellipse.js +0 -98
- package/lib/shapes/rotated-rectangle.js +0 -125
- package/lib/shapes/shape.js +0 -26
- package/lib/shapes/triangle.js +0 -216
- package/lib/shapes/triangle.test.js +0 -73
- package/lib/state.js +0 -69
- package/lib/worker.js +0 -50
- package/main.js +0 -6
- package/main.test.js +0 -39
- package/module.js +0 -126
- package/notes.md +0 -15
- package/readme.md +0 -149
- package/rollup.config.js +0 -28
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
import random, { normal } from '../random'
|
|
2
|
-
|
|
3
|
-
import rasterize from '../rasterize'
|
|
4
|
-
import Scanline from '../scanline'
|
|
5
|
-
import Shape from './shape'
|
|
6
|
-
|
|
7
|
-
export default class RotatedRectangle extends Shape {
|
|
8
|
-
constructor (opts) {
|
|
9
|
-
super(opts)
|
|
10
|
-
if (!opts) return
|
|
11
|
-
|
|
12
|
-
this.x1 = random.int(0, this.width - 1)
|
|
13
|
-
this.y1 = random.int(0, this.height - 1)
|
|
14
|
-
|
|
15
|
-
this.x2 = Math.max(0, Math.min(this.width - 1, this.x1 + random.int(-16, 16)))
|
|
16
|
-
this.y2 = Math.max(0, Math.min(this.height - 1, this.y1 + random.int(-16, 16)))
|
|
17
|
-
|
|
18
|
-
this.angle = random.float() * 360
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
copy () {
|
|
22
|
-
const shape = new RotatedRectangle()
|
|
23
|
-
shape.width = this.width
|
|
24
|
-
shape.height = this.height
|
|
25
|
-
shape.x1 = this.x1
|
|
26
|
-
shape.y1 = this.y1
|
|
27
|
-
shape.x2 = this.x2
|
|
28
|
-
shape.y2 = this.y2
|
|
29
|
-
shape.angle = this.angle
|
|
30
|
-
return shape
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
mutate () {
|
|
34
|
-
const { width, height } = this
|
|
35
|
-
const shape = this.copy()
|
|
36
|
-
const m = 16
|
|
37
|
-
|
|
38
|
-
switch (random.int(0, 2)) {
|
|
39
|
-
case 0:
|
|
40
|
-
shape.x1 = Math.max(0, Math.min(width - 1, shape.x1 + normal() * m))
|
|
41
|
-
shape.y1 = Math.max(0, Math.min(height - 1, shape.y1 + normal() * m))
|
|
42
|
-
break
|
|
43
|
-
|
|
44
|
-
case 1:
|
|
45
|
-
shape.x2 = Math.max(0, Math.min(width - 1, shape.x2 + normal() * m))
|
|
46
|
-
shape.y2 = Math.max(0, Math.min(height - 1, shape.y2 + normal() * m))
|
|
47
|
-
break
|
|
48
|
-
|
|
49
|
-
case 2:
|
|
50
|
-
shape.angle = shape.angle + normal() * m
|
|
51
|
-
break
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
return shape
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
rasterize () {
|
|
58
|
-
const points = this.getPoints()
|
|
59
|
-
const lines = rasterize(points)
|
|
60
|
-
return Scanline.filter(lines, this.width, this.height)
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
getPoints () {
|
|
64
|
-
const { x1, y1, x2, y2, angle } = this
|
|
65
|
-
|
|
66
|
-
const xm1 = Math.min(x1, x2)
|
|
67
|
-
const xm2 = Math.max(x1, x2)
|
|
68
|
-
const ym1 = Math.min(y1, y2)
|
|
69
|
-
const ym2 = Math.max(y1, y2)
|
|
70
|
-
|
|
71
|
-
const cx = (xm1 + xm2) / 2
|
|
72
|
-
const cy = (ym1 + ym2) / 2
|
|
73
|
-
|
|
74
|
-
const ox1 = xm1 - cx
|
|
75
|
-
const ox2 = xm2 - cx
|
|
76
|
-
const oy1 = ym1 - cy
|
|
77
|
-
const oy2 = ym2 - cy
|
|
78
|
-
|
|
79
|
-
const rads = angle * Math.PI / 180.0
|
|
80
|
-
const c = Math.cos(rads)
|
|
81
|
-
const s = Math.sin(rads)
|
|
82
|
-
|
|
83
|
-
const ulx = (ox1 * c - oy1 * s + cx) | 0
|
|
84
|
-
const uly = (ox1 * s + oy1 * c + cy) | 0
|
|
85
|
-
const blx = (ox1 * c - oy2 * s + cx) | 0
|
|
86
|
-
const bly = (ox1 * s + oy2 * c + cy) | 0
|
|
87
|
-
const urx = (ox2 * c - oy1 * s + cx) | 0
|
|
88
|
-
const ury = (ox2 * s + oy1 * c + cy) | 0
|
|
89
|
-
const brx = (ox2 * c - oy2 * s + cx) | 0
|
|
90
|
-
const bry = (ox2 * s + oy2 * c + cy) | 0
|
|
91
|
-
|
|
92
|
-
return [
|
|
93
|
-
{
|
|
94
|
-
x: ulx,
|
|
95
|
-
y: uly
|
|
96
|
-
},
|
|
97
|
-
{
|
|
98
|
-
x: urx,
|
|
99
|
-
y: ury
|
|
100
|
-
},
|
|
101
|
-
{
|
|
102
|
-
x: brx,
|
|
103
|
-
y: bry
|
|
104
|
-
},
|
|
105
|
-
{
|
|
106
|
-
x: blx,
|
|
107
|
-
y: bly
|
|
108
|
-
}
|
|
109
|
-
]
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
draw (ctx) {
|
|
113
|
-
throw new Error('TODO')
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
toSVG (attrs = '') {
|
|
117
|
-
const points = this.getPoints()
|
|
118
|
-
.map((point) => `${point.x} ${point.y}`)
|
|
119
|
-
.join(' ')
|
|
120
|
-
|
|
121
|
-
return (
|
|
122
|
-
`<polygon ${attrs} points="${points}" />`
|
|
123
|
-
)
|
|
124
|
-
}
|
|
125
|
-
}
|
package/lib/shapes/shape.js
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
export default class Shape {
|
|
2
|
-
constructor (opts = { }) {
|
|
3
|
-
this.width = opts.width
|
|
4
|
-
this.height = opts.height
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
copy () {
|
|
8
|
-
throw new Error('TODO')
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
mutate () {
|
|
12
|
-
throw new Error('TODO')
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
rasterize () {
|
|
16
|
-
throw new Error('TODO')
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
draw (ctx, scale) {
|
|
20
|
-
throw new Error('TODO')
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
toSVG () {
|
|
24
|
-
throw new Error('TODO')
|
|
25
|
-
}
|
|
26
|
-
}
|
package/lib/shapes/triangle.js
DELETED
|
@@ -1,216 +0,0 @@
|
|
|
1
|
-
import random, { normal } from '../random'
|
|
2
|
-
|
|
3
|
-
import Scanline from '../scanline'
|
|
4
|
-
import Shape from './shape'
|
|
5
|
-
|
|
6
|
-
export default class Triangle extends Shape {
|
|
7
|
-
constructor (opts) {
|
|
8
|
-
super(opts)
|
|
9
|
-
if (!opts) return
|
|
10
|
-
|
|
11
|
-
do {
|
|
12
|
-
this.x1 = random.int(0, this.width - 1)
|
|
13
|
-
this.y1 = random.int(0, this.height - 1)
|
|
14
|
-
|
|
15
|
-
this.x2 = this.x1 + random.int(-15, 15)
|
|
16
|
-
this.y2 = this.y1 + random.int(-15, 15)
|
|
17
|
-
|
|
18
|
-
this.x3 = this.x1 + random.int(-15, 15)
|
|
19
|
-
this.y3 = this.y1 + random.int(-15, 15)
|
|
20
|
-
} while (!this.isValid())
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
copy () {
|
|
24
|
-
const shape = new Triangle()
|
|
25
|
-
shape.width = this.width
|
|
26
|
-
shape.height = this.height
|
|
27
|
-
shape.x1 = this.x1
|
|
28
|
-
shape.y1 = this.y1
|
|
29
|
-
shape.x2 = this.x2
|
|
30
|
-
shape.y2 = this.y2
|
|
31
|
-
shape.x3 = this.x3
|
|
32
|
-
shape.y3 = this.y3
|
|
33
|
-
return shape
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
mutate () {
|
|
37
|
-
const { width, height } = this
|
|
38
|
-
const m = 16
|
|
39
|
-
let shape = this.copy()
|
|
40
|
-
let n = 0
|
|
41
|
-
|
|
42
|
-
while (true) {
|
|
43
|
-
switch (random.int(0, 2)) {
|
|
44
|
-
case 0:
|
|
45
|
-
shape.x1 = Math.max(-m, Math.min(width - 1 + m, (shape.x1 + normal() * m)))
|
|
46
|
-
shape.y1 = Math.max(-m, Math.min(height - 1 + m, (shape.y1 + normal() * m)))
|
|
47
|
-
break
|
|
48
|
-
|
|
49
|
-
case 1:
|
|
50
|
-
shape.x2 = Math.max(-m, Math.min(width - 1 + m, (shape.x2 + normal() * m)))
|
|
51
|
-
shape.y2 = Math.max(-m, Math.min(height - 1 + m, (shape.y2 + normal() * m)))
|
|
52
|
-
break
|
|
53
|
-
|
|
54
|
-
case 2:
|
|
55
|
-
shape.x3 = Math.max(-m, Math.min(width - 1 + m, (shape.x3 + normal() * m)))
|
|
56
|
-
shape.y3 = Math.max(-m, Math.min(height - 1 + m, (shape.y3 + normal() * m)))
|
|
57
|
-
break
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
if (shape.isValid()) {
|
|
61
|
-
return shape
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
if (++n > 128) {
|
|
65
|
-
shape = this.copy()
|
|
66
|
-
n = 0
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
isValid () {
|
|
72
|
-
const minDegrees = 15
|
|
73
|
-
|
|
74
|
-
let a1, a2, a3
|
|
75
|
-
{
|
|
76
|
-
let x1 = (this.x2 - this.x1)
|
|
77
|
-
let y1 = (this.y2 - this.y1)
|
|
78
|
-
let x2 = (this.x3 - this.x1)
|
|
79
|
-
let y2 = (this.y3 - this.y1)
|
|
80
|
-
const d1 = Math.sqrt(x1 * x1 + y1 * y1)
|
|
81
|
-
const d2 = Math.sqrt(x2 * x2 + y2 * y2)
|
|
82
|
-
x1 /= d1
|
|
83
|
-
y1 /= d1
|
|
84
|
-
x2 /= d2
|
|
85
|
-
y2 /= d2
|
|
86
|
-
a1 = degrees(Math.acos(x1 * x2 + y1 * y2))
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
{
|
|
90
|
-
let x1 = (this.x1 - this.x2)
|
|
91
|
-
let y1 = (this.y1 - this.y2)
|
|
92
|
-
let x2 = (this.x3 - this.x2)
|
|
93
|
-
let y2 = (this.y3 - this.y2)
|
|
94
|
-
const d1 = Math.sqrt(x1 * x1 + y1 * y1)
|
|
95
|
-
const d2 = Math.sqrt(x2 * x2 + y2 * y2)
|
|
96
|
-
x1 /= d1
|
|
97
|
-
y1 /= d1
|
|
98
|
-
x2 /= d2
|
|
99
|
-
y2 /= d2
|
|
100
|
-
a2 = degrees(Math.acos(x1 * x2 + y1 * y2))
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
a3 = 180 - a1 - a2
|
|
104
|
-
return a1 > minDegrees && a2 > minDegrees && a3 > minDegrees
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
rasterize () {
|
|
108
|
-
const { width, height } = this
|
|
109
|
-
const lines = rasterize(this.x1, this.y1, this.x2, this.y2, this.x3, this.y3)
|
|
110
|
-
return Scanline.filter(lines, width, height)
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
draw (ctx) {
|
|
114
|
-
ctx.beginPath()
|
|
115
|
-
ctx.moveTo(this.x1, this.y1)
|
|
116
|
-
ctx.lineTo(this.x2, this.y2)
|
|
117
|
-
ctx.lineTo(this.x3, this.y3)
|
|
118
|
-
ctx.fill()
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
toSVG (attrs = '') {
|
|
122
|
-
return (
|
|
123
|
-
`<polygon ${attrs} points="${this.x1},${this.y1} ${this.x2},${this.y2} ${this.x3},${this.y3}" />`
|
|
124
|
-
)
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
function degrees (radians) {
|
|
129
|
-
return 180 * radians / Math.PI
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
function rasterize (x1, y1, x2, y2, x3, y3) {
|
|
133
|
-
let t
|
|
134
|
-
|
|
135
|
-
if (y1 > y3) {
|
|
136
|
-
t = x1
|
|
137
|
-
x1 = x3
|
|
138
|
-
x3 = t
|
|
139
|
-
|
|
140
|
-
t = y1
|
|
141
|
-
y1 = y3
|
|
142
|
-
y3 = t
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
if (y1 > y2) {
|
|
146
|
-
t = x1
|
|
147
|
-
x1 = x2
|
|
148
|
-
x2 = t
|
|
149
|
-
|
|
150
|
-
t = y1
|
|
151
|
-
y1 = y2
|
|
152
|
-
y2 = t
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
if (y2 > y3) {
|
|
156
|
-
t = x2
|
|
157
|
-
x2 = x3
|
|
158
|
-
x3 = t
|
|
159
|
-
|
|
160
|
-
t = y2
|
|
161
|
-
y2 = y3
|
|
162
|
-
y3 = t
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
if (y2 === y3) {
|
|
166
|
-
return rasterizeBottom(x1, y1, x2, y2, x3, y3)
|
|
167
|
-
} else if (y1 === y2) {
|
|
168
|
-
return rasterizeTop(x1, y1, x2, y2, x3, y3)
|
|
169
|
-
} else {
|
|
170
|
-
const x4 = x1 + (((y2 - y1) / (y3 - y1)) * (x3 - x1)) | 0
|
|
171
|
-
const y4 = y2
|
|
172
|
-
|
|
173
|
-
return []
|
|
174
|
-
.concat(rasterizeBottom(x1, y1, x2, y2, x4, y4))
|
|
175
|
-
.concat(rasterizeTop(x2, y2, x4, y4, x3, y3))
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
function rasterizeBottom (x1, y1, x2, y2, x3, y3) {
|
|
180
|
-
const lines = []
|
|
181
|
-
|
|
182
|
-
const s1 = (x2 - x1) / (y2 - y1)
|
|
183
|
-
const s2 = (x3 - x1) / (y3 - y1)
|
|
184
|
-
let ax = x1
|
|
185
|
-
let bx = x1
|
|
186
|
-
|
|
187
|
-
for (let y = y1; y <= y2; ++y) {
|
|
188
|
-
const a = ax
|
|
189
|
-
const b = bx
|
|
190
|
-
|
|
191
|
-
ax += s1
|
|
192
|
-
bx += s2
|
|
193
|
-
|
|
194
|
-
lines.push(new Scanline(y, a, b))
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
return lines
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
function rasterizeTop (x1, y1, x2, y2, x3, y3) {
|
|
201
|
-
const lines = []
|
|
202
|
-
|
|
203
|
-
const s1 = (x3 - x1) / (y3 - y1)
|
|
204
|
-
const s2 = (x3 - x2) / (y3 - y2)
|
|
205
|
-
let ax = x3
|
|
206
|
-
let bx = x3
|
|
207
|
-
|
|
208
|
-
for (let y = y3; y >= y1; y--) {
|
|
209
|
-
ax -= s1
|
|
210
|
-
bx -= s2
|
|
211
|
-
|
|
212
|
-
lines.push(new Scanline(y, ax, bx))
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
return lines
|
|
216
|
-
}
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
import test from 'ava'
|
|
2
|
-
|
|
3
|
-
import context from '../context'
|
|
4
|
-
// import core from '../core'
|
|
5
|
-
import Triangle from './triangle'
|
|
6
|
-
|
|
7
|
-
test('new Triangle()', async (t) => {
|
|
8
|
-
const image = context.createImage(512, 512)
|
|
9
|
-
|
|
10
|
-
for (let i = 0; i < 10000; ++i) {
|
|
11
|
-
const shape = new Triangle(image)
|
|
12
|
-
|
|
13
|
-
t.true(shape.x1 >= -16)
|
|
14
|
-
t.true(shape.x1 < 512 + 16)
|
|
15
|
-
t.true(shape.y1 >= -16)
|
|
16
|
-
t.true(shape.y1 < 512 + 16)
|
|
17
|
-
|
|
18
|
-
t.true(shape.x2 >= -16)
|
|
19
|
-
t.true(shape.x2 < 512 + 16)
|
|
20
|
-
t.true(shape.y2 >= -16)
|
|
21
|
-
t.true(shape.y2 < 512 + 16)
|
|
22
|
-
|
|
23
|
-
t.true(shape.x3 >= -16)
|
|
24
|
-
t.true(shape.x3 < 512 + 16)
|
|
25
|
-
t.true(shape.y3 >= -16)
|
|
26
|
-
t.true(shape.y3 < 512 + 16)
|
|
27
|
-
|
|
28
|
-
t.true(shape.isValid())
|
|
29
|
-
|
|
30
|
-
const shape2 = shape.copy()
|
|
31
|
-
t.deepEqual(shape, shape2)
|
|
32
|
-
}
|
|
33
|
-
})
|
|
34
|
-
|
|
35
|
-
test('Triangle.mutate', async (t) => {
|
|
36
|
-
const image = context.createImage(512, 512)
|
|
37
|
-
|
|
38
|
-
for (let i = 0; i < 10000; ++i) {
|
|
39
|
-
const base = new Triangle(image)
|
|
40
|
-
Object.freeze(base)
|
|
41
|
-
const shape = base.mutate()
|
|
42
|
-
|
|
43
|
-
t.is(base.width, shape.width)
|
|
44
|
-
t.is(base.height, shape.height)
|
|
45
|
-
|
|
46
|
-
t.true(shape.x1 >= -16)
|
|
47
|
-
t.true(shape.x1 < 512 + 16)
|
|
48
|
-
t.true(shape.y1 >= -16)
|
|
49
|
-
t.true(shape.y1 < 512 + 16)
|
|
50
|
-
|
|
51
|
-
t.true(shape.x2 >= -16)
|
|
52
|
-
t.true(shape.x2 < 512 + 16)
|
|
53
|
-
t.true(shape.y2 >= -16)
|
|
54
|
-
t.true(shape.y2 < 512 + 16)
|
|
55
|
-
|
|
56
|
-
t.true(shape.x3 >= -16)
|
|
57
|
-
t.true(shape.x3 < 512 + 16)
|
|
58
|
-
t.true(shape.y3 >= -16)
|
|
59
|
-
t.true(shape.y3 < 512 + 16)
|
|
60
|
-
|
|
61
|
-
t.true(shape.isValid())
|
|
62
|
-
|
|
63
|
-
/*
|
|
64
|
-
let s = shape
|
|
65
|
-
for (let j = 0; j < 5000; ++j) {
|
|
66
|
-
s = s.mutate()
|
|
67
|
-
const lines = s.rasterize()
|
|
68
|
-
core.drawLines(image, { r: 255, g: 0, b: 0, a: 128 }, lines)
|
|
69
|
-
await context.saveImage(image, `${j}.png`)
|
|
70
|
-
}
|
|
71
|
-
*/
|
|
72
|
-
}
|
|
73
|
-
})
|
package/lib/state.js
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
import randomInt from 'random-int'
|
|
4
|
-
import shapeFactory from './shapes/factory'
|
|
5
|
-
|
|
6
|
-
export default class State {
|
|
7
|
-
constructor (opts) {
|
|
8
|
-
if (!opts) return
|
|
9
|
-
|
|
10
|
-
const {
|
|
11
|
-
worker,
|
|
12
|
-
shape,
|
|
13
|
-
alpha
|
|
14
|
-
} = opts
|
|
15
|
-
|
|
16
|
-
this.worker = worker
|
|
17
|
-
this.shape = shape
|
|
18
|
-
this.score = -1
|
|
19
|
-
|
|
20
|
-
if (!alpha) {
|
|
21
|
-
this.alpha = 128
|
|
22
|
-
this.mutateAlpha = true
|
|
23
|
-
} else {
|
|
24
|
-
this.alpha = alpha
|
|
25
|
-
this.mutateAlpha = false
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
copy () {
|
|
30
|
-
const state = new State()
|
|
31
|
-
state.worker = this.worker
|
|
32
|
-
state.shape = this.shape // .copy()
|
|
33
|
-
state.score = this.score
|
|
34
|
-
state.alpha = this.alpha
|
|
35
|
-
state.mutateAlpha = this.mutateAlpha
|
|
36
|
-
return state
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
energy () {
|
|
40
|
-
if (this.score < 0) {
|
|
41
|
-
this.score = this.worker.energy(this.shape, this.alpha)
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
return this.score
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
mutate () {
|
|
48
|
-
const state = this.copy()
|
|
49
|
-
state.shape = state.shape.mutate()
|
|
50
|
-
if (state.mutateAlpha) {
|
|
51
|
-
state.alpha = Math.max(1, Math.min(255, (state.alpha + randomInt(-10, 10)) | 0))
|
|
52
|
-
}
|
|
53
|
-
state.score = -1
|
|
54
|
-
return state
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
static create (worker, shapeType, alpha) {
|
|
58
|
-
const shape = shapeFactory(shapeType, {
|
|
59
|
-
width: worker.width,
|
|
60
|
-
height: worker.height
|
|
61
|
-
})
|
|
62
|
-
|
|
63
|
-
return new State({
|
|
64
|
-
worker,
|
|
65
|
-
shape,
|
|
66
|
-
alpha
|
|
67
|
-
})
|
|
68
|
-
}
|
|
69
|
-
}
|
package/lib/worker.js
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
import core from './core'
|
|
4
|
-
|
|
5
|
-
export default class Worker {
|
|
6
|
-
constructor (opts) {
|
|
7
|
-
const {
|
|
8
|
-
context,
|
|
9
|
-
target
|
|
10
|
-
} = opts
|
|
11
|
-
|
|
12
|
-
this.context = context
|
|
13
|
-
this.target = target
|
|
14
|
-
this.width = target.width
|
|
15
|
-
this.height = target.height
|
|
16
|
-
|
|
17
|
-
this.counter = 0
|
|
18
|
-
this.current = null
|
|
19
|
-
this.score = 0
|
|
20
|
-
|
|
21
|
-
this.buffer = context.createImage(this.width, this.height)
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
init (current, score) {
|
|
25
|
-
this.current = current
|
|
26
|
-
this.score = score
|
|
27
|
-
this.counter = 0
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
energy (shape, alpha) {
|
|
31
|
-
this.counter++
|
|
32
|
-
|
|
33
|
-
const lines = shape.rasterize()
|
|
34
|
-
const color = core.computeColor(this.target, this.current, lines, alpha)
|
|
35
|
-
let score
|
|
36
|
-
|
|
37
|
-
if (this.context.PARTIALS) {
|
|
38
|
-
core.copyLines(this.buffer, this.current, lines)
|
|
39
|
-
core.drawLines(this.buffer, color, lines)
|
|
40
|
-
score = core.differencePartial(this.target, this.current, this.buffer, this.score, lines)
|
|
41
|
-
} else {
|
|
42
|
-
this.buffer.data.set(this.current.data)
|
|
43
|
-
core.drawLines(this.buffer, color, lines)
|
|
44
|
-
score = core.difference(this.target, this.buffer)
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
// console.log('worker.energy', this.counter, score)
|
|
48
|
-
return score
|
|
49
|
-
}
|
|
50
|
-
}
|
package/main.js
DELETED
package/main.test.js
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import test from 'ava'
|
|
2
|
-
import path from 'path'
|
|
3
|
-
|
|
4
|
-
import primitive from './main'
|
|
5
|
-
|
|
6
|
-
const fixturesPath = path.join(__dirname, 'media')
|
|
7
|
-
|
|
8
|
-
const fixtures = [
|
|
9
|
-
'monalisa.png',
|
|
10
|
-
'lena.png'
|
|
11
|
-
]
|
|
12
|
-
|
|
13
|
-
const shapeTypes = [
|
|
14
|
-
'triangle',
|
|
15
|
-
'ellipse',
|
|
16
|
-
'rotated-ellipse',
|
|
17
|
-
'rectangle',
|
|
18
|
-
'rotated-rectangle',
|
|
19
|
-
'random'
|
|
20
|
-
]
|
|
21
|
-
|
|
22
|
-
fixtures.forEach((fixture) => {
|
|
23
|
-
const input = path.join(fixturesPath, fixture)
|
|
24
|
-
|
|
25
|
-
shapeTypes.forEach((shapeType) => {
|
|
26
|
-
test(`${fixture} - ${shapeType}`, async (t) => {
|
|
27
|
-
const model = await primitive({
|
|
28
|
-
input,
|
|
29
|
-
shapeType,
|
|
30
|
-
numSteps: 10,
|
|
31
|
-
numCandidateShapes: 5,
|
|
32
|
-
numCandidateMutations: 30,
|
|
33
|
-
log: console.log.bind(console)
|
|
34
|
-
})
|
|
35
|
-
|
|
36
|
-
t.true(model.score < 1)
|
|
37
|
-
})
|
|
38
|
-
})
|
|
39
|
-
})
|