ассоциативные массивы в openscad?

#dictionary #openscad #3d-printing

#словарь #openscad #3d-печать

Вопрос:

Есть ли в openscad какой-либо языковой примитив для ассоциативных массивов со строковыми ключами (он же хэш-карты, он же словари)? Или есть какое-либо соглашение о том, как эмулировать ассоциативные массивы?

Пока все, о чем я могу думать, — это использовать векторы и переменные для сопоставления индексов в векторе с именами, удобочитаемыми человеком. Это означает, что нет хорошего, читаемого способа определить вектор, вам просто нужно его прокомментировать.

Представьте, что я хочу написать что-то похожее на структуру данных Python:

 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,
   },
   # ...
}
  

такой, что я могу ссылаться на него в определениях моделей каким-то узнаваемым способом, подобным хэш-карте, например, передавая bobbin_metrics['majacraft'] что-то как metrics и ссылаясь metrics['close_wheel_diameter'] .

Пока что мои лучшие усилия выглядят так

 # 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]
  

Я думаю, это сработает. Но это U.G.L.Y.. Не совсем «я пишу приложения на bash «, некрасиво, но недалеко.

Есть ли способ лучше?

Я готов поддерживать набор данных за пределами openscad и иметь генератор для включаемого файла, если потребуется, но я бы предпочел этого не делать.


Кроме того, в честь 1 апреля я пропускаю тег blink и задаюсь вопросом, будет ли работать маркер прокрутки? Пробовал их 🙂

Ответ №1:

Я поиграл с функцией OpenSCAD search (), которая описана в приведенном здесь руководстве;

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

Следующий шаблон допускает форму ассоциативного списка, возможно, он не является оптимальным, но предоставляет способ настроить структуру словаря и получить значение по строковому ключу;

 // 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]);
  

Вышесказанное приводит к;

 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    
  

Лично я бы сделал что-то подобное на Python, а затем сгенерировал OpenSCAD в качестве промежуточного файла или, возможно, использовал библиотеку SolidPython.

Комментарии:

1. работает на Archlinux, openscad 2015.03-3, но только с шаблонами соответствия максимум 15 символов

2. Большое вам спасибо. Это отличная идея.

Ответ №2:

Пример функции, которая использует search() и не выдает никаких предупреждений.

 available_specs = [
  ["mgn7c", 1,2,3,4],
  ["mgn7h", 2,3,4,5],
];

function selector(item) = available_specs[search([item], available_specs)[0]];

chosen_spec = selector("mgn7c");

echo("Specification was returned from function", chosen_spec);
  

Вышесказанное приведет к следующему результату:

 ECHO: "Specification was returned from function", ["mgn7c", 1, 2, 3, 4]
  

Другой очень похожий подход заключается в использовании понимания списка с помощью оператора condition, точно так же, как, например, в Python. Делает то же самое, выглядит немного проще.

 function selector(item) = [
  for (spec = available_specs)
  if (spec[0] == item)
  spec
];