Search code examples
moduleoverloadingopenscad

Switch on argument type


Using Open SCAD, I have a module that, like cube(), has a size parameter that can be a single value or a vector of three values. Ultimately, I want a vector of three values.

If the caller passes a single value, I'd like all three values of the vector to be the same. I don't see anything in the language documentation about detecting the type of an argument. So I came up with this hack:

module my_cubelike_thing(size=1) {
  dimensions = concat(size, size, size);
  width  = dimensions[0];
  length = dimensions[1];
  height = dimensions[2];
  // ... use width, length, and height ...
}

When size is a single value, the result of the concat is exactly what I want: three copies of the value.

When size is a three-value vector, the result of the concat is nine-value vector, and my code just ignores the last six values.

It works but only because what I want in the single value case is to replicate the value. Is there a general way to switch on the argument type and do different things depending on that type?


Solution

  • If type of size only can be single value or a vector with 3 values, the type can helpwise be found by the special value undef:

    a = [3,5,8];
    // a = 5;
    if (a[0] == undef) {
        dimensions = concat(a, a, a);
        // do something
        cube(size=dimensions,center=false);
    }
    else {
        dimensions = a;
        // do something
        cube(size=dimensions,center=false);
    }
    

    But assignments are only valid in the scope in which they are defined , documnetation of openscad. So in each subtree much code is needed and i would prefere to validate the type of size in an external script (e.g. python3) and write the openscad-code with the assignment of variables to a file, which can be included in the openscad-file, here my short test-code:

    #!/usr/bin/env python3
    # -*- coding: utf-8 -*-
    
    import os
    
    # size = 20
    size = [20,15,10]
    
    if type(size) == int:
        dimensions = [size, size, size]
    elif type(size) == list:
        dimensions = size
    else:
        # if other types possible
        pass
    
    with open('variablen.scad', 'w') as wObj:
        for i, v in enumerate(['l', 'w', 'h']):
            wObj.write('{} = {};\n'.format(v, dimensions[i]))
    
    os.system('openscad ./typeDef.scad')
    

    content of variablen.scad:

    l = 20;
    w = 15;
    h = 10;
    

    and typeDef.scad can look like this

    include <./variablen.scad>;
    
    module my_cubelike_thing() {
        linear_extrude(height=h, center=false) square(l, w);
    }
    
    my_cubelike_thing();