rubysketch 0.3.0 → 0.3.5
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.
- checksums.yaml +4 -4
- data/ChangeLog.md +38 -0
- data/Rakefile +1 -0
- data/VERSION +1 -1
- data/lib/rubysketch/processing.rb +1030 -255
- data/lib/rubysketch/window.rb +5 -5
- data/test/helper.rb +24 -0
- data/test/processing/test_utility.rb +29 -0
- data/test/processing/test_vector.rb +397 -0
- metadata +9 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0df24de4fc3eabd1c7880d51ff34ef8389b44bef43a8159c75e9e6c651953c0d
|
4
|
+
data.tar.gz: cf03a57e9ecbf8a63f0b089c4588c0cd041ef93e2b92c69a580b8aa1f013659e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 953e09a5b8da7f8798186e3f0a4e4b9ca636a5c7a34cdd1eca26da30f09221ac31fe3c5ed9ebc8e498060f84b88de4bb14738ef8054e30544c38ca664522f050
|
7
|
+
data.tar.gz: 4c4ae42689cfda821c84617c2925fc48b6af3ad3672d8dd1c603b999427762b5439cbf7c879a06fdf8830f83632d5e01bd9197d1cf528f6ae948a38728063a2a
|
data/ChangeLog.md
CHANGED
@@ -1,6 +1,44 @@
|
|
1
1
|
# RubySketch ChangeLog
|
2
2
|
|
3
3
|
|
4
|
+
## [0.3.5] - 2020-08-02
|
5
|
+
|
6
|
+
- add random()
|
7
|
+
- add sin(), cos(), tan(), asin(), acos(), atan() and atan2()
|
8
|
+
- make Vector class accessible from user script context
|
9
|
+
- fix error on calling rotate()
|
10
|
+
|
11
|
+
|
12
|
+
## [0.3.4] - 2020-08-02
|
13
|
+
|
14
|
+
- delete Utility module
|
15
|
+
|
16
|
+
|
17
|
+
## [0.3.3] - 2020-08-01
|
18
|
+
|
19
|
+
- add Vector class
|
20
|
+
|
21
|
+
|
22
|
+
## [0.3.2] - 2020-07-22
|
23
|
+
|
24
|
+
- text() draws to the baseline by default
|
25
|
+
- add textWidth(), textAscent(), textDescent() and textAlign()
|
26
|
+
- change initial color for fill() and stroke()
|
27
|
+
- change initial background color to grayscale 0.8
|
28
|
+
|
29
|
+
|
30
|
+
## [0.3.1] - 2020-07-17
|
31
|
+
|
32
|
+
- add touchStarted(), touchEnded(), touchMoved() and touches()
|
33
|
+
- make all event handler drawable
|
34
|
+
- limit font max size to 256
|
35
|
+
|
36
|
+
|
37
|
+
## [0.3.0] - 2020-05-21
|
38
|
+
|
39
|
+
- add createGraphics()
|
40
|
+
|
41
|
+
|
4
42
|
## [0.2.7] - 2020-04-17
|
5
43
|
|
6
44
|
- add strokeCap() and strokeJoin()
|
data/Rakefile
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.3.
|
1
|
+
0.3.5
|
@@ -6,13 +6,574 @@ module RubySketch
|
|
6
6
|
module Processing
|
7
7
|
|
8
8
|
|
9
|
+
# @private
|
10
|
+
DEG2RAD__ = Math::PI / 180.0
|
11
|
+
|
12
|
+
# @private
|
13
|
+
RAD2DEG__ = 180.0 / Math::PI
|
14
|
+
|
15
|
+
|
16
|
+
# Vector class.
|
17
|
+
#
|
18
|
+
class Vector
|
19
|
+
|
20
|
+
include Comparable
|
21
|
+
|
22
|
+
# Initialize vector object.
|
23
|
+
#
|
24
|
+
# @overload new()
|
25
|
+
# @overload new(x)
|
26
|
+
# @overload new(x, y)
|
27
|
+
# @overload new(x, y, z)
|
28
|
+
# @overload new(v)
|
29
|
+
# @overload new(a)
|
30
|
+
#
|
31
|
+
# @param x [Numeric] x of vector
|
32
|
+
# @param y [Numeric] y of vector
|
33
|
+
# @param z [Numeric] z of vector
|
34
|
+
# @param v [Vector] vector object to copy
|
35
|
+
# @param a [Array] array like [x, y, z]
|
36
|
+
#
|
37
|
+
def initialize (x = 0, y = 0, z = 0, context: nil)
|
38
|
+
@point = case x
|
39
|
+
when Rays::Point then x.dup
|
40
|
+
when Vector then x.getInternal__.dup
|
41
|
+
when Array then Rays::Point.new x[0] || 0, x[1] || 0, x[2] || 0
|
42
|
+
else Rays::Point.new x || 0, y || 0, z || 0
|
43
|
+
end
|
44
|
+
@context = context || Context.context__
|
45
|
+
end
|
46
|
+
|
47
|
+
# Initializer for dup or clone
|
48
|
+
#
|
49
|
+
def initialize_copy (o)
|
50
|
+
@point = o.getInternal__.dup
|
51
|
+
end
|
52
|
+
|
53
|
+
# Copy vector object
|
54
|
+
#
|
55
|
+
# @return [Vector] duplicated vector object
|
56
|
+
#
|
57
|
+
alias copy dup
|
58
|
+
|
59
|
+
# Sets x, y and z.
|
60
|
+
#
|
61
|
+
# @overload set(x)
|
62
|
+
# @overload set(x, y)
|
63
|
+
# @overload set(x, y, z)
|
64
|
+
# @overload set(v)
|
65
|
+
# @overload set(a)
|
66
|
+
#
|
67
|
+
# @param x [Numeric] x of vector
|
68
|
+
# @param y [Numeric] y of vector
|
69
|
+
# @param z [Numeric] z of vector
|
70
|
+
# @param v [Vector] vector object to copy
|
71
|
+
# @param a [Array] array with x, y, z
|
72
|
+
#
|
73
|
+
# @return [nil] nil
|
74
|
+
#
|
75
|
+
def set (*args)
|
76
|
+
initialize *args
|
77
|
+
self
|
78
|
+
end
|
79
|
+
|
80
|
+
# Gets x value.
|
81
|
+
#
|
82
|
+
# @return [Numeric] x value of vector
|
83
|
+
#
|
84
|
+
def x ()
|
85
|
+
@point.x
|
86
|
+
end
|
87
|
+
|
88
|
+
# Gets y value.
|
89
|
+
#
|
90
|
+
# @return [Numeric] y value of vector
|
91
|
+
#
|
92
|
+
def y ()
|
93
|
+
@point.y
|
94
|
+
end
|
95
|
+
|
96
|
+
# Gets z value.
|
97
|
+
#
|
98
|
+
# @return [Numeric] z value of vector
|
99
|
+
#
|
100
|
+
def z ()
|
101
|
+
@point.z
|
102
|
+
end
|
103
|
+
|
104
|
+
# Sets x value.
|
105
|
+
#
|
106
|
+
# @return [Numeric] x value of vector
|
107
|
+
#
|
108
|
+
def x= (x)
|
109
|
+
@point.x = x
|
110
|
+
end
|
111
|
+
|
112
|
+
# Sets y value.
|
113
|
+
#
|
114
|
+
# @return [Numeric] y value of vector
|
115
|
+
#
|
116
|
+
def y= (y)
|
117
|
+
@point.y = y
|
118
|
+
end
|
119
|
+
|
120
|
+
# Sets z value.
|
121
|
+
#
|
122
|
+
# @return [Numeric] z value of vector
|
123
|
+
#
|
124
|
+
def z= (z)
|
125
|
+
@point.z = z
|
126
|
+
end
|
127
|
+
|
128
|
+
# Returns the interpolated vector between 2 vectors.
|
129
|
+
#
|
130
|
+
# @overload lerp(v, amount)
|
131
|
+
# @overload lerp(x, y, amount)
|
132
|
+
# @overload lerp(x, y, z, amount)
|
133
|
+
#
|
134
|
+
# @param v [Vector] vector to interpolate
|
135
|
+
# @param x [Numeric] x of vector to interpolate
|
136
|
+
# @param y [Numeric] y of vector to interpolate
|
137
|
+
# @param z [Numeric] z of vector to interpolate
|
138
|
+
# @param amount [Numeric] amount to interpolate
|
139
|
+
#
|
140
|
+
# @return [Vector] interporated vector
|
141
|
+
#
|
142
|
+
def lerp (*args, amount)
|
143
|
+
v = toVector__ *args
|
144
|
+
self.x = Context.lerp x, v.x, amount
|
145
|
+
self.y = Context.lerp y, v.y, amount
|
146
|
+
self.z = Context.lerp z, v.z, amount
|
147
|
+
self
|
148
|
+
end
|
149
|
+
|
150
|
+
# Returns the interpolated vector between 2 vectors.
|
151
|
+
#
|
152
|
+
# @param v1 [Vector] vector to interpolate
|
153
|
+
# @param v2 [Vector] vector to interpolate
|
154
|
+
# @param amount [Numeric] amount to interpolate
|
155
|
+
#
|
156
|
+
# @return [Vector] interporated vector
|
157
|
+
#
|
158
|
+
def self.lerp (v1, v2, amount)
|
159
|
+
v1.dup.lerp v2, amount
|
160
|
+
end
|
161
|
+
|
162
|
+
# Returns x, y, z as an array
|
163
|
+
#
|
164
|
+
# @return [Array] array of x, y, z
|
165
|
+
#
|
166
|
+
def array ()
|
167
|
+
@point.to_a 3
|
168
|
+
end
|
169
|
+
|
170
|
+
# Adds a vector.
|
171
|
+
#
|
172
|
+
# @overload add(v)
|
173
|
+
# @overload add(x, y)
|
174
|
+
# @overload add(x, y, z)
|
175
|
+
#
|
176
|
+
# @param v [Vector] vector to add
|
177
|
+
# @param x [Vector] x of vector to add
|
178
|
+
# @param y [Vector] y of vector to add
|
179
|
+
# @param z [Vector] z of vector to add
|
180
|
+
#
|
181
|
+
# @return [Vector] added vector
|
182
|
+
#
|
183
|
+
def add (*args)
|
184
|
+
@point += toVector__(*args).getInternal__
|
185
|
+
self
|
186
|
+
end
|
187
|
+
|
188
|
+
# Subtracts a vector.
|
189
|
+
#
|
190
|
+
# @overload sub(v)
|
191
|
+
# @overload sub(x, y)
|
192
|
+
# @overload sub(x, y, z)
|
193
|
+
#
|
194
|
+
# @param v [Vector] vector to subtract
|
195
|
+
# @param x [Vector] x of vector to subtract
|
196
|
+
# @param y [Vector] y of vector to subtract
|
197
|
+
# @param z [Vector] z of vector to subtract
|
198
|
+
#
|
199
|
+
# @return [Vector] subtracted vector
|
200
|
+
#
|
201
|
+
def sub (*args)
|
202
|
+
@point -= toVector__(*args).getInternal__
|
203
|
+
self
|
204
|
+
end
|
205
|
+
|
206
|
+
# Multiplies a vector by scalar.
|
207
|
+
#
|
208
|
+
# @param num [Numeric] number to multiply the vector
|
209
|
+
#
|
210
|
+
# @return [Vector] multiplied vector
|
211
|
+
#
|
212
|
+
def mult (num)
|
213
|
+
@point *= num
|
214
|
+
self
|
215
|
+
end
|
216
|
+
|
217
|
+
# Divides a vector by scalar.
|
218
|
+
#
|
219
|
+
# @param num [Numeric] number to divide the vector
|
220
|
+
#
|
221
|
+
# @return [Vector] divided vector
|
222
|
+
#
|
223
|
+
def div (num)
|
224
|
+
@point /= num
|
225
|
+
self
|
226
|
+
end
|
227
|
+
|
228
|
+
# Adds a vector.
|
229
|
+
#
|
230
|
+
# @param v [Vector] vector to add
|
231
|
+
#
|
232
|
+
# @return [Vector] added vector
|
233
|
+
#
|
234
|
+
def + (v)
|
235
|
+
dup.add v
|
236
|
+
end
|
237
|
+
|
238
|
+
# Subtracts a vector.
|
239
|
+
#
|
240
|
+
# @param v [Vector] vector to subtract
|
241
|
+
#
|
242
|
+
# @return [Vector] subtracted vector
|
243
|
+
#
|
244
|
+
def - (v)
|
245
|
+
dup.sub v
|
246
|
+
end
|
247
|
+
|
248
|
+
# Multiplies a vector by scalar.
|
249
|
+
#
|
250
|
+
# @param num [Numeric] number to multiply the vector
|
251
|
+
#
|
252
|
+
# @return [Vector] multiplied vector
|
253
|
+
#
|
254
|
+
def * (num)
|
255
|
+
dup.mult num
|
256
|
+
end
|
257
|
+
|
258
|
+
# Divides a vector by scalar.
|
259
|
+
#
|
260
|
+
# @param num [Numeric] number to divide the vector
|
261
|
+
#
|
262
|
+
# @return [Vector] divided vector
|
263
|
+
#
|
264
|
+
def / (num)
|
265
|
+
dup.div num
|
266
|
+
end
|
267
|
+
|
268
|
+
# Adds 2 vectors.
|
269
|
+
#
|
270
|
+
# @overload add(v1, v2)
|
271
|
+
# @overload add(v1, v2, target)
|
272
|
+
#
|
273
|
+
# @param v1 [Vector] a vector
|
274
|
+
# @param v2 [Vector] another vector
|
275
|
+
# @param target [Vector] vector to store added vector
|
276
|
+
#
|
277
|
+
# @return [Vector] added vector
|
278
|
+
#
|
279
|
+
def self.add (v1, v2, target = nil)
|
280
|
+
v = v1 + v2
|
281
|
+
target.set v if self === target
|
282
|
+
v
|
283
|
+
end
|
284
|
+
|
285
|
+
# Subtracts 2 vectors.
|
286
|
+
#
|
287
|
+
# @overload sub(v1, v2)
|
288
|
+
# @overload sub(v1, v2, target)
|
289
|
+
#
|
290
|
+
# @param v1 [Vector] a vector
|
291
|
+
# @param v2 [Vector] another vector
|
292
|
+
# @param target [Vector] vector to store subtracted vector
|
293
|
+
#
|
294
|
+
# @return [Vector] subtracted vector
|
295
|
+
#
|
296
|
+
def self.sub (v1, v2, target = nil)
|
297
|
+
v = v1 - v2
|
298
|
+
target.set v if self === target
|
299
|
+
v
|
300
|
+
end
|
301
|
+
|
302
|
+
# Multiplies a vector by scalar.
|
303
|
+
#
|
304
|
+
# @overload mult(v, num)
|
305
|
+
# @overload mult(v, num, target)
|
306
|
+
#
|
307
|
+
# @param v [Vector] a vector
|
308
|
+
# @param num [Numeric] number to multiply the vector
|
309
|
+
# @param target [Vector] vector to store multiplied vector
|
310
|
+
#
|
311
|
+
# @return [Vector] multiplied vector
|
312
|
+
#
|
313
|
+
def self.mult (v1, num, target = nil)
|
314
|
+
v = v1 * num
|
315
|
+
target.set v if self === target
|
316
|
+
v
|
317
|
+
end
|
318
|
+
|
319
|
+
# Divides a vector by scalar.
|
320
|
+
#
|
321
|
+
# @overload div(v, num)
|
322
|
+
# @overload div(v, num, target)
|
323
|
+
#
|
324
|
+
# @param v [Vector] a vector
|
325
|
+
# @param num [Numeric] number to divide the vector
|
326
|
+
# @param target [Vector] vector to store divided vector
|
327
|
+
#
|
328
|
+
# @return [Vector] divided vector
|
329
|
+
#
|
330
|
+
def self.div (v1, num, target = nil)
|
331
|
+
v = v1 / num
|
332
|
+
target.set v if self === target
|
333
|
+
v
|
334
|
+
end
|
335
|
+
|
336
|
+
# Returns the length of the vector.
|
337
|
+
#
|
338
|
+
# @return [Numeric] length
|
339
|
+
#
|
340
|
+
def mag ()
|
341
|
+
@point.length
|
342
|
+
end
|
343
|
+
|
344
|
+
# Returns squared length of the vector.
|
345
|
+
#
|
346
|
+
# @return [Numeric] squared length
|
347
|
+
#
|
348
|
+
def magSq ()
|
349
|
+
Rays::Point::dot(@point, @point)
|
350
|
+
end
|
351
|
+
|
352
|
+
# Changes the length of the vector.
|
353
|
+
#
|
354
|
+
# @overload setMag(len)
|
355
|
+
# @overload setMag(target, len)
|
356
|
+
#
|
357
|
+
# @param len [Numeric] length of new vector
|
358
|
+
# @param target [Vector] vector to store new vector
|
359
|
+
#
|
360
|
+
# @return [Vector] vector with new length
|
361
|
+
#
|
362
|
+
def setMag (target = nil, len)
|
363
|
+
(target || self).set @point.normal * len
|
364
|
+
end
|
365
|
+
|
366
|
+
# Changes the length of the vector to 1.0.
|
367
|
+
#
|
368
|
+
# @param target [Vector] vector to store the normalized vector
|
369
|
+
#
|
370
|
+
# @return [Vector] normalized vector
|
371
|
+
#
|
372
|
+
def normalize (target = nil)
|
373
|
+
(target || self).set @point.normal
|
374
|
+
end
|
375
|
+
|
376
|
+
# Changes the length of the vector if it's length is greater than the max value.
|
377
|
+
#
|
378
|
+
# @param max [Numeric] max length
|
379
|
+
#
|
380
|
+
# @return [Vector] new vector
|
381
|
+
#
|
382
|
+
def limit (max)
|
383
|
+
setMag max if magSq > max ** 2
|
384
|
+
self
|
385
|
+
end
|
386
|
+
|
387
|
+
# Returns the distance of 2 vectors.
|
388
|
+
#
|
389
|
+
# @param v [Vector] a vector
|
390
|
+
#
|
391
|
+
# @return [Numeric] the distance
|
392
|
+
#
|
393
|
+
def dist (v)
|
394
|
+
(self - v).mag
|
395
|
+
end
|
396
|
+
|
397
|
+
# Returns the distance of 2 vectors.
|
398
|
+
#
|
399
|
+
# @param v1 [Vector] a vector
|
400
|
+
# @param v2 [Vector] another vector
|
401
|
+
#
|
402
|
+
# @return [Numeric] the distance
|
403
|
+
#
|
404
|
+
def self.dist (v1, v2)
|
405
|
+
v1.dist v2
|
406
|
+
end
|
407
|
+
|
408
|
+
# Calculates the dot product of 2 vectors.
|
409
|
+
#
|
410
|
+
# @overload dot(v)
|
411
|
+
# @overload dot(x, y)
|
412
|
+
# @overload dot(x, y, z)
|
413
|
+
#
|
414
|
+
# @param v [Vector] a vector
|
415
|
+
# @param x [Numeric] x of vector
|
416
|
+
# @param y [Numeric] y of vector
|
417
|
+
# @param z [Numeric] z of vector
|
418
|
+
#
|
419
|
+
# @return [Numeric] result of dot product
|
420
|
+
#
|
421
|
+
def dot (*args)
|
422
|
+
Rays::Point::dot getInternal__, toVector__(*args).getInternal__
|
423
|
+
end
|
424
|
+
|
425
|
+
# Calculates the dot product of 2 vectors.
|
426
|
+
#
|
427
|
+
# @param v1 [Vector] a vector
|
428
|
+
# @param v2 [Vector] another vector
|
429
|
+
#
|
430
|
+
# @return [Numeric] result of dot product
|
431
|
+
#
|
432
|
+
def self.dot (v1, v2)
|
433
|
+
v1.dot v2
|
434
|
+
end
|
435
|
+
|
436
|
+
# Calculates the cross product of 2 vectors.
|
437
|
+
#
|
438
|
+
# @overload cross(v)
|
439
|
+
# @overload cross(x, y)
|
440
|
+
# @overload cross(x, y, z)
|
441
|
+
#
|
442
|
+
# @param v [Vector] a vector
|
443
|
+
# @param x [Numeric] x of vector
|
444
|
+
# @param y [Numeric] y of vector
|
445
|
+
# @param z [Numeric] z of vector
|
446
|
+
#
|
447
|
+
# @return [Numeric] result of cross product
|
448
|
+
#
|
449
|
+
def cross (a, *rest)
|
450
|
+
target = self.class === rest.last ? rest.pop : nil
|
451
|
+
v = self.class.new Rays::Point::cross getInternal__, toVector__(a, *rest).getInternal__
|
452
|
+
target.set v if self.class === target
|
453
|
+
v
|
454
|
+
end
|
455
|
+
|
456
|
+
# Calculates the cross product of 2 vectors.
|
457
|
+
#
|
458
|
+
# @param v1 [Vector] a vector
|
459
|
+
# @param v2 [Vector] another vector
|
460
|
+
#
|
461
|
+
# @return [Numeric] result of cross product
|
462
|
+
#
|
463
|
+
def self.cross (v1, v2, target = nil)
|
464
|
+
v1.cross v2, target
|
465
|
+
end
|
466
|
+
|
467
|
+
# Rotate the vector.
|
468
|
+
#
|
469
|
+
# @param angle [Numeric] the angle of rotation
|
470
|
+
#
|
471
|
+
# @return [Vector] rotated this object
|
472
|
+
#
|
473
|
+
def rotate (angle)
|
474
|
+
angle = @context ? @context.toAngle__(angle) : angle * RAD2DEG__
|
475
|
+
@point.rotate! angle
|
476
|
+
self
|
477
|
+
end
|
478
|
+
|
479
|
+
# Returns the angle of rotation for this vector.
|
480
|
+
#
|
481
|
+
# @return [Numeric] the angle in radians
|
482
|
+
#
|
483
|
+
def heading ()
|
484
|
+
Math.atan2 y, x
|
485
|
+
end
|
486
|
+
|
487
|
+
# Returns rotated new vector.
|
488
|
+
#
|
489
|
+
# @param angle [Numeric] the angle of rotation
|
490
|
+
# @param target [Vector] vector to store new vector
|
491
|
+
#
|
492
|
+
# @return [Vector] rotated vector
|
493
|
+
#
|
494
|
+
def self.fromAngle (angle, target = nil)
|
495
|
+
v = self.new(1, 0, 0).rotate(angle)
|
496
|
+
target.set v if target
|
497
|
+
v
|
498
|
+
end
|
499
|
+
|
500
|
+
# Returns angle between 2 vectors.
|
501
|
+
#
|
502
|
+
# @param v1 [Vector] a vector
|
503
|
+
# @param v2 [Vector] another vector
|
504
|
+
#
|
505
|
+
# @return [Numeric] angle in radians
|
506
|
+
#
|
507
|
+
def self.angleBetween (v1, v2)
|
508
|
+
x1, y1, z1 = v1.array
|
509
|
+
x2, y2, z2 = v2.array
|
510
|
+
return 0 if (x1 == 0 && y1 == 0 && z1 == 0) || (x2 == 0 && y2 == 0 && z2 == 0)
|
511
|
+
|
512
|
+
x = dot(v1, v2) / (v1.mag * v2.mag)
|
513
|
+
return Math::PI if x <= -1
|
514
|
+
return 0 if x >= 1
|
515
|
+
return Math.acos x
|
516
|
+
end
|
517
|
+
|
518
|
+
# Returns a new 2D unit vector with a random direction.
|
519
|
+
#
|
520
|
+
# @param target [Vector] a vector to store the new vector
|
521
|
+
#
|
522
|
+
# @return [Vector] a random vector
|
523
|
+
#
|
524
|
+
def self.random2D (target = nil)
|
525
|
+
v = self.fromAngle rand 0.0...(Math::PI * 2)
|
526
|
+
target.set v if target
|
527
|
+
v
|
528
|
+
end
|
529
|
+
|
530
|
+
# Returns a new 3D unit vector with a random direction.
|
531
|
+
#
|
532
|
+
# @param target [Vector] a vector to store the new vector
|
533
|
+
#
|
534
|
+
# @return [Vector] a random vector
|
535
|
+
#
|
536
|
+
def self.random3D (target = nil)
|
537
|
+
angle = rand 0.0...(Math::PI * 2)
|
538
|
+
z = rand -1.0..1.0
|
539
|
+
z2 = z ** 2
|
540
|
+
x = Math.sqrt(1.0 - z2) * Math.cos(angle)
|
541
|
+
y = Math.sqrt(1.0 - z2) * Math.sin(angle)
|
542
|
+
v = self.new x, y, z
|
543
|
+
target.set v if target
|
544
|
+
v
|
545
|
+
end
|
546
|
+
|
547
|
+
# @private
|
548
|
+
def inspect ()
|
549
|
+
"<##{self.class.name} #{x}, #{y}, #{z}>"
|
550
|
+
end
|
551
|
+
|
552
|
+
# @private
|
553
|
+
def <=> (o)
|
554
|
+
@point <=> o.getInternal__
|
555
|
+
end
|
556
|
+
|
557
|
+
# @private
|
558
|
+
protected def getInternal__ ()
|
559
|
+
@point
|
560
|
+
end
|
561
|
+
|
562
|
+
# @private
|
563
|
+
private def toVector__ (*args)
|
564
|
+
self.class === args.first ? args.first : self.class.new(*args)
|
565
|
+
end
|
566
|
+
|
567
|
+
end# Vector
|
568
|
+
|
569
|
+
|
9
570
|
# Image object.
|
10
571
|
#
|
11
572
|
class Image
|
12
573
|
|
13
574
|
# @private
|
14
575
|
def initialize (image)
|
15
|
-
@
|
576
|
+
@image = image
|
16
577
|
end
|
17
578
|
|
18
579
|
# Gets width of image.
|
@@ -20,7 +581,7 @@ module RubySketch
|
|
20
581
|
# @return [Numeric] width of image
|
21
582
|
#
|
22
583
|
def width ()
|
23
|
-
@
|
584
|
+
@image.width
|
24
585
|
end
|
25
586
|
|
26
587
|
# Gets height of image.
|
@@ -28,7 +589,7 @@ module RubySketch
|
|
28
589
|
# @return [Numeric] height of image
|
29
590
|
#
|
30
591
|
def height ()
|
31
|
-
@
|
592
|
+
@image.height
|
32
593
|
end
|
33
594
|
|
34
595
|
# Resizes image.
|
@@ -39,8 +600,8 @@ module RubySketch
|
|
39
600
|
# @return [nil] nil
|
40
601
|
#
|
41
602
|
def resize (width, height)
|
42
|
-
@
|
43
|
-
painter.image @
|
603
|
+
@image = Rays::Image.new(width, height).paint do |painter|
|
604
|
+
painter.image @image, 0, 0, width, height
|
44
605
|
end
|
45
606
|
nil
|
46
607
|
end
|
@@ -64,7 +625,7 @@ module RubySketch
|
|
64
625
|
#
|
65
626
|
def copy (img = nil, sx, sy, sw, sh, dx, dy, dw, dh)
|
66
627
|
img ||= self
|
67
|
-
@
|
628
|
+
@image.paint do |painter|
|
68
629
|
painter.image img.getInternal__, sx, sy, sw, sh, dx, dy, dw, dh
|
69
630
|
end
|
70
631
|
end
|
@@ -74,12 +635,12 @@ module RubySketch
|
|
74
635
|
# @param filename [String] file name to save image
|
75
636
|
#
|
76
637
|
def save (filename)
|
77
|
-
@
|
638
|
+
@image.save filename
|
78
639
|
end
|
79
640
|
|
80
641
|
# @private
|
81
642
|
def getInternal__ ()
|
82
|
-
@
|
643
|
+
@image
|
83
644
|
end
|
84
645
|
|
85
646
|
end# Image
|
@@ -143,10 +704,36 @@ module RubySketch
|
|
143
704
|
end# TextBounds
|
144
705
|
|
145
706
|
|
707
|
+
# Touch object.
|
708
|
+
#
|
709
|
+
class Touch
|
710
|
+
|
711
|
+
# Horizontal position of touch
|
712
|
+
#
|
713
|
+
attr_reader :x
|
714
|
+
|
715
|
+
# Vertical position of touch
|
716
|
+
#
|
717
|
+
attr_reader :y
|
718
|
+
|
719
|
+
# @private
|
720
|
+
def initialize (x, y)
|
721
|
+
@x, @y = x, y
|
722
|
+
end
|
723
|
+
|
724
|
+
def id ()
|
725
|
+
raise NotImplementedError
|
726
|
+
end
|
727
|
+
|
728
|
+
end# Touch
|
729
|
+
|
730
|
+
|
146
731
|
# Drawing context
|
147
732
|
#
|
148
733
|
module GraphicsContext
|
149
734
|
|
735
|
+
Vector = Processing::Vector
|
736
|
+
|
150
737
|
# PI / 2
|
151
738
|
#
|
152
739
|
HALF_PI = Math::PI / 2
|
@@ -187,7 +774,7 @@ module RubySketch
|
|
187
774
|
#
|
188
775
|
CORNERS = :CORNERS
|
189
776
|
|
190
|
-
# Mode for rectMode(), ellipseMode() and
|
777
|
+
# Mode for rectMode(), ellipseMode(), imageMode() and textAlign().
|
191
778
|
#
|
192
779
|
CENTER = :CENTER
|
193
780
|
|
@@ -195,6 +782,21 @@ module RubySketch
|
|
195
782
|
#
|
196
783
|
RADIUS = :RADIUS
|
197
784
|
|
785
|
+
# Mode for textAlign().
|
786
|
+
LEFT = :LEFT
|
787
|
+
|
788
|
+
# Mode for textAlign().
|
789
|
+
RIGHT = :RIGHT
|
790
|
+
|
791
|
+
# Mode for textAlign().
|
792
|
+
TOP = :TOP
|
793
|
+
|
794
|
+
# Mode for textAlign().
|
795
|
+
BOTTOM = :BOTTOM
|
796
|
+
|
797
|
+
# Mode for textAlign().
|
798
|
+
BASELINE = :BASELINE
|
799
|
+
|
198
800
|
# Mode for strokeCap().
|
199
801
|
#
|
200
802
|
BUTT = :butt
|
@@ -211,7 +813,10 @@ module RubySketch
|
|
211
813
|
#
|
212
814
|
SQUARE = :square
|
213
815
|
|
214
|
-
def setup__ ()
|
816
|
+
def setup__ (painter)
|
817
|
+
@painter__ = painter
|
818
|
+
@painter__.miter_limit = 10
|
819
|
+
|
215
820
|
@drawing = false
|
216
821
|
@hsbColor__ = false
|
217
822
|
@colorMaxes__ = [1.0] * 4
|
@@ -219,6 +824,8 @@ module RubySketch
|
|
219
824
|
@rectMode__ = nil
|
220
825
|
@ellipseMode__ = nil
|
221
826
|
@imageMode__ = nil
|
827
|
+
@textAlignH__ = nil
|
828
|
+
@textAlignV__ = nil
|
222
829
|
@matrixStack__ = []
|
223
830
|
@styleStack__ = []
|
224
831
|
|
@@ -227,6 +834,10 @@ module RubySketch
|
|
227
834
|
rectMode CORNER
|
228
835
|
ellipseMode CENTER
|
229
836
|
imageMode CORNER
|
837
|
+
textAlign LEFT
|
838
|
+
|
839
|
+
fill 255
|
840
|
+
stroke 0
|
230
841
|
end
|
231
842
|
|
232
843
|
def beginDraw ()
|
@@ -264,10 +875,11 @@ module RubySketch
|
|
264
875
|
# @return [nil] nil
|
265
876
|
#
|
266
877
|
def colorMode (mode, *maxes)
|
878
|
+
mode = mode.upcase.to_sym
|
267
879
|
raise ArgumentError, "invalid color mode: #{mode}" unless [RGB, HSB].include?(mode)
|
268
880
|
raise ArgumentError unless [0, 1, 3, 4].include?(maxes.size)
|
269
881
|
|
270
|
-
@hsbColor__ = mode
|
882
|
+
@hsbColor__ = mode == HSB
|
271
883
|
case maxes.size
|
272
884
|
when 1 then @colorMaxes__ = [maxes.first.to_f] * 4
|
273
885
|
when 3, 4 then @colorMaxes__[0...maxes.size] = maxes.map &:to_f
|
@@ -311,8 +923,8 @@ module RubySketch
|
|
311
923
|
# @return [nil] nil
|
312
924
|
#
|
313
925
|
def angleMode (mode)
|
314
|
-
@angleScale__ = case mode
|
315
|
-
when RADIANS then
|
926
|
+
@angleScale__ = case mode.upcase.to_sym
|
927
|
+
when RADIANS then RAD2DEG__
|
316
928
|
when DEGREES then 1.0
|
317
929
|
else raise ArgumentError, "invalid angle mode: #{mode}"
|
318
930
|
end
|
@@ -320,7 +932,7 @@ module RubySketch
|
|
320
932
|
end
|
321
933
|
|
322
934
|
# @private
|
323
|
-
|
935
|
+
def toAngle__ (angle)
|
324
936
|
angle * @angleScale__
|
325
937
|
end
|
326
938
|
|
@@ -479,26 +1091,49 @@ module RubySketch
|
|
479
1091
|
# Sets font.
|
480
1092
|
#
|
481
1093
|
# @param name [String] font name
|
482
|
-
# @param size [Numeric] font size
|
1094
|
+
# @param size [Numeric] font size (max 256)
|
483
1095
|
#
|
484
1096
|
# @return [Font] current font
|
485
1097
|
#
|
486
1098
|
def textFont (name = nil, size = nil)
|
487
|
-
|
1099
|
+
setFont__ name, size if name || size
|
488
1100
|
Font.new @painter__.font
|
489
1101
|
end
|
490
1102
|
|
491
1103
|
# Sets text size.
|
492
1104
|
#
|
493
|
-
# @param size [Numeric] font size
|
1105
|
+
# @param size [Numeric] font size (max 256)
|
494
1106
|
#
|
495
1107
|
# @return [nil] nil
|
496
1108
|
#
|
497
1109
|
def textSize (size)
|
498
|
-
|
1110
|
+
setFont__ @painter__.font.name, size
|
499
1111
|
nil
|
500
1112
|
end
|
501
1113
|
|
1114
|
+
def textWidth (str)
|
1115
|
+
@painter__.font.width str
|
1116
|
+
end
|
1117
|
+
|
1118
|
+
def textAscent ()
|
1119
|
+
@painter__.font.ascent
|
1120
|
+
end
|
1121
|
+
|
1122
|
+
def textDescent ()
|
1123
|
+
@painter__.font.descent
|
1124
|
+
end
|
1125
|
+
|
1126
|
+
def textAlign (horizontal, vertical = BASELINE)
|
1127
|
+
@textAlignH__ = horizontal
|
1128
|
+
@textAlignV__ = vertical
|
1129
|
+
end
|
1130
|
+
|
1131
|
+
# @private
|
1132
|
+
def setFont__ (name, size)
|
1133
|
+
size = 256 if size && size > 256
|
1134
|
+
@painter__.font name, size
|
1135
|
+
end
|
1136
|
+
|
502
1137
|
# Clears screen.
|
503
1138
|
#
|
504
1139
|
# @overload background(str)
|
@@ -728,15 +1363,35 @@ module RubySketch
|
|
728
1363
|
#
|
729
1364
|
# @overload text(str)
|
730
1365
|
# @overload text(str, x, y)
|
1366
|
+
# @overload text(str, a, b, c, d)
|
731
1367
|
#
|
732
1368
|
# @param str [String] text to draw
|
733
1369
|
# @param x [Numeric] horizontal position of the text
|
734
1370
|
# @param y [Numeric] vertical position of the text
|
1371
|
+
# @param a [Numeric] equivalent to parameters of the rect(), see rectMode()
|
1372
|
+
# @param b [Numeric] equivalent to parameters of the rect(), see rectMode()
|
1373
|
+
# @param c [Numeric] equivalent to parameters of the rect(), see rectMode()
|
1374
|
+
# @param d [Numeric] equivalent to parameters of the rect(), see rectMode()
|
735
1375
|
#
|
736
1376
|
# @return [nil] nil
|
737
1377
|
#
|
738
|
-
def text (str, x, y)
|
1378
|
+
def text (str, x, y, x2 = nil, y2 = nil)
|
739
1379
|
assertDrawing__
|
1380
|
+
if x2
|
1381
|
+
raise ArgumentError, "missing y2 parameter" unless y2
|
1382
|
+
x, y, w, h = toXYWH__ @rectMode__, x, y, x2, y2
|
1383
|
+
case @textAlignH__
|
1384
|
+
when RIGHT then x += w - @painter__.font.width(str)
|
1385
|
+
when CENTER then x += (w - @painter__.font.width(str)) / 2
|
1386
|
+
end
|
1387
|
+
case @textAlignV__
|
1388
|
+
when BOTTOM then y += h - @painter__.font.height
|
1389
|
+
when CENTER then y += (h - @painter__.font.height) / 2
|
1390
|
+
else
|
1391
|
+
end
|
1392
|
+
else
|
1393
|
+
y -= @painter__.font.ascent
|
1394
|
+
end
|
740
1395
|
@painter__.text str, x, y
|
741
1396
|
nil
|
742
1397
|
end
|
@@ -933,12 +1588,12 @@ module RubySketch
|
|
933
1588
|
end
|
934
1589
|
|
935
1590
|
# @private
|
936
|
-
def getInternal__ ()
|
1591
|
+
private def getInternal__ ()
|
937
1592
|
@image__
|
938
1593
|
end
|
939
1594
|
|
940
1595
|
# @private
|
941
|
-
def assertDrawing__ ()
|
1596
|
+
private def assertDrawing__ ()
|
942
1597
|
raise "call beginDraw() before drawing" unless @drawing
|
943
1598
|
end
|
944
1599
|
|
@@ -952,9 +1607,8 @@ module RubySketch
|
|
952
1607
|
include GraphicsContext
|
953
1608
|
|
954
1609
|
def initialize (width, height)
|
955
|
-
|
956
|
-
@image__
|
957
|
-
@painter__ = @image__.painter
|
1610
|
+
@image__ = Rays::Image.new width, height
|
1611
|
+
setup__ @image__.painter
|
958
1612
|
end
|
959
1613
|
|
960
1614
|
def beginDraw ()
|
@@ -972,34 +1626,247 @@ module RubySketch
|
|
972
1626
|
end# Graphics
|
973
1627
|
|
974
1628
|
|
975
|
-
|
1629
|
+
# Processing context
|
1630
|
+
#
|
1631
|
+
module Context
|
1632
|
+
|
1633
|
+
include GraphicsContext, Math
|
1634
|
+
|
1635
|
+
@@context__ = nil
|
1636
|
+
|
1637
|
+
def self.context__ ()
|
1638
|
+
@@context__
|
1639
|
+
end
|
976
1640
|
|
977
1641
|
# @private
|
978
|
-
|
1642
|
+
def setup__ (window)
|
1643
|
+
@@context__ = self
|
1644
|
+
|
1645
|
+
@window__ = window
|
1646
|
+
@image__ = @window__.canvas
|
1647
|
+
super @window__.canvas_painter.paint {background 0.8}
|
1648
|
+
|
1649
|
+
@loop__ = true
|
1650
|
+
@redraw__ = false
|
1651
|
+
@frameCount__ = 0
|
1652
|
+
@mousePos__ =
|
1653
|
+
@mousePrevPos__ = Rays::Point.new 0
|
1654
|
+
@mousePressed__ = false
|
1655
|
+
@touches__ = []
|
1656
|
+
|
1657
|
+
@window__.before_draw = proc {beginDraw}
|
1658
|
+
@window__.after_draw = proc {endDraw}
|
1659
|
+
|
1660
|
+
drawFrame = -> {
|
1661
|
+
@image__ = @window__.canvas
|
1662
|
+
@painter__ = @window__.canvas_painter
|
1663
|
+
begin
|
1664
|
+
push
|
1665
|
+
@drawBlock__.call if @drawBlock__
|
1666
|
+
ensure
|
1667
|
+
pop
|
1668
|
+
@frameCount__ += 1
|
1669
|
+
end
|
1670
|
+
}
|
1671
|
+
|
1672
|
+
@window__.draw = proc do |e|
|
1673
|
+
if @loop__ || @redraw__
|
1674
|
+
@redraw__ = false
|
1675
|
+
drawFrame.call
|
1676
|
+
end
|
1677
|
+
@mousePrevPos__ = @mousePos__
|
1678
|
+
end
|
1679
|
+
|
1680
|
+
updatePointerStates = -> event, pressed = nil {
|
1681
|
+
@mousePos__ = event.pos
|
1682
|
+
@mousePressed__ = pressed if pressed != nil
|
1683
|
+
@touches__ = event.positions.map {|pos| Touch.new pos.x, pos.y}
|
1684
|
+
}
|
1685
|
+
|
1686
|
+
@window__.pointer_down = proc do |e|
|
1687
|
+
updatePointerStates.call e, true
|
1688
|
+
(@touchStartedBlock__ || @mousePressedBlock__)&.call
|
1689
|
+
end
|
1690
|
+
|
1691
|
+
@window__.pointer_up = proc do |e|
|
1692
|
+
updatePointerStates.call e, false
|
1693
|
+
(@touchEndedBlock__ || @mouseReleasedBlock__)&.call
|
1694
|
+
end
|
1695
|
+
|
1696
|
+
@window__.pointer_move = proc do |e|
|
1697
|
+
updatePointerStates.call e
|
1698
|
+
(@touchMovedBlock__ || @mouseMovedBlock__)&.call
|
1699
|
+
end
|
1700
|
+
|
1701
|
+
@window__.pointer_drag = proc do |e|
|
1702
|
+
updatePointerStates.call e
|
1703
|
+
(@touchMovedBlock__ || @mouseDraggedBlock__)&.call
|
1704
|
+
end
|
1705
|
+
end
|
1706
|
+
|
1707
|
+
# Define setup block.
|
1708
|
+
#
|
1709
|
+
def setup (&block)
|
1710
|
+
@window__.setup = block
|
1711
|
+
nil
|
1712
|
+
end
|
1713
|
+
|
1714
|
+
# Define draw block.
|
1715
|
+
#
|
1716
|
+
def draw (&block)
|
1717
|
+
@drawBlock__ = block if block
|
1718
|
+
nil
|
1719
|
+
end
|
1720
|
+
|
1721
|
+
def key (&block)
|
1722
|
+
@window__.key = block
|
1723
|
+
nil
|
1724
|
+
end
|
1725
|
+
|
1726
|
+
def mousePressed (&block)
|
1727
|
+
@mousePressedBlock__ = block if block
|
1728
|
+
@mousePressed__
|
1729
|
+
end
|
1730
|
+
|
1731
|
+
def mouseReleased (&block)
|
1732
|
+
@mouseReleasedBlock__ = block if block
|
1733
|
+
nil
|
1734
|
+
end
|
1735
|
+
|
1736
|
+
def mouseMoved (&block)
|
1737
|
+
@mouseMovedBlock__ = block if block
|
1738
|
+
nil
|
1739
|
+
end
|
1740
|
+
|
1741
|
+
def mouseDragged (&block)
|
1742
|
+
@mouseDraggedBlock__ = block if block
|
1743
|
+
nil
|
1744
|
+
end
|
1745
|
+
|
1746
|
+
def touchStarted (&block)
|
1747
|
+
@touchStartedBlock__ = block if block
|
1748
|
+
nil
|
1749
|
+
end
|
1750
|
+
|
1751
|
+
def touchEnded (&block)
|
1752
|
+
@touchEndedBlock__ = block if block
|
1753
|
+
nil
|
1754
|
+
end
|
1755
|
+
|
1756
|
+
def touchMoved (&block)
|
1757
|
+
@touchMovedBlock__ = block if block
|
1758
|
+
nil
|
1759
|
+
end
|
979
1760
|
|
980
1761
|
# @private
|
981
|
-
|
1762
|
+
private def size__ (width, height)
|
1763
|
+
raise 'size() must be called on startup or setup block' if @started__
|
982
1764
|
|
983
|
-
|
1765
|
+
@painter__.__send__ :end_paint
|
1766
|
+
@window__.__send__ :reset_canvas, width, height
|
1767
|
+
@painter__.__send__ :begin_paint
|
1768
|
+
|
1769
|
+
@auto_resize__ = false
|
1770
|
+
end
|
1771
|
+
|
1772
|
+
def windowWidth ()
|
1773
|
+
@window__.width
|
1774
|
+
end
|
1775
|
+
|
1776
|
+
def windowHeight ()
|
1777
|
+
@window__.height
|
1778
|
+
end
|
1779
|
+
|
1780
|
+
# Returns number of frames since program started.
|
984
1781
|
#
|
985
|
-
# @
|
1782
|
+
# @return [Integer] total number of frames
|
986
1783
|
#
|
987
|
-
|
1784
|
+
def frameCount ()
|
1785
|
+
@frameCount__
|
1786
|
+
end
|
1787
|
+
|
1788
|
+
# Returns number of frames per second.
|
988
1789
|
#
|
989
|
-
|
990
|
-
|
1790
|
+
# @return [Float] frames per second
|
1791
|
+
#
|
1792
|
+
def frameRate ()
|
1793
|
+
@window__.event.fps
|
991
1794
|
end
|
992
1795
|
|
993
|
-
#
|
1796
|
+
# Returns pixel density
|
994
1797
|
#
|
995
|
-
# @
|
1798
|
+
# @return [Numeric] pixel density
|
996
1799
|
#
|
997
|
-
|
1800
|
+
def displayDensity ()
|
1801
|
+
@painter__.pixel_density
|
1802
|
+
end
|
1803
|
+
|
1804
|
+
# Returns mouse x position
|
998
1805
|
#
|
999
|
-
|
1000
|
-
|
1806
|
+
# @return [Numeric] horizontal position of mouse
|
1807
|
+
#
|
1808
|
+
def mouseX ()
|
1809
|
+
@mousePos__.x
|
1810
|
+
end
|
1811
|
+
|
1812
|
+
# Returns mouse y position
|
1813
|
+
#
|
1814
|
+
# @return [Numeric] vertical position of mouse
|
1815
|
+
#
|
1816
|
+
def mouseY ()
|
1817
|
+
@mousePos__.y
|
1818
|
+
end
|
1819
|
+
|
1820
|
+
# Returns mouse x position in previous frame
|
1821
|
+
#
|
1822
|
+
# @return [Numeric] horizontal position of mouse
|
1823
|
+
#
|
1824
|
+
def pmouseX ()
|
1825
|
+
@mousePrevPos__.x
|
1001
1826
|
end
|
1002
1827
|
|
1828
|
+
# Returns mouse y position in previous frame
|
1829
|
+
#
|
1830
|
+
# @return [Numeric] vertical position of mouse
|
1831
|
+
#
|
1832
|
+
def pmouseY ()
|
1833
|
+
@mousePrevPos__.y
|
1834
|
+
end
|
1835
|
+
|
1836
|
+
# Returns array of touches
|
1837
|
+
#
|
1838
|
+
# @return [Array] Touch objects
|
1839
|
+
#
|
1840
|
+
def touches ()
|
1841
|
+
@touches__
|
1842
|
+
end
|
1843
|
+
|
1844
|
+
# Enables calling draw block on every frame.
|
1845
|
+
#
|
1846
|
+
# @return [nil] nil
|
1847
|
+
#
|
1848
|
+
def loop ()
|
1849
|
+
@loop__ = true
|
1850
|
+
end
|
1851
|
+
|
1852
|
+
# Disables calling draw block on every frame.
|
1853
|
+
#
|
1854
|
+
# @return [nil] nil
|
1855
|
+
#
|
1856
|
+
def noLoop ()
|
1857
|
+
@loop__ = false
|
1858
|
+
end
|
1859
|
+
|
1860
|
+
# Calls draw block to redraw frame.
|
1861
|
+
#
|
1862
|
+
# @return [nil] nil
|
1863
|
+
#
|
1864
|
+
def redraw ()
|
1865
|
+
@redraw__ = true
|
1866
|
+
end
|
1867
|
+
|
1868
|
+
module_function
|
1869
|
+
|
1003
1870
|
# Returns the absolute number of the value.
|
1004
1871
|
#
|
1005
1872
|
# @param value [Numeric] number
|
@@ -1193,278 +2060,186 @@ module RubySketch
|
|
1193
2060
|
value < min ? min : (value > max ? max : value)
|
1194
2061
|
end
|
1195
2062
|
|
1196
|
-
#
|
1197
|
-
#
|
1198
|
-
# @overload noise(x)
|
1199
|
-
# @overload noise(x, y)
|
1200
|
-
# @overload noise(x, y, z)
|
2063
|
+
# Converts degree to radian.
|
1201
2064
|
#
|
1202
|
-
# @param
|
1203
|
-
# @param y [Numeric] vertical point in noise space
|
1204
|
-
# @param z [Numeric] depth point in noise space
|
2065
|
+
# @param degree [Numeric] degree to convert
|
1205
2066
|
#
|
1206
|
-
# @return [Numeric]
|
2067
|
+
# @return [Numeric] radian
|
1207
2068
|
#
|
1208
|
-
def
|
1209
|
-
|
2069
|
+
def radians (degree)
|
2070
|
+
degree * DEG2RAD__
|
1210
2071
|
end
|
1211
2072
|
|
1212
|
-
#
|
2073
|
+
# Converts radian to degree.
|
1213
2074
|
#
|
1214
|
-
# @param
|
1215
|
-
# @param extension [String] type of image to load (ex. 'png')
|
2075
|
+
# @param radian [Numeric] radian to convert
|
1216
2076
|
#
|
1217
|
-
# @return [
|
2077
|
+
# @return [Numeric] degree
|
1218
2078
|
#
|
1219
|
-
def
|
1220
|
-
|
1221
|
-
Image.new Rays::Image.load filename
|
1222
|
-
end
|
1223
|
-
|
1224
|
-
# @private
|
1225
|
-
private def getImage__ (uri, ext)
|
1226
|
-
ext ||= File.extname uri
|
1227
|
-
raise "unsupported image type -- #{ext}" unless ext =~ /^\.?(png)$/i
|
1228
|
-
|
1229
|
-
tmpdir = Pathname(Dir.tmpdir) + Digest::SHA1.hexdigest(self.class.name)
|
1230
|
-
path = tmpdir + Digest::SHA1.hexdigest(uri)
|
1231
|
-
path = path.sub_ext ext
|
1232
|
-
|
1233
|
-
unless path.file?
|
1234
|
-
URI.open uri do |input|
|
1235
|
-
tmpdir.mkdir unless tmpdir.directory?
|
1236
|
-
path.open('w') do |output|
|
1237
|
-
while buf = input.read(2 ** 16)
|
1238
|
-
output.write buf
|
1239
|
-
end
|
1240
|
-
end
|
1241
|
-
end
|
1242
|
-
end
|
1243
|
-
path.to_s
|
1244
|
-
end
|
1245
|
-
|
1246
|
-
def createGraphics (width, height)
|
1247
|
-
Graphics.new width, height
|
1248
|
-
end
|
1249
|
-
|
1250
|
-
end# Utility
|
1251
|
-
|
1252
|
-
|
1253
|
-
# Processing context
|
1254
|
-
#
|
1255
|
-
module Context
|
1256
|
-
|
1257
|
-
include GraphicsContext, Utility, Math
|
1258
|
-
|
1259
|
-
# @private
|
1260
|
-
def setup__ (window)
|
1261
|
-
super()
|
1262
|
-
@loop__ = true
|
1263
|
-
@redraw__ = false
|
1264
|
-
@frameCount__ = 0
|
1265
|
-
@mouseX__ =
|
1266
|
-
@mouseY__ =
|
1267
|
-
@mousePrevX__ =
|
1268
|
-
@mousePrevY__ = 0
|
1269
|
-
@mousePressed__ = false
|
1270
|
-
|
1271
|
-
@window__ = window
|
1272
|
-
@image__ = @window__.canvas
|
1273
|
-
@painter__ = @window__.canvas_painter
|
1274
|
-
|
1275
|
-
@painter__.miter_limit = 10
|
1276
|
-
|
1277
|
-
drawFrame = -> event {
|
1278
|
-
@image__ = @window__.canvas
|
1279
|
-
@painter__ = @window__.canvas_painter
|
1280
|
-
begin
|
1281
|
-
push
|
1282
|
-
@drawBlock__.call event if @drawBlock__
|
1283
|
-
ensure
|
1284
|
-
pop
|
1285
|
-
@frameCount__ += 1
|
1286
|
-
end
|
1287
|
-
}
|
1288
|
-
|
1289
|
-
updateMouseState = -> x, y, pressed = nil {
|
1290
|
-
@mouseX__ = x
|
1291
|
-
@mouseY__ = y
|
1292
|
-
@mousePressed__ = pressed if pressed != nil
|
1293
|
-
}
|
1294
|
-
|
1295
|
-
updateMousePrevPos = -> {
|
1296
|
-
@mousePrevX__ = @mouseX__
|
1297
|
-
@mousePrevY__ = @mouseY__
|
1298
|
-
}
|
1299
|
-
|
1300
|
-
@window__.before_draw = proc {beginDraw}
|
1301
|
-
@window__.after_draw = proc {endDraw}
|
1302
|
-
|
1303
|
-
@window__.draw = proc do |e|
|
1304
|
-
if @loop__ || @redraw__
|
1305
|
-
@redraw__ = false
|
1306
|
-
drawFrame.call e
|
1307
|
-
end
|
1308
|
-
updateMousePrevPos.call
|
1309
|
-
end
|
1310
|
-
|
1311
|
-
@window__.pointer_down = proc do |e|
|
1312
|
-
updateMouseState.call e.x, e.y, true
|
1313
|
-
@mousePressedBlock__.call e if @mousePressedBlock__
|
1314
|
-
end
|
1315
|
-
|
1316
|
-
@window__.pointer_up = proc do |e|
|
1317
|
-
updateMouseState.call e.x, e.y, false
|
1318
|
-
@mouseReleasedBlock__.call e if @mouseReleasedBlock__
|
1319
|
-
end
|
1320
|
-
|
1321
|
-
@window__.pointer_move = proc do |e|
|
1322
|
-
updateMouseState.call e.x, e.y
|
1323
|
-
@mouseMovedBlock__.call e if @mouseMovedBlock__
|
1324
|
-
end
|
1325
|
-
|
1326
|
-
@window__.pointer_drag = proc do |e|
|
1327
|
-
updateMouseState.call e.x, e.y
|
1328
|
-
@mouseDraggedBlock__.call e if @mouseDraggedBlock__
|
1329
|
-
end
|
2079
|
+
def degrees (radian)
|
2080
|
+
radian * RAD2DEG__
|
1330
2081
|
end
|
1331
2082
|
|
1332
|
-
#
|
2083
|
+
# Returns the sine of an angle.
|
1333
2084
|
#
|
1334
|
-
|
1335
|
-
@window__.setup = block
|
1336
|
-
nil
|
1337
|
-
end
|
1338
|
-
|
1339
|
-
# Define draw block.
|
2085
|
+
# @param angle [Numeric] angle in radians
|
1340
2086
|
#
|
1341
|
-
|
1342
|
-
|
1343
|
-
|
1344
|
-
|
1345
|
-
|
1346
|
-
def key (&block)
|
1347
|
-
@window__.key = block
|
1348
|
-
nil
|
1349
|
-
end
|
1350
|
-
|
1351
|
-
def mousePressed (&block)
|
1352
|
-
@mousePressedBlock__ = block if block
|
1353
|
-
@mousePressed__
|
1354
|
-
end
|
1355
|
-
|
1356
|
-
def mouseReleased (&block)
|
1357
|
-
@mouseReleasedBlock__ = block if block
|
1358
|
-
nil
|
1359
|
-
end
|
1360
|
-
|
1361
|
-
def mouseMoved (&block)
|
1362
|
-
@mouseMovedBlock__ = block if block
|
1363
|
-
nil
|
1364
|
-
end
|
1365
|
-
|
1366
|
-
def mouseDragged (&block)
|
1367
|
-
@mouseDraggedBlock__ = block if block
|
1368
|
-
nil
|
1369
|
-
end
|
1370
|
-
|
1371
|
-
# @private
|
1372
|
-
private def size__ (width, height)
|
1373
|
-
raise 'size() must be called on startup or setup block' if @started__
|
1374
|
-
|
1375
|
-
@painter__.__send__ :end_paint
|
1376
|
-
@window__.__send__ :reset_canvas, width, height
|
1377
|
-
@painter__.__send__ :begin_paint
|
1378
|
-
|
1379
|
-
@auto_resize__ = false
|
1380
|
-
end
|
1381
|
-
|
1382
|
-
def windowWidth ()
|
1383
|
-
@window__.width
|
2087
|
+
# @return [Numeric] the sine
|
2088
|
+
#
|
2089
|
+
def sin (angle)
|
2090
|
+
Math.sin angle
|
1384
2091
|
end
|
1385
2092
|
|
1386
|
-
|
1387
|
-
|
2093
|
+
# Returns the cosine of an angle.
|
2094
|
+
#
|
2095
|
+
# @param angle [Numeric] angle in radians
|
2096
|
+
#
|
2097
|
+
# @return [Numeric] the cosine
|
2098
|
+
#
|
2099
|
+
def cos (angle)
|
2100
|
+
Math.cos angle
|
1388
2101
|
end
|
1389
2102
|
|
1390
|
-
# Returns
|
2103
|
+
# Returns the ratio of the sine and cosine of an angle.
|
1391
2104
|
#
|
1392
|
-
# @
|
2105
|
+
# @param angle [Numeric] angle in radians
|
1393
2106
|
#
|
1394
|
-
|
1395
|
-
|
2107
|
+
# @return [Numeric] the tangent
|
2108
|
+
#
|
2109
|
+
def tan (angle)
|
2110
|
+
Math.tan angle
|
1396
2111
|
end
|
1397
2112
|
|
1398
|
-
# Returns
|
2113
|
+
# Returns the inverse of sin().
|
1399
2114
|
#
|
1400
|
-
# @
|
2115
|
+
# @param value [Numeric] value for calculation
|
1401
2116
|
#
|
1402
|
-
|
1403
|
-
|
2117
|
+
# @return [Numeric] the arc sine
|
2118
|
+
#
|
2119
|
+
def asin (value)
|
2120
|
+
Math.asin value
|
1404
2121
|
end
|
1405
2122
|
|
1406
|
-
# Returns
|
2123
|
+
# Returns the inverse of cos().
|
1407
2124
|
#
|
1408
|
-
# @
|
2125
|
+
# @param value [Numeric] value for calculation
|
1409
2126
|
#
|
1410
|
-
|
1411
|
-
|
2127
|
+
# @return [Numeric] the arc cosine
|
2128
|
+
#
|
2129
|
+
def acos (value)
|
2130
|
+
Math.acos value
|
1412
2131
|
end
|
1413
2132
|
|
1414
|
-
# Returns
|
2133
|
+
# Returns the inverse of tan().
|
1415
2134
|
#
|
1416
|
-
# @
|
2135
|
+
# @param value [Numeric] value for valculation
|
1417
2136
|
#
|
1418
|
-
|
1419
|
-
|
2137
|
+
# @return [Numeric] the arc tangent
|
2138
|
+
#
|
2139
|
+
def atan (value)
|
2140
|
+
Math.atan value
|
1420
2141
|
end
|
1421
2142
|
|
1422
|
-
# Returns
|
2143
|
+
# Returns the angle from a specified point.
|
1423
2144
|
#
|
1424
|
-
# @
|
2145
|
+
# @param y [Numeric] y of the point
|
2146
|
+
# @param x [Numeric] x of the point
|
1425
2147
|
#
|
1426
|
-
|
1427
|
-
|
2148
|
+
# @return [Numeric] the angle in radians
|
2149
|
+
#
|
2150
|
+
def atan2 (y, x)
|
2151
|
+
Math.atan2 y, x
|
1428
2152
|
end
|
1429
2153
|
|
1430
|
-
# Returns
|
2154
|
+
# Returns the perlin noise value.
|
1431
2155
|
#
|
1432
|
-
# @
|
2156
|
+
# @overload noise(x)
|
2157
|
+
# @overload noise(x, y)
|
2158
|
+
# @overload noise(x, y, z)
|
1433
2159
|
#
|
1434
|
-
|
1435
|
-
|
2160
|
+
# @param x [Numeric] horizontal point in noise space
|
2161
|
+
# @param y [Numeric] vertical point in noise space
|
2162
|
+
# @param z [Numeric] depth point in noise space
|
2163
|
+
#
|
2164
|
+
# @return [Numeric] noise value (0.0..1.0)
|
2165
|
+
#
|
2166
|
+
def noise (x, y = 0, z = 0)
|
2167
|
+
Rays.perlin(x, y, z) / 2.0 + 0.5
|
1436
2168
|
end
|
1437
2169
|
|
1438
|
-
# Returns
|
2170
|
+
# Returns a random number in range low...high
|
1439
2171
|
#
|
1440
|
-
# @
|
2172
|
+
# @overload random(high)
|
2173
|
+
# @overload random(low, high)
|
1441
2174
|
#
|
1442
|
-
|
1443
|
-
|
2175
|
+
# @param low [Numeric] lower limit
|
2176
|
+
# @param high [Numeric] upper limit
|
2177
|
+
#
|
2178
|
+
# @return [Float] random number
|
2179
|
+
#
|
2180
|
+
def random (low = nil, high)
|
2181
|
+
rand (low || 0).to_f...high.to_f
|
1444
2182
|
end
|
1445
2183
|
|
1446
|
-
#
|
2184
|
+
# Creates a new vector.
|
1447
2185
|
#
|
1448
|
-
# @
|
2186
|
+
# @overload createVector()
|
2187
|
+
# @overload createVector(x, y)
|
2188
|
+
# @overload createVector(x, y, z)
|
1449
2189
|
#
|
1450
|
-
|
1451
|
-
|
2190
|
+
# @param x [Numeric] x of new vector
|
2191
|
+
# @param y [Numeric] y of new vector
|
2192
|
+
# @param z [Numeric] z of new vector
|
2193
|
+
#
|
2194
|
+
# @return [Vector] new vector
|
2195
|
+
#
|
2196
|
+
def createVector (*args)
|
2197
|
+
Vector.new *args
|
1452
2198
|
end
|
1453
2199
|
|
1454
|
-
#
|
2200
|
+
# Creates a new off-screen graphics context object.
|
1455
2201
|
#
|
1456
|
-
# @
|
2202
|
+
# @param width [Numeric] width of graphics image
|
2203
|
+
# @param height [Numeric] height of graphics image
|
1457
2204
|
#
|
1458
|
-
|
1459
|
-
|
2205
|
+
# @return [Graphics] graphics object
|
2206
|
+
#
|
2207
|
+
def createGraphics (width, height)
|
2208
|
+
Graphics.new width, height
|
1460
2209
|
end
|
1461
2210
|
|
1462
|
-
#
|
2211
|
+
# Loads image.
|
1463
2212
|
#
|
1464
|
-
# @
|
2213
|
+
# @param filename [String] file name to load image
|
2214
|
+
# @param extension [String] type of image to load (ex. 'png')
|
1465
2215
|
#
|
1466
|
-
|
1467
|
-
|
2216
|
+
# @return [Image] loaded image object
|
2217
|
+
#
|
2218
|
+
def loadImage (filename, extension = nil)
|
2219
|
+
filename = getImage__ filename, extension if filename =~ %r|^https?://|
|
2220
|
+
Image.new Rays::Image.load filename
|
2221
|
+
end
|
2222
|
+
|
2223
|
+
# @private
|
2224
|
+
private def getImage__ (uri, ext)
|
2225
|
+
ext ||= File.extname uri
|
2226
|
+
raise "unsupported image type -- #{ext}" unless ext =~ /^\.?(png)$/i
|
2227
|
+
|
2228
|
+
tmpdir = Pathname(Dir.tmpdir) + Digest::SHA1.hexdigest(self.class.name)
|
2229
|
+
path = tmpdir + Digest::SHA1.hexdigest(uri)
|
2230
|
+
path = path.sub_ext ext
|
2231
|
+
|
2232
|
+
unless path.file?
|
2233
|
+
URI.open uri do |input|
|
2234
|
+
tmpdir.mkdir unless tmpdir.directory?
|
2235
|
+
path.open('w') do |output|
|
2236
|
+
while buf = input.read(2 ** 16)
|
2237
|
+
output.write buf
|
2238
|
+
end
|
2239
|
+
end
|
2240
|
+
end
|
2241
|
+
end
|
2242
|
+
path.to_s
|
1468
2243
|
end
|
1469
2244
|
|
1470
2245
|
end# Context
|