dictionaryopenscad3d-printing

associative arrays in openscad?


Does openscad have any language primitive for string-keyed associative arrays (a.k.a hash maps, a.k.a dictionaries)? Or is there any convention for how to emulate associative arrays?

So far all I can think of is using vectors and using variables to map indexes into the vector to human readable names. That means there's no nice, readable way to define the vector, you just have to comment it.

Imagine I want to write something akin to the Python data structure:

bobbin_metrics = {
   'majacraft': {
      'shaft_inner_diameter': 9.0,
      'shaft_outer_diameter': 19.5,
      'close_wheel_diameter': 60.1,
      # ...
   },
   'majacraft_jumbo': {
      'shaft_inner_diameter': 9.0,
      'shaft_outer_diameter': 25.0,
      'close_wheel_diameter': 100.0,
   },
   # ...
}

such that I can reference it in model definitions in some recognisably hash-map-like way, like passing bobbin_metrics['majacraft'] to something as metrics and referencing metrics['close_wheel_diameter'].

So far my best effort looks like

# Vector indexes into bobbin-metrics arrays
BM_SHAFT_INNER_DIAMETER = 0
BM_SHAFT_OUTER_DIAMETER = 1
BM_CLOSE_WHEEL_DIAMETER = 2

bobbin_metrics_majacraft = [
    9.0,      # shaft inner diameter
    19.5,     # shaft outer diameter
    60.1,     # close-side wheel diameter
    # ....
];

bobbin_metrics_majacraft_jumbo = [
    9.0,      # shaft inner diameter
    25.0,     # shaft outer diameter
    100.0,     # close-side wheel diameter
    # ....
];

bobbin_metrics = [
    bobbin_metrics_majacraft,
    bobbin_metrics_majacraft_jumbo,
    # ...
];

# Usage when passed a bobbin metrics vector like
# bobbin_metrics_majacraft as 'metrics' to a function

    metrics[BM_SHAFT_INNER_DIAMETER]

I think that'll work. But it's U.G.L.Y.. Not quite "I write applications in bash" ugly, but not far off.

Is there a better way?

I'm prepared to maintain the data set outside openscad and have a generator for an include file if I have to, but I'd rather not.


Also, in honour of April 1 I miss the blink tag and wonder if the scrolling marquee will work? Tried 'em :)


Solution

  • I played around with the OpenSCAD search() function which is documented in the manual here;

    https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Other_Language_Features#Search
    

    The following pattern allows a form of associative list, it may not be optimal but does provide a way to set up a dictionary structure and retrieve a value against a string key;

    // associative searching
    // dp 2019
    // - define the dictionary
    dict = [
          ["shaft_inner_diameter", 9.0],
          ["shaft_outer_diameter", 19.5],
          ["close_wheel_diameter", 60.1]
          ];
    
    // specify the serach term
    term = "close_wheel_diameter";
    
    // execute the search
    find = search(term, dict);
    
    // process results
    echo("1", find);
    echo ("2",dict[find[0]]);
    echo ("3",dict[find[0]][1]);
    

    The above produces;

    Compiling design (CSG Tree generation)...
      WARNING: search term not found: "l"
    ...
      WARNING: search term not found: "r"
    ECHO: "1", [2, 0]
    ECHO: "2", ["close_wheel_diameter", 60.1]
    ECHO: "3", 60.1    
    

    Personally, I would do this sort of thing in Python then generate the OpenSCAD as an intermediate file or maybe use the SolidPython library.