24 | 24 |
|
25 | 25 |
Janet janet_wrap_point(Geom::Point const &x) {
|
26 | 26 |
Geom::Point *box = (Geom::Point *)janet_abstract(&geom_point_type, sizeof(Geom::Point));
|
27 | |
*box = (Geom::Point)x;
|
28 | |
return janet_wrap_abstract(box);
|
29 | |
}
|
30 | |
|
|
27 |
*box = Geom::Point(x);
|
|
28 |
return janet_wrap_abstract(box);
|
|
29 |
}
|
|
30 |
|
|
31 |
Janet janet_wrap_point(Geom::IntPoint const &x) {
|
|
32 |
Geom::Point *box = (Geom::Point *)janet_abstract(&geom_point_type, sizeof(Geom::Point));
|
|
33 |
*box = Geom::Point(x);
|
|
34 |
return janet_wrap_abstract(box);
|
|
35 |
}
|
31 | 36 |
|
32 | 37 |
Geom::Point janet_unwrap_point(Janet x) {
|
33 | 38 |
if (janet_checktype(x, JANET_ABSTRACT)) {
|
|
36 | 41 |
return *(Geom::Point *)abst;
|
37 | 42 |
}
|
38 | 43 |
|
39 | |
janet_panic("not a point");
|
40 | |
return Geom::Point();
|
41 | |
}
|
42 | |
|
|
44 |
janet_panic("expected a geom/point");
|
|
45 |
}
|
|
46 |
|
|
47 |
Geom::Point janet_unwrap_point_or_scalar(Janet x) {
|
|
48 |
if (janet_checktype(x, JANET_ABSTRACT)) {
|
|
49 |
void *abst = janet_unwrap_abstract(x);
|
|
50 |
if (janet_abstract_type(abst) == &geom_point_type)
|
|
51 |
return *(Geom::Point *)abst;
|
|
52 |
} else if (janet_checktype(x, JANET_NUMBER)) {
|
|
53 |
double val = janet_unwrap_number(x);
|
|
54 |
return Geom::Point(val, val);
|
|
55 |
}
|
|
56 |
|
|
57 |
janet_panic("expected a geom/point");
|
|
58 |
}
|
|
59 |
|
|
60 |
|
|
61 |
Geom::Point& janet_unwrap_point_ref(Janet x) {
|
|
62 |
if (janet_checktype(x, JANET_ABSTRACT)) {
|
|
63 |
void *abst = janet_unwrap_abstract(x);
|
|
64 |
if (janet_abstract_type(abst) == &geom_point_type)
|
|
65 |
return *(Geom::Point *)abst;
|
|
66 |
}
|
|
67 |
|
|
68 |
janet_panic("expected a geom/point");
|
|
69 |
}
|
43 | 70 |
|
44 | 71 |
extern "C" Janet cfun_geom_point_new(int32_t argc, Janet *argv) {
|
45 | 72 |
janet_fixarity(argc, 2);
|
|
56 | 83 |
{NULL, NULL, NULL}
|
57 | 84 |
};
|
58 | 85 |
|
59 | |
|
60 | |
#define OPMETHOD(name, oper) \
|
|
86 |
static Janet cfun_geom_point_add(int32_t argc, Janet *argv) {
|
|
87 |
janet_arity(argc, 2, -1);
|
|
88 |
Geom::Point *box = (Geom::Point *)janet_abstract(&geom_point_type, sizeof(Geom::Point));
|
|
89 |
*box = janet_unwrap_point(argv[0]);
|
|
90 |
for (int i = 1; i < argc; i++)
|
|
91 |
*box += janet_unwrap_point(argv[i]);
|
|
92 |
return janet_wrap_abstract(box);
|
|
93 |
}
|
|
94 |
|
|
95 |
static Janet cfun_geom_point_add_mut(int32_t argc, Janet *argv) {
|
|
96 |
janet_arity(argc, 2, -1);
|
|
97 |
Geom::Point *box = (Geom::Point *)janet_getabstract(argv, 0, &geom_point_type);
|
|
98 |
for (int i = 1; i < argc; i++)
|
|
99 |
*box += janet_unwrap_point(argv[i]);
|
|
100 |
return janet_wrap_abstract(box);
|
|
101 |
}
|
|
102 |
|
|
103 |
static Janet cfun_geom_point_sub(int32_t argc, Janet *argv) {
|
|
104 |
janet_arity(argc, 2, -1);
|
|
105 |
Geom::Point *box = (Geom::Point *)janet_abstract(&geom_point_type, sizeof(Geom::Point));
|
|
106 |
*box = janet_unwrap_point(argv[0]);
|
|
107 |
for (int i = 1; i < argc; i++)
|
|
108 |
*box -= janet_unwrap_point(argv[i]);
|
|
109 |
return janet_wrap_abstract(box);
|
|
110 |
}
|
|
111 |
|
|
112 |
static Janet cfun_geom_point_sub_mut(int32_t argc, Janet *argv) {
|
|
113 |
janet_arity(argc, 2, -1);
|
|
114 |
Geom::Point *box = (Geom::Point *)janet_getabstract(argv, 0, &geom_point_type);
|
|
115 |
for (int i = 1; i < argc; i++)
|
|
116 |
*box -= janet_unwrap_point(argv[i]);
|
|
117 |
return janet_wrap_abstract(box);
|
|
118 |
}
|
|
119 |
|
|
120 |
static Janet cfun_geom_point_mul(int32_t argc, Janet *argv) {
|
|
121 |
janet_arity(argc, 2, -1);
|
|
122 |
Geom::Point *box = (Geom::Point *)janet_abstract(&geom_point_type, sizeof(Geom::Point));
|
|
123 |
*box = janet_unwrap_point(argv[0]);
|
|
124 |
for (int i = 1; i < argc; i++) {
|
|
125 |
Geom::Point arg = janet_unwrap_point_or_scalar(argv[i]);
|
|
126 |
(*box)[0] *= arg[0];
|
|
127 |
(*box)[1] *= arg[1];
|
|
128 |
}
|
|
129 |
return janet_wrap_abstract(box);
|
|
130 |
}
|
|
131 |
|
|
132 |
static Janet cfun_geom_point_mul_mut(int32_t argc, Janet *argv) {
|
|
133 |
janet_arity(argc, 2, -1);
|
|
134 |
Geom::Point *box = (Geom::Point *)janet_getabstract(argv, 0, &geom_point_type);
|
|
135 |
for (int i = 1; i < argc; i++) {
|
|
136 |
Geom::Point arg = janet_unwrap_point_or_scalar(argv[i]);
|
|
137 |
(*box)[0] *= arg[0];
|
|
138 |
(*box)[1] *= arg[1];
|
|
139 |
}
|
|
140 |
return janet_wrap_abstract(box);
|
|
141 |
}
|
|
142 |
|
|
143 |
static Janet cfun_geom_point_div(int32_t argc, Janet *argv) {
|
|
144 |
janet_arity(argc, 2, -1);
|
|
145 |
Geom::Point *box = (Geom::Point *)janet_abstract(&geom_point_type, sizeof(Geom::Point));
|
|
146 |
*box = janet_unwrap_point(argv[0]);
|
|
147 |
for (int i = 1; i < argc; i++) {
|
|
148 |
Geom::Point arg = janet_unwrap_point_or_scalar(argv[i]);
|
|
149 |
(*box)[0] /= arg[0];
|
|
150 |
(*box)[1] /= arg[1];
|
|
151 |
}
|
|
152 |
return janet_wrap_abstract(box);
|
|
153 |
}
|
|
154 |
|
|
155 |
static Janet cfun_geom_point_div_mut(int32_t argc, Janet *argv) {
|
|
156 |
janet_arity(argc, 2, -1);
|
|
157 |
Geom::Point *box = (Geom::Point *)janet_getabstract(argv, 0, &geom_point_type);
|
|
158 |
for (int i = 1; i < argc; i++) {
|
|
159 |
Geom::Point arg = janet_unwrap_point_or_scalar(argv[i]);
|
|
160 |
(*box)[0] /= arg[0];
|
|
161 |
(*box)[1] /= arg[1];
|
|
162 |
}
|
|
163 |
return janet_wrap_abstract(box);
|
|
164 |
}
|
|
165 |
|
|
166 |
static Janet cfun_geom_point_eq(int32_t argc, Janet *argv) {
|
|
167 |
janet_fixarity(argc, 2);
|
|
168 |
Geom::Point& v1 = janet_unwrap_point_ref(argv[0]);
|
|
169 |
Geom::Point& v2 = janet_unwrap_point_ref(argv[1]);
|
|
170 |
return janet_wrap_boolean(v1 == v2);
|
|
171 |
}
|
|
172 |
|
|
173 |
static Janet cfun_geom_point_lt(int32_t argc, Janet *argv) {
|
|
174 |
janet_fixarity(argc, 2);
|
|
175 |
Geom::Point& v1 = janet_unwrap_point_ref(argv[0]);
|
|
176 |
Geom::Point& v2 = janet_unwrap_point_ref(argv[1]);
|
|
177 |
return janet_wrap_boolean(v1 < v2);
|
|
178 |
}
|
|
179 |
|
|
180 |
#define CONSTMETHOD(name, method, type) \
|
61 | 181 |
static Janet cfun_geom_point_##name(int32_t argc, Janet *argv) { \
|
62 | |
janet_arity(argc, 2, -1); \
|
63 | |
Geom::Point *box = (Geom::Point *)janet_abstract(&geom_point_type, sizeof(Geom::Point)); \
|
64 | |
*box = janet_unwrap_point(argv[0]); \
|
65 | |
for (int i = 1; i < argc; i++) \
|
66 | |
*box oper##= janet_unwrap_point(argv[i]); \
|
67 | |
return janet_wrap_abstract(box); \
|
68 | |
} \
|
69 | |
\
|
70 | |
static Janet cfun_geom_point_##name##_mut(int32_t argc, Janet *argv) { \
|
71 | |
janet_arity(argc, 2, -1); \
|
72 | |
Geom::Point *box = (Geom::Point *)janet_abstract(&geom_point_type, sizeof(Geom::Point)); \
|
73 | |
for (int i = 1; i < argc; i++) \
|
74 | |
*box oper##= janet_unwrap_point(argv[i]); \
|
75 | |
return janet_wrap_abstract(box); \
|
76 | |
}
|
77 | |
|
78 | |
OPMETHOD(add, +)
|
79 | |
OPMETHOD(sub, -)
|
|
182 |
janet_fixarity(argc, 1); \
|
|
183 |
Geom::Point *box = (Geom::Point *)janet_getabstract(argv, 0, &geom_point_type); \
|
|
184 |
return janet_wrap_##type(box->method()); \
|
|
185 |
}
|
|
186 |
|
|
187 |
CONSTMETHOD(is_zero, isZero, boolean)
|
|
188 |
CONSTMETHOD(is_finite, isFinite, boolean)
|
|
189 |
CONSTMETHOD(is_normalized, isNormalized, boolean)
|
|
190 |
|
|
191 |
CONSTMETHOD(x, x, number)
|
|
192 |
CONSTMETHOD(y, y, number)
|
|
193 |
CONSTMETHOD(length, length, number)
|
|
194 |
|
|
195 |
CONSTMETHOD(cw, cw, point)
|
|
196 |
CONSTMETHOD(ccw, ccw, point)
|
|
197 |
CONSTMETHOD(round, round, point)
|
|
198 |
CONSTMETHOD(floor, floor, point)
|
|
199 |
CONSTMETHOD(ceil, ceil, point)
|
|
200 |
CONSTMETHOD(normalize, normalized, point)
|
|
201 |
|
|
202 |
static Janet cfun_geom_point_normalize_mut(int32_t argc, Janet *argv) {
|
|
203 |
janet_fixarity(argc, 1);
|
|
204 |
Geom::Point *box = (Geom::Point *)janet_getabstract(argv, 0, &geom_point_type);
|
|
205 |
box->normalize();
|
|
206 |
return janet_wrap_point(*box);
|
|
207 |
}
|
80 | 208 |
|
81 | 209 |
static JanetMethod geom_point_methods[] = {
|
82 | |
{"+", cfun_geom_point_add},
|
83 | |
{"-", cfun_geom_point_sub},
|
|
210 |
{"+", cfun_geom_point_add},
|
|
211 |
{"-", cfun_geom_point_sub},
|
|
212 |
{"*", cfun_geom_point_mul},
|
|
213 |
{"/", cfun_geom_point_div},
|
|
214 |
{"<", cfun_geom_point_lt},
|
|
215 |
{"==", cfun_geom_point_eq},
|
|
216 |
|
|
217 |
{"+!", cfun_geom_point_add_mut},
|
|
218 |
{"-!", cfun_geom_point_sub_mut},
|
|
219 |
{"*!", cfun_geom_point_mul_mut},
|
|
220 |
{"/!", cfun_geom_point_div_mut},
|
|
221 |
|
|
222 |
{"zero?", cfun_geom_point_is_zero},
|
|
223 |
{"finite?", cfun_geom_point_is_finite},
|
|
224 |
{"normalized?", cfun_geom_point_is_normalized},
|
|
225 |
|
|
226 |
{"x", cfun_geom_point_x},
|
|
227 |
{"y", cfun_geom_point_y},
|
|
228 |
{"length", cfun_geom_point_length},
|
|
229 |
|
|
230 |
{"cw", cfun_geom_point_cw},
|
|
231 |
{"ccw", cfun_geom_point_ccw},
|
|
232 |
{"round", cfun_geom_point_round},
|
|
233 |
{"floor", cfun_geom_point_floor},
|
|
234 |
{"ceil", cfun_geom_point_ceil},
|
|
235 |
{"normalize", cfun_geom_point_normalize},
|
|
236 |
|
|
237 |
{"normalize!", cfun_geom_point_normalize_mut},
|
|
238 |
|
84 | 239 |
{NULL, NULL}
|
85 | 240 |
};
|
86 | 241 |
|
|
89 | 244 |
if (!janet_checktype(key, JANET_KEYWORD))
|
90 | 245 |
janet_panicf("expected keyword, got %v", key);
|
91 | 246 |
|
92 | |
uint8_t const *keystr = janet_unwrap_keyword(key);
|
93 | |
if (janet_string_equal(keystr, janet_cstring("x"))) {
|
94 | |
return janet_wrap_number(box->x());
|
95 | |
} else if (janet_string_equal(keystr, janet_cstring("y"))) {
|
96 | |
return janet_wrap_number(box->y());
|
97 | |
} else {
|
98 | |
return janet_getmethod(keystr, geom_point_methods);
|
99 | |
}
|
|
247 |
return janet_getmethod(janet_unwrap_keyword(key), geom_point_methods);
|
100 | 248 |
}
|
101 | 249 |
|
102 | 250 |
extern "C" void janet_lib_geom_point(JanetTable *env) {
|