omdl  v0.9.5
OpenSCAD Mechanical Design Library
Script
include <omdl-base.scad>;
include <common/validation.scad>;
echo( str("openscad version ", version()) );
// test-values columns
test_c =
[
["id", "identifier"],
["td", "description"],
["tv", "test value"]
];
// test-values rows
test_r =
[
["fac", "Function argument count", undef
],
["crp", "Result precision", undef
],
["t01", "All undefined", [undef,undef,undef,undef,undef,undef]
],
],
["t03", "All scalars", [60, 50, 40, 30, 20, 10]
],
["t04", "All 1d vectors", [[99], [58], [12], [42], [15], [1]]
],
["t05", "All 2d vectors", [
[99,2], [58,16], [12,43],
[42,13], [15,59], [1,85]
]
],
["t06", "All 3d vectors", [
[199,20,55], [158,116,75], [12,43,90],
[42,13,34], [15,59,45], [62,33,69]
]
],
["t07", "All 4d vectors", [
[169,27,35,10], [178,016,25,20], [12,43,90,30],
[42,13,34,60], [15,059,45,50], [62,33,69,40]
]
],
["t08", "Orthogonal vectors", [
]
],
["t09", "Coplanar vectors", [
+x_axis3d_uv, +y_axis3d_uv, [2,2,0],
]
]
];
test_ids = table_get_row_ids( test_r );
// expected columns: ("id" + one column for each test)
good_c = merge_p([concat("id", test_ids), concat("identifier", test_ids)]);
// expected rows: ("golden" test results), use 'skip' to skip test
skip = -1; // skip test
good_r =
[ // function
["distance_pp",
2, // fac
4, // crp
undef, // t01
undef, // t02
undef, // t03
undef, // t04
43.3244, // t05
106.2873, // t06
undef, // t07
1.4142, // t08
1.4142 // t09
],
["is_left_ppp",
3, // fac
4, // crp
undef, // t01
undef, // t02
undef, // t03
undef, // t04
-463, // t05
17009, // t06
undef, // t07
1, // t08
-3 // t09
],
["point_to_3d",
1, // fac
4, // crp
undef, // t01
undef, // t02
undef, // t03
undef, // t04
[99,2,0], // t05
[199,20,55], // t06
undef, // t07
x_axis3d_uv, // t08
x_axis3d_uv // t09
],
["line_dim",
2, // fac
4, // crp
undef, // t01
undef, // t02
2, // t03
undef, // t04
2, // t05
3, // t06
undef, // t07
3, // t08
3 // t09
],
["line_tp",
2, // fac
4, // crp
undef, // t01
undef, // t02
[60,50], // t03
undef, // t04
[58,16], // t05
[158,116,75], // t06
undef, // t07
y_axis3d_uv, // t08
y_axis3d_uv // t09
],
["line_ip",
2, // fac
4, // crp
undef, // t01
undef, // t02
origin2d, // t03
undef, // t04
[99,2], // t05
[199,20,55], // t06
undef, // t07
x_axis3d_uv, // t08
x_axis3d_uv // t09
],
["vol_to_origin",
2, // fac
4, // crp
undef, // t01
undef, // t02
[60,50], // t03
undef, // t04
[-41,14], // t05
[-41,96,20], // t06
undef, // t07
[-1,1,0], // t08
[-1,1,0] // t09
],
["dot_ll",
4, // fac
4, // crp
undef, // t01
undef, // t02
3900, // t03
undef, // t04
-1650, // t05
-5230, // t06
undef, // t07
1, // t08
0 // t09
],
["cross_ll",
4, // fac
4, // crp
skip, // t01
skip, // t02
skip, // t03
skip, // t04
810, // t05
[-4776,-1696,-1650], // t06
skip, // t07
[-1,-1,1], // t08
[0,0,4] // t09
],
["striple_lll",
6, // fac
4, // crp
skip, // t01
skip, // t02
skip, // t03
skip, // t04
[-14760,5040], // t05
-219976, // t06
skip, // t07
-2, // t08
0 // t09
],
["angle_ll",
4, // fac
4, // crp
undef, // t01
undef, // t02
-2.9357, // t03
undef, // t04
153.8532, // t05
134.4573, // t06
undef, // t07
60, // t08
90 // t09
],
["angle_lll",
6, // fac
4, // crp
skip, // t01
skip, // t02
skip, // t03
skip, // t04
skip, // t05
-91.362, // t06
skip, // t07
-63.4349, // t08
0 // t09
],
["unit_l",
2, // fac
4, // crp
undef, // t01
undef, // t02
[.7682,0.6402], // t03
undef, // t04
[-0.9464,0.3231], // t05
[-0.3857,0.9032,0.1882], // t06
undef, // t07
[-0.7071,0.7071,0], // t08
[-0.7071,0.7071,0] // t09
],
["are_coplanar_lll",
6, // fac
4, // crp
skip, // t01
skip, // t02
skip, // t03
skip, // t04
skip, // t05
false, // t06
skip, // t07
false, // t08
true // t09
],
["plane_to_normal",
2, // fac
4, // crp
skip, // t01
skip, // t02
[60,50,0], // t03
skip, // t04
[0,0,1468], // t05
[-4880,-6235,19924], // t06
skip, // t07
z_axis3d_uv, // t08
z_axis3d_uv // t09
]
];
// sanity-test tables
table_check( test_r, test_c, false );
table_check( good_r, good_c, false );
// validate helper function and module
function get_value( vid ) = table_get_value(test_r, test_c, vid, "tv");
function gv( vid, e ) = get_value( vid )[e];
module log_test( m ) { log_type ( "test", m ); }
module log_skip( f ) { log_test ( str("ignore: '", f, "'") ); }
module run( fname, vid )
{
value_text = table_get_value(test_r, test_c, vid, "td");
if ( table_get_value(good_r, good_c, fname, vid) != skip )
children();
else
log_test( str(vid, " -skip-: '", fname, "(", value_text, ")'") );
}
module test( fname, fresult, vid, pair )
{
value_text = table_get_value(test_r, test_c, vid, "td");
fname_argc = table_get_value(good_r, good_c, fname, "fac");
comp_prcsn = table_get_value(good_r, good_c, fname, "crp");
pass_value = table_get_value(good_r, good_c, fname, vid);
test_pass = validate(cv=fresult, t="almost", ev=pass_value, p=comp_prcsn, pf=true);
farg_text = (pair == true)
? strl(append_e(", ", sequence_ns(select_r(get_value(vid), [0:fname_argc-1]), n=2, s=2), r=false, j=false, l=false))
: strl(append_e(", ", select_r(get_value(vid), [0:fname_argc-1]), r=false, j=false, l=false));
test_text = validate(str(fname, "(", farg_text, ")=", pass_value), fresult, "almost", pass_value, comp_prcsn);
if ( pass_value != skip )
{
if ( !test_pass )
log_test( str(vid, " ", test_text, " (", value_text, ")") );
else
log_test( str(vid, " ", test_text) );
}
else
log_test( str(vid, " -skip-: '", fname, "(", value_text, ")'") );
}
// Indirect function calls would be very useful here!!!
run_ids = delete( test_ids, mv=["fac", "crp"] );
// set 1: identify
log_skip( "is_point()" );
log_skip( "is_vector()" );
log_skip( "is_line()" );
log_skip( "is_vol()" );
log_skip( "is_plane()" );
// set 2: point
for (vid=run_ids) run("distance_pp",vid) test( "distance_pp", distance_pp(gv(vid,0),gv(vid,1)), vid, false );
log_skip( "distance_pl()" );
log_skip( "distance_pn()" );
for (vid=run_ids) run("is_left_ppp",vid) test( "is_left_ppp", is_left_ppp(gv(vid,0),gv(vid,1),gv(vid,2)), vid, false );
log_skip( "point_closest_pl()" );
log_skip( "point_closest_pn()" );
for (vid=run_ids) run("point_to_3d",vid) test( "point_to_3d", point_to_3d(gv(vid,0)), vid, false );
log_skip( "interpolate2d_l_pp()" );
// set 3: vector
// set 4: line (or vector)
log_skip( "line2d_new()" );
log_skip( "line3d_new()" );
log_skip( "line_new()" );
for (vid=run_ids) run("line_dim",vid) test( "line_dim", line_dim([gv(vid,0),gv(vid,1)]), vid, true );
for (vid=run_ids) run("line_tp",vid) test( "line_tp", line_tp([gv(vid,0),gv(vid,1)]), vid, true );
for (vid=run_ids) run("line_ip",vid) test( "line_ip", line_ip([gv(vid,0),gv(vid,1)]), vid, true );
for (vid=run_ids) run("vol_to_origin",vid) test( "vol_to_origin", vol_to_origin([gv(vid,0),gv(vid,1)]), vid, true );
log_skip( "vol_to_point()" );
for (vid=run_ids) run("dot_ll",vid) test( "dot_ll", dot_ll([gv(vid,0),gv(vid,1)],[gv(vid,2),gv(vid,3)]), vid, true );
for (vid=run_ids) run("cross_ll",vid) test( "cross_ll", cross_ll([gv(vid,0),gv(vid,1)],[gv(vid,2),gv(vid,3)]), vid, true );
for (vid=run_ids) run("striple_lll",vid) test( "striple_lll", striple_lll([gv(vid,0),gv(vid,1)],[gv(vid,2),gv(vid,3)],[gv(vid,4),gv(vid,5)]), vid, true );
for (vid=run_ids) run("angle_ll",vid) test( "angle_ll", angle_ll([gv(vid,0),gv(vid,1)],[gv(vid,2),gv(vid,3)]), vid, true );
for (vid=run_ids) run("angle_lll",vid) test( "angle_lll", angle_lll([gv(vid,0),gv(vid,1)],[gv(vid,2),gv(vid,3)],[gv(vid,4),gv(vid,5)]), vid, true );
for (vid=run_ids) run("unit_l",vid) test( "unit_l", unit_l([gv(vid,0),gv(vid,1)]), vid, true );
for (vid=run_ids) run("are_coplanar_lll",vid) test( "are_coplanar_lll", are_coplanar_lll([gv(vid,0),gv(vid,1)],[gv(vid,2),gv(vid,3)],[gv(vid,4),gv(vid,5)]), vid, true );
// set 5: plane and pnorm
for (vid=run_ids) run("plane_to_normal",vid) test( "plane_to_normal", plane_to_normal([gv(vid,0),gv(vid,1)]), vid, true );
// end_include
module log_type(t, m)
Output diagnostic message to console.
Definition: console.scad:284
x_axis3d_uv
<vector-3d> The unit vector of the positive x-axis in 3d Euclidean space.
Definition: constants.scad:428
z_axis3d_uv
<vector-3d> The unit vector of the positive z-axis in 3d Euclidean space.
Definition: constants.scad:434
origin2d
<point-2d> The origin point coordinate in 2d Euclidean space.
Definition: constants.scad:407
origin3d
<point-3d> The origin point coordinate in 3-dimensional Euclidean space.
Definition: constants.scad:425
y_axis3d_uv
<vector-3d> The unit vector of the positive y-axis in 3d Euclidean space.
Definition: constants.scad:431
empty_lst
<list> A list with no values (the empty list).
Definition: constants.scad:304
function validate(d, cv, t, ev, p=4, pf=false)
Compare a computed test value with an known good result.
function line_tp(l)
Return the terminal point of a line or vector.
function dot_ll(l1, l2)
Compute the dot product of two lines or vectors in a 3d or 2d-space.
function are_coplanar_lll(l1, l2, l3, d=6)
Test if three lines or vectors are coplanar in 3d-space.
function angle_ll(l1, l2, s=true)
Compute the angle between two lines or vectors in a 3d or 2d-space.
function line_dim(l)
Return the number of dimensions of a line or vector.
function striple_lll(l1, l2, l3)
Compute the scalar triple product of three lines or vectors in a 3d or 2d-space.
function angle_lll(l1, l2, n)
Compute the angle between two lines or vectors in a 3d-space.
function vol_to_origin(l)
Convert line to vector by shifting it to the origin.
function point_to_3d(p)
Return 3d point unchanged or add a zeroed third dimension to 2d point.
function line_ip(l)
Return the initial point of a line or vector.
function cross_ll(l1, l2)
Compute the cross product of two lines or vectors in a 3d or 2d-space.
function is_left_ppp(p1, p2, p3)
Test if a point is left, on, or right of an infinite line in a 2d-space.
function unit_l(l)
Compute the normalized unit vector of a line or vector.
function plane_to_normal(n, cw=true)
Convert a planes' normal specification into a normal vector.
function distance_pp(p1, p2)
Compute the distance between two points.
function select_r(v, i)
Select a range of elements from an iterable value.
function append_e(nv, v, r=true, j=true, l=true)
Append a value to each element of an iterable value.
function sequence_ns(v, n=1, s=1, w=false)
Return a list of all n-element sequential-subsets of an iterable value.
function strl(v)
Convert a list of values to a concatenated string.
function merge_p(v, j=true)
Parallel-merge the iterable elements of a list.
module table_check(r, c, verbose=false)
Perform basic format checks on a table and output errors to console.
Definition: table.scad:595
function table_get_row_ids(r)
Form a list of all table row identifiers.
function table_get_value(r, c, ri, ci)
Get the table cell value for a specified row and column identifier.