Openscad руководство на русском

Создание простейшего модуля[править]

В качестве нашей первой модели мы создадим простой 2 х 3 х 4 кубоид. В OpenSCAD-редакторе наберите следующую команду:

Пример 1 — простой кубоид:
Простейший кубоид в OpenSCAD

Компиляция и визуализация нашей первой модели[править]

Теперь кубоид может быть скомпилирован и визуализирован нажатием клавиши F6 в активном окне OpenSCAD-редактора.

Открытие существующей учебной модели[править]

OpenSCAD после запуска

Откройте один из множества примеров, которые идут с OpenSCAD (File, Examples, и, например, example002.scad). Или Вы можете скопировать и вставить этот простой пример в окно OpenSCAD-редактора:

Пример 1 — example002.scad:
difference() {
 	cube(30, center=true);
 	sphere(20);
 }
 translate([0, 0, 30]) {
 	cylinder(h=40, r=10);
 }
OpenSCAD после вставки кода примера и нажатия F5

Когда нажмете F5, то получите графическое представление сценария, набранного в окне OpenSCAD-редактора.

Вам доступны три типа перемещений в окне предпросмотра:

  1. Перетаскивание левой кнопкой мыши для вращения модели. В нижней строке окна будет меняться величина rotate.
  2. Перетаскивание правой кнопкой мыши для перемещения модели. В нижней строке окна будет меняться величина translate.
  3. Использование колеса прокрутки мыши для приближения и удаления модели. В нижней строке окна будет меняться величина distance.

Позиционирование объекта[править]

Мы уже увидели как создать простой кубоид. Наша следующая задача состоит в размещении идентичного кубоида по соседству с уже существующим:

Пример 1 — позиционирование объекта:
cube([2,3,4]);
translate([3,0,0])
cube([2,3,4]);
Позиционирование объекта в OpenSCAD

Отсутствие точки с запятой после команды переноса[править]

Обратите внимание на отсутствие точки с запятой после команды переноса (translate). Это связано с тем, что команда переноса связана со следующим объектом. Если точка с запятой не будет пропущена, то эффект смены позиции прекратится и второй кубоид будет размещен на той же позиции, что и первый.

Изменение цвета объекта[править]

Мы можем изменять цвет объекта, передавая команде color RGB-значение цвета. Вместо традиционных RGB-значений от 0 до 255 используются значения с плавающей точкой от 0.0 до 1.0 (результат деления традиционного RGB-значения на 255).

Пример 1 — изменение цвета объекта:
color([1,0,0]) cube([2,3,4]);
translate([3,0,0])
color([0,1,0]) cube([2,3,4]);
translate([6,0,0])
color([0,0,1]) cube([2,3,4]);
OpenSCAD меняет цвет объекта

Режимы просмотра[править]

Окно просмотра OpenSCAD предлагает пользователю различные режимы просмотра, которые влияют на отображение модели.

OpenCGS[править]

Данный режим просмотра (View -> OpenCGS) будет использовать библиотеку OpenCGS (открытая библиотека конструктивной сплошной геометрии) для генерации представления модели с применением OpenGL. Если библиотека OpenCGS не доступна или видеокарта/драйвер не поддерживают OpenGL, то в этом режиме модель не будет отображена.

CGAL-поверхности[править]

Режим CGAL-поверхности (View -> CGAL Surfaces) это базовый режим просмотра модели, в котором отображается модель при нажатии клавиши F6 (Компиляция и построение).

Только CGAL-сетка[править]

Режим Только CGAL-сетка (View -> CGAL Grid Only) позволяет увидеть модель, составленную только из ребер — эдаких строительных лесов на которые впоследствии «натягивается» поверхность.

Предварительный просмотр[править]

В режиме Предварительного просмотр (View -> Trown Together) модель строится и отображается очень быстро, но не всегда верно: какие-то грани или поверхности могут отображаться, хотя при полноценном построении должны быть удалены. Именно в этом режиме отображается модель при нажатии клавиши F5 (Компиляция и предварительный просмотр).

На чтение 10 мин. Просмотров 611 Опубликовано 10.05.2021

Вы всегда хотели создавать свои собственные 3D-модели? А как насчет 3D-печати детали, которую вы разработали? Существует множество программ для 3D-моделирования, но их может быть сложно использовать, если вы не артистичны (как я). OpenSCAD позволяет создавать модели специально для 3D-печати, используя только код . Не волнуйтесь, если вы тоже не умеете кодировать, сегодня я расскажу вам об основах.

Содержание

  1. Что такое OpenSCAD?
  2. Подготовка к настройке
  3. Основы
  4. Advanced Coding
  5. Экспорт

Что такое OpenSCAD?

OpenSCAD – это бесплатное средство моделирования Solid Computer Aided Design . Он доступен для Windows, Mac и Linux. Что отличает его от многих других программ, так это то, что вы разрабатываете детали, используя код вместо мыши. Это позволяет очень легко выполнять математические вычисления, сохранять размеры в переменных, изменять размеры деталей и многое другое.

Есть некоторые факторы, которые необходимо учитывать при 3D-печати моделей, но многие из них применимы к 3D-печати CAD-моделей в целом, а не только к проектам OpenSCAD. Если вы хотите узнать больше о 3D-печати, ознакомьтесь с нашим руководством для начинающих. Если вам нужен более интерактивный разработчик моделей, прочтите руководство по созданию объектов в Sketchup.

Подготовка к настройке

Во-первых, перейдите на страницу загрузок и найдите версию OpenSCAD, подходящую для вашей операционной системы. Я использую Mac OS, но эти принципы OpenSCAD применимы ко всем системам.

После установки откройте его. Вам будет представлено это меню запуска:

Это показывает вы открываете файлы, которые открывались последними, и дает вам возможность загрузить несколько примеров. Не стесняйтесь взглянуть на некоторые из примеров, однако я обнаружил, что они еще больше сбивают с толку, когда только начинаете. В этом руководстве создайте новый файл, нажав кнопку new .

После открытия вам будет представлен этот простой интерфейс:

Он разделен на три основные области. Слева находится ваш редактор и меню. Здесь вы напишете свой код, в котором еще не будет кода, так как вы создаете новый файл. Вверху есть несколько кнопок меню для выполнения основных задач, таких как загрузка, сохранение, отмена и т. Д.

В правом нижнем углу находится консоль . Она покажет вам любые ошибки при построении модели.

Последний раздел – это основной интерфейс вверху справа. Здесь вы можете взаимодействовать со своей моделью, но не сможете редактировать ее здесь (вы будете писать код для этого).

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

Сохраните новый файл, нажав кнопку сохранения в меню редактора или выбрав в Файл > Сохранить .

Основы

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

Вот первая фигура, простой прямоугольник:

А вот код для этого:

  cube (); //создаем куб  

Чтобы заставить ваш код выполнить и построить модель, вам необходимо предварительно просмотреть его. OpenSCAD будет делать это по умолчанию при каждом сохранении, или вы можете нажать F5 для принудительного обновления. Поэкспериментируйте с перемещением в трехмерном пространстве, удерживая левую или правую кнопку мыши.

Теперь получается красивый куб, но без каких-либо измерений он не очень полезен. OpenSCAD не работает в какой-либо конкретной системе измерения, вместо этого все единицы относятся друг к другу. Вы можете создать коробку 20 x 10, и любая другая программа (например, ваш слайсер для 3D-печати) может интерпретировать их, будь то метрическая или британская система мер. На самом деле это обеспечивает большую гибкость.

Давайте добавим некоторые измерения в ваш куб. Вы делаете это, передавая параметры методу cube :

  cube (size = [10, 20, 30]); //прямоугольник  

Значения 10 , 20 и 30 представляют размер куба по осям X , Y и Z . Обратите внимание, как получился прямоугольник гораздо большего размера:

По умолчанию OpenSCAD рисует компоненты снизу слева. Вы можете отрегулировать это, установив для параметра center значение true .. Вот код для этого с прямоугольником:

  cube (size = [10, 20, 30], center = true); //прямоугольник по центру  

А вот как это выглядит:

Центрирование объектов хорошо работает для простых форм, но усложняет работу с несимметричными объектами. Вам нужно будет решить, какой метод лучше всего подходит для вас.

Переходя к более сложной форме, вот цилиндр :

Вот код для его создания:

  цилиндр (d = 10, h = 10, center = true); //цилиндр  

В отличие от кубиков , цилиндры автоматически рисуются в центре осей X и Y. Параметр d означает диаметр (вместо этого вы можете передать радиус, если хотите). Параметр h – это высота. Но что-то здесь не так. Этот цилиндр выглядит довольно «блочным». Вам нужно увеличить количество нарисованных граней по окружности. Это легко сделать – добавьте в код цилиндра следующий параметр.

  $ fn = 100  

Таким образом, определение цилиндра выглядит следующим образом:

  цилиндр (d = 10, h = 10, center = true, $ fn = 100);  

