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
data/ext/larb/mat2d.c
ADDED
|
@@ -0,0 +1,397 @@
|
|
|
1
|
+
#include "mat2d.h"
|
|
2
|
+
#include "matrix_utils.h"
|
|
3
|
+
|
|
4
|
+
#include <math.h>
|
|
5
|
+
|
|
6
|
+
static void mat2d_free(void *ptr) {
|
|
7
|
+
xfree(ptr);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
static size_t mat2d_memsize(const void *ptr) {
|
|
11
|
+
return sizeof(Mat2dData);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
static const rb_data_type_t mat2d_type = {
|
|
15
|
+
"Mat2d",
|
|
16
|
+
{0, mat2d_free, mat2d_memsize},
|
|
17
|
+
0,
|
|
18
|
+
0,
|
|
19
|
+
RUBY_TYPED_FREE_IMMEDIATELY,
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
static VALUE cMat2d = Qnil;
|
|
23
|
+
static VALUE cVec2 = Qnil;
|
|
24
|
+
static VALUE cMat3 = Qnil;
|
|
25
|
+
|
|
26
|
+
static Mat2dData *mat2d_get(VALUE obj) {
|
|
27
|
+
Mat2dData *data = NULL;
|
|
28
|
+
TypedData_Get_Struct(obj, Mat2dData, &mat2d_type, data);
|
|
29
|
+
return data;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
static VALUE mat2d_build(VALUE klass, const double *values) {
|
|
33
|
+
VALUE obj = mat2d_alloc(klass);
|
|
34
|
+
Mat2dData *data = mat2d_get(obj);
|
|
35
|
+
for (int i = 0; i < 6; i++) {
|
|
36
|
+
data->data[i] = values[i];
|
|
37
|
+
}
|
|
38
|
+
return obj;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
static VALUE mat2d_build6(VALUE klass, double v0, double v1, double v2,
|
|
42
|
+
double v3, double v4, double v5) {
|
|
43
|
+
double values[6] = {v0, v1, v2, v3, v4, v5};
|
|
44
|
+
return mat2d_build(klass, values);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
VALUE mat2d_alloc(VALUE klass) {
|
|
48
|
+
Mat2dData *data = ALLOC(Mat2dData);
|
|
49
|
+
data->data[0] = 1.0;
|
|
50
|
+
data->data[1] = 0.0;
|
|
51
|
+
data->data[2] = 0.0;
|
|
52
|
+
data->data[3] = 1.0;
|
|
53
|
+
data->data[4] = 0.0;
|
|
54
|
+
data->data[5] = 0.0;
|
|
55
|
+
return TypedData_Wrap_Struct(klass, &mat2d_type, data);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
VALUE mat2d_initialize(int argc, VALUE *argv, VALUE self) {
|
|
59
|
+
rb_check_frozen(self);
|
|
60
|
+
VALUE data_arg = Qnil;
|
|
61
|
+
Mat2dData values = {{1.0, 0.0, 0.0, 1.0, 0.0, 0.0}};
|
|
62
|
+
rb_scan_args(argc, argv, "01", &data_arg);
|
|
63
|
+
if (argc != 0) {
|
|
64
|
+
VALUE ary = rb_check_array_type(data_arg);
|
|
65
|
+
if (NIL_P(ary)) {
|
|
66
|
+
rb_raise(rb_eTypeError, "expected Array");
|
|
67
|
+
}
|
|
68
|
+
if (RARRAY_LEN(ary) != 6) {
|
|
69
|
+
rb_raise(rb_eArgError, "expected 6 elements");
|
|
70
|
+
}
|
|
71
|
+
for (int i = 0; i < 6; i++) {
|
|
72
|
+
values.data[i] = NUM2DBL(rb_ary_entry(ary, i));
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
rb_check_frozen(self);
|
|
76
|
+
*mat2d_get(self) = values;
|
|
77
|
+
return self;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
static VALUE mat2d_initialize_copy(VALUE self, VALUE other) {
|
|
81
|
+
if (self == other) return self;
|
|
82
|
+
rb_obj_init_copy(self, other);
|
|
83
|
+
*mat2d_get(self) = *mat2d_get(other);
|
|
84
|
+
return self;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
static VALUE mat2d_class_identity(VALUE klass) {
|
|
88
|
+
return mat2d_alloc(klass);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
static VALUE mat2d_class_zero(VALUE klass) {
|
|
92
|
+
return mat2d_build6(klass, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
static VALUE mat2d_class_translation(VALUE klass, VALUE x, VALUE y) {
|
|
96
|
+
return mat2d_build6(klass, 1.0, 0.0, 0.0, 1.0, NUM2DBL(x),
|
|
97
|
+
NUM2DBL(y));
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
static VALUE mat2d_class_rotation(VALUE klass, VALUE radians) {
|
|
101
|
+
double r = NUM2DBL(radians);
|
|
102
|
+
double c = cos(r);
|
|
103
|
+
double s = sin(r);
|
|
104
|
+
return mat2d_build6(klass, c, s, -s, c, 0.0, 0.0);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
static VALUE mat2d_class_scaling(VALUE klass, VALUE x, VALUE y) {
|
|
108
|
+
return mat2d_build6(klass, NUM2DBL(x), 0.0, 0.0,
|
|
109
|
+
NUM2DBL(y), 0.0, 0.0);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
static VALUE mat2d_class_from_rotation_translation_scale(VALUE klass,
|
|
113
|
+
VALUE rotation,
|
|
114
|
+
VALUE translation,
|
|
115
|
+
VALUE scale) {
|
|
116
|
+
double r = NUM2DBL(rotation);
|
|
117
|
+
double c = cos(r);
|
|
118
|
+
double s = sin(r);
|
|
119
|
+
double sx = NUM2DBL(rb_funcall(scale, rb_intern("x"), 0));
|
|
120
|
+
double sy = NUM2DBL(rb_funcall(scale, rb_intern("y"), 0));
|
|
121
|
+
double tx = NUM2DBL(rb_funcall(translation, rb_intern("x"), 0));
|
|
122
|
+
double ty = NUM2DBL(rb_funcall(translation, rb_intern("y"), 0));
|
|
123
|
+
|
|
124
|
+
return mat2d_build6(klass, c * sx, s * sx, -s * sy, c * sy, tx, ty);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
VALUE mat2d_aref(VALUE self, VALUE index) {
|
|
128
|
+
Mat2dData *data = mat2d_get(self);
|
|
129
|
+
long idx = NUM2LONG(index);
|
|
130
|
+
if (idx < 0 || idx > 5) {
|
|
131
|
+
return Qnil;
|
|
132
|
+
}
|
|
133
|
+
return DBL2NUM(data->data[idx]);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
VALUE mat2d_aset(VALUE self, VALUE index, VALUE value) {
|
|
137
|
+
rb_check_frozen(self);
|
|
138
|
+
Mat2dData *data = mat2d_get(self);
|
|
139
|
+
long idx = NUM2LONG(index);
|
|
140
|
+
if (idx < 0 || idx > 5) {
|
|
141
|
+
rb_raise(rb_eIndexError, "index %ld out of range", idx);
|
|
142
|
+
}
|
|
143
|
+
double component = NUM2DBL(value);
|
|
144
|
+
rb_check_frozen(self);
|
|
145
|
+
data->data[idx] = component;
|
|
146
|
+
return value;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
VALUE mat2d_mul(VALUE self, VALUE other) {
|
|
150
|
+
Mat2dData *a = mat2d_get(self);
|
|
151
|
+
|
|
152
|
+
if (rb_obj_is_kind_of(other, cMat2d)) {
|
|
153
|
+
Mat2dData *b = mat2d_get(other);
|
|
154
|
+
return mat2d_build6(
|
|
155
|
+
rb_obj_class(self),
|
|
156
|
+
a->data[0] * b->data[0] + a->data[2] * b->data[1],
|
|
157
|
+
a->data[1] * b->data[0] + a->data[3] * b->data[1],
|
|
158
|
+
a->data[0] * b->data[2] + a->data[2] * b->data[3],
|
|
159
|
+
a->data[1] * b->data[2] + a->data[3] * b->data[3],
|
|
160
|
+
a->data[0] * b->data[4] + a->data[2] * b->data[5] + a->data[4],
|
|
161
|
+
a->data[1] * b->data[4] + a->data[3] * b->data[5] + a->data[5]);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
if (rb_obj_is_kind_of(other, cVec2)) {
|
|
165
|
+
double x = NUM2DBL(rb_funcall(other, rb_intern("x"), 0));
|
|
166
|
+
double y = NUM2DBL(rb_funcall(other, rb_intern("y"), 0));
|
|
167
|
+
VALUE vec2_class = rb_const_get(mLarb, rb_intern("Vec2"));
|
|
168
|
+
return rb_funcall(vec2_class, rb_intern("new"), 2,
|
|
169
|
+
DBL2NUM(a->data[0] * x + a->data[2] * y + a->data[4]),
|
|
170
|
+
DBL2NUM(a->data[1] * x + a->data[3] * y + a->data[5]));
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if (rb_obj_is_kind_of(other, rb_cNumeric)) {
|
|
174
|
+
double s = NUM2DBL(other);
|
|
175
|
+
return mat2d_build6(rb_obj_class(self), a->data[0] * s, a->data[1] * s,
|
|
176
|
+
a->data[2] * s, a->data[3] * s, a->data[4] * s,
|
|
177
|
+
a->data[5] * s);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
rb_raise(rb_eTypeError, "unsupported operand for Mat2d multiplication");
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
VALUE mat2d_add(VALUE self, VALUE other) {
|
|
184
|
+
Mat2dData *a = mat2d_get(self);
|
|
185
|
+
Mat2dData *b = mat2d_get(other);
|
|
186
|
+
return mat2d_build6(rb_obj_class(self), a->data[0] + b->data[0],
|
|
187
|
+
a->data[1] + b->data[1], a->data[2] + b->data[2],
|
|
188
|
+
a->data[3] + b->data[3], a->data[4] + b->data[4],
|
|
189
|
+
a->data[5] + b->data[5]);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
VALUE mat2d_sub(VALUE self, VALUE other) {
|
|
193
|
+
Mat2dData *a = mat2d_get(self);
|
|
194
|
+
Mat2dData *b = mat2d_get(other);
|
|
195
|
+
return mat2d_build6(rb_obj_class(self), a->data[0] - b->data[0],
|
|
196
|
+
a->data[1] - b->data[1], a->data[2] - b->data[2],
|
|
197
|
+
a->data[3] - b->data[3], a->data[4] - b->data[4],
|
|
198
|
+
a->data[5] - b->data[5]);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
VALUE mat2d_determinant(VALUE self) {
|
|
202
|
+
Mat2dData *a = mat2d_get(self);
|
|
203
|
+
return DBL2NUM(a->data[0] * a->data[3] - a->data[1] * a->data[2]);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
VALUE mat2d_inverse(VALUE self) {
|
|
207
|
+
const double *a = mat2d_get(self)->data;
|
|
208
|
+
double values[9] = {a[0], a[1], 0.0, a[2], a[3], 0.0, a[4], a[5], 1.0};
|
|
209
|
+
double inverse[9];
|
|
210
|
+
larb_matrix_inverse(values, inverse, 3);
|
|
211
|
+
return mat2d_build6(rb_obj_class(self), inverse[0], inverse[1], inverse[3],
|
|
212
|
+
inverse[4], inverse[6], inverse[7]);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
VALUE mat2d_translate(VALUE self, VALUE x, VALUE y) {
|
|
216
|
+
Mat2dData *a = mat2d_get(self);
|
|
217
|
+
double dx = NUM2DBL(x);
|
|
218
|
+
double dy = NUM2DBL(y);
|
|
219
|
+
return mat2d_build6(rb_obj_class(self), a->data[0], a->data[1], a->data[2],
|
|
220
|
+
a->data[3], a->data[0] * dx + a->data[2] * dy + a->data[4],
|
|
221
|
+
a->data[1] * dx + a->data[3] * dy + a->data[5]);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
VALUE mat2d_rotate(VALUE self, VALUE radians) {
|
|
225
|
+
VALUE rot = mat2d_class_rotation(cMat2d, radians);
|
|
226
|
+
return mat2d_mul(self, rot);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
VALUE mat2d_scale(VALUE self, VALUE x, VALUE y) {
|
|
230
|
+
Mat2dData *a = mat2d_get(self);
|
|
231
|
+
double sx = NUM2DBL(x);
|
|
232
|
+
double sy = NUM2DBL(y);
|
|
233
|
+
return mat2d_build6(rb_obj_class(self), a->data[0] * sx, a->data[1] * sx,
|
|
234
|
+
a->data[2] * sy, a->data[3] * sy, a->data[4], a->data[5]);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
VALUE mat2d_extract_translation(VALUE self) {
|
|
238
|
+
Mat2dData *a = mat2d_get(self);
|
|
239
|
+
VALUE vec2_class = rb_const_get(mLarb, rb_intern("Vec2"));
|
|
240
|
+
return rb_funcall(vec2_class, rb_intern("new"), 2, DBL2NUM(a->data[4]),
|
|
241
|
+
DBL2NUM(a->data[5]));
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
static void mat2d_decompose(const Mat2dData *a, double *sx, double *sy) {
|
|
245
|
+
for (int i = 0; i < 6; i++) {
|
|
246
|
+
if (!isfinite(a->data[i])) {
|
|
247
|
+
rb_raise(rb_eArgError, "Cannot decompose non-finite components");
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
*sx = hypot(a->data[0], a->data[1]);
|
|
251
|
+
*sy = hypot(a->data[2], a->data[3]);
|
|
252
|
+
if (*sx == 0.0 || *sy == 0.0 || !isfinite(*sx) || !isfinite(*sy)) {
|
|
253
|
+
rb_raise(rb_eArgError, "Cannot decompose zero or non-finite scale");
|
|
254
|
+
}
|
|
255
|
+
double x0 = a->data[0] / *sx, y0 = a->data[1] / *sx;
|
|
256
|
+
double x1 = a->data[2] / *sy, y1 = a->data[3] / *sy;
|
|
257
|
+
if (fabs(x0 * x1 + y0 * y1) > 1e-6) {
|
|
258
|
+
rb_raise(rb_eArgError, "Cannot decompose shear");
|
|
259
|
+
}
|
|
260
|
+
if (x0 * y1 - y0 * x1 < 0.0) *sx = -*sx;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
VALUE mat2d_extract_rotation(VALUE self) {
|
|
264
|
+
Mat2dData *a = mat2d_get(self);
|
|
265
|
+
double sx, sy;
|
|
266
|
+
mat2d_decompose(a, &sx, &sy);
|
|
267
|
+
return DBL2NUM(atan2(a->data[1] / sx, a->data[0] / sx));
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
VALUE mat2d_extract_scale(VALUE self) {
|
|
271
|
+
double sx, sy;
|
|
272
|
+
mat2d_decompose(mat2d_get(self), &sx, &sy);
|
|
273
|
+
return rb_funcall(cVec2, rb_intern("new"), 2, DBL2NUM(sx), DBL2NUM(sy));
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
VALUE mat2d_frobenius_norm(VALUE self) {
|
|
277
|
+
Mat2dData *a = mat2d_get(self);
|
|
278
|
+
double norm = 0.0;
|
|
279
|
+
for (int i = 0; i < 6; i++) {
|
|
280
|
+
norm = hypot(norm, a->data[i]);
|
|
281
|
+
}
|
|
282
|
+
return DBL2NUM(norm);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
VALUE mat2d_to_mat3(VALUE self) {
|
|
286
|
+
Mat2dData *a = mat2d_get(self);
|
|
287
|
+
VALUE mat3_class = rb_const_get(mLarb, rb_intern("Mat3"));
|
|
288
|
+
return rb_funcall(mat3_class, rb_intern("new"), 1,
|
|
289
|
+
rb_ary_new3(9, DBL2NUM(a->data[0]), DBL2NUM(a->data[1]),
|
|
290
|
+
DBL2NUM(0.0), DBL2NUM(a->data[2]),
|
|
291
|
+
DBL2NUM(a->data[3]), DBL2NUM(0.0),
|
|
292
|
+
DBL2NUM(a->data[4]), DBL2NUM(a->data[5]),
|
|
293
|
+
DBL2NUM(1.0)));
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
VALUE mat2d_to_a(VALUE self) {
|
|
297
|
+
Mat2dData *a = mat2d_get(self);
|
|
298
|
+
VALUE ary = rb_ary_new_capa(6);
|
|
299
|
+
for (int i = 0; i < 6; i++) {
|
|
300
|
+
rb_ary_push(ary, DBL2NUM(a->data[i]));
|
|
301
|
+
}
|
|
302
|
+
return ary;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
VALUE mat2d_data(VALUE self) {
|
|
306
|
+
return mat2d_to_a(self);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
VALUE mat2d_equal(VALUE self, VALUE other) {
|
|
310
|
+
if (!rb_obj_is_kind_of(other, cMat2d)) {
|
|
311
|
+
return Qfalse;
|
|
312
|
+
}
|
|
313
|
+
Mat2dData *a = mat2d_get(self);
|
|
314
|
+
Mat2dData *b = mat2d_get(other);
|
|
315
|
+
for (int i = 0; i < 6; i++) {
|
|
316
|
+
if (a->data[i] != b->data[i]) {
|
|
317
|
+
return Qfalse;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
return Qtrue;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
VALUE mat2d_near(int argc, VALUE *argv, VALUE self) {
|
|
324
|
+
VALUE other = Qnil;
|
|
325
|
+
VALUE epsilon = Qnil;
|
|
326
|
+
|
|
327
|
+
rb_scan_args(argc, argv, "11", &other, &epsilon);
|
|
328
|
+
Mat2dData *a = mat2d_get(self);
|
|
329
|
+
Mat2dData *b = mat2d_get(other);
|
|
330
|
+
double eps = argc < 2 ? 1e-6 : NUM2DBL(epsilon);
|
|
331
|
+
if (!isfinite(eps) || eps <= 0.0) {
|
|
332
|
+
rb_raise(rb_eArgError, "epsilon must be finite and positive");
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
for (int i = 0; i < 6; i++) {
|
|
336
|
+
if (!(fabs(a->data[i] - b->data[i]) < eps)) {
|
|
337
|
+
return Qfalse;
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
return Qtrue;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
VALUE mat2d_inspect(VALUE self) {
|
|
344
|
+
Mat2dData *a = mat2d_get(self);
|
|
345
|
+
VALUE str = rb_str_new_cstr("Mat2d[");
|
|
346
|
+
for (int i = 0; i < 6; i++) {
|
|
347
|
+
VALUE formatted = rb_funcall(rb_mKernel, rb_intern("format"), 2,
|
|
348
|
+
rb_str_new_cstr("%.4f"), DBL2NUM(a->data[i]));
|
|
349
|
+
if (i > 0) {
|
|
350
|
+
rb_str_cat_cstr(str, ", ");
|
|
351
|
+
}
|
|
352
|
+
rb_str_concat(str, formatted);
|
|
353
|
+
}
|
|
354
|
+
rb_str_cat_cstr(str, "]");
|
|
355
|
+
return str;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
void Init_mat2d(VALUE module) {
|
|
359
|
+
cMat2d = rb_define_class_under(module, "Mat2d", rb_cObject);
|
|
360
|
+
cVec2 = rb_const_get(mLarb, rb_intern("Vec2"));
|
|
361
|
+
cMat3 = rb_const_get(mLarb, rb_intern("Mat3"));
|
|
362
|
+
|
|
363
|
+
rb_define_alloc_func(cMat2d, mat2d_alloc);
|
|
364
|
+
rb_define_method(cMat2d, "initialize", mat2d_initialize, -1);
|
|
365
|
+
rb_define_method(cMat2d, "initialize_copy", mat2d_initialize_copy, 1);
|
|
366
|
+
|
|
367
|
+
rb_define_singleton_method(cMat2d, "identity", mat2d_class_identity, 0);
|
|
368
|
+
rb_define_singleton_method(cMat2d, "zero", mat2d_class_zero, 0);
|
|
369
|
+
rb_define_singleton_method(cMat2d, "translation", mat2d_class_translation,
|
|
370
|
+
2);
|
|
371
|
+
rb_define_singleton_method(cMat2d, "rotation", mat2d_class_rotation, 1);
|
|
372
|
+
rb_define_singleton_method(cMat2d, "scaling", mat2d_class_scaling, 2);
|
|
373
|
+
rb_define_singleton_method(cMat2d, "from_rotation_translation_scale",
|
|
374
|
+
mat2d_class_from_rotation_translation_scale, 3);
|
|
375
|
+
|
|
376
|
+
rb_define_method(cMat2d, "data", mat2d_data, 0);
|
|
377
|
+
rb_define_method(cMat2d, "[]", mat2d_aref, 1);
|
|
378
|
+
rb_define_method(cMat2d, "[]=", mat2d_aset, 2);
|
|
379
|
+
rb_define_method(cMat2d, "*", mat2d_mul, 1);
|
|
380
|
+
rb_define_method(cMat2d, "+", mat2d_add, 1);
|
|
381
|
+
rb_define_method(cMat2d, "-", mat2d_sub, 1);
|
|
382
|
+
rb_define_method(cMat2d, "determinant", mat2d_determinant, 0);
|
|
383
|
+
rb_define_method(cMat2d, "inverse", mat2d_inverse, 0);
|
|
384
|
+
rb_define_method(cMat2d, "translate", mat2d_translate, 2);
|
|
385
|
+
rb_define_method(cMat2d, "rotate", mat2d_rotate, 1);
|
|
386
|
+
rb_define_method(cMat2d, "scale", mat2d_scale, 2);
|
|
387
|
+
rb_define_method(cMat2d, "extract_translation", mat2d_extract_translation, 0);
|
|
388
|
+
rb_define_method(cMat2d, "extract_rotation", mat2d_extract_rotation, 0);
|
|
389
|
+
rb_define_method(cMat2d, "extract_scale", mat2d_extract_scale, 0);
|
|
390
|
+
rb_define_method(cMat2d, "frobenius_norm", mat2d_frobenius_norm, 0);
|
|
391
|
+
rb_define_method(cMat2d, "to_mat3", mat2d_to_mat3, 0);
|
|
392
|
+
rb_define_method(cMat2d, "to_a", mat2d_to_a, 0);
|
|
393
|
+
rb_define_method(cMat2d, "==", mat2d_equal, 1);
|
|
394
|
+
rb_define_method(cMat2d, "near?", mat2d_near, -1);
|
|
395
|
+
rb_define_method(cMat2d, "inspect", mat2d_inspect, 0);
|
|
396
|
+
rb_define_alias(cMat2d, "to_s", "inspect");
|
|
397
|
+
}
|
data/ext/larb/mat2d.h
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
#ifndef MAT2D_H
|
|
2
|
+
#define MAT2D_H
|
|
3
|
+
|
|
4
|
+
#include "larb.h"
|
|
5
|
+
|
|
6
|
+
typedef struct {
|
|
7
|
+
double data[6];
|
|
8
|
+
} Mat2dData;
|
|
9
|
+
|
|
10
|
+
void Init_mat2d(VALUE module);
|
|
11
|
+
VALUE mat2d_alloc(VALUE klass);
|
|
12
|
+
VALUE mat2d_initialize(int argc, VALUE *argv, VALUE self);
|
|
13
|
+
|
|
14
|
+
VALUE mat2d_aref(VALUE self, VALUE index);
|
|
15
|
+
VALUE mat2d_aset(VALUE self, VALUE index, VALUE value);
|
|
16
|
+
VALUE mat2d_mul(VALUE self, VALUE other);
|
|
17
|
+
VALUE mat2d_add(VALUE self, VALUE other);
|
|
18
|
+
VALUE mat2d_sub(VALUE self, VALUE other);
|
|
19
|
+
VALUE mat2d_determinant(VALUE self);
|
|
20
|
+
VALUE mat2d_inverse(VALUE self);
|
|
21
|
+
VALUE mat2d_translate(VALUE self, VALUE x, VALUE y);
|
|
22
|
+
VALUE mat2d_rotate(VALUE self, VALUE radians);
|
|
23
|
+
VALUE mat2d_scale(VALUE self, VALUE x, VALUE y);
|
|
24
|
+
VALUE mat2d_extract_translation(VALUE self);
|
|
25
|
+
VALUE mat2d_extract_rotation(VALUE self);
|
|
26
|
+
VALUE mat2d_extract_scale(VALUE self);
|
|
27
|
+
VALUE mat2d_frobenius_norm(VALUE self);
|
|
28
|
+
VALUE mat2d_to_mat3(VALUE self);
|
|
29
|
+
VALUE mat2d_to_a(VALUE self);
|
|
30
|
+
VALUE mat2d_equal(VALUE self, VALUE other);
|
|
31
|
+
VALUE mat2d_near(int argc, VALUE *argv, VALUE self);
|
|
32
|
+
VALUE mat2d_inspect(VALUE self);
|
|
33
|
+
VALUE mat2d_data(VALUE self);
|
|
34
|
+
|
|
35
|
+
#endif
|