1include <../std.scad>
2
3
4module test_translate() {
5 vals = [[-1,-2,-3],[0,0,0],[3,6,2],[1,2,3],[243,75,147]];
6 for (val=vals) {
7 assert_equal(translate(val), [[1,0,0,val.x],[0,1,0,val.y],[0,0,1,val.z],[0,0,0,1]]);
8 assert_equal(translate(val, p=[1,2,3]), [1,2,3]+val);
9 }
10 // Verify that module at least doesn't crash.
11 translate([-5,-5,-5]) translate([0,0,0]) translate([5,5,5]) union(){};
12}
13test_translate();
14
15
16module test_move() {
17 vals = [[-1,-2,-3],[0,0,0],[3,6,2],[1,2,3],[243,75,147]];
18 for (val=vals) {
19 assert_equal(move(val), [[1,0,0,val.x],[0,1,0,val.y],[0,0,1,val.z],[0,0,0,1]]);
20 assert_equal(move(val, p=[1,2,3]), [1,2,3]+val);
21 }
22 // Verify that module at least doesn't crash.
23 move([-5,-5,-5]) union(){};
24 move([5,5,5]) union(){};
25 sq = square(10);
26 assert_equal(move("centroid", sq), move(-centroid(sq),sq));
27 assert_equal(move("mean", vals), move(-mean(vals), vals));
28 assert_equal(move("box", vals), move(-mean(pointlist_bounds(vals)),vals));
29}
30test_move();
31
32
33module test_left() {
34 assert_equal(left(5),[[1,0,0,-5],[0,1,0,0],[0,0,1,0],[0,0,0,1]]);
35 assert_equal(left(0),[[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]]);
36 assert_equal(left(-5),[[1,0,0,5],[0,1,0,0],[0,0,1,0],[0,0,0,1]]);
37 assert_equal(left(5,p=[1,2,3]),[-4,2,3]);
38 assert_equal(left(0,p=[1,2,3]),[1,2,3]);
39 assert_equal(left(-5,p=[1,2,3]),[6,2,3]);
40 // Verify that module at least doesn't crash.
41 left(-5) left(0) left(5) union(){};
42}
43test_left();
44
45
46module test_right() {
47 assert_equal(right(-5),[[1,0,0,-5],[0,1,0,0],[0,0,1,0],[0,0,0,1]]);
48 assert_equal(right(0),[[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]]);
49 assert_equal(right(5),[[1,0,0,5],[0,1,0,0],[0,0,1,0],[0,0,0,1]]);
50 assert_equal(right(-5,p=[1,2,3]),[-4,2,3]);
51 assert_equal(right(0,p=[1,2,3]),[1,2,3]);
52 assert_equal(right(5,p=[1,2,3]),[6,2,3]);
53 // Verify that module at least doesn't crash.
54 right(-5) right(0) right(5) union(){};
55}
56test_right();
57
58
59module test_back() {
60 assert_equal(back(-5),[[1,0,0,0],[0,1,0,-5],[0,0,1,0],[0,0,0,1]]);
61 assert_equal(back(0),[[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]]);
62 assert_equal(back(5),[[1,0,0,0],[0,1,0,5],[0,0,1,0],[0,0,0,1]]);
63 assert_equal(back(-5,p=[1,2,3]),[1,-3,3]);
64 assert_equal(back(0,p=[1,2,3]),[1,2,3]);
65 assert_equal(back(5,p=[1,2,3]),[1,7,3]);
66 // Verify that module at least doesn't crash.
67 back(-5) back(0) back(5) union(){};
68}
69test_back();
70
71
72module test_fwd() {
73 assert_equal(fwd(5),[[1,0,0,0],[0,1,0,-5],[0,0,1,0],[0,0,0,1]]);
74 assert_equal(fwd(0),[[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]]);
75 assert_equal(fwd(-5),[[1,0,0,0],[0,1,0,5],[0,0,1,0],[0,0,0,1]]);
76 assert_equal(fwd(5,p=[1,2,3]),[1,-3,3]);
77 assert_equal(fwd(0,p=[1,2,3]),[1,2,3]);
78 assert_equal(fwd(-5,p=[1,2,3]),[1,7,3]);
79 // Verify that module at least doesn't crash.
80 fwd(-5) fwd(0) fwd(5) union(){};
81}
82test_fwd();
83
84
85module test_down() {
86 assert_equal(down(5),[[1,0,0,0],[0,1,0,0],[0,0,1,-5],[0,0,0,1]]);
87 assert_equal(down(0),[[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]]);
88 assert_equal(down(-5),[[1,0,0,0],[0,1,0,0],[0,0,1,5],[0,0,0,1]]);
89 assert_equal(down(5,p=[1,2,3]),[1,2,-2]);
90 assert_equal(down(0,p=[1,2,3]),[1,2,3]);
91 assert_equal(down(-5,p=[1,2,3]),[1,2,8]);
92 // Verify that module at least doesn't crash.
93 down(-5) down(0) down(5) union(){};
94}
95test_down();
96
97
98module test_up() {
99 assert_equal(up(-5),[[1,0,0,0],[0,1,0,0],[0,0,1,-5],[0,0,0,1]]);
100 assert_equal(up(0),[[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]]);
101 assert_equal(up(5),[[1,0,0,0],[0,1,0,0],[0,0,1,5],[0,0,0,1]]);
102 assert_equal(up(-5,p=[1,2,3]),[1,2,-2]);
103 assert_equal(up(0,p=[1,2,3]),[1,2,3]);
104 assert_equal(up(5,p=[1,2,3]),[1,2,8]);
105 // Verify that module at least doesn't crash.
106 up(-5) up(0) up(5) union(){};
107}
108test_up();
109
110
111module test_scale() {
112 cb = cube(1);
113 vals = [[-1,-2,-3],[1,1,1],[3,6,2],[1,2,3],[243,75,147]];
114 for (val=vals) {
115 assert_equal(scale(point2d(val)), [[val.x,0,0,0],[0,val.y,0,0],[0,0,1,0],[0,0,0,1]]);
116 assert_equal(scale(val), [[val.x,0,0,0],[0,val.y,0,0],[0,0,val.z,0],[0,0,0,1]]);
117 assert_equal(scale(val, p=[1,2,3]), v_mul([1,2,3], val));
118 scale(val) union(){};
119 }
120 assert_equal(scale(3), [[3,0,0,0],[0,3,0,0],[0,0,3,0],[0,0,0,1]]);
121 assert_equal(scale(3, p=[1,2,3]), 3*[1,2,3]);
122 assert_equal(scale(3, p=cb), cube(3));
123 assert_equal(scale(2, p=square(1)), square(2));
124 assert_equal(scale(2, cp=[1,1], p=square(1)), square(2, center=true));
125 assert_equal(scale([2,3], p=square(1)), square([2,3]));
126 assert_equal(scale([2,2], cp=[0.5,0.5], p=square(1)), move([-0.5,-0.5], p=square([2,2])));
127 assert_equal(scale([2,3,4], p=cb), cube([2,3,4]));
128 assert_equal(scale([-2,-3,-4], p=cb), [[for (p=cb[0]) v_mul(p,[-2,-3,-4])], [for (f=cb[1]) reverse(f)]]);
129 // Verify that module at least doesn't crash.
130 scale(-5) scale(5) union(){};
131}
132test_scale();
133
134
135module test_xscale() {
136 vals = [1,-1,-2,-3,10,147];
137 for (val=vals) {
138 assert_equal(xscale(val), [[val,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]]);
139 assert_equal(xscale(val, p=[1,2,3]), [val*1,2,3]);
140 xscale(val) union(){};
141 }
142 // Verify that module at least doesn't crash.
143 xscale(-5) xscale(5) union(){};
144}
145test_xscale();
146
147
148module test_yscale() {
149 vals = [1,-1,-2,-3,10,147];
150 for (val=vals) {
151 assert_equal(yscale(val), [[1,0,0,0],[0,val,0,0],[0,0,1,0],[0,0,0,1]]);
152 assert_equal(yscale(val, p=[1,2,3]), [1,val*2,3]);
153 yscale(val) union(){};
154 }
155 // Verify that module at least doesn't crash.
156 yscale(-5) yscale(5) union(){};
157}
158test_yscale();
159
160
161module test_zscale() {
162 vals = [1,-1,-2,-3,10,147];
163 for (val=vals) {
164 assert_equal(zscale(val), [[1,0,0,0],[0,1,0,0],[0,0,val,0],[0,0,0,1]]);
165 assert_equal(zscale(val, p=[1,2,3]), [1,2,val*3]);
166 zscale(val) union(){};
167 }
168 // Verify that module at least doesn't crash.
169 zscale(-5) zscale(5) union(){};
170}
171test_zscale();
172
173
174module test_mirror() {
175 vals = [LEFT,RIGHT,FWD,BACK,DOWN,UP,BACK+UP+RIGHT,FWD+LEFT];
176 for (val=vals) {
177 v = unit(val);
178 a = v.x;
179 b = v.y;
180 c = v.z;
181 m = [
182 [1-2*a*a, -2*b*a, -2*c*a, 0],
183 [ -2*a*b, 1-2*b*b, -2*c*b, 0],
184 [ -2*a*c, -2*b*c, 1-2*c*c, 0],
185 [ 0, 0, 0, 1]
186 ];
187 assert_approx(mirror(val), m, str("mirror(",val,")"));
188 assert_approx(mirror(val, p=[1,2,3]), apply(m, [1,2,3]), str("mirror(",val,",p=...)"));
189 // Verify that module at least doesn't crash.
190 mirror(val) union(){};
191 }
192}
193test_mirror();
194
195
196module test_xflip() {
197 assert_approx(xflip(), [[-1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]]);
198 assert_approx(xflip(p=[1,2,3]), [-1,2,3]);
199 // Verify that module at least doesn't crash.
200 xflip() union(){};
201}
202test_xflip();
203
204
205module test_yflip() {
206 assert_approx(yflip(), [[1,0,0,0],[0,-1,0,0],[0,0,1,0],[0,0,0,1]]);
207 assert_approx(yflip(p=[1,2,3]), [1,-2,3]);
208 // Verify that module at least doesn't crash.
209 yflip() union(){};
210}
211test_yflip();
212
213
214module test_zflip() {
215 assert_approx(zflip(), [[1,0,0,0],[0,1,0,0],[0,0,-1,0],[0,0,0,1]]);
216 assert_approx(zflip(p=[1,2,3]), [1,2,-3]);
217 // Verify that module at least doesn't crash.
218 zflip() union(){};
219}
220test_zflip();
221
222
223
224module test_rot() {
225 pts2d = 50 * [for (x=[-1,0,1],y=[-1,0,1]) [x,y]];
226 pts3d = 50 * [for (x=[-1,0,1],y=[-1,0,1],z=[-1,0,1]) [x,y,z]];
227 vecs2d = [
228 for (x=[-1,0,1], y=[-1,0,1]) if(x!=0||y!=0) [x,y],
229 polar_to_xy(1, -75),
230 polar_to_xy(1, 75)
231 ];
232 vecs3d = [
233 LEFT, RIGHT, FRONT, BACK, DOWN, UP,
234 spherical_to_xyz(1, -30, 45),
235 spherical_to_xyz(1, 0, 45),
236 spherical_to_xyz(1, 30, 45),
237 spherical_to_xyz(2, -30, 135),
238 spherical_to_xyz(1, 30, 135),
239 spherical_to_xyz(1, -30, 75),
240 spherical_to_xyz(1, 45, 45),
241 ];
242 angs = [-180, -90, 0, 30, 45, 90];
243 for (a = [-360*3:360:360*3]) {
244 assert_approx(rot(a), affine3d_identity(), info=str("rot(",a,") != identity"));
245 assert_approx(rot(a,p=pts2d), pts2d, info=str("rot(",a,",p=...), 2D"));
246 assert_approx(rot(a,p=pts3d), pts3d, info=str("rot(",a,",p=...), 3D"));
247 }
248 assert_approx(rot(90), [[0,-1,0,0],[1,0,0,0],[0,0,1,0],[0,0,0,1]]);
249 for (a=angs) {
250 assert_approx(rot(a), affine3d_zrot(a), info=str("Z angle (only) = ",a));
251 assert_approx(rot([a,0,0]), affine3d_xrot(a), info=str("X angle = ",a));
252 assert_approx(rot([0,a,0]), affine3d_yrot(a), info=str("Y angle = ",a));
253 assert_approx(rot([0,0,a]), affine3d_zrot(a), info=str("Z angle = ",a));
254
255 assert_approx(rot(a,p=pts2d), apply(affine3d_zrot(a),pts2d), info=str("Z angle (only) = ",a, ", p=..., 2D"));
256 assert_approx(rot([0,0,a],p=pts2d), apply(affine3d_zrot(a),pts2d), info=str("Z angle = ",a, ", p=..., 2D"));
257
258 assert_approx(rot(a,p=pts3d), apply(affine3d_zrot(a),pts3d), info=str("Z angle (only) = ",a, ", p=..., 3D"));
259 assert_approx(rot([a,0,0],p=pts3d), apply(affine3d_xrot(a),pts3d), info=str("X angle = ",a, ", p=..., 3D"));
260 assert_approx(rot([0,a,0],p=pts3d), apply(affine3d_yrot(a),pts3d), info=str("Y angle = ",a, ", p=..., 3D"));
261 assert_approx(rot([0,0,a],p=pts3d), apply(affine3d_zrot(a),pts3d), info=str("Z angle = ",a, ", p=..., 3D"));
262 }
263 for (xa=angs, ya=angs, za=angs) {
264 assert_approx(
265 rot([xa,ya,za]),
266 affine3d_zrot(za) * affine3d_yrot(ya) * affine3d_xrot(xa),
267 info=str("[X,Y,Z] = ",[xa,ya,za])
268 );
269 assert_approx(
270 rot([xa,ya,za],p=pts3d),
271 apply(
272 affine3d_zrot(za) * affine3d_yrot(ya) * affine3d_xrot(xa),
273 pts3d
274 ),
275 info=str("[X,Y,Z] = ",[xa,ya,za], ", p=...")
276 );
277 }
278 for (vec1 = vecs3d) {
279 for (ang = angs) {
280 assert_approx(
281 rot(a=ang, v=vec1),
282 affine3d_rot_by_axis(vec1,ang),
283 info=str("a = ",ang,", v = ", vec1)
284 );
285 assert_approx(
286 rot(a=ang, v=vec1, p=pts3d),
287 apply(affine3d_rot_by_axis(vec1,ang), pts3d),
288 info=str("a = ",ang,", v = ", vec1, ", p=...")
289 );
290 }
291 }
292 for (vec1 = vecs2d) {
293 for (vec2 = vecs2d) {
294 assert_approx(
295 rot(from=vec1, to=vec2, p=pts2d),
296 apply(affine2d_zrot(v_theta(vec2)-v_theta(vec1)), pts2d),
297 info=str(
298 "from = ", vec1, ", ",
299 "to = ", vec2, ", ",
300 "p=..., 2D"
301 )
302 );
303 }
304 }
305 for (vec1 = vecs3d) {
306 for (vec2 = vecs3d) {
307 for (a = angs) {
308 assert_approx(
309 rot(from=vec1, to=vec2, a=a),
310 affine3d_rot_from_to(vec1,vec2) * affine3d_rot_by_axis(vec1,a),
311 info=str(
312 "from = ", vec1, ", ",
313 "to = ", vec2, ", ",
314 "a = ", a
315 )
316 );
317 assert_approx(
318 rot(from=vec1, to=vec2, a=a, p=pts3d),
319 apply(
320 affine3d_rot_from_to(vec1,vec2) * affine3d_rot_by_axis(vec1,a),
321 pts3d
322 ),
323 info=str(
324 "from = ", vec1, ", ",
325 "to = ", vec2, ", ",
326 "a = ", a, ", ",
327 "p=..., 3D"
328 )
329 );
330 }
331 }
332 }
333}
334test_rot();
335
336
337module test_xrot() {
338 vals = [-270,-135,-90,45,0,30,45,90,135,147,180];
339 path = path3d(pentagon(d=100), 50);
340 for (a=vals) {
341 m = [[1,0,0,0],[0,cos(a),-sin(a),0],[0,sin(a),cos(a),0],[0,0,0,1]];
342 assert_approx(xrot(a), m);
343 assert_approx(xrot(a, p=path[0]), apply(m, path[0]));
344 assert_approx(xrot(a, p=path), apply(m, path));
345 // Verify that module at least doesn't crash.
346 xrot(a) union(){};
347 }
348}
349test_xrot();
350
351
352module test_yrot() {
353 vals = [-270,-135,-90,45,0,30,45,90,135,147,180];
354 path = path3d(pentagon(d=100), 50);
355 for (a=vals) {
356 m = [[cos(a),0,sin(a),0],[0,1,0,0],[-sin(a),0,cos(a),0],[0,0,0,1]];
357 assert_approx(yrot(a), m);
358 assert_approx(yrot(a, p=path[0]), apply(m, path[0]));
359 assert_approx(yrot(a, p=path), apply(m, path));
360 // Verify that module at least doesn't crash.
361 yrot(a) union(){};
362 }
363}
364test_yrot();
365
366
367module test_zrot() {
368 vals = [-270,-135,-90,45,0,30,45,90,135,147,180];
369 path = path3d(pentagon(d=100), 50);
370 for (a=vals) {
371 m = [[cos(a),-sin(a),0,0],[sin(a),cos(a),0,0],[0,0,1,0],[0,0,0,1]];
372 assert_approx(zrot(a), m);
373 assert_approx(zrot(a, p=path[0]), apply(m, path[0]));
374 assert_approx(zrot(a, p=path), apply(m, path));
375 // Verify that module at least doesn't crash.
376 zrot(a) union(){};
377 }
378}
379test_zrot();
380
381
382
383module test_frame_map() {
384 assert(approx(frame_map(x=[1,1,0], y=[-1,1,0]), affine3d_zrot(45)));
385 assert(approx(frame_map(x=[0,1,0], y=[0,0,1]), rot(v=[1,1,1],a=120)));
386}
387test_frame_map();
388
389
390module test_skew() {
391 m = affine3d_skew(sxy=2, sxz=3, syx=4, syz=5, szx=6, szy=7);
392 assert_approx(skew(sxy=2, sxz=3, syx=4, syz=5, szx=6, szy=7), m);
393 assert_approx(skew(sxy=2, sxz=3, syx=4, syz=5, szx=6, szy=7, p=[1,2,3]), apply(m,[1,2,3]));
394 // Verify that module at least doesn't crash.
395 skew(undef,2,3,4,5,6,7) union(){};
396}
397test_skew();
398
399
400module test_apply() {
401 assert(approx(apply(affine3d_xrot(90),2*UP),2*FRONT));
402 assert(approx(apply(affine3d_yrot(90),2*UP),2*RIGHT));
403 assert(approx(apply(affine3d_zrot(90),2*UP),2*UP));
404 assert(approx(apply(affine3d_zrot(90),2*RIGHT),2*BACK));
405 assert(approx(apply(affine3d_zrot(90),2*BACK+2*RIGHT),2*BACK+2*LEFT));
406 assert(approx(apply(affine3d_xrot(135),2*BACK+2*UP),2*sqrt(2)*FWD));
407 assert(approx(apply(affine3d_yrot(135),2*RIGHT+2*UP),2*sqrt(2)*DOWN));
408 assert(approx(apply(affine3d_zrot(45),2*BACK+2*RIGHT),2*sqrt(2)*BACK));
409
410 module check_path_apply(mat,path)
411 assert_approx(apply(mat,path),path3d([for (p=path) mat*concat(p,1)]));
412
413 check_path_apply(xrot(45), path3d(rect(100)));
414 check_path_apply(yrot(45), path3d(rect(100)));
415 check_path_apply(zrot(45), path3d(rect(100)));
416 check_path_apply(rot([20,30,40])*scale([0.9,1.1,1])*move([10,20,30]), path3d(rect(100)));
417
418 module check_patch_apply(mat,patch)
419 assert_approx(apply(mat,patch), [for (path=patch) path3d([for (p=path) mat*concat(p,1)])]);
420
421 flat = [for (x=[-50:25:50]) [for (y=[-50:25:50]) [x,y,0]]];
422 check_patch_apply(xrot(45), flat);
423 check_patch_apply(yrot(45), flat);
424 check_patch_apply(zrot(45), flat);
425 check_patch_apply(rot([20,30,40])*scale([0.9,1.1,1])*move([10,20,30]), flat);
426}
427test_apply();
428
429
430module test_is_2d_transform() {
431 assert(!is_2d_transform(affine2d_identity()));
432 assert(!is_2d_transform(affine2d_translate([5,8])));
433 assert(!is_2d_transform(affine2d_scale([3,4])));
434 assert(!is_2d_transform(affine2d_zrot(30)));
435 assert(!is_2d_transform(affine2d_mirror([-1,1])));
436 assert(!is_2d_transform(affine2d_skew(30,15)));
437
438 assert(is_2d_transform(affine3d_identity()));
439 assert(is_2d_transform(affine3d_translate([30,40,0])));
440 assert(!is_2d_transform(affine3d_translate([30,40,50])));
441 assert(is_2d_transform(affine3d_scale([3,4,1])));
442 assert(!is_2d_transform(affine3d_xrot(30)));
443 assert(!is_2d_transform(affine3d_yrot(30)));
444 assert(is_2d_transform(affine3d_zrot(30)));
445 assert(is_2d_transform(affine3d_skew(sxy=2)));
446 assert(is_2d_transform(affine3d_skew(syx=2)));
447 assert(!is_2d_transform(affine3d_skew(szx=2)));
448 assert(!is_2d_transform(affine3d_skew(szy=2)));
449}
450test_is_2d_transform();
451
452
453
454
455
456
457// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap