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