larb 0.1.0 → 1.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +13 -1
- data/README.md +63 -1
- data/ext/larb/color.c +449 -0
- data/ext/larb/color.h +35 -0
- data/ext/larb/extconf.rb +11 -0
- data/ext/larb/larb.c +27 -0
- data/ext/larb/larb.h +31 -0
- data/ext/larb/mat2.c +303 -0
- data/ext/larb/mat2.h +30 -0
- data/ext/larb/mat2d.c +397 -0
- data/ext/larb/mat2d.h +35 -0
- data/ext/larb/mat3.c +455 -0
- data/ext/larb/mat3.h +33 -0
- data/ext/larb/mat4.c +651 -0
- data/ext/larb/mat4.h +31 -0
- data/ext/larb/matrix_utils.h +97 -0
- data/ext/larb/quat.c +567 -0
- data/ext/larb/quat.h +39 -0
- data/ext/larb/quat2.c +511 -0
- data/ext/larb/quat2.h +39 -0
- data/ext/larb/vec2.c +365 -0
- data/ext/larb/vec2.h +43 -0
- data/ext/larb/vec3.c +538 -0
- data/ext/larb/vec3.h +52 -0
- data/ext/larb/vec4.c +361 -0
- data/ext/larb/vec4.h +38 -0
- data/lib/larb/version.rb +5 -0
- data/lib/larb.rb +2 -14
- data/test/larb/color_test.rb +299 -0
- data/test/larb/mat2_test.rb +144 -0
- data/test/larb/mat2d_test.rb +197 -0
- data/test/larb/mat3_test.rb +147 -0
- data/test/larb/mat4_test.rb +347 -0
- data/test/larb/matrix_test.rb +135 -0
- data/test/larb/native_value_test.rb +157 -0
- data/test/larb/quat2_test.rb +254 -0
- data/test/larb/quat_test.rb +284 -0
- data/test/larb/vec2_test.rb +274 -0
- data/test/larb/vec3_test.rb +373 -0
- data/test/larb/vec4_test.rb +196 -0
- data/test/test_helper.rb +4 -0
- metadata +60 -18
- data/Rakefile +0 -11
- data/lib/larb/color.rb +0 -148
- data/lib/larb/mat2.rb +0 -119
- data/lib/larb/mat2d.rb +0 -180
- data/lib/larb/mat3.rb +0 -238
- data/lib/larb/mat4.rb +0 -329
- data/lib/larb/quat.rb +0 -238
- data/lib/larb/quat2.rb +0 -193
- data/lib/larb/vec2.rb +0 -150
- data/lib/larb/vec3.rb +0 -218
- data/lib/larb/vec4.rb +0 -125
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../test_helper"
|
|
4
|
+
|
|
5
|
+
class ColorTest < Test::Unit::TestCase
|
|
6
|
+
def test_bytes_clamp_before_integer_conversion
|
|
7
|
+
[1e8, 1e300, Float::INFINITY].each do |large|
|
|
8
|
+
assert_equal [255, 0, 128, 255], Larb::Color.new(large, -large, 0.5, 1).to_bytes
|
|
9
|
+
assert_equal "#ff0080ff", Larb::Color.new(large, -large, 0.5, 1).to_hex
|
|
10
|
+
end
|
|
11
|
+
4.times do |i|
|
|
12
|
+
values = [0, 0, 0, 1]
|
|
13
|
+
values[i] = Float::NAN
|
|
14
|
+
assert_raise(ArgumentError) { Larb::Color.new(*values).to_bytes }
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def test_from_hex_validates_the_entire_string
|
|
19
|
+
["#gg0000", "#ff0000zz", "#ff0000ffjunk", "f#f0000", "", "#fff",
|
|
20
|
+
"#ffff", " ff0000", "#ff0000\n", "ff0000\0", "#ff0000"].each do |hex|
|
|
21
|
+
assert_raise(ArgumentError, hex.inspect) { Larb::Color.from_hex(hex) }
|
|
22
|
+
end
|
|
23
|
+
assert_raise(TypeError) { Larb::Color.from_hex(nil) }
|
|
24
|
+
assert_equal [255, 128, 0, 170], Larb::Color.from_hex("#FF8000aA").to_bytes
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def test_new_with_default_values
|
|
28
|
+
c = Larb::Color.new
|
|
29
|
+
assert_equal 0.0, c.r
|
|
30
|
+
assert_equal 0.0, c.g
|
|
31
|
+
assert_equal 0.0, c.b
|
|
32
|
+
assert_equal 1.0, c.a
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def test_new_with_given_values
|
|
36
|
+
c = Larb::Color.new(0.1, 0.2, 0.3, 0.4)
|
|
37
|
+
assert_equal 0.1, c.r
|
|
38
|
+
assert_equal 0.2, c.g
|
|
39
|
+
assert_equal 0.3, c.b
|
|
40
|
+
assert_equal 0.4, c.a
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def test_bracket_syntax
|
|
44
|
+
c = Larb::Color[0.1, 0.2, 0.3, 0.4]
|
|
45
|
+
assert_equal 0.1, c.r
|
|
46
|
+
assert_equal 0.2, c.g
|
|
47
|
+
assert_equal 0.3, c.b
|
|
48
|
+
assert_equal 0.4, c.a
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def test_bracket_syntax_default_alpha
|
|
52
|
+
c = Larb::Color[0.1, 0.2, 0.3]
|
|
53
|
+
assert_equal 1.0, c.a
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def test_rgb
|
|
57
|
+
c = Larb::Color.rgb(0.5, 0.6, 0.7)
|
|
58
|
+
assert_equal 0.5, c.r
|
|
59
|
+
assert_equal 0.6, c.g
|
|
60
|
+
assert_equal 0.7, c.b
|
|
61
|
+
assert_equal 1.0, c.a
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def test_rgba
|
|
65
|
+
c = Larb::Color.rgba(0.1, 0.2, 0.3, 0.4)
|
|
66
|
+
assert_equal 0.1, c.r
|
|
67
|
+
assert_equal 0.2, c.g
|
|
68
|
+
assert_equal 0.3, c.b
|
|
69
|
+
assert_equal 0.4, c.a
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def test_from_bytes
|
|
73
|
+
c = Larb::Color.from_bytes(255, 128, 0, 255)
|
|
74
|
+
assert_equal 1.0, c.r
|
|
75
|
+
assert_in_delta 0.5, c.g, 0.01
|
|
76
|
+
assert_equal 0.0, c.b
|
|
77
|
+
assert_equal 1.0, c.a
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def test_from_bytes_default_alpha
|
|
81
|
+
c = Larb::Color.from_bytes(255, 0, 0)
|
|
82
|
+
assert_equal 1.0, c.a
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def test_from_hex
|
|
86
|
+
c = Larb::Color.from_hex("#ff8000")
|
|
87
|
+
assert_equal 1.0, c.r
|
|
88
|
+
assert_in_delta 0.5, c.g, 0.01
|
|
89
|
+
assert_equal 0.0, c.b
|
|
90
|
+
assert_equal 1.0, c.a
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def test_from_hex_without_hash
|
|
94
|
+
c = Larb::Color.from_hex("ff0000")
|
|
95
|
+
assert_equal 1.0, c.r
|
|
96
|
+
assert_equal 0.0, c.g
|
|
97
|
+
assert_equal 0.0, c.b
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def test_from_hex_with_alpha
|
|
101
|
+
c = Larb::Color.from_hex("#ff000080")
|
|
102
|
+
assert_equal 1.0, c.r
|
|
103
|
+
assert_in_delta 0.5, c.a, 0.01
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def test_black
|
|
107
|
+
c = Larb::Color.black
|
|
108
|
+
assert_equal 0.0, c.r
|
|
109
|
+
assert_equal 0.0, c.g
|
|
110
|
+
assert_equal 0.0, c.b
|
|
111
|
+
assert_equal 1.0, c.a
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def test_white
|
|
115
|
+
c = Larb::Color.white
|
|
116
|
+
assert_equal 1.0, c.r
|
|
117
|
+
assert_equal 1.0, c.g
|
|
118
|
+
assert_equal 1.0, c.b
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def test_red
|
|
122
|
+
c = Larb::Color.red
|
|
123
|
+
assert_equal 1.0, c.r
|
|
124
|
+
assert_equal 0.0, c.g
|
|
125
|
+
assert_equal 0.0, c.b
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def test_green
|
|
129
|
+
c = Larb::Color.green
|
|
130
|
+
assert_equal 0.0, c.r
|
|
131
|
+
assert_equal 1.0, c.g
|
|
132
|
+
assert_equal 0.0, c.b
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def test_blue
|
|
136
|
+
c = Larb::Color.blue
|
|
137
|
+
assert_equal 0.0, c.r
|
|
138
|
+
assert_equal 0.0, c.g
|
|
139
|
+
assert_equal 1.0, c.b
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def test_yellow
|
|
143
|
+
c = Larb::Color.yellow
|
|
144
|
+
assert_equal 1.0, c.r
|
|
145
|
+
assert_equal 1.0, c.g
|
|
146
|
+
assert_equal 0.0, c.b
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def test_cyan
|
|
150
|
+
c = Larb::Color.cyan
|
|
151
|
+
assert_equal 0.0, c.r
|
|
152
|
+
assert_equal 1.0, c.g
|
|
153
|
+
assert_equal 1.0, c.b
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def test_magenta
|
|
157
|
+
c = Larb::Color.magenta
|
|
158
|
+
assert_equal 1.0, c.r
|
|
159
|
+
assert_equal 0.0, c.g
|
|
160
|
+
assert_equal 1.0, c.b
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def test_transparent
|
|
164
|
+
c = Larb::Color.transparent
|
|
165
|
+
assert_equal 0.0, c.r
|
|
166
|
+
assert_equal 0.0, c.g
|
|
167
|
+
assert_equal 0.0, c.b
|
|
168
|
+
assert_equal 0.0, c.a
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def test_add
|
|
172
|
+
c1 = Larb::Color.new(0.1, 0.2, 0.3, 0.4)
|
|
173
|
+
c2 = Larb::Color.new(0.2, 0.3, 0.4, 0.5)
|
|
174
|
+
result = c1 + c2
|
|
175
|
+
assert_in_delta 0.3, result.r, 1e-10
|
|
176
|
+
assert_in_delta 0.5, result.g, 1e-10
|
|
177
|
+
assert_in_delta 0.7, result.b, 1e-10
|
|
178
|
+
assert_in_delta 0.9, result.a, 1e-10
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
def test_subtract
|
|
182
|
+
c1 = Larb::Color.new(0.5, 0.6, 0.7, 0.8)
|
|
183
|
+
c2 = Larb::Color.new(0.1, 0.2, 0.3, 0.4)
|
|
184
|
+
result = c1 - c2
|
|
185
|
+
assert_in_delta 0.4, result.r, 1e-10
|
|
186
|
+
assert_in_delta 0.4, result.g, 1e-10
|
|
187
|
+
assert_in_delta 0.4, result.b, 1e-10
|
|
188
|
+
assert_in_delta 0.4, result.a, 1e-10
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
def test_multiply_by_scalar
|
|
192
|
+
c = Larb::Color.new(0.2, 0.3, 0.4, 0.5)
|
|
193
|
+
result = c * 2
|
|
194
|
+
assert_in_delta 0.4, result.r, 1e-10
|
|
195
|
+
assert_in_delta 0.6, result.g, 1e-10
|
|
196
|
+
assert_in_delta 0.8, result.b, 1e-10
|
|
197
|
+
assert_in_delta 1.0, result.a, 1e-10
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
def test_multiply_by_color
|
|
201
|
+
c1 = Larb::Color.new(0.5, 0.5, 0.5, 1.0)
|
|
202
|
+
c2 = Larb::Color.new(1.0, 0.5, 0.0, 1.0)
|
|
203
|
+
result = c1 * c2
|
|
204
|
+
assert_in_delta 0.5, result.r, 1e-10
|
|
205
|
+
assert_in_delta 0.25, result.g, 1e-10
|
|
206
|
+
assert_equal 0.0, result.b
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
def test_lerp
|
|
210
|
+
c1 = Larb::Color.new(0, 0, 0, 0)
|
|
211
|
+
c2 = Larb::Color.new(1, 1, 1, 1)
|
|
212
|
+
result = c1.lerp(c2, 0.5)
|
|
213
|
+
assert_equal 0.5, result.r
|
|
214
|
+
assert_equal 0.5, result.g
|
|
215
|
+
assert_equal 0.5, result.b
|
|
216
|
+
assert_equal 0.5, result.a
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
def test_clamp
|
|
220
|
+
c = Larb::Color.new(-0.5, 1.5, 0.5, 2.0)
|
|
221
|
+
result = c.clamp
|
|
222
|
+
assert_equal 0.0, result.r
|
|
223
|
+
assert_equal 1.0, result.g
|
|
224
|
+
assert_equal 0.5, result.b
|
|
225
|
+
assert_equal 1.0, result.a
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
def test_to_bytes
|
|
229
|
+
c = Larb::Color.new(1.0, 0.5, 0.0, 1.0)
|
|
230
|
+
bytes = c.to_bytes
|
|
231
|
+
assert_equal 255, bytes[0]
|
|
232
|
+
assert_equal 128, bytes[1]
|
|
233
|
+
assert_equal 0, bytes[2]
|
|
234
|
+
assert_equal 255, bytes[3]
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
def test_to_hex
|
|
238
|
+
c = Larb::Color.new(1.0, 0.0, 0.0, 1.0)
|
|
239
|
+
assert_equal "#ff0000ff", c.to_hex
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
def test_to_vec3
|
|
243
|
+
c = Larb::Color.new(0.1, 0.2, 0.3, 1.0)
|
|
244
|
+
v = c.to_vec3
|
|
245
|
+
assert_instance_of Larb::Vec3, v
|
|
246
|
+
assert_equal 0.1, v.x
|
|
247
|
+
assert_equal 0.2, v.y
|
|
248
|
+
assert_equal 0.3, v.z
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
def test_to_vec4
|
|
252
|
+
c = Larb::Color.new(0.1, 0.2, 0.3, 0.4)
|
|
253
|
+
v = c.to_vec4
|
|
254
|
+
assert_instance_of Larb::Vec4, v
|
|
255
|
+
assert_equal 0.1, v.x
|
|
256
|
+
assert_equal 0.2, v.y
|
|
257
|
+
assert_equal 0.3, v.z
|
|
258
|
+
assert_equal 0.4, v.w
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
def test_to_a
|
|
262
|
+
c = Larb::Color.new(0.1, 0.2, 0.3, 0.4)
|
|
263
|
+
assert_equal [0.1, 0.2, 0.3, 0.4], c.to_a
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
def test_from_vec4
|
|
267
|
+
v = Larb::Vec4.new(0.1, 0.2, 0.3, 0.4)
|
|
268
|
+
c = Larb::Color.from_vec4(v)
|
|
269
|
+
assert_equal 0.1, c.r
|
|
270
|
+
assert_equal 0.2, c.g
|
|
271
|
+
assert_equal 0.3, c.b
|
|
272
|
+
assert_equal 0.4, c.a
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
def test_from_vec3
|
|
276
|
+
v = Larb::Vec3.new(0.1, 0.2, 0.3)
|
|
277
|
+
c = Larb::Color.from_vec3(v)
|
|
278
|
+
assert_equal 0.1, c.r
|
|
279
|
+
assert_equal 0.2, c.g
|
|
280
|
+
assert_equal 0.3, c.b
|
|
281
|
+
assert_equal 1.0, c.a
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
def test_from_vec3_with_alpha
|
|
285
|
+
v = Larb::Vec3.new(0.1, 0.2, 0.3)
|
|
286
|
+
c = Larb::Color.from_vec3(v, 0.5)
|
|
287
|
+
assert_equal 0.5, c.a
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
def test_inspect
|
|
291
|
+
c = Larb::Color.new(0.1, 0.2, 0.3, 0.4)
|
|
292
|
+
assert_equal "Color[0.1, 0.2, 0.3, 0.4]", c.inspect
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
def test_to_s
|
|
296
|
+
c = Larb::Color.new(0.1, 0.2, 0.3, 0.4)
|
|
297
|
+
assert_equal c.inspect, c.to_s
|
|
298
|
+
end
|
|
299
|
+
end
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../test_helper"
|
|
4
|
+
|
|
5
|
+
class Mat2Test < Test::Unit::TestCase
|
|
6
|
+
def test_new_identity_by_default
|
|
7
|
+
m = Larb::Mat2.new
|
|
8
|
+
assert_equal 1.0, m[0]
|
|
9
|
+
assert_equal 0.0, m[1]
|
|
10
|
+
assert_equal 0.0, m[2]
|
|
11
|
+
assert_equal 1.0, m[3]
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def test_new_with_data
|
|
15
|
+
m = Larb::Mat2.new([1, 2, 3, 4])
|
|
16
|
+
assert_equal [1, 2, 3, 4], m.data
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def test_identity
|
|
20
|
+
m = Larb::Mat2.identity
|
|
21
|
+
assert_equal 1.0, m[0]
|
|
22
|
+
assert_equal 1.0, m[3]
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def test_zero
|
|
26
|
+
m = Larb::Mat2.zero
|
|
27
|
+
4.times { |i| assert_equal 0.0, m[i] }
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def test_rotation
|
|
31
|
+
m = Larb::Mat2.rotation(Math::PI / 2)
|
|
32
|
+
assert_in_delta 0.0, m[0], 1e-10
|
|
33
|
+
assert_in_delta 1.0, m[1], 1e-10
|
|
34
|
+
assert_in_delta(-1.0, m[2], 1e-10)
|
|
35
|
+
assert_in_delta 0.0, m[3], 1e-10
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def test_scaling
|
|
39
|
+
m = Larb::Mat2.scaling(2, 3)
|
|
40
|
+
assert_equal 2.0, m[0]
|
|
41
|
+
assert_equal 3.0, m[3]
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def test_from_vec2
|
|
45
|
+
v1 = Larb::Vec2.new(1, 2)
|
|
46
|
+
v2 = Larb::Vec2.new(3, 4)
|
|
47
|
+
m = Larb::Mat2.from_vec2(v1, v2)
|
|
48
|
+
assert_equal [1.0, 2.0, 3.0, 4.0], m.data
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def test_multiply_mat2
|
|
52
|
+
m1 = Larb::Mat2.rotation(Math::PI / 4)
|
|
53
|
+
m2 = Larb::Mat2.rotation(Math::PI / 4)
|
|
54
|
+
result = m1 * m2
|
|
55
|
+
expected = Larb::Mat2.rotation(Math::PI / 2)
|
|
56
|
+
assert result.near?(expected)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def test_multiply_vec2
|
|
60
|
+
m = Larb::Mat2.rotation(Math::PI / 2)
|
|
61
|
+
v = Larb::Vec2.new(1, 0)
|
|
62
|
+
result = m * v
|
|
63
|
+
assert_in_delta 0.0, result.x, 1e-10
|
|
64
|
+
assert_in_delta 1.0, result.y, 1e-10
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def test_multiply_scalar
|
|
68
|
+
m = Larb::Mat2.identity
|
|
69
|
+
result = m * 2
|
|
70
|
+
assert_equal 2.0, result[0]
|
|
71
|
+
assert_equal 2.0, result[3]
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def test_add
|
|
75
|
+
m1 = Larb::Mat2.identity
|
|
76
|
+
m2 = Larb::Mat2.identity
|
|
77
|
+
result = m1 + m2
|
|
78
|
+
assert_equal 2.0, result[0]
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def test_subtract
|
|
82
|
+
m1 = Larb::Mat2.identity
|
|
83
|
+
m2 = Larb::Mat2.identity
|
|
84
|
+
result = m1 - m2
|
|
85
|
+
assert_equal 0.0, result[0]
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def test_determinant
|
|
89
|
+
m = Larb::Mat2.identity
|
|
90
|
+
assert_equal 1.0, m.determinant
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def test_determinant_scaling
|
|
94
|
+
m = Larb::Mat2.scaling(2, 3)
|
|
95
|
+
assert_equal 6.0, m.determinant
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def test_inverse
|
|
99
|
+
m = Larb::Mat2.scaling(2, 4)
|
|
100
|
+
inv = m.inverse
|
|
101
|
+
result = m * inv
|
|
102
|
+
assert result.near?(Larb::Mat2.identity)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def test_inverse_singular
|
|
106
|
+
m = Larb::Mat2.zero
|
|
107
|
+
assert_raise_message("Matrix is not invertible") { m.inverse }
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def test_transpose
|
|
111
|
+
m = Larb::Mat2.new([1, 2, 3, 4])
|
|
112
|
+
result = m.transpose
|
|
113
|
+
assert_equal [1, 3, 2, 4], result.data
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def test_adjoint
|
|
117
|
+
m = Larb::Mat2.new([1, 2, 3, 4])
|
|
118
|
+
adj = m.adjoint
|
|
119
|
+
assert_equal 4.0, adj[0]
|
|
120
|
+
assert_equal(-2.0, adj[1])
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def test_frobenius_norm
|
|
124
|
+
m = Larb::Mat2.new([1, 2, 2, 0])
|
|
125
|
+
assert_equal 3.0, m.frobenius_norm
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def test_equality
|
|
129
|
+
m1 = Larb::Mat2.identity
|
|
130
|
+
m2 = Larb::Mat2.identity
|
|
131
|
+
assert_equal m1, m2
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def test_near
|
|
135
|
+
m1 = Larb::Mat2.identity
|
|
136
|
+
m2 = Larb::Mat2.new([1.0000001, 0, 0, 1.0000001])
|
|
137
|
+
assert m1.near?(m2)
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def test_inspect
|
|
141
|
+
m = Larb::Mat2.identity
|
|
142
|
+
assert_match(/Mat2/, m.inspect)
|
|
143
|
+
end
|
|
144
|
+
end
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../test_helper"
|
|
4
|
+
|
|
5
|
+
class Mat2dTest < Test::Unit::TestCase
|
|
6
|
+
def test_new_identity_by_default
|
|
7
|
+
m = Larb::Mat2d.new
|
|
8
|
+
assert_equal 1.0, m[0]
|
|
9
|
+
assert_equal 0.0, m[1]
|
|
10
|
+
assert_equal 0.0, m[2]
|
|
11
|
+
assert_equal 1.0, m[3]
|
|
12
|
+
assert_equal 0.0, m[4]
|
|
13
|
+
assert_equal 0.0, m[5]
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def test_new_with_data
|
|
17
|
+
data = [1, 2, 3, 4, 5, 6]
|
|
18
|
+
m = Larb::Mat2d.new(data)
|
|
19
|
+
assert_equal [1, 2, 3, 4, 5, 6], m.data
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def test_identity
|
|
23
|
+
m = Larb::Mat2d.identity
|
|
24
|
+
assert_equal 1.0, m[0]
|
|
25
|
+
assert_equal 1.0, m[3]
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def test_zero
|
|
29
|
+
m = Larb::Mat2d.zero
|
|
30
|
+
6.times { |i| assert_equal 0.0, m[i] }
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def test_translation
|
|
34
|
+
m = Larb::Mat2d.translation(10, 20)
|
|
35
|
+
assert_equal 10.0, m[4]
|
|
36
|
+
assert_equal 20.0, m[5]
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def test_rotation
|
|
40
|
+
m = Larb::Mat2d.rotation(Math::PI / 2)
|
|
41
|
+
assert_in_delta 0.0, m[0], 1e-10
|
|
42
|
+
assert_in_delta 1.0, m[1], 1e-10
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def test_scaling
|
|
46
|
+
m = Larb::Mat2d.scaling(2, 3)
|
|
47
|
+
assert_equal 2.0, m[0]
|
|
48
|
+
assert_equal 3.0, m[3]
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def test_from_rotation_translation_scale
|
|
52
|
+
m = Larb::Mat2d.from_rotation_translation_scale(
|
|
53
|
+
0,
|
|
54
|
+
Larb::Vec2.new(10, 20),
|
|
55
|
+
Larb::Vec2.new(2, 3)
|
|
56
|
+
)
|
|
57
|
+
assert_equal 2.0, m[0]
|
|
58
|
+
assert_equal 3.0, m[3]
|
|
59
|
+
assert_equal 10.0, m[4]
|
|
60
|
+
assert_equal 20.0, m[5]
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def test_multiply_mat2d
|
|
64
|
+
m1 = Larb::Mat2d.translation(10, 0)
|
|
65
|
+
m2 = Larb::Mat2d.translation(5, 0)
|
|
66
|
+
result = m1 * m2
|
|
67
|
+
assert_equal 15.0, result[4]
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def test_multiply_vec2
|
|
71
|
+
m = Larb::Mat2d.translation(10, 20)
|
|
72
|
+
v = Larb::Vec2.new(0, 0)
|
|
73
|
+
result = m * v
|
|
74
|
+
assert_equal 10.0, result.x
|
|
75
|
+
assert_equal 20.0, result.y
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def test_multiply_rotation_translation
|
|
79
|
+
m = Larb::Mat2d.rotation(Math::PI / 2) * Larb::Mat2d.translation(1, 0)
|
|
80
|
+
v = Larb::Vec2.new(0, 0)
|
|
81
|
+
result = m * v
|
|
82
|
+
assert_in_delta 0.0, result.x, 1e-10
|
|
83
|
+
assert_in_delta 1.0, result.y, 1e-10
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def test_determinant
|
|
87
|
+
m = Larb::Mat2d.identity
|
|
88
|
+
assert_equal 1.0, m.determinant
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def test_determinant_scaling
|
|
92
|
+
m = Larb::Mat2d.scaling(2, 3)
|
|
93
|
+
assert_equal 6.0, m.determinant
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def test_inverse
|
|
97
|
+
m = Larb::Mat2d.translation(10, 20) * Larb::Mat2d.scaling(2, 2)
|
|
98
|
+
inv = m.inverse
|
|
99
|
+
result = m * inv
|
|
100
|
+
assert result.near?(Larb::Mat2d.identity)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def test_inverse_singular
|
|
104
|
+
m = Larb::Mat2d.zero
|
|
105
|
+
assert_raise_message("Matrix is not invertible") { m.inverse }
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def test_translate
|
|
109
|
+
m = Larb::Mat2d.identity
|
|
110
|
+
result = m.translate(5, 10)
|
|
111
|
+
assert_equal 5.0, result[4]
|
|
112
|
+
assert_equal 10.0, result[5]
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def test_rotate
|
|
116
|
+
m = Larb::Mat2d.identity
|
|
117
|
+
result = m.rotate(Math::PI / 2)
|
|
118
|
+
assert_in_delta 0.0, result[0], 1e-10
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def test_scale
|
|
122
|
+
m = Larb::Mat2d.identity
|
|
123
|
+
result = m.scale(2, 3)
|
|
124
|
+
assert_equal 2.0, result[0]
|
|
125
|
+
assert_equal 3.0, result[3]
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def test_extract_translation
|
|
129
|
+
m = Larb::Mat2d.translation(10, 20)
|
|
130
|
+
t = m.extract_translation
|
|
131
|
+
assert_equal 10.0, t.x
|
|
132
|
+
assert_equal 20.0, t.y
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def test_extract_rotation
|
|
136
|
+
m = Larb::Mat2d.rotation(Math::PI / 4)
|
|
137
|
+
angle = m.extract_rotation
|
|
138
|
+
assert_in_delta Math::PI / 4, angle, 1e-10
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def test_extract_scale
|
|
142
|
+
m = Larb::Mat2d.scaling(2, 3)
|
|
143
|
+
s = m.extract_scale
|
|
144
|
+
assert_in_delta 2.0, s.x, 1e-10
|
|
145
|
+
assert_in_delta 3.0, s.y, 1e-10
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def test_to_mat3
|
|
149
|
+
m = Larb::Mat2d.translation(10, 20)
|
|
150
|
+
m3 = m.to_mat3
|
|
151
|
+
assert_instance_of Larb::Mat3, m3
|
|
152
|
+
assert_equal 10.0, m3[6]
|
|
153
|
+
assert_equal 20.0, m3[7]
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def test_equality
|
|
157
|
+
m1 = Larb::Mat2d.identity
|
|
158
|
+
m2 = Larb::Mat2d.identity
|
|
159
|
+
assert_equal m1, m2
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def test_near
|
|
163
|
+
m1 = Larb::Mat2d.identity
|
|
164
|
+
m2 = Larb::Mat2d.new([1.0000001, 0, 0, 1.0000001, 0, 0])
|
|
165
|
+
assert m1.near?(m2)
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
def test_inspect
|
|
169
|
+
m = Larb::Mat2d.identity
|
|
170
|
+
assert_match(/Mat2d/, m.inspect)
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
def test_decomposition_round_trips_signed_scales
|
|
174
|
+
[-1, 1].repeated_permutation(2) do |signs|
|
|
175
|
+
[0, Math::PI / 2, 1.2].each do |angle|
|
|
176
|
+
matrix = Larb::Mat2d.from_rotation_translation_scale(
|
|
177
|
+
angle, Larb::Vec2.new(1, 2), Larb::Vec2.new(signs[0] * 2, signs[1] * 3)
|
|
178
|
+
)
|
|
179
|
+
scale = matrix.extract_scale
|
|
180
|
+
assert_equal signs.inject(:*) < 0, scale.x < 0
|
|
181
|
+
rebuilt = Larb::Mat2d.from_rotation_translation_scale(
|
|
182
|
+
matrix.extract_rotation, matrix.extract_translation, scale
|
|
183
|
+
)
|
|
184
|
+
assert rebuilt.to_a.all?(&:finite?)
|
|
185
|
+
matrix.to_a.zip(rebuilt.to_a).each { |a, b| assert_in_delta a, b, 1e-9 }
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
def test_decomposition_rejects_shear_zero_scale_and_nonfinite_values
|
|
191
|
+
[Larb::Mat2d.new([1, 0, 0.5, 1, 0, 0]), Larb::Mat2d.scaling(0, 1),
|
|
192
|
+
Larb::Mat2d.scaling(Float::NAN, 1)].each do |matrix|
|
|
193
|
+
assert_raise(ArgumentError) { matrix.extract_scale }
|
|
194
|
+
assert_raise(ArgumentError) { matrix.extract_rotation }
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
end
|