geom_craft 0.0.1

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.
data/workbench/vec2.rb ADDED
@@ -0,0 +1,538 @@
1
+ require "./setup"
2
+
3
+ #+hidden: true
4
+ require "./setup"
5
+
6
+ #+title2: 短かく書けるようにする
7
+
8
+ # ```ruby
9
+ # V = Vec2
10
+ # ```
11
+
12
+ # 整数と同じぐらい手短に書きたいので、V = Vec2 として V を使いたい。
13
+
14
+ #+title2: クラスメソッド
15
+
16
+ #+title3: 生成する
17
+
18
+ V.new # => (0.0, 0.0)
19
+ V.new(3, 4) # => (3, 4)
20
+
21
+ # new は冗長なのであまり使いたくない。
22
+
23
+ #+title3: [] が使える
24
+
25
+ V[] # => (0.0, 0.0)
26
+ V[3, 4] # => (3, 4)
27
+
28
+ # 基本的に `[]` を使う。
29
+
30
+ #+title3: 要素には何でも入れられる
31
+
32
+ V[true, false] # => (true, false)
33
+ V[3, 4] # => (3, 4)
34
+ V[3.0, 4.0] # => (3.0, 4.0)
35
+ V["Left", "Right"] # => (Left, Right)
36
+
37
+ # といっても数値か論理値を想定している。
38
+ # 数値が整数なら浮動小数点に変換したりなどしない。
39
+ # でも整数が途中で浮動小数点になることはある。
40
+
41
+ #+title3: 同じ値で生成する
42
+
43
+ V.splat(3) # => (3, 3)
44
+
45
+ #+title3: 角度から生成する
46
+
47
+ v = V.from_angle(45.deg_to_rad) # => (0.7071067811865476, 0.7071067811865475)
48
+ v.angle.rad_to_deg.round # => 45
49
+
50
+ #+title3: あらかじめ決まった値で生成する
51
+
52
+ V.zero # => (0.0, 0.0)
53
+ V.one # => (1.0, 1.0)
54
+ V.neg_one # => (-1.0, -1.0)
55
+
56
+ V.nan # => (NaN, NaN)
57
+
58
+ V.max # => (Infinity, Infinity)
59
+ V.min # => (-Infinity, -Infinity)
60
+
61
+ V.x # => (1.0, 0.0)
62
+ V.neg_x # => (-1.0, 0.0)
63
+ V.y # => (0.0, 1.0)
64
+ V.neg_y # => (0.0, -1.0)
65
+
66
+ V.right # => (1.0, 0.0)
67
+ V.left # => (-1.0, 0.0)
68
+ V.down # => (0.0, 1.0)
69
+ V.up # => (0.0, -1.0)
70
+
71
+ V.axes # => [(1.0, 0.0), (0.0, 1.0)]
72
+
73
+ #+title3: 乱数で生成する
74
+
75
+ V.rand # => (0.45540195241887316, 0.8155600583050552)
76
+ V.rand(100) # => (96, 65)
77
+
78
+ # 引数は Kernel.rand と同じ
79
+
80
+ #+title3: 正規分布で生成する
81
+
82
+ V.rand_norm # => (1.3316033319284861, -0.7085766966845889)
83
+ V.rand_norm(sigma: 2) # => (2.5913164945497753, -0.3554689651945139)
84
+ V.rand_norm(mu: 100) # => (101.35469833250185, 101.08830026901417)
85
+
86
+ # - sigma → 1σ区間の幅 (初期値: 1.0)
87
+ # - mu → 中心 (初期値: 0.0)
88
+
89
+ #+title2: インスタンスメソッド
90
+
91
+ #+title3: 配列化する
92
+
93
+ V[3, 4].to_a # => [3, 4]
94
+
95
+ # 次のメソッドたちは to_a に委譲している。
96
+
97
+ #+BEGIN_SRC
98
+ v = V.one
99
+
100
+ v.each # => #<Enumerator: [1.0, 1.0]:each>
101
+ v == v # => true
102
+ v.eql?(v) # => true
103
+ v.hash # => -2591597074245692329
104
+ v <=> v # => 0
105
+ v.to_ary # => [1.0, 1.0]
106
+ v[0] # => 1.0
107
+ #+END_SRC
108
+
109
+ #+title3: Enumerable 対応
110
+
111
+ V[true, true].all? # => true
112
+ V[false, true].any? # => true
113
+ V[false, false].none? # => true
114
+ V.one.sum # => 2.0
115
+ V.one.count # => 2
116
+
117
+ #+title3: 文字列化する
118
+
119
+ V[3, 4].to_s # => "(3, 4)"
120
+
121
+ #+title3: 文字列化する (デバッグ用)
122
+
123
+ V[3, 4].inspect # => "(3, 4)"
124
+
125
+ # `[]` を使うと配列と区別がつかないため `()` を使う。
126
+
127
+ #+title3: Hash 化する
128
+
129
+ V[3, 4].to_h # => {x: 3, y: 4}
130
+ V[3, 4].to_h(prefix: "a") # => {ax: 3, ay: 4}
131
+ V[3, 4].to_h(suffix: "1") # => {x1: 3, y1: 4}
132
+
133
+ # suffix の指定で Ruby 2D のような座標をシンボルで書くタイプにも変換しやすくする。
134
+
135
+ #+hidden: true
136
+ # #+title3: 置き換える
137
+ # v = V[3, 4]
138
+ # v.object_id # => 60
139
+ # v.replace(V[7, 8])
140
+ # v # =>
141
+ # v.object_id # =>
142
+
143
+ # object_id は変わっていない。
144
+ # Value Object 化する場合は取る。
145
+
146
+ #+hidden: true
147
+ # # def scale(s)
148
+ # # self * s
149
+ # # end
150
+
151
+ #+title3: 各成分同士の最小・最大
152
+
153
+ V[3, 6].min(V[4, 5]) # => (3, 5)
154
+ V[3, 6].max(V[4, 5]) # => (4, 6)
155
+
156
+ #+title3: 指定の範囲内に入れる
157
+
158
+ V[1, 9].clamp(V[3, 3], V[4, 4]) # => (3, 4)
159
+
160
+ #+title3: 大きい方・小さい方の要素を得る
161
+
162
+ V[3, 4].min_element # => 3
163
+ V[3, 4].max_element # => 4
164
+
165
+ #+title3: 比較
166
+
167
+ v = V[3, 4]
168
+ v.cmpeq(v) # => (true, true)
169
+ v.cmpne(v) # => (false, false)
170
+ v.cmpge(v) # => (true, true)
171
+ v.cmpgt(v) # => (false, false)
172
+ v.cmple(v) # => (true, true)
173
+ v.cmplt(v) # => (false, false)
174
+
175
+ # 結果で条件分岐する場合はさらに `any?` `all?` `none?` などを呼ぶ。
176
+
177
+ #+title3: 絶対値
178
+
179
+ V[-3, -4].abs # => (3, 4)
180
+
181
+ #+title3: 符号のみを保持したベクトルを返す
182
+
183
+ V[3, -4].signum # => (1, -1)
184
+ V[-3, 4].signum # => (-1, 1)
185
+
186
+ V[3, -4].sign # => (1, -1)
187
+ V[-3, 4].sign # => (-1, 1)
188
+
189
+ #+title3: 符号のみをコピーする
190
+
191
+ V[-3, 6].copysign(V[7, -8]) # => (3, -6)
192
+
193
+ # コピーといっても破壊的ではない。
194
+
195
+ #+title3: 有限?
196
+
197
+ V[3, 4].finite? # => true
198
+
199
+ #+title3: NaN か?
200
+
201
+ V.nan.nan? # => true
202
+
203
+ #+title3: NaN の要素だけ true なベクトルを返す
204
+
205
+ V[1.0, 0.0 / 0.0].nan_mask # => (false, true)
206
+
207
+ #+title3: 二乗したときの長さ
208
+
209
+ V[3, 4].length_squared # => 25
210
+
211
+ #+title3: 長さ
212
+
213
+ V[3, 4].length # => 5.0
214
+
215
+ V[3, 4].norm # => 5.0
216
+ V[3, 4].mag # => 5.0
217
+ V[3, 4].magnitude # => 5.0
218
+
219
+ # ライブラリによってメソッド名が異なるためいろんな alias を用意している。
220
+ # Ruby の Matrix の Vector にある r は半径と誤読するため alias にしない。
221
+
222
+ #+title3: 長さの逆数
223
+
224
+ V[3, 4].length_recip # => 0.2
225
+
226
+ # これがあると割り算を掛け算に変換できる。
227
+
228
+ 100 / V[3, 4].length # => 20.0
229
+ 100 * V[3, 4].length_recip # => 20.0
230
+
231
+ #+title3: 対象との差分の長さの二乗
232
+
233
+ V[4, 5].distance_squared_to(V[1, 1]) # => 25
234
+
235
+ #+title3: 対象との差分の長さ
236
+
237
+ V[4, 5].distance_to(V[1, 1]) # => 5.0
238
+
239
+ #+title3: 正規化
240
+
241
+ V[3, 4].normalize # => (0.6000000000000001, 0.8)
242
+ V[3, 4].normalize.length # => 1.0
243
+
244
+ # 0ベクトルは正規化できない
245
+
246
+ V.zero.normalize rescue $! # => RuntimeError
247
+
248
+ #+title3: 正規化できない場合は nil を返す版
249
+
250
+ V.zero.try_normalize # => nil
251
+
252
+ #+title3: 正規化できない場合は zero を返す版
253
+
254
+ V.zero.normalize_or_zero # => (0.0, 0.0)
255
+
256
+ #+title3: 正規化してあるか?
257
+
258
+ V[3, 4].normalized? # => false
259
+ V[3, 4].normalize.normalized? # => true
260
+
261
+ #+title3: 射影
262
+
263
+ a = V[2.0, 5.0]
264
+ b = V[6.0, 3.0]
265
+
266
+ # a から b への正射影
267
+
268
+ a.project_onto(b) # => (3.6, 1.8)
269
+
270
+ # これは b を地面と考えたとき太陽視点での a の影または b を地面として垂直にジャンプした a の着地点に相当する。
271
+ # project_onto がやっていることは
272
+
273
+ # 1. 地面の方を正規化して内積を求めると影の長さが求まる
274
+ # 1. それを地面の方向に伸ばす(正規化した b だけスケールする)と位置が求まる
275
+
276
+ a.dot(b.normalize) * b.normalize # => (3.6, 1.8)
277
+
278
+ # 射影先が正規化されていればその処理を省けるので専用のメソッドがある。
279
+
280
+ a.project_onto_normalized(b.normalize) # => (3.6, 1.8)
281
+
282
+ # 射影できない場合は例外を出す
283
+
284
+ V.zero.project_onto(V.zero) rescue $! # => RuntimeError
285
+
286
+ #+title3: 垂直方向への射影
287
+
288
+ a.reject_from(b) # => (-1.6, 3.2)
289
+
290
+ # これは b を地面と考えたときの真横から強い光を当てて壁にできる影または b を地面と考えたときのジャンプした a の高さに相当する。
291
+ # これは単に `a - 着地点(a から b への投射)` でも求まる。
292
+
293
+ a - a.project_onto(b) # => (-1.6, 3.2)
294
+
295
+ # 上の射影と同様に地面が正規化されている版もある。
296
+
297
+ a.reject_from_normalized(b.normalize) # => (-1.6, 3.2)
298
+
299
+ #+title3: 小数部補正
300
+
301
+ V[3.4, 4.5].round # => (3, 5)
302
+ V[3.4, 4.5].floor # => (3, 4)
303
+ V[3.4, 4.5].ceil # => (4, 5)
304
+ V[3.4, 4.5].truncate # => (3, 4)
305
+ V[3.4, 4.5].trunc # => (3, 4)
306
+
307
+ #+title3: 小数部のみ残す
308
+
309
+ V[3.4, 4.5].fract # => (0.3999999999999999, 0.5)
310
+
311
+ #+title3: 指数関数
312
+
313
+ V[3, 4].exp # => (20.085536923187668, 54.598150033144236)
314
+ V[Math::E**3, Math::E**4] # => (20.085536923187664, 54.59815003314423)
315
+
316
+ # Math::E を参照するより exp を使った方が精度が高いらしい
317
+
318
+ #+title3: べき乗
319
+
320
+ V[3, 4]**2 # => (9, 16)
321
+ V[3, 4].pow(2) # => (9, 16)
322
+ V[3, 4].pow(2, 5) # => (4, 1)
323
+
324
+ #+title3: 逆数
325
+
326
+ V[3, 4].recip # => (0.3333333333333333, 0.25)
327
+
328
+ # 逆数を使うと割り算を掛け算に変換できる。
329
+
330
+ V.splat(100.0) / V[3, 4] # => (33.333333333333336, 25.0)
331
+ V.splat(100.0) * V[3, 4].recip # => (33.33333333333333, 25.0)
332
+
333
+ # 掛け算にすると右辺・左辺を気しなくてよくなるので逆にして
334
+
335
+ V[3, 4].recip * V.splat(100.0) # => (33.33333333333333, 25.0)
336
+
337
+ # と書ける。もし割り算だと左右を入れ替えると当然結果が変わってしまう。
338
+
339
+ V[3, 4] / V.splat(100.0) # => (0.03, 0.04)
340
+
341
+ #+title3: 線形補間
342
+
343
+ V[3, 3].lerp(V[4, 4], 0.0) # => (3.0, 3.0)
344
+ V[3, 3].lerp(V[4, 4], 0.5) # => (3.5, 3.5)
345
+ V[3, 3].lerp(V[4, 4], 1.0) # => (4.0, 4.0)
346
+
347
+ # alias
348
+
349
+ V[3, 3].mix(V[4, 4], 0.5) # => (3.5, 3.5)
350
+
351
+ #+title3: 誤差を許容した比較
352
+
353
+ V.zero.abs_diff_eq(V[0.0, 0.01], 0.00) # => false
354
+ V.zero.abs_diff_eq(V[0.0, 0.01], 0.01) # => true
355
+
356
+ #+title3: 長さ補正
357
+
358
+ V[3, 4].length # => 5.0
359
+
360
+ V[3, 4].clamp_length(6, 7) # => (3.6, 4.8)
361
+ V[3, 4].clamp_length(6, 7).length # => 6.0
362
+
363
+ V[3, 4].clamp_length_min(6) # => (3.6, 4.8)
364
+ V[3, 4].clamp_length_min(6).length # => 6.0
365
+
366
+ V[3, 4].clamp_length_max(4) # => (2.4, 3.2)
367
+ V[3, 4].clamp_length_max(4).length # => 4.0
368
+
369
+ # 長さを指定して new したいとき:
370
+
371
+ V.one.clamp_length_min(5) # => (3.5355339059327373, 3.5355339059327373)
372
+
373
+ #+title3: 指定のベクトルの倍数の近い方に四捨五入で合わせる
374
+
375
+ V[5.0, 14.0].snapped(V[10.0, 10.0]) # => (10.0, 10.0)
376
+
377
+ #+title3: 2点間の角度差
378
+
379
+ a = V[2.0, 0.0]
380
+ b = V[1.0, 0.0]
381
+ b.angle_to(a) # => 0.0
382
+ b.angle_between(a) # => 0.0
383
+ a.angle - b.angle # => 0.0
384
+
385
+ #+title3: 自分から相手を見たときの角度
386
+
387
+ a = V[2.0, 0.0]
388
+ b = V[1.0, 0.0]
389
+ a.angle_to_point(b) # => 3.141592653589793
390
+
391
+ # 両方を位置ベクトルと見なしたときの a から b 方向への角度を返す。
392
+
393
+ #+title3: 角度
394
+
395
+ V[2, 2].angle # => 0.7853981633974483
396
+
397
+ #+title3: 回転
398
+
399
+ v0 = V.from_angle(30.deg_to_rad) * 100
400
+
401
+ # 30度(長さ100)のベクトルを60度回転して90度になる例:
402
+
403
+ v1 = v0.rotate(60.deg_to_rad)
404
+ v1.round(2) # => (0.0, 100.0)
405
+ v1.angle.rad_to_deg.round # => 90
406
+ v1.length # => 100.0
407
+
408
+ # rotate には方向ベクトルを渡してもよい。
409
+
410
+ v1 = v0.rotate(V.from_angle(60.deg_to_rad))
411
+ v1.round # => (0, 100)
412
+
413
+ # 回転される側の方向に角度を足して再度生成する方法もある。
414
+
415
+ v1 = V.from_angle(v0.angle + 60.deg_to_rad) * v0.length
416
+ v1.round(2) # => (0.0, 100.0)
417
+ v1.angle.rad_to_deg.round # => 90
418
+ v1.length # => 100.0
419
+
420
+ # それを簡単にしたのが rotate_angle_add になる。
421
+
422
+ v1 = v0.rotate_angle_add(60.deg_to_rad)
423
+ v1.round(2) # => (0.0, 100.0)
424
+ v1.angle.rad_to_deg.round # => 90
425
+ v1.length # => 100.0
426
+
427
+ # 後者は glam のメソッドにはなかったが glam の方法より速かったので入れてある。
428
+
429
+ #+title3: 内積
430
+
431
+ V[2, 3].dot(V[4, 5]) # => 23
432
+ V[2, 3].inner_product(V[4, 5]) # => 23
433
+ 2 * 4 + 3 * 5 # => 23
434
+
435
+ # - a.dot(b) → a.x * b.x + a.y * b.y
436
+ # - 底辺 = 斜辺.dot(地面.normalize)
437
+
438
+ #+title3: 外積
439
+
440
+ V[2, 3].cross(V[4, 5]) # => -2
441
+ V[2, 3].perp_dot(V[4, 5]) # => -2
442
+ V[2, 3].outer_product(V[4, 5]) # => -2
443
+ 2 * 5 - 4 * 3 # => -2
444
+
445
+ # - a.cross(b) → a.x * b.y - a.y * b.x
446
+ # - 対辺 = 地面.normalize.cross(斜辺)
447
+
448
+ #+title3: 法線
449
+
450
+ V[2, 3].perp # => (-3, 2)
451
+ V[2, 3].right90 # => (-3, 2)
452
+
453
+ #+title3: 法線の逆向き
454
+
455
+ V[2, 3].left90 # => (3, -2)
456
+
457
+ # left right の動作が画面下方向を正とする座標系に依存しているのがちょっと気持ち悪い。
458
+
459
+ #+title3: 壁ずり・反射・鏡像ベクトル
460
+
461
+ a = V[600.0, 340.0]
462
+ b = V[200.0, 60.0]
463
+ c = V[360.0, 52.0]
464
+ d = V[400.0, 200.0]
465
+ n = (b - a).perp.normalize # => (0.5734623443633283, -0.8192319205190405)
466
+ speed = d - c # => (40.0, 148.0)
467
+ speed.slide(n) # => (96.37583892617451, 67.46308724832214)
468
+ speed.bounce(n) # => (152.75167785234902, -13.073825503355721)
469
+ speed.reflect(n) # => (-152.75167785234902, 13.073825503355721)
470
+
471
+ # 引数には法線の正規化を渡す。
472
+
473
+ #+title3: 演算
474
+
475
+ v0 = V[2, 3]
476
+ v1 = V[4, 5]
477
+
478
+ # 演算子
479
+
480
+ v0 + v1 # => (6, 8)
481
+ v0 - v1 # => (-2, -2)
482
+ v0 * v1 # => (8, 15)
483
+ v0 / v1 # => (0, 0)
484
+ v0 % v1 # => (2, 3)
485
+ -v0 # => (-2, -3)
486
+ +v0 # => (2, 3)
487
+
488
+ # メソッド版
489
+
490
+ v0.add(v1) # => (6, 8)
491
+ v0.sub(v1) # => (-2, -2)
492
+ v0.mul(v1) # => (8, 15)
493
+ v0.div(v1) # => (0, 0)
494
+ v0.fdiv(v1) # => (0.5, 0.6)
495
+ v0.ceildiv(v1) # => (1, 1)
496
+ v0.modulo(v1) # => (2, 3)
497
+ v0.neg # => (-2, -3)
498
+
499
+ # `/` と `div` と `fdiv` は数値に対する実行と同じで微妙に結果が異なる。
500
+
501
+ #+title3: 要素入れ替え
502
+
503
+ V.x.xy # => (1.0, 0.0)
504
+ V.x.yx # => (0.0, 1.0)
505
+ V.x.xx # => (1.0, 1.0)
506
+ V.x.yy # => (0.0, 0.0)
507
+
508
+ #+title3: 中央
509
+
510
+ v0 = V.one.clamp_length_min(5)
511
+ v0.length # => 5.0
512
+
513
+ v0.center.length # => 2.5
514
+
515
+ v0.middle.length # => 2.5
516
+
517
+ # alias として middle もある。
518
+
519
+ #+title3: 位置ベクトルと見なしたとき対象が含まれるか?
520
+
521
+ v0 = V[3, 4]
522
+ v1 = V[4, 5]
523
+ v0.cover?(v1) # => false
524
+ v0.cover?(v1, padding: 1) # => true
525
+
526
+ # v0 の先端との当たり判定を行いたいときに用いる。
527
+
528
+ #+title3: 配列のようにソートできる
529
+
530
+ [V[3, 4], V[1, 2]].sort # => [(1, 2), (3, 4)]
531
+
532
+ #+title3: 中身が似ていればハッシュキーは同じ
533
+
534
+ V[3, 4].hash # => -249668369487262050
535
+ V[3, 4].hash # => -249668369487262050
536
+ V[3, 4].eql?(V[3, 4]) # => true
537
+ h = { V[3, 4] => true } # => {(3, 4) => true}
538
+ h[V[3, 4]] # => true
metadata ADDED
@@ -0,0 +1,110 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: geom_craft
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - akicho8
8
+ bindir: bin
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: rake
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: '0'
19
+ type: :development
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: '0'
26
+ - !ruby/object:Gem::Dependency
27
+ name: rspec
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ - !ruby/object:Gem::Dependency
41
+ name: test-unit
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ type: :development
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ description: This is a Ruby library inspired by the Rect and 2D vector libraries used
55
+ in the Rust Nannou framework
56
+ email:
57
+ - akicho8@gmail.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - ".gitignore"
63
+ - ".rspec"
64
+ - Gemfile
65
+ - LICENSE.txt
66
+ - README.md
67
+ - Rakefile
68
+ - geom_craft.gemspec
69
+ - lib/geom_craft.rb
70
+ - lib/geom_craft/core_ext.rb
71
+ - lib/geom_craft/core_ext/math.rb
72
+ - lib/geom_craft/core_ext/numeric.rb
73
+ - lib/geom_craft/rand_norm.rb
74
+ - lib/geom_craft/range2.rb
75
+ - lib/geom_craft/rect.rb
76
+ - lib/geom_craft/top_level_bind.rb
77
+ - lib/geom_craft/vec2.rb
78
+ - lib/geom_craft/version.rb
79
+ - spec/geom_craft_spec.rb
80
+ - spec/spec_helper.rb
81
+ - workbench/core_ext.rb
82
+ - workbench/range2.rb
83
+ - workbench/rect.rb
84
+ - workbench/setup.rb
85
+ - workbench/vec2.rb
86
+ homepage: ''
87
+ licenses:
88
+ - MIT
89
+ metadata: {}
90
+ rdoc_options: []
91
+ require_paths:
92
+ - lib
93
+ required_ruby_version: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ required_rubygems_version: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ requirements: []
104
+ rubygems_version: 3.6.7
105
+ specification_version: 4
106
+ summary: This is a Ruby library inspired by the Rect and 2D vector libraries used
107
+ in the Rust Nannou framework
108
+ test_files:
109
+ - spec/geom_craft_spec.rb
110
+ - spec/spec_helper.rb