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