OpenFlexure Microscope OpenSCAD docs

libs/libdict.scad

function _is_in_str(value, list)
[Source]
function _is_in_str(value, list) =
    search([value], list) != [[]];
function _is_in_num(value, list)
[Source]
function _is_in_num(value, list) =
    search(value, list) != [];
function is_in(value, list)
[Source]
function is_in(value, list) =
    assert(is_num(value) || is_string(value) , "is_in: value must be a number or string")
    assert(is_list(list), "is_in: list must be a list")
    is_num(value) ? _is_in_num(value, list) : _is_in_str(value, list);
function _libdict_sum_list(list, starting_element=0, running_total=0)
[Source]
function _libdict_sum_list(list, starting_element=0, running_total=0) =
    starting_element >= len(list) ?
        running_total :
        _libdict_sum_list(list, starting_element + 1, running_total + list[starting_element]);

* * Sum a list * This recursive function sums a list. It should be called with one * argument (the list); the other two arguments simply allow it to be * "tail-recursive" which lets OpenSCAD optimise it better. This is * very close to the example given in the OpenSCAD docs.

function _check_errant_match(list, match)
[Source]
function _check_errant_match(list, match) = let(
    non_list = [for (m = match) is_list(list[m])? 0 : 1],
    number_of_non_lists = _libdict_sum_list(non_list)
) number_of_non_lists == 1 ? 0 : 1;

* * When checking a list for uniqueness, we can get "errant matches". * An errant match is when a non-list matches with the first element in a list. * i.e. it would consider [1, [1,0]] to be non-unique. We cannot know which * element is the non-list but we do know that it is errant if exactly one * of them is not a list. * If two elements are non-lists, they must be identical in order to have matched.
* Similarly, if all elements are lists, they must be identical because search * will have matched them as whole lists. * The argument "list" is the list we are checking for uniqueness, and "match" is * a vector of indices that have been returned by search.

function is_unique(list)
[Source]
function is_unique(list) =
    assert(is_list(list), "is_unique: list must be a list")
    let(
        matches = search(list, list, 0),
        // Assign 1 or 0 depending on is the match length for each element
        // return wether any matches are greater than one (mathcing more than
        // itself)
        // note cannot search for true or false so using 1 and zero
        bool_list = [for (match = matches) if (len(match)==1) 0
            // should put a 1 here to show they matched but in the case of
            // [1, [1]] it will match both, so need to check if they are
            // both lists or both not list
            else _check_errant_match(list, match)]
    ) !is_in(1, bool_list);
function _is_pairs(list)
[Source]
function _is_pairs(list) =
    !is_list(list) ? false :
        len(list)==0 ? false :
            !is_in(0, [for (pair = list) is_list(pair) && len(pair)==2 ? 1: 0]);
function _is_list_of_strings(list)
[Source]
function _is_list_of_strings(list) =
    !is_in(0, [for (item = list) is_string(item) && len(item)>0 ? 1: 0]);
function _keylist(dict)
[Source]
function _keylist(dict)  = [for (pair=dict) pair[0]];
function valid_dict(dict)
[Source]
function valid_dict(dict) =
    //if the input are not pairs return instantly
    !_is_pairs(dict) ? false : let (
        //if they are pairs get all keys
        keys = _keylist(dict),
        all_strings =  _is_list_of_strings(keys),
        unique = is_unique(keys)
    ) (all_strings && unique) ? true : false;
function key_lookup(key, dict)
[Source]
function key_lookup(key, dict) =
    assert(is_string(key), "`key` must be a string")
    assert(valid_dict(dict), "`dict` must be a valid 'dictionary'")
    let(
        // key is in [] because otherwise openscad will search for each letter rather than the string.
        index = search([key], dict, 1, 0)[0]
    )  assert (index!=[], "Key lookup failed, key not found!") dict[index][1];
function replace_value(key, value, dict)
[Source]
function replace_value(key, value, dict) =
    assert(is_string(key), "`key` must be a string")
    assert(valid_dict(dict), "`dict` must be a valid 'dictionary'")
    assert(is_in(key, _keylist(dict)), "`key` not found in dictionary!")
    [for (kv_pair = dict) key!=kv_pair[0] ? kv_pair : [key, value]];
function replace_multiple_values(rep_dict, dict)
[Source]
function replace_multiple_values(rep_dict, dict) =
    assert(valid_dict(rep_dict), "`rep dict` must be a valid 'dictionary'")
    assert(valid_dict(dict), "`dict` must be a valid 'dictionary'")
    let(
        // loop over all keys in replacement dict checking they are in the original
        rep_keys = [for (key = _keylist(rep_dict))
            assert(is_in(key, _keylist(dict)), "`key` not found in dictionary!")
            key
        ]
    ) //Finally return the updated dictionary using this long list comprehension.
    [
        for (kv_pair = dict) let(
            key = kv_pair[0],
            // check if this key is in the replacement dictionary and if so return index
            // key is in [] because otherwise openscad will search for each letter rather
            // than the string.
            index = search([key], rep_dict, 1, 0)[0]
            // if index is empty return original key value pair, else return the key with
            // the replaced value
        ) index == [] ? kv_pair : [key, rep_dict[index][1]]
    ];