Вот как это выглядит:

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

Применять преобразования к фигурам легко. Перед созданием фигур необходимо вызвать специальные методы. Вот как повернуть цилиндр с помощью метода rotate :

  повернуть (a = [0, 90, 0]) цилиндр (d = 10, h = 10, center = true); //повернутый цилиндр  

Значения, переданные в параметр a , представляют угол поворота осей X, Y и Z. Вот результат:

Еще одна очень полезная функция – перевести . Это позволяет вам перемещать объекты в трехмерном пространстве. Еще раз, вам нужно будет передать количество движения для каждой оси. Вот результат:

Вот код:

  translate (v = [0, 25, 0]) цилиндр (d = 10, h =  10, center = true);//переведенный цилиндр  

Понимание метода translate – одна из самых важных вещей, которые вы можете сделать. Это необходимо для разработки самых сложных дизайнов.

Наконец, еще одна полезная форма – сфера :

Вот код:

  сфера (d = 100);  

Как и цилиндр, вы можете сгладить это, используя приведенный выше код $ fn .

Advanced Coding

Теперь, когда вы знаете основы, давайте рассмотрим некоторые более сложные навыки. При разработке часть, это помогает подумать о том, как ее можно составить из более мелких фигур и предметов. Вам не нужно этого делать, и вы можете «придумывать» по ходу дела, но это действительно помогает иметь приблизительный план – пусть даже он только в голове.

Давайте создадим расширенную форму: куб с выдолбленной внутренней сферой. Создайте куб и сферу с center , для которого установлено значение true. Вычтите одно из другого, используя метод difference :

  difference () {
//вычитание
куб (размер = [50, 50, 50], центр = true); //внешний куб
сфера (d = 65, center = true); //внутренняя сфера
}

Вот результат:

Поэкспериментируйте с диаметром (параметр d ) сферы и посмотрите, что произойдет.

В OpenSCAD обычно есть много способов выполнить одну и ту же задачу. Если вам нужна канавка в кубе, вы можете вычесть из него еще один куб или добавить еще два над ним. Обычно не имеет значения, каким образом все делается, но в зависимости от сложности детали может быть проще сначала выполнить определенные манипуляции.

Вот как создать канал в кубе. Вместо того, чтобы использовать другой куб, использование цилиндра создаст закругленный канал. Обратите внимание, как снова используется метод difference и как методы translate и rotate используются для управления фигурами. . Использование метода rotate часто затрудняет преобразование, поэтому поиграйте с параметрами, пока не добьетесь желаемого результата.. Вот код:

  difference () {
//вычитание
куб (размер = [50, 150, 50]); //внешний куб
translate (v = [25, 150, 50]) повернуть (a = [90, 0, 0]) цилиндр (d = 40, h = 150); //канал цилиндра
}

Вот как это выглядит:

Вам может быть интересно, что это за зелень. Это здесь, потому что 3D-модель сейчас только предварительный просмотр. Чтобы исправить это, нажмите F6 , чтобы полностью отобразить модель. Это может занять некоторое время, в зависимости от сложности. Предварительный просмотр ( F5 ) обычно достаточно хорош во время работы. Вот как выглядит окончательный рендеринг (со значением $ fn , равным 100):

Вот еще один сложный пример. Скажем, вы хотели закрепить что-нибудь с помощью болта. Создать отверстие с помощью цилиндра достаточно просто, но что, если вы хотите установить головку болта заподлицо для болтов с потайной головкой? Вы можете просто создать большой цилиндр для головки болта, но это будет выглядеть не очень красиво. Решением является фаска, которую можно создать с помощью метода цилиндр . Хитрость здесь в том, чтобы указать два диаметра – d1 и d2 . Сделайте эти размеры разных размеров, а все остальное сделает OpenSCAD.

Поскольку я британец, я буду использовать здесь метрические размеры для болта с потайной головкой M5. Вы можете легко отрегулировать это, чтобы оно соответствовало любым креплениям, которые хотите использовать. Вот код:

  $ fn = 100; 
//настройки болта
m5_clearance_diameter = 5.5;
m5_head_clearance_diameter = 11;
m5_head_depth = 5;
difference () {
//вычитаем
куб (20, 20, 20);
bolt_hole (10, 10 , 20);
bolt_bevel (10, 10, 15);
}
модуль bolt_hole (x, y, height) {
/* Отверстие M5 под углом 90 град. */
translate (v = [x, y, 0]) цилиндр (d = m5_clearance_diameter, h = height);
}
модуль bolt_bevel (x, y, z) {
//Фаска M5
преобразовать (v = [x, y, z]) цилиндр (d2 = m5_head_clearance_diameter, d1 = m5_clearance_diameter, h = m5_head_depth);
}

Обратите внимание, как размеры болтов хранятся в переменных? Это значительно упрощает кодирование и сопровождение. Один из методов, с которым вы, возможно, еще не сталкивались, – это module . Это позволяет вам определить блок кода, который будет выполняться в любое время. На самом деле это функция . Вы должны использовать модули и переменные для любой сложной формы, так как они упрощают чтение и ускоряют внесение изменений. Вот как выглядит фаска:

Давайте посмотрим на последний пример. Допустим, вы хотите создать серию отверстий по окружности. Вы можете вручную измерить, преобразовать и повернуть все это, но даже с модулями this было бы утомительно. Вот конечный результат, 10 цилиндров даже распределены по кругу:

Вот код:

  $ fn = 100; 
number_of_holes = 10;
for (i = [1: 360/number_of_holes: 360]) {
//number_of_holes определяет количество запусков этого кода
make_cylinder (i);
}
module make_cylinder (i) {
//делаем цилиндр и даже распределяем
вращать ([0, 0, i]) переводить ([10, 0, 0]) цилиндр (h = 2, r = 2);
}

Этот код проще, чем можно было ожидать. Цикл for используется для вызова make_cylinder десять раз. Так как круг состоит из 360 градусов и 360/10 = 36, каждый цилиндр нужно повернуть на инкр. температура 36 градусов. Каждая итерация этого цикла будет увеличивать переменную i на 36. Этот цикл вызывает модуль make_cylinder , который просто рисует цилиндр и позиционирует его в соответствии с градусами. перешли к нему по петле. Вы можете нарисовать больше или меньше цилиндров, изменив переменную number_of_holes – хотя вы можете изменить интервал, если вы это сделаете. Вот как выглядят 100 цилиндров, они немного перекрываются:

Экспорт

Теперь, когда вы знаете, как кодировать в OpenScad, необходимо сделать последний шаг, прежде чем вы сможете печатать свои модели на 3D-принтере. Вам необходимо экспортировать свой дизайн из OpenSCAD в стандартный формат STL , используемый большинством 3D-принтеров. к счастью, есть кнопка экспорта в STL: Меню редактора > Вверху справа :

На сегодня все. Теперь у вас должно быть отличное рабочее знание OpenSCAD – все сложные вещи строятся на этих основах, и многие сложные формы на самом деле представляют собой множество простых вместе взятых..

В качестве проблемы, почему бы не взглянуть на некоторые из наших проектов 3D-печати и попытаться воссоздать детали в OpenSCAD:

  • 3D Printables для Настольные фэнтези-ролевые игры
  • Пользовательские кнопки быстрого доступа
  • Electronic D20
  • Игры, которые можно распечатать в 3D

Вы узнали какие-нибудь новые трюки сегодня? Какая ваша любимая функция OpenSCAD? Перейдете ли вы в ближайшее время с другого инструмента САПР? Дайте нам знать в комментариях ниже!

.

Введение

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

В основу 3D-script редактора OpenSCAD положена абсолютно обратная парадигма, в данном редакторе полностью отсутствует какой либо графический интерфейс для создания 3D-объектов, нет ни одной «кнопки» или пункта «меню» при помощи которого вы могли бы создать какой либо графический примитив и произвести над ним какую либо манипуляцию. Создание всех объектов в OpenSCAD и манипуляции над ними происходят только посредством заранее подготовленного script-кода.

Предлагаю Вам самим ознакомиться с представленным ниже руководством и самому решить оправдан либо такой подход к созданию и анимации 3D-сцен.

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

Инструкция по скачиванию, установке и настройки программы не прилагается, подразумевается что если вы решили овладеть OpenScad, то значит вы достаточно технически грамотны чтобы разобраться в таких вопросах самостоятельно.

Данное пособие рассчитано на читателей минимально знакомых с синтаксисом си-подобных языков.

1. Графические примитивы

Напишем две строки кода первой сцены/программы:

$fn = 32;
sphere();

Запустим их на исполнение и получим картинку примерно следующего вида:

Очевидно что строка-2 отвечает за создание сферы, а поскольку никакие параметры, при создании сферы, не были явно указаны, она была создана с параметрами по умолчанию.

Значение первой строки это специальная переменная (Special variables), о чем свидетельствует символ доллара, определяющая на сколько секторов будет разбита любая окружность. Как видно мы установили ее значение равным 32 для большей визуальной гладкости криволинейных поверхностей.

Не стоит беспокоиться о необходимости запоминания сотен специальных переменных, их всего 10 штук, следующих типов:

  • $fa, $fs, $fn гладкость криволинейных поверхностей;

  • $t время;

  • $vpr, $vpt,, $vpd,, $vpf место расположения и ориентация камеры;

  • $children номер «наследника/последователя»;

  • $preview выбор кнопки рендера

Напишим новый код и запустим его:

$fn = 32;
cylinder();

Как можно заметить поведение цилиндра более сложно чем сферы, во первых он считает своей осью симметрии исключительноось-Z, а во вторых располагает одну из своих торцевых поверхностей в плоскости-XY с центром в начале координат.

Задействуем теперь все доступные параметры примитива, которых не так и много, чтобы увидить все доступные модификации по умолчанию:

$fn = 32;
cylinder(h = 3, d1 = 2, d2 = 1, center = true);

Как можно заметить, цилиндр поддерживает крайне небольшое количество модификаторов параметров, среди которых даже нету модификатора координат.

Для полноты картины расмотрим третий графический примитив cube().

$fn = 32;
cube([3,2,1],  center = true)

Кроме выше указанных графических примитивов существуют еще несколько графических примитивов 3D и 2D, расматривать которые в данной статье мы не будем.

2. Манипуляторы примитивы

Добавте в код манипулятор translate() и самостоятельно измените его параметры отслеживая изменения. Обратите внимание что параметры должны быть не только переданы модификатору, посредством размещения внутри оператора(), но и быль заключены в оператор[] который преобразует три одиночных числа x,y,z в вектор вида [x,y,z], принимаемый на входе модификатор translate(). Если нарушить данное правило, то модификатор translate() расширит первое одиночное число X до вектора [x,0,0].

$fn = 32;
translate([3,2,1])
    cylinder(h = 3, d1 = 2, d2 = 1, center = true); 

Обратите внимание, что после модификатора translate() не нужно указывать оператор; это вызвано тем, что модификатор оказывает воздействие на первый же примитив следующий за ним, если же за модификатором будет следовать следующий модификатор, то их общее действие сложиться и будет применено к первому же примитиву, следующему за цепочкой модификаторов.

Добавим в код второй манитулятор rotate(), и попробуем две различных комбинации их сочетания:

$fn = 32;
rotate([90, 0, 0])
    translate([3,2,1])
        cylinder(h = 3, d1 = 2, d2 = 1, center = true);
        
translate([3,2,1])
    rotate([90, 0, 0])
        cylinder(h = 3, d1 = 2, d2 = 1, center = true);

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

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

3. Составные объекты (модули)

Напишем код создающий объект состоящий из трех примитивов, моделирующий стержень круглого сечения и переменного диаметра.

$fn = 32;
cylinder(h = 3, d = 2);     
translate([0, 0, 3])
    cylinder(h = 2, d1 = 2, d2 = 1);
translate([0, 0, 3 + 2])
    cylinder(h = 1, d = 1);

Обратите внимание что поскольку действие модификаторов распространяется только на примитив который следует за ним и заканчивается при достижении ;. в строке-5 было необходимо сложить высоту первого и второго цилиндра, для того чтобы третий оказался выше них обоих.

Изменим код чтобы продемонстрировать как можно распространить действие одного модификатора на несколько примитивов.

$fn = 32;
cylinder(h = 3, d = 2);     
translate([0, 0, 3]) {
    cylinder(h = 2, d1 = 2, d2 = 1);
    translate([0, 0, 2])
        cylinder(h = 1, d = 1);
};

Заключение группы модификаторов и примитивов в один блок, посредством фигурных скобок, позволяет оперировать ими как одним целым.

Введем в код символьные константы, для придания ему большей читабельности и облегчения его дальнейшего совершенствования.

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

$fn = 32;

diam1 = 2;
diam2 = 1;
heig1 = 3;
heig2 = 2;
heig3 = 1;

cylinder(h = heig1, d = diam1);     
translate([0, 0, heig1]) {
    cylinder(h = heig2, d1 = diam1, d2 = diam2);
    translate([0, 0, heig2])
        cylinder(h = heig3, d = diam2);
};

Прорисовка объекта совершенно не изменилась, но зато теперь мы можем изменять его весь целиком меняя значения всего лишь нескольких констант.

Инкапсулируем фигуру, сделав из нее «шаблон», для будущего применения изменив код следующим образом.

$fn = 32;

module Arm(diam1 = 2, diam2 = 1, heig1 = 3, heig2 = 2, heig3 = 1) {
    cylinder(h = heig1, d = diam1);     
    translate([0, 0, heig1]) {
        cylinder(h = heig2, d1 = diam1, d2 = diam2);
        translate([0, 0, heig2])
            cylinder(h = heig3, d = diam2);
    };
};

Как можно заметить после этих изменений объект пропал. Это произошло потому что теперь код лишь «описывает» объект, но не создает его, добавим в самый конец файла еще одну строку и повторим рендер.

Arm();

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

4. Проверка типа параметра

Напишем код для создания стержня который может опционально заканчиваться «втулкой», внесем изменение в код в два этапа, для реализации указанного функционала.

$fn = 32;

module Arm(list = [[1,2],[1,2,3]]) {
    echo(Arm = list);
    diam =  list[0];
    heig =  list[1];
    
    cylinder(h = heig[0], d = diam[0]);     
    translate([0, 0, heig[0]]) {
        cylinder(h = heig[1], d1 = diam[0], d2 = diam[1]);
        translate([0, 0, heig[1]])
            cylinder(h = heig[2], d = diam[1]);
    };
};

Arm();

В указанном коде количество передаваемых параметров сократилось до одного, которому присвоено символическое имя list, но одновременно указанный параметр представляет собой сложным вектором, состоящим из двух простых векторов.

В начала модуля мы раскладываем сложный вектор на два простых, с символическими более простыми и понятными именами diam, heig, и осуществляем все дальнейщие посроения и манипуляции уже посредством этих векторов.

Под термином сложный/простой подразумевается содержит ли вектор в себе подвекторы или состоит только из чисел.

Особо стоит отметить модификатор echo, как несложно догадаться он выводит в консоль содержимое вектора list. Сейчас значение list известно нам заранее, но в будущем при отладке более сложного кода всегда полезно видеть входные параметры.

Найдите консоль и посмотрите что было передано.

Напишем дополнительные элементы кода для реализующими требуемого функционала.

$fn = 32;

module Arm(list = [[[1,2],[1,2,3]], 3, 2]) {
    echo(Arm = list);
    diam =  list[0][0];
    heig =  list[0][1];
    fork = [list[1], list[2]];
    
    if (is_num(fork[0]))
        rotate([0, 90])
            cylinder(h = fork[0], d = diam[0], center = true);
            
    cylinder(h = heig[0], d = diam[0]);     
    translate([0, 0, heig[0]]) {
        cylinder(h = heig[1], d1 = diam[0], d2 = diam[1]);
        translate([0, 0, heig[1]]) {
            cylinder(h = heig[2], d = diam[1]);
            
            if (is_num(fork[1]))
                translate([0, 0, heig[2]])
                    rotate([0, 90])
                        cylinder(h = fork[1], d = diam[2], center = true);
        };
    };
};

Arm();

В строке-9 и строке-19, посредством оператора is_num мы проводим проверку определен ли параметр фактически и является ли он числом, и если параметр определен производим отрисовку дополнительных элементов объекта.

5. Рекурсивный вызов и передача объектов по вектору

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

$fn = 32;

module Arm(list = [[[1,2],[1,2,3],[1,[2,1],undef]], undef, 2]) {
    echo( Arm = list);
    diam =  list[0][0];
    heig =  list[0][1];
    next =  list[0][2];
    fork = [list[1], list[2]];
    
    if (is_num(fork[0]))
        rotate([0, 90])
            cylinder(h = fork[0], d = diam[0], center = true);
    
    cylinder(h = heig[0], d = diam[0]);     
    translate([0, 0, heig[0]]) {
        cylinder(h = heig[1], d1 = diam[0], d2 = diam[1]);
        translate([0, 0, heig[1]])
        
        if (is_list(next)) {
            diam = [diam[1],next[0]];
            heig = [heig[2],next[1][0],next[1][1]];
            next =  next[2];
            Arm([[diam,heig,next],undef,fork[1]]);
        }
        else {
            cylinder(h = heig[2], d = diam[1]);
            
            if (is_num(fork[1]))
                translate([0, 0, heig[2]])
                    rotate([0, 90])
                        cylinder(h = fork[1], d = diam[1], center = true);
        };
    };
};

Arm();

Применив в строке-23 рекурсивный вызов модуля Arm можно создавать объекты состоящие из неограниченного числа однотипных блоков.

6. Вложенные модули и сокрытие имен

Напишем код для создания плоской закругленной пластины Slab, с возможностью рекурсивного вызова для добавления дополнительных звений. Поскольку код Slab аналогичен коду Arm, предлагаю читателю разобраться с ним самостоятельно.

$fn = 32;

module Slab (list = [3,1,.5,[30,30],[2,30,undef]]) {
    echo(Slab = list);
    length    = list[0];
    diameter  = list[1];
    thickness = list[2];
    angle     = is_list(list[3]) ? list[3]:
                 is_num(list[3]) ? [0, list[3]]: [0,0];
    next      = list[4];
    
    rotate([0, 0, angle[0]]) {
        cylinder(h = thickness, d = diameter, center = true);
        translate([length / 2, 0, 0])
            cube([length, diameter, thickness], center = true);
        translate([length, 0, 0])
            if (is_list(next))
                rotate([0, 0, angle[1]])
                    Slab([next[0], diameter, thickness, next[1], next[2]]);
            else
                cylinder(h = thickness, d = diameter, center = true);
    };
};

Slab();

Стоит обратить внимание что значение константы angle, определяемое в строках-8,9, зависит от того является ли переданный параметр вектором.

Напишем теперь код создающий две параллельных пластинки Fork, которые в последствии применим в Arm.

module Fork (list = [1,[1,1,.5,[30,30],[2,30,[1,-30]]]]) {
    echo(Fork = list);
    gap       = list[0];
    thickness = list[1][2];
    slab      = list[1];
        
    translate([0, 0,  (thickness + gap) / 2])
        Slab(slab);
    translate([0, 0, -(thickness + gap) / 2])
        Slab(slab);
};
Fork();

Как легко заметить для создания модуля Fork, необходим модуль Slab. При этом модуль Slab имеет глобальную видимость и доступен для всех прочих модулей, что может создать конфликт имен. Инкапсулируем модуль Slab внутри модуля Fork.

$fn = 32;

module Fork (list = [1,[1,1,.5,[30,30],[2,30,[1,-30]]]]) {
    echo(Fork = list);
    gap       = list[0];
    thickness = list[1][2];
    slab      = list[1];
        
    translate([0, 0,  (thickness + gap) / 2])
        Slab(slab);
    translate([0, 0, -(thickness + gap) / 2])
        Slab(slab);
    
    module Slab (list = [3,1,.5,[30,30],[2,30,undef]]) {
        echo(Slab = list);
        length    = list[0];
        diameter  = list[1];
        thickness = list[2];
        angle     = is_list(list[3]) ? list[3]:
                     is_num(list[3]) ? [0, list[3]]: [0,0];
        next      = list[4];
        
        rotate([0, 0, angle[0]]) {
            cylinder(h = thickness, d = diameter, center = true);
            translate([length / 2, 0, 0])
                cube([length, diameter, thickness], center = true);
            translate([length, 0, 0])
                if (is_list(next))
                    rotate([0, 0, angle[1]])
                        Slab([next[0], diameter, thickness, next[1], next[2]]);
                else
                    cylinder(h = thickness, d = diameter, center = true);
        };
    };
};
Fork();

Теперь попытка создания модуля Slab за пределами модуля Fork будет приводить к ошибке.

По умолчанию все символические имена существуют только в пределах объявленного блока, а при совпадении имен более «нижний» уровень перекрывает более «высокий».

7. Подключение дополнительных файлов

Сохраним код содержащий определение Fork в отдельном файле с именем Fork.scad

Напишем код который позволит нам присоединить к «верхнему» концу Arm вилку Fork применив директиву include.

$fn = 32;

module Arm(list = [[[1,2],[1,2,3],[1,[2,1],undef]],
                  undef, 
                  [1,[1,1,.5,[-30,30],[1,30,[1,-30,undef]]]]]) {
    echo( Arm = list);
    diam =  list[0][0];
    heig =  list[0][1];
    next =  list[0][2];
    fork = [list[1], list[2]];
    
    if (is_num(fork[0]))
        rotate([0, 90])
            cylinder(h = fork[0], d = diam[0], center = true);
    
    cylinder(h = heig[0], d = diam[0]);     
    translate([0, 0, heig[0]]) {
        cylinder(h = heig[1], d1 = diam[0], d2 = diam[1]);
        translate([0, 0, heig[1]])
        
        if (is_list(next)) {
            diam = [diam[1],next[0]];
            heig = [heig[2],next[1][0],next[1][1]];
            next =  next[2];
            Arm([[diam,heig,next],undef,fork[1]]);
        }
        else {
            cylinder(h = heig[2], d = diam[1]);
            
            if (!is_undef(fork[1]))
                translate([0, 0, heig[2]])
                    rotate([0, -90])
                        if (is_list(fork[1])) {
                            heig = fork[1][0];
                            cylinder(h = heig, d = diam[1], center = true);
                            Fork(fork[1]); 
                        }
                        else
                            cylinder(h = diam[1], d = diam[1], center = true);
        };
    };
    include<Fork.scad>;
};

Arm();

8. Наследование

Предположим необходимо создать двухзвенный манипулятор, текущая версия модуля Arm вполне работоспособна и позволяет создать два звена манипулятора, но она не позволяет объединить их в один объект посредством какой либо простой манипуляции.

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

Реализуем требуемый функционал посредством технологии наследования реализованной в операторе children, добавив его в существующий код.

$fn = 32;

module Arm(list = [[[1,2],[1,2,3],[1,[2,1],undef]],
                  1, 
                  [1,[1,1,.5,[-30,30],[2,30,[1,-30]]]]]) {
    echo( Arm = list);
    diam =  list[0][0];
    heig =  list[0][1];
    next =  list[0][2];
    fork = [list[1], list[2]];
    
    if (is_num(fork[0]))
        rotate([0, 90])
            cylinder(h = fork[0], d = diam[0], center = true);
    
    cylinder(h = heig[0], d = diam[0]);     
    translate([0, 0, heig[0]]) {
        cylinder(h = heig[1], d1 = diam[0], d2 = diam[1]);
        translate([0, 0, heig[1]])
        
        if (is_list(next)) {
            diam = [diam[1],next[0]];
            heig = [heig[2],next[1][0],next[1][1]];
            next =  next[2];
            Arm([[diam,heig,next],undef,fork[1]])
                children();
        }
        else {
            cylinder(h = heig[2], d = diam[1]);
            translate([0, 0, heig[2]])      
                if (is_undef(fork[1])) 
                    children();
                else {
                    if (is_list(fork[1])) {
                        heig = fork[1][0];
                        rotate([0, -90])
                            cylinder(h = heig, d = diam[1], center = true);
                        Fork(fork[1])
                            children();
                    }
                    else {
                        rotate([0, -90])
                            cylinder(h = diam[1], d = diam[1], center = true);
                        children();
                    };
                };
        };
    };
    include<Fork.scad>;
};

Arm() Arm();

Добавление в оператора children() позволила разместить второе звено манипулятора на месте второй, зависимой оси первого манипулятора.

Впрочем полученный код не полон, в случае попытки добавить манипулятору вилку, не важно на каком конце, второе звено манипулятора разместиться не на конце вилки, а на оси втулки. Так происходит потому что код вилки не имеет функционал наследования, добавим его и модернизируем код Arm для поддержки нового функционала.

$fn = 32;

module Fork (list = [1,[1,1,.5,[30,30],[2,30,[1,-30]]]]) {
    echo(Fork = list);
    gap       = list[0];
    thickness = list[1][2];
    slab      = list[1];
        
    rotate([0, -90]) {
        translate([0, 0,  (thickness + gap) / 2])
            Slab(slab);
        translate([0, 0, -(thickness + gap) / 2])
            Slab(slab)
                translate([0, 0,  (thickness + gap) / 2])
                    rotate([0, 90])
                        children();
    };
    
    module Slab (list = [3,1,.5,[30,30],[2,30,undef]]) {
        echo(Slab = list);
        length    = list[0];
        diameter  = list[1];
        thickness = list[2];
        angle     = is_list(list[3]) ? list[3]:
                     is_num(list[3]) ? [0, list[3]]: [0,0];
        next      = list[4];
        
        rotate([0, 0, angle[0]]) {
            cylinder(h = thickness, d = diameter, center = true);
            translate([length / 2, 0, 0])
                cube([length, diameter, thickness], center = true);
            translate([length, 0, 0]) {
                if (is_list(next)) {
                    rotate([0, 0, angle[1]])
                        Slab([next[0], diameter, thickness, next[1], next[2]])
                            children();
                }
                else {
                    cylinder(h = thickness, d = diameter, center = true);
                    children();
                };
            };
        };
    };
};

0. Анимация

Это маленькая затравка для подогрева интереса к следующему посту. Замените последнию строку кода в файл Arm.scad, создающию два объекта Arm, на строку указанную ниже и запустите анимацию.

rotate([$t * 360]) Arm() rotate([$t * 360]) Arm();

Послесловие

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

Introduction: OpenSCAD: Introduction and Notes

This started out as a way of me putting some notes online for the kind of things I found myself regularly searching for, mainly for personal use. It’s grown to a bit more of an introduction to OpenSCAD than I was planning so I thought I’d publish here and I hope it is of use to anyone interested in the area. If you have questions I’ll try and answer them in the comments bellow.

Intro

OpenSCAD is a free opensource CAD program, it runs on Windows, Mac and Linux.

Like many CAD packages an easy way to start is to build your object from 3D ‘primitive’ shapes, e.g. cubes, cylinders and spheres. A little different from many other packages it’s not directly interactive, you can’t grab a point or edge and drag it out. Instead you describe thing programmatically and OpenSCAD interprets your code. This may take a little getting used to but it means if you want an obscure feature you can just write it!

First two go-to references are:

  • OpenSCAD user manual wiki book
  • OpenSCAD cheat sheet

Instructables already has several guides including some some useful specifics such as:

  • Animating with OpenScad
  • Loft in OpenSCAD

If you find (or have written) others please message me and I’ll add to the list.

Step 1: Some Basics

A few quick basics…

  • Primitives
  • Comments
  • Modules & functions

Primitives

The three basic 3D primitives are:

  • Cube
  • Cylinder
  • Sphere

Sizes and co-ordinates are given ([X, Y, Z]) and each instruction ends with a semi-colon.

F5 shows a preview of your object and F6 will do a full render, I only do a full render when I’m exporting for 3D printing or laser cutting, it can take a little while based on the complexity of you object and the power of your machine.

A full description (and useful reference for all things OpenSCAD) can be found at: OpenSCAD user manual the section on primitives is at: Primitives.

Sphere

The simplest of the primitive shapes, pass it a size, either radius or diameter and press F5 to preview.

— Note: On a mac air it needs fn+F5 to preview.

sphere(d=10);

This preview doesn’t look very smooth, we can set the number of faces on an object with ‘$fn=’ inside the brackets. If you place a ‘$fn’ at the start of a project all objects after will aim for that number of faces unless specified otherwise.

sphere(d=10, $fn=200);

You can set this as high or as low as you want but be aware that calculating millions of faces will take much longer!

Cube

A cube can be described with:

cube(10);

This would be a cube, 10mm on each side. Pressing F5 will show a preview of the cube.

Alternatively you could use:

cube([10,20,30]);

This would make a cuboid with X=10mm, Y= 20mm and Z=30mm.

You will notice one corner is at 0,0,0. We can center any primitive with:

cube([10,20,30], center = true);

In this case the center of the cube is now at 0,0,0.

Cylinder

A cylinder can be described with using ‘r’ for the radius or, ‘d’ for the diameter. you also need to give it a height ‘h’.

cylinder(d = 10, h  = 10);

Again, this preview doesn’t look very smooth, we can set the number of faces on an object with $fn= inside the brackets.

cylinder(d = 10, h  = 10, $fn = 250);

You can also set it lower than the default, for example:

cylinder(d = 10, h  = 10, $fn = 3);

This gives a triangular prism. It’s maybe not quite the size you want but we can sort that kind of thing out in the modules section.

Cylinder — cone

You can give a cylinder two diameters to make a cone, d1 is the lower and d2 the upper.

cylinder (d1=40, d2=20, h=20);

Comments

It’s always handy to leave a few hints as to what you were aiming to do, OpenSCAD allows commenting in the code with either ‘//’ for one line or block commenting with ‘/* …… */’

// Single line commented out
/* Large block 

removed from preview

 and render */

Modules & functions

A handy way to organise code, make parts and reuse code is to use modules and functions, OpenSCADs name for reusable blocks of code. Enclosed in curly brackets and end with a semi colon.

I use modules to make up parts of a large objects, this means once I’m happy with a final assembly I can the use the module for printing or laser cutting etc.

module test_part(){


};

When you want to use the module call it with:

test_part();

A module will make a part (or sub-part etc.) but doesn’t return anything. OpenSCAD can also do functions, these will return a value, e.g doing a calculation.

function sine_vec_func (range)= [for (x = range) [ x, sin(x)]];

This world generate a list of vector point ([x,y}), we could check the out put with an echo:

sin_vector = sine_vec_func([0:180]);
echo (sin_vector);

So I assign the output of the function to a variable called sin_vector, by calling it and passing a range. Then I echo (print to terminal) the variable to check it’s what I think it should be.

Step 2: Moving Things Around

With a few basic shapes we now want to position and manipulate them. The main functions for this are:

  • Translate
  • Rotate
  • Scale

Translate

This moves the object to the co-ordinates X, Y, Z.

translate([10,20,0]) sphere(d=10);

So the center of the sphere is off set from 0,0,0 by 10 in the x axis, 20 in the y axis and 0 in the z axis.

Rotate

This rotates about an axis, X, Y, Z.

rotate([0,20,45]) cube([10,20,30);

Scale

This will scale your object along the X,Y or Z axis. This is a relative scaling, so ‘1’ is the original size, and e.g. ‘2’ double and ‘0.5’ would be half the original size.

scale([1,1,2]) sphere(d=10);

Step 3: Difference

This is possibly the most important function! It allows you to remove one shape from another.

An example would be adding a hole for a bolt:

difference(){
	cube([30,30,3]);
	translate([15,15,-0.1]) cylinder(d=3.2, h=3.2);
};

The syntax is that the first shape has all following shapes removed, in the above case a 30x30x3mm plate has a 3.2mm hole through the middle. To keep things neat, the object being remove should sit proud of the surfaces it is cutting though, in the above case I used a cylinder of 3.2mm to go though a 3mm plate, offsetting by 0.1mm so that the cylinder removed is 0.1mm above and bellow the plate. The second picture has a 3mm cylinder removed from a 3mm plate, as you can see there isn’t a hole. I think it’s left an infinitely thin surface because the command is unclear.

It’s also easy to do a difference with multiple shapes:

difference(){
	cube([30,30,3]);
	translate([15,15,-0.1]) cylinder(d=3.2, h=3.2);
	translate([5,5,-0.1]) cube([2,3,3.2]);
	translate([23,22,-0.1]) cube([2,3,3.2]);
};

If you are having problems getting an object in the correct place then ‘#’ will highlight it, this will make an object being differenced appear as an opaque red making easier to see where it is:

difference(){
	cube([30,30,3]);
	translate([15,15,-0.1]) cylinder(d=3.2, h=3.2);
	translate([5,5,-0.1]) cube([2,3,3.2]);
	#translate([23,22,2]) cube([2,3,3.2]);
};

Step 4: Importing Models

You may want to use an existing model such as an .stl or .dxf:

import("path/to.yourfile.stl", convexity = 3);

You can also drag your file into the code window to generate this.

The you can apply any functions you need, such as difference, scale and intersection.

Step 5: Modules I Use…

The more I use OpenSCAD the more I reused solutions from previous designs, my original aim for these notes was to share some of these modules, so here is a collection of things I’ve found or written which now make drawing quicker and easier:

Copy Mirror

This is from the OpenSCAD forum from Greg Frost, it copies and mirrors the part follows the function.

module copy_mirror(vec=[0,1,0]){
	children();
	mirror(vec) children();
};

This is one of my go-to functions for anything symmetrical. You can change the axis around which the copy is mirrored by changing the ‘vec’, leaving it empty will mirror along the Y axis. A quick use example would if I have four mount points arranged around a center I can draw one, mirror it across the Y axis then mirror this pair across the X axis.

Copy translate

Based on Greg’s module this will clone the original part and move it to the desired vector.

module copy_translate(vec=[0,0,0]){
	children();  // This maintains the original part
	translate(vec) children();
};

So to copy a part an move it 50mm along the X axis you would use:

copy_translate([50,0,0]) cube(20);

This is quick and useful for cloning once or twice, if I was doing more I’d probably use a for loop.

For loops

This idea of using a module part to clone a part can be built on with a for loop to repeat a part many times:

for (i=[0:20:100]){
	translate([i,0,0]) part();
};

So this would make ‘part()’ and place it at 0, 20, 40, 60, 80 and 100 along the X axis.

The ‘for loop’ outputs the value ‘i’, this is each value in the range 0:100 with a step size of 20. The value of ‘i’ is then used as the x value of a translate. The value of ‘i’ could be used for anything, scale, rotate, translate. It can also be changed e.g. multiplied by 10 ( i*10).

Rounded boxes

This takes a little longer to render than a plain cube but looks a bit nicer is some places.

module rounded_edge_box(x_dim, y_dim, z_dim, radius){
    hull(){
        //Bottom
        translate([radius,radius,radius]) sphere(radius);
        translate([x_dim-radius,radius,radius]) sphere(radius);
        translate([radius,y_dim-2*radius,radius]) sphere(radius);
        translate([x_dim-radius,y_dim-2*radius,radius]) sphere(radius);
        
        //Top
        translate([radius,radius,z_dim-radius]) sphere(radius);
        translate([x_dim-radius,radius,z_dim-radius]) sphere(radius);
        translate([radius,y_dim-2*radius,z_dim-radius]) sphere(radius);
        translate([x_dim-radius,y_dim-2*radius,z_dim-radius]) sphere(radius);
    };
};

There was an excellent video by MakersMuse on the pros and cons of chamfer and filleted edges for 3D printing.

Ruler

I like to pull in an object to show scale of a design, one of my preferred items is a 30cm ruler (or 12″ if you are that way inclined). I have a ruler of these dimensions to hand in the real world and I can use it to double check I’ve got critical dimensions right.

module ruler(ruler_length = 300, ruler_thickness = 2, ruler_height = 20){

    translate([0,0,ruler_thickness])rotate([-90,0,0])difference(){
        union(){
            cube([ruler_length, ruler_thickness, ruler_height]);
            translate([ruler_length,ruler_thickness,ruler_height/2])rotate([90,0,0]) linear_extrude(height = ruler_thickness)circle(r=ruler_height/2);    
        };        
        translate([ruler_length+5,ruler_thickness+0.5,ruler_height/2])rotate([90,0,0])color("Gainsboro")cylinder(r=2, h= ruler_thickness+1, $fn=24);
        // Measurement ticks long
        for (i = [0 : 10 : ruler_length]){
            translate([i, -0.05, 0]) {
                color("Gray")cube([0.1, 0.1, ruler_height]);
            };            
        };

	// Measurement ticks short
        for (i = [0 : 1 : ruler_length]){
            translate([i, -0.05, 0]) {
                color("Gray")cube([0.1, 0.1, 5]);
                //translate([0,0,12]) color("Gray")cube([0.1, 0.1, 5]);       
            };
        };

	// Measurement ticks v.short
        for (i = [0 : 0.5 : 50]){
            translate([i, -0.05, 0]) {
                color("Gray")cube([0.1, 0.1, 2.5]);        
            };
        }; 
        
        // Measurement Numbers
        for (i = [10 : 10 : ruler_length]){
            translate([i, -0.05, 0]) {
                color("Black")translate([0,ruler_thickness,10.25]) rotate([90,0,0]) linear_extrude(height = 2.2)text(str(i), size=2, halign = "center");
            };
        };           
    };
};

Protractor

Similar to the ruler, this is great for scale and allows me to double check I’ve got angles correct.

module protractor(){
	translate([0,0,1]) difference(){
        	color("Gainsboro", 0.5)cylinder(r=50, h= 2, center= true, $fn=128);
        	color("Gainsboro", 0.5)translate([0,-25,0])cube([100, 50, 4], center= true);
        
        	// Ruler long ticks & Numbers
        	for (i = [10 : 10 : 90]){
            		translate([-50+i, -0.05, 1.01])rotate([-90,0,0])color("Gray")cube([0.1, 0.1, 5]);
            		color("Black")translate([-50+i, 5.5, -0.01]) rotate([0,0,0]) linear_extrude(height = 1.05)text(str(i), size=2, halign = "center");
        	};
        
        	// Ruler short ticks
        	for (i = [0 : 5 : 95]){
            		translate([-50+i, -0.05, 1.01])rotate([-90,0,0])color("Gray")cube([0.1, 0.1, 2.5]);  
        	};
        	for (i = [0 : 1 : 99]){
            		translate([-50+i, -0.05, 1.01])rotate([-90,0,0])color("Gray")cube([0.1, 0.1, 1]);  
        	};
        
        	// Protractor Large ticks and numbers
        	for (i = [10 : 10 : 170]){
            		rotate([0,0,90-i])translate([0,5+42.5,1])color("Gray")cube([0.1, 5, 1.1], center = true);
            		color("Black")rotate([0,0,90-i])translate([0,42.5,0])linear_extrude(height = 1.05)text(str(i), size=2, halign = "center");
            		rotate([0,0,90-i])translate([0,5+22.5,1])color("Gray")cube([0.1, 25, 1.1], center = true);
        	};
        	// Protractor small ticks
        	for (i = [5 : 5 : 175]){
            		rotate([0,0,90-i])translate([0,5+44,1])color("Gray")cube([0.1, 2.5, 1.1], center = true);
            	};
        	// Protractor v.small ticks
        	for (i = [1 : 1 : 179]){
            		rotate([0,0,90-i])translate([0,5+45,1])color("Gray")cube([0.1, 1, 1.1], center = true);
            	};
	};   
};

Nut/Bolt head

This is just a simple way to take an edge-to-edge size and get the diameter of the circle needed, then doing a 6 faced cylinder (well 8 with top and bottom). It may or may not be easier to extrude a polygon but I like doing this way…

function indiameter_to_diameter(d) = d/(sqrt(3)/2);
module hexagon(indiameter, height = 2){
    diameter = indiameter_to_diameter(indiameter);
    translate([0,0,0])  cylinder(d=diameter, h = height, $fn=6);
};

So an M3 bolt has a 5.5mm head so I would do hexagon(5.5); most of the time I make a bolt module or a lookup so an M3 bolt has the right size shaft, head etc.

module M3_nut(){
    difference(){
        hexagon(indiameter = 5.5, height = 3);
	translate([0,0,-1])cylinder(d=3, h=4);
    };

Standoff

Using the hexagon module and indiameter function. Being able to reuse code to quick make new objects is one of the major strengths of OpenSCAD!

module M3_standoff(body_height=5, screw_height=5){<br>    body_size = 5.5;
    bolt_diameter = 3;
    
    hexagon(indiameter = body_size, height = body_height);
    translate([0,0,-screw_height])cylinder(d=bolt_diameter, h=screw_height);
};

I could (and perhaps should) have made a universal standoff module then specific modules for the sizes I have.

Different views

It depends on what you are building and how it will be used. For me most of my drawings will eventually be 3D printed or laser cut. So I make multiple modules of different part layouts. The first one I call «design_view()» this lays out parts as they will be used when they exist, showing each part in the finial layout. I make another called «print_layout()» which has the parts spaced orientated for printing. This allows me to quickly move from seeing (or exporting pictures) of a design to something I can send to print.

I’ll add to this as I find or make useful things. I have a load of old designs I need to dig through, I’m getting better (I think) so many of the older ones aren’t great and i only tend to update them if I encounter a similar problem again.

Step 6: A Worked Example — Lamp

There’s a nice lamp in the fusion 360 tutorial, this is sort of similar. There will be other ways to make the shapes, many of them much better, I’m trying to give an examples for people to play with. If you know of a better way add it to the comments!

Shade

The fusion tutorial uses a 2d shape with a rotate extrude so I will do something similar. OpenScad has three 2D primitives, circle, square and polygon. We could build the shade from scaled circles but I want to try plotting it as a curve. One way to do this is to use a function:

function sine_vec_points (range)= [for (x = range) [ x, sin(x*1.25)*100]];

This will return a set of vector co-ordinates for the range given. So for every value in ‘range’ we return [ x (i.e the value), and f(x) which in this case is sin(x) with a multiplier. The advantage of this is that we can swap, change or reuse my curve more easily.

Next we use the vector to plot a 2D curve. The vector points are made and used to plot a polygon. This module has a default value for range given [0:180], if you call the module with a range it overrides this.

module shade_base_2d(range = [0:180]){
    curve_vec_points = sine_vec_points(range);
    rotate([0,0,21]) polygon(points=curve_vec_points);    
};

The base shape of the lamp is a rotate_extrude of the curve…

module shade_base(range = [0:180]){
    curve_vec_points = sine_vec_points(range);
    rotate_extrude(angle = 360, convexity = 4) rotate([0,0,21]) polygon(points=curve_vec_points);    
};

The lamp shade is made from differencing two of the extrusions off set by -2mm and making a hole in the middle for an LED or bulb:

module shade(){<br>    difference(){
        shade_base();
        translate([0,0,-2])shade_base();
        translate([0,0,0]) cylinder(d=50, h=150);
   }; 
};

Base

Starting with the back foot, make a hull between two spheres.

module base(){

    // Back leg
    hull(){
        translate([0,0,20]) sphere(d=20);  
        translate([-50,0,5]) sphere(d=10);  
    };
};
base();

To make the foot a little more streamlined, scale the sphere:

module base(){

    // Back leg
    hull(){
        translate([0,0,20]) sphere(d=20);  
        translate([-50,0,5]) scale([1,0.75,1]) sphere(d=10);  
    };
};
base();

Next add two front feet in a similar manner, make two spheres and hull between them:

module base(){
    // Back leg
    hull(){
        translate([0,0,20]) sphere(d=20);  
        translate([-50,0,5]) scale([1,0.75,1]) sphere(d=10);  
    };
    // Front left
    hull(){
        translate([0,0,20]) sphere(d=20);  
        translate([60,-40,5]) rotate([0,0,-30]) scale([1,0.5,1]) sphere(d=10);  
    };
    // Front right
    hull(){
        translate([0,0,20]) sphere(d=20);  
        translate([60,40,5]) rotate([0,0,30]) scale([1,0.5,1]) sphere(d=10);  
    };
};
base();

This time I’ve rotated the scaled spheres a little.

Arm

Most of the dimensions for the arm were set by how I laid out the base and shade. The lower arm is a cylinder, scaled 1.5 fold along the x axis to make it oval. The upper arm is two parallel scaled cylinders.

I made a joining plate for articulation:

module plate(){
    rotate([90,0,0]) difference(){
        hull(){
           translate([0,10,0]) cylinder(d=10, h=3);
           translate([10,0,0]) cylinder(d=10, h=3); 
           translate([-10,0,0]) cylinder(d=10, h=3);  
        };
        
        translate([0,10,-1]) cylinder(d=3, h=6);
        translate([10,0,-1]) cylinder(d=3, h=6); 
        translate([-10,0,-1]) cylinder(d=3, h=6); 
    };
};

This used a hull on three cylinders, the same co-ordinates were used to difference out some bolt holes.

Assembly

With the parts all sorted it’s now time to put them together, I’ve also coloured them at this stage. Here the lengths and angles of the arm parts are tweaked to make everything join. There’s a nice color table in the wiki book to help get things looking nice in the preview.

module design_view(){
translate([55,0,120]) rotate([0,-30,0]) scale([0.25,0.25,0.25]) color("WhiteSmoke") shade(); translate([0,0,20]) rotate([0,0,0]) arm(); translate([0,0,0]) rotate([0,0,0]) color("DimGray") base(); };

Step 7: Exporting for the Real World

3D Printing

To export an object you need to first render it with F6. This can take a little while depending on the complexity of your design, how it’s been made ($fn, hull etc.) and your hardware.

Once rendered the object can be exported as an .stl and then imported into your favorite slicer!

With most (all?) of the printers I’ve used so far I find smaller holes (M2 and M3) need to be made a smidge bigger for printing, It’s worth trying a quick test print early on. For my Ender3 I use 3.5mm as an M3 through hole (it should be 3.4mm) because I get a little slump and would need to use a needle file to get things perfect.

Laser cutting

Exporting for laser cutting needs an extra couple of steps.

BE AWARE: OpenSCAD is inherently dimensionless, most packages assume you are working in mm but every so often you find one which doesn’t. I had an issue with a another package reading my dimensions as px, using 72px inch and making everything tiny, and I heard a horror story of a drawing being imported with dimensions treated as inches not mm and it wasn’t caught until after manufacture.

I make all my parts as modules so once the design is finished I make a cube the size of the stock (e.g. 500mm x 500mm acrylic) then lay out my parts inside the boundaries. Once I’m happy I’ve got the best/most efficient use of material then I do a projection. This make a 2D version of your 3D parts.

This works really well for sheet material, I then do a projection through it to give a 2D shape with all the holes, cut outs etc.

projection() part();

So an example would be a 5mm sheet with a few holes:

difference(){    
    cube([100,100,5]);
    for (i = [10:10:90]){
        translate([i,50,-1]) cylinder(d=3.4, h=7);
    };
};

Then the projection would be a 2D object which could be exported:

projection(cut=true) difference(){
    cube([100,100,5]);
    for (i = [10:10:90]){
        translate([i,50,-1]) cylinder(d=3.4, h=7);
    };
};

The pictures look similar but the first one has thickness, the second one is 2D.

On my system this projection takes a lot of thinking about once parts get complex.

For some laser cutting services you sometimes need to change the colour of the lines, red for cut though and green for engraving, so I export the projection as an svg file (scalable vector graphic) then open and edit in Inkscape.

Other places prefer .dxf, so far every time I’ve imported a .dxf it’s asked about the scaling to mm and all has been good.

Для изготовления механической детали требуется чертеж. Все началось с бумаги, и первые программы САПР использовали точно такой же стиль. На рисунках даже стандартные квадраты, чтобы обозначить каждый рисунок. Все это пригодится при запуске в производство в крупных корпорациях. Однако, когда вы начнете изготавливать новую механическую деталь, вам могут потребоваться другие методы.

Методы 3D CAD позволяют увидеть всю деталь такой, какая она есть. Вы также можете крутить и крутить. В расширенном программном обеспечении вы также можете моделировать движение. Во всех случаях вы рисуете части, используя графический интерфейс. Это отлично подходит для изготовления коробок и цилиндров, но если вы хотите создать более сложные формы, вам могут понадобиться математические методы.

Введите стандартный способ описания любого материала с помощью команд.

Что делает openSCAD таким особенным?

В openSCAD вы ничего не рисуете указателем или пером. Вы кодируете весь кусок с помощью команд и функций. Это неудобно для инженеров-механиков, но для программистов у вас другая ситуация. Помимо личных предпочтений, у вас также есть преимущество в точности. Когда вы разрабатываете его с помощью кода, у вас есть точность в коде.

Самая мощная особенность openSCAD — бинарные операции. Вы можете использовать бинарные операторы, чтобы соединить части или вырезать материал. Куб с отверстием в центре легко сделать, вытянув цилиндр из куба. Некоторые из этих операций доступны в другом программном обеспечении САПР, но естественно использовать их в openSCAD.

Что нужно вашему проекту?

После того, как вы положили свой дизайн на салфетку, вы можете подумать, что вам нужно увидеть, что происходит, когда вы пытаетесь сделать его полноценным. Не волнуйтесь; есть окно предварительного просмотра, в которое вы можете смотреть, пока пишете код. Как только вы поймете основные идеи, вы узнаете, подходит ли он лучше всего для вашего проекта.

Короче говоря, если вы хотите создавать небольшие детали сложной формы, вам следует попробовать openSCAD. Для полного оборудования и механических систем вы хотите использовать более сложные графические приложения. Сказав это, все дело вкуса. Вы можете создавать сложные формы с помощью всего кода, не могли бы вы написать код всей машины??

Установка

OpenSCAD, доступный в ваших стандартных репозиториях для большинства дистрибутивов, также может быть установлен с помощью оснастки и AppImage. Интересно то, что у вас также есть второй пакет, который включает винты, шестерни и общие формы. Самый новый пакет находится в оснастке openscad-nightly.

sudo apt установить openscad
sudo snap установить openscad-nightly

Если вы хотите использовать прилагаемые винты, которые поставляются в виде отдельного пакета, используйте репозитории вашего дистрибутива.

sudo apt установить openscad-mcad

Использование входящих в комплект деталей — это другой вопрос, который будет рассмотрен ниже.

Несколько стандартных форм

Принципы создания сценариев САПР заключаются в том, что у вас есть несколько стандартных геометрических фигур. Вы используете эти формы и объединяете их в более сложные формы. Стандартные формы — круг, квадрат и многоугольник для 2D. Для 3D у вас есть сфера, куб, цилиндр и многогранник. Используя одни из них для сборки, а другие для резки, вы можете создавать очень сложные формы.

Также есть текстовая функция, которая создает 2D-текст. Когда вам нужно создать чертежи для дальнейшей обработки, вы можете использовать команду проекции. Эта команда вырезает 3D-фигуру по плоскости, чтобы вы могли перенести ее на чертеж. Вы также можете добавлять фигуры из других программ или даже изображения, используя команду импорта. Это также работает с 3D-фигурами.

Кроме того, вы можете выдавливать формы из существующих объектов.

Трансформации

По умолчанию вы создаете все части в центральной точке сетки во всех измерениях. Это заставляет их все пересекаться. Когда у вас есть несколько фигур, вы хотите, чтобы они были размещены в нужном месте и повернуты. Это самые простые функции, translate помещает объект в другое место. Команда поворота вращает объект или дочерние объекты. У вас также есть функция зеркального отражения, которая создает копию объекта, отраженную вокруг данной оси.

Другие преобразования нуждаются в примерах для объяснения. Короче говоря, корпус создает внешние линии самых разных форм. Попробуйте с двумя кружками и объедините их с корпусом (). Или код ниже.

translate ([- 10,0,0])
hull ()
цилиндр (30, 5, 1);
куб (9);
сфера (12);

Операция Минковского обычно используется для создания кромок; если вы хотите, чтобы они округлились, используйте сферу.

Логические операции

Многие части не могут быть созданы только из квадратов, цилиндров и сфер. Первое, что вы можете сделать, это объединить и вырезать несколько фигур в одну. Для этого вы используете логические операторы. Это союз, различие и пересечение.

union ()
куб ([35, 5, 2], center = true);
цилиндр (h = 2, r = 5, center = true);

В приведенном выше коде вы получаете цельный кусок с лампочкой в ​​центре. Чтобы сделать трубку, вы берете разницу между одним цилиндром и другим.

разница()
цилиндр (h = 15, r1 = 30, r2 = 30, center = true);
цилиндр (h = 15, r1 = 25, r2 = 25, center = true);

По мере продвижения вы будете использовать это и многое другое. Вот пример перекрестка.

пересечение ()

повернуть ([45,0.0])
цилиндр (h = 40, r = 4, center = true);
translate (5,5,5)
цилиндр (h = 40, r = 6, center = true);

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

Для петель

Многие из ваших дизайнов будут иметь одно и то же множество раз, подумайте о патио. Их обычно делают из нескольких досок с промежутками между ними. В этом случае вы делаете одну доску и просто перебираете ее с помощью цикла for.

разрыв = 8;
plank_width = (bed_width / 4) — промежуток;
num_planks = 4;
для (plank_x_pos = [0: 1: num_planks — 1])

перевести ([ширина_планки * ширина_планки + расстояние * положение_плоскости, 0,0])
куб ([ширина_планки, 4,200]);

Без цикла for вы бы написали куб и операторы перевода четыре раза. Вы также должны были бы рассчитать, как далеко уйдет следующая доска. Даже из четырех частей это решение выглядит намного проще. В примере вы также можете увидеть переменные, которые необходимо установить. Все переменные устанавливаются во время компиляции, это важно, поскольку вы можете столкнуться с проблемами отладки, если будете думать о них как о значениях в других языках программирования. Как вы увидите позже, вы также можете сделать все патио модулем.

Математика

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

для (i = [0:36])
перевести ([i * 10,0,0])
цилиндр (r = 5, h = cos (i * 10) * 50 + 60);

Вышеупомянутая функция создает длинный прямой ряд цилиндров разной высоты. Основные функции связаны с тригонометрией. Однако с помощью случайных функций округления и стандартных операторов вы можете создать практически все, что угодно. Также есть поддержка векторов, матриц и квадратного корня. Даже с этими функциями вы можете далеко продвинуться. Однако они не охватывают все, что вы можете себе представить; вместо этого вы можете создавать функции.

Модули и функции

У вас есть много модулей, включенных в установку openSCAD. Однако вы также можете скачать другие библиотеки. В вашем дистрибутиве вы, вероятно, найдете MCAD, также называемый openscad-mcad. Для установки под Ubuntu.

$ sudo apt установить openscad-mcad

Внутри этого пакета вы найдете как модули, так и функции. Прежде чем начинать какой-либо проект, поищите библиотеки и модули. Уже есть библиотека винтов, и это только начало. Отсутствует часть вашего дизайна? Создавайте собственные модули; вы используете их для создания новых частей. Когда вы используете параметры, вы можете сделать из них множество версий. Лучший способ создать модуль — сделать дизайн в виде отдельного файла, выяснить, что должно быть динамическим, и добавить «модуль» вокруг части.

Чтобы использовать модуль, вы называете его по имени. Поскольку многие модули поставляются в отдельных файлах, вы должны поместить оператор include в начало файла. Обратите внимание на разницу между оператором include и оператором use. Если вы хотите, чтобы все в файле выполнялось, вы «включаете» его, если вы хотите, чтобы были определены только модули и функции, «используйте» файл. Чтобы убедиться, что вы можете использовать модули, вы должны поместить их в текущий каталог вашей модели или в один из путей поиска.

Во-первых, давайте посмотрим на несколько, которые вы можете скачать и использовать.

Винты

В пакете из предыдущего раздела вы можете найти много чего. Одна группа — винты! Вы можете опробовать их, загрузив их в приложение и вызвав модуль. В библиотеке MCAD можно найти множество винтов. Есть много других коллекций из других источников. Чтобы использовать винт, создайте файл, содержащий инструкцию include для нужного вам модуля. Теперь, где бы вы ни захотели использовать модуль, вы можете использовать имя модуля для создания своего винта.

включать

;
ball_groove (12, 40, 2);

Это винт, который может поместиться в мяч. Вы также можете найти nut_and_bolts_scad, который определяет метрические винты и болты. Дизайнеры использовали веб-сайт, на котором вы можете найти болты, и создали метод, который вы можете использовать. Другой пример — отверстие под болт.

включать
разница()
куб ([12,16,20], center = true);
перевести ([0,0, -3])
boltHole (8, длина = 300);

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

Изготовление тележки

Чтобы изготовить любую конструкцию любой сложности, нужно будет делать по одной детали. Позже вы объедините их друг с другом. Как мы уже упоминали ранее, вы можете использовать модули и функции. Лучший способ начать — решить, где вам нужно установить переменные. Для простой тележки вам нужны высота, колесная база и длина. Вам нужно установить значения в одном месте и использовать их, чтобы детали соответствовали дизайну. Возможно, вам понадобится больше ценностей, но не ставьте их все в начале. Когда вы начинаете новый проект, у вас не будут готовы все части, поэтому будьте готовы что-то изменить.

колесная база = 150;
длина тележки = колесная база * 1.2;
cartwidth = 50;
диаметр колеса = 25;
высота подвески = (диаметр колеса / 2) + 5;
translate ([колесная база / 2, ширина тележки, 0])
повернуть ([90,0,0])
цилиндр (r = радиус колеса, 10, центр = истинный);
translate ([колесная база / 2, — (ширина тележки), 0])
повернуть ([90,0,0])
цилиндр (r = радиус колеса, 10, центр = истинный);

Код показывает код первых двух колес. Если немного подумать, то, наверное, можно сделать задние колеса. Чтобы добавить зенитку, поверхность, на которой размещается весь материал, вы просто добавляете куб. Используйте переменные, которые вы указали в коде.

translate ([0, 0, Suspensionheight])
куб ([длина тележки, ширина тележки, 10], центр = истина);

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

Теперь вам нужно добавить оси и подвеску. Оси могут быть простыми цилиндрами, которые проходят между колесами. Вы размещаете их так же, как и колеса, используя вращение и перемещение. На самом деле лучше всего использовать одни и те же значения.

перевести ([колесная база / 2,0,0])
повернуть ([90,0,0])
цилиндр (r = радиус колеса * 0.25, h = (ширина тележки * 2) + 15, center = true);

Код здесь ставит переднюю ось на место. Задняя ось, я оставляю вас, читатель, чтобы выяснить. Мы можем решить проблему с приостановкой разными способами. В этом случае мы будем простыми.

// Приостановка
translate ([колесная база / 2, 0, высота подвески])
rotate ([90,0,0])

разница()
цилиндр (r = высота подвески, 10, центр = истинный);
цилиндр (r = высота подвески — 5, 11, центр = true);
куб ([102, высота подвеса / 6, 12], center = true);

перевести ([высота подвески, 0, 0])
цилиндр (r = высота подвески / 3, h = 12, центр = true);
translate ([- Suspensionheight, 0, 0])
цилиндр (r = высота подвески / 3, h = 12, центр = true);

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

Код корзины доступен по адресу https: // github.com / matstage / Carriage! Дальнейшее развитие событий может произойти позже.

Библиотеки

В предыдущей части вы использовали только круги. Любые проекты, использующие только эти примитивы, не будут лучшими для всех приложений. Вам нужно создавать красивые и эффективные дизайны. Решение — математика! Чтобы добавить это, вы должны начать с использования чужих библиотек.

Есть большое количество библиотек, созданных умными людьми в сообществе. Люди, которые создают, — это пользователи, которые решают свои проблемы, а затем любезно делятся этим со всеми. Спасибо вам всем! Хороший пример — dotSCAD; для примера подвески вы можете найти кривую Безье.

Экспорт в другое программное обеспечение

Если у вас есть достойный дизайн, вы можете использовать его в другом программном обеспечении. Вы можете экспортировать в stl, dwg и множество других форматов. Ваши энтузиасты 3D-печати могут использовать файлы stl прямо в программах слайсера.

Альтернативы

Еще одна интересная альтернатива — ImplicitCAD. Это программное обеспечение находится в стадии разработки. Вы должны запустить его командную строку, и для этого требуется Haskell в вашей системе. Большинство стандартных установок не имеют Haskell!

Заключение

На первый взгляд, использовать openSCAD очень сложно. Преодолеть кривую обучения — это немного сложно, но для многих пользователей оно того стоит. Благодаря проектам внести свой вклад в проект. У вас есть много функций, доступных в конце команды git. Простое освоение основ создания механических конструкций с помощью кода меняет ваше представление о формах. Это полезно, даже если вы продолжите использовать указатель и щелкать мышью, чтобы реализовать другие проекты.

  • https: // www.openscad.org / документация.html?версия = 2019.05
  • http: // edutechwiki.униж.ch / en / OpenScad_beginners_tutorial
  • https: // www.openscad.org / cheatsheet / index.html

Понравилась статья? Поделить с друзьями:
  • Амоксициллин ветеринарный инструкция по применению цена
  • Сбор бруснивер инструкция по применению отзывы взрослым
  • С руководством погранслужбы
  • Регистрация по месту жительства через госуслуги пошаговая инструкция для детей
  • Приемы руководства творческими играми