суббота, 28 декабря 2019 г.

OpenSCAD. Функции, модули, библиотеки

Функции в OpenSCAD предназначены для вычисления каких-либо значений и всегда возвращают свой результат. Объявление функции имеет вид 

    function название(список_аргументов) = тело_функции;

При объявлении можно задавать значения аргументов по умолчанию с помощью знака равенства. В вызове функции агрументы могут быть просто перечислены в порядке объявления, либо переданы по имени. Язык программирования поддерживает использование тернарного оператора условие ? действие_1 : действие_2, который может быть использован, в частности, для организации рекурсивных вызовов. 


В качестве примера рассмотрим функцию poly(), вычисляющую значение полинома в точке x по схеме Горнера. Коэффициенты полинома заданы в виде вектора. Поскольку, язык не допускает изменение значения переменной, вместо цикла использована рекурсия. Основная работа происходит во вспомогательной функции poly1(), которая сравнивает счётчик с длиной вектора коэффициентов (функция len()) и рекурсивно вычисляет результат. Команда let() позволяет объявить временные переменные в теле функции для упрощения дальнейших вычислений. Результат выводится в консоль функцией echo(), которая отображает значения всех своих аргументов. 


Согласно описанию, в OpenSCAD можно создавать лямбда-функции и присваивать их переменным в let(), однако, у меня данный функционал не заработал. Возможно, дело в версии программы. 

В отличие от функции, модуль не возвращает значения, а строит объекты или определяет операции над ними. Синтаксис объявления имеет вид 

    module название(список_аргументов) { тело_модуля } 

Тело модуля может включать в себя практически любые инструкции, разрешённые в OpenSCAD, включая объявление вспомогательных функций и модулей. Можно даже строить объекты с помощью рекурсивных вызовов, главное, помнить про ограниченность глубины стека.

В качестве примера создадим модуль, который строит простого снеговика из 5-ти шаров. Можно заметить, что если за точку отсчёта взять средний шар ("тело"), то остальные элементы можно разместить по периметру, задавая угол поворота и радиус элементов. Эту функциональность реализует вспомогательный модуль addBall(). Получаемые таким образом элементы снеговика комбинируются в единый блок и окрашиваются белым цветом. 

Как было сказано выше, модули могут определять не только геометрические объекты, но и операции над ними. Для обращения к потомку используется команда children(), которая допускает использование различных аргументов, например, индекса конкретного потомка. Следующий код приводит к случайному размещению элемента на поле заданного размера. Число потомков определяется параметром $children, индексация начинается с нуля. Функция rands() генерирует вектор случайных чисел заданной длины в указаном диапазоне. 


В данном примере используется тип данных range, который определяется как [начало : шаг : конец] и является списком элементов из заданного диапазона. Для обхода потомков использован цикл for

Текстовый формат представления моделей и операций над ними упрощает повторное использование кода и создание библиотек элементов. Список наиболее функциональных из них можно найти на сайте www.openscad.org.  Подключение библиотеки производится ключевыми словами include и use. В первом случае, импортируемый код будет "вставлен" в ваш сценарий, соответственно, если в нём присутствуют какие-то исполняемые действия и вызовы, они будут исполнены. Во втором случае загружаются только объявления функций и модулей. 

Допустим, написанный ранее код был сохранён в файл snowman.scad. В следующем примере показано использование импортированного кода. Поскольку операция randomize() может работать с несколькими потомками, в первом случае мы вручную создаём каждого отдельного снеговика (синий цвет). Если объектов много, эффективнее генерировать их в цикле, что и сделано во втором случае. 


 

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

Отправить комментарий