OpenSCAD Урок 2. Учимся на простых примерах - функции minkowski, hull, projection. Модели плоских (2D) фигур. |
Результатом работы функции является Сумма Минковского для нескольких тел. Точки поверхностей N тел векторно суммируются - результатом является некая новая фигура. На слух это воспринимается с трудом, но визуально это достаточно легко понять - поэтому приведу несколько примеров работы с данной функцией.
minkowski(){ cube([10,10,1], true); scale([0.7,0.5,0.3]) sphere(3, $fn=50); };
minkowski(){ rotate([0,90,0])cylinder(3,1,2, true, $fn=50); cubeM([10,10,1]); }
minkowski(){ cylinder(3,1,2, true, $fn=50); cubeM([10,10,1]); }
Для случая когда одно из слагаемых имеет прямые грани - сумма Минковского выглядит достаточно просто. Если же применять её к сферическим поверхностям с искажённой формой - результат будет сложно представить заранее. Предлагаю вам поэкспериментировать самостоятельно.
Принцип действия полностью соответствует названию. Представьте, что вы размещаете в пространстве две произвольные фигура, а потом обтягиваете их резиновой оболочкой - это и есть функция hull().
hull(){ translate([5,5,5]) sphere(10, $fn=100); cube([10,10,10], true); }; |
hull- в некоторых случаях просто незаменима. С трудом могу себе представить, как в OpenSCAD, без неё, можно сделать переход из трубы с круглым сечением в трубу с квадратным сечением. С hull() это можно сделать в несколько строк кода.
difference(){ hull(){ translate([0,0,10])cylinder(0.1, 5, 5, true, $fn=100); translate([0,0,-10])cube([10,10,0.1], true); }; scale([0.9,0.9,1.01]) hull(){ translate([0,0,10])cylinder(0.1, 5, 5, true, $fn=100); translate([0,0,-10])cube([10,10,0.1], true); }; } |
Из несимметричных объектов, с помощью вращений и переносов, невозможно получить зеркальную копию. От мучений по постройке зеркальной копии модели нас спасает функция с одноимённым названием mirror. В качестве входного параметра, функция принимает координаты вектора нормали (перпендикуляра) к плоскости отражения. По умолчанию вектором нормали является ось X ( mirror([1,0,0]) ), а плоскостью отражения соответственно является плоскость YZ. Плоскость отражения всегда проходит через центр координат
translate([-5,0,5]) color("green")mirror() union(){ translate([0,0,7])cylinder(14,5,5, true, $fn=100); rotate([0,90,0])cylinder(25,5,5, $fn=100); rotate([90,0,0])translate([0,0,-20])cube([10,10,40], true); }; translate([5,0,-5]) rotate([0,90,0]) union(){ translate([0,0,7])cylinder(14,5,5, true, $fn=100); rotate([0,90,0])cylinder(25,5,5, $fn=100); rotate([90,0,0])translate([0,0,-20])cube([10,10,40], true); }; |
resize([10,20,30]) cube(5); resize([10,20,30]) { ... };
Функция multmatrix - реализует в OpenSCAD аффинные преобразования. Одной матрицей можно задать вращение, перемещение, отражение, сжатие/растяжение и "искревление". Что понимать под "искривлением"? Представьте, что вместо декартовых координат с углом между осями в 90 гр. вам дали систему координат с углом, например 60 гр. соответственно все точки поверхности "наклонили". Например, квадрат стал параллелограммом с углами 60 и 120 гр.
В каких то ситуациях функция multmatrix может быть удобна, но она достаточно сложна для понимания - особенно для тех кто не знаком с линейной алгеброй, матрицами и т.д.. Приведу пример, большей частью для информации, чтобы иметь представление, о чём идёт речь.
a=45; b=45; c=45; kx=0.5; ky=0.5; kz=1;
A=[[1, 0, 0, 0], [0, cos(a), -sin(a), 0], [0, sin(a), cos(a), 0], [0, 0, 0, 1]]; |
B=[[ cos(b), 0, sin(b), 0], [ 0, 1, 0, 0], [-sin(b), 0, cos(b), 0], [0, 0, 0, 1]]; |
C=[[ cos(c),-sin(c), 0, 0], [ sin(c), cos(c), 0, 0], [ 0, 0, 1, 0], [ 0, 0, 0, 1]]; |
K=[[kx, 0, 0, 0], [0, ky, 0, 0], [0, 0, kz, 0], [0, 0, 0, 1]]; |
M=A*K; multmatrix(M)cube(10,true);
Здесь матрицы A, B, C - это вращение, матрица K - это коэффициенты сжатия растяжения по осям X, Y, Z.
Если вы имели дело с линейной алгеброй (матрицами), то обратили внимание, что в приведённом примере OpenSCAD поддерживает операции умножения и сложения матриц.
Работа с матрицами как с объектами линейной алгеброй, не совсем простая задача - это не совсем "просто" таблицы. В общем случае применение таких "монстров" неоправданно, и вполне можно обойтись стандартными функциями перемещение, вращение, сжатие/растяжение.
Функция color для расцветки модели и её частей. На вход функции попадает или массив, или текстовая переменна обозначающая "название цвета". Для случая массива - задаётся [R, G, B], где R, G, B соответственно доля красного, зелёного и синего цветов в значениях от 0 до 1. Например [0,1,0] это чисто зелёный (стандартно параметры RGB задаются от 0 до 255, но разработчики OpenSCAD почему то решили сделать по-другому). Для случая задания цвета текстовой переменной - пишется название цвета в двойных кавычках "red", "black", "green" и т.п., или цвета с заковыристыми названиями "cadetblue". Таблица с названиями цветов приведена ниже.
Кроме цвета, может быть задан четвёртый параметр - прозрачность объекта от 0 (полностью прозрачный), до 1 (совсем не прозрачный). Единственно с прозрачностью вышел "косяк", а может и не "косяк", может так задумывалось - в общем, иногда прозрачность только местами прозрачная. Смотрите пример ниже.
color("red", 0.5) cube(10,true); color([0,0,1], 0.5)cube([5,5,20],true); |
|
|
|
|
|
|
difference(){ cube(10,true); cube([5,5,20],true); // * ! # % };
Без модификатора. |
*...; *{...} |
!...; !{...} |
#...; #{...} |
%...; %{...} |
Функция реализует проекцию и сечение. Проекция модели осуществляется НА плоскости XY, а сечение модели осуществляется ПО самой плоскости XY - других вариантов не предусмотрено. Если вам нужны "нестандартные" сечения или проекции - вращаете и перемещаете модель относительно плоскости XY до тех пор пока не получите желаемого.
Если входной параметр функции - cut установлен в true функция будет выдавать сечение объекта плоскостью XY ( Z=0 ).
Если cut установлен в false, или параметр незадан - получаем проекцию фигуры на XY.
Следует иметь ввиду, что на выходе projection получается 2D объект - не имеющий высоты, хотя визуально она присутствует. Соответственно, как и с любым другим 2D объектом - можно выполнять операции linear_extrude и rotate_extrude, которые будут рассмотрены ниже, но нельзя выполнять многие функции для 3D объектов.
В примере ниже приведены несколько сечений модели при разных её положениях по оси Z. Проекция фигуры совпадает с первым её сечением на картинке.
color("green") projection(cut=true) translate([0,0,-5]) // z = 5, 2, -2, -5 difference(){ hull(){ translate([0,0,5])cylinder(0.1, 5, 5, true, $fn=100); translate([0,0,-5])cube([10,10,0.1], true); }; cube([5,5,11], true); rotate([0,90,0])cylinder(12, 3, 2, true, $fn=100); };
Плоские примитивы в OpenSCAD представлены прямоугольником square, кругом circle, многоугольником polygon. Прямоугольник и круг в пояснении они особо не нуждаются примеры кода с полным и сокращенным написанием приведены ниже. Остановлюсь на многоугольнике. Очень мощный инструмент при правильном использовании (смотри пример ниже). Входными параметрами функции polygon являются массив точки заданных координатами X,Y (Z=0) и массив содержащий путь обхода точек, если массив обхода по точкам не задан принимается та очерёдность, в которой указаны точки. Зачем нужен путь обхода по точкам? Надеюсь, у всех в детстве была игра соединить точки по номерам и получить интересный рисунок, если вы отклонялись от указанного порядка - рисунок не получался. Здесь ситуация аналогична. Забыл указать про ещё один параметр convexity. Данный параметр необходим только для правильного отображения фигуры, в окне пред просмотра на конечный результат он не влияет. Параметр определяет количество точек пересечения произвольного луча с многоугольником. Допусти для буквы "С" 4 точки пересечения (луч вошёл, вышел, вошёл, вышел), а для буквы "Е" уже 6 точек пересечения. На практике не помню, чтоб у меня появлялись проблемы в отображении объекта если я не указывал этот параметр. (Позже: если параметр не указан проблемы с отображением всё таки появляются. Пример бага приведу ниже при разборе функции linear_extrude. )
Функция Polygon поддерживает возможность многократного "вырезания" отверстий в многограннике за счёт указания путей обхода точек, внутренних отверстий. Давайте посмотрим, как это реализуется.
И так функция polygon:
polygon( points=[ [10,10], [10,-10], [-10,-10], [-10,10], [4,4], [4,8], [8,8], [8,4], [-4, -4], [-6,-8], [-3,-8] ], paths=[ [0,1,2,3], [4,5,6,7], [8,9,10] ], convexity=6 ); |
polygon( [ [10,10], [10,-10], [-10,-10], [-10,10], [4,4], [4,8], [8,8], [8,4], [-4, -4], [-6,-8], [-3,-8] ], [ [0,1,2,3], [4,5,6,7], [8,9,10] ] ); |
square(size = 10); square(10); square([10,20]); square(10,false); square([10,20],true); square([10,20],center=false); square(size=[10, 20], center=true); square(center=false, size=[10, 20]); |
/*через задание радиуса*/ circle(10); circle(r=10); /*через задание диаметра*/ circle(d=20); circle(d=20, $fn=50); color("green") translate([0,0,5]) resize([30,10]) circle(d=20, $fn=50); color("red") translate([0,0,10]) circle(d=20, $fn=3); |
color("green") translate([0,0,5]) polygon([[0,10],[5,5],[0,0],[7,3],[15,0],[10,8],[12,15], [7,8]]); color("red") polygon( [ for (a = [0 : 1 : 359]) [(sin(5*a)+5)* sin(a), (sin(5*a)+5)* cos(a)] ] ); |
Функция служит для создания плоской модели текста. Если же вам нужен объёмный текс - вам помогут text + linear_extrude(см. ниже), всё это займёт пару строк кода.
Теперь подробней. Функция поддерживает все основные языки (в том числе и русский). Шрифты берутся из набора Windows, если вам не хватает, для полного счастья, какого либо шрифта загружаете в Windows новый шрифт, соответственно он появляется в openscad. Шрифт удобно выбирать через Word - выбранный шрифт должен поддерживать русский алфавит (Word - в окне выбора шрифта, кроме английских букв, должна быть строчка с русскими буквами). В самом OpenSCAD так же есть шпаргалка шрифтов Справка/Список шрифтов - здесь удобно подсмотреть поддерживаемые стили шрифта: жирный (bold), курсив (italic) и т.п..
Функция поддерживает символы Юникода \u... (см. пример ниже). Коды можно посмотреть в том же Word. Выбираем вставить символ - в открывшемся окне можно найти символ и его код.
Небольшой совет: помните функцию resize - она здесь хорошо подходит, если вам нужно получить буквы строго заданной высоты.
text(text="\u00A9 Наш Колхоз", language="ru", font="Segoe Script:style=Bold", $fn=30); |
Функция смещает контур плоской фигуры внутрь или наружу, относительно исходной фигуры, а так же закругляет или срезать углы. Получается нечто вроде фаски.
Исходные параметры:
Зелёный - исходный многоугольник. Жёлтый - результат работы функции.
Небольшой совет: если вы хотите закруглить и внешние, и внутренние углы - примените функцию offset дважды: offset(r=4, $fn=30) offset(r=-2, $fn=30). Итоговый радиус скругления +2.
offset(r=-2)offset(r=4) difference(){ square(20,true); translate([30*sqrt(2),0,0]) rotate([0,0,45]) square(60,true); }; |
linear_extrude - позволяет "выдавливать" из произвольной, плоской модели колонки ("колбаски") необходимой длинны. Параметры функции:
linear_extrude(height=50, center=true, scale=[2,2], slices=100, twist=240) polygon( [ for (a = [0 : 1 : 359]) [(2*sin(6*a)+10)* sin(a), (2*sin(6*a)+10)* cos(a)] ] ); |
Обещанное отступление про параметр convexity.
Уже после написания данной урока - наткнулся на необходимость указывать параметр convexity в нескольких своих моделях. Насколько я понимаю, convexity призван помочь графическому движку openscad правильно отобразить 3D модель на 2D мониторе. Условно графический движок иногда не совсем может "сообразить" какую грань объекта показать пользователю впереди, а какую позади. Соответственно чем больше в модели "складок" тем сложнее справится графическому движку.
Из полученного опыта хотелось бы выделить. Первое, случаи, в которых необходимо указывать параметр convexity - достаточно редки. Возникают они при использовании linear_extrude, rotate_extrude. В моделях с относительно сложной геометрией, наличием множества отверстий или граней. Второе, опыт говорит о том, что указание параметра convexity иногда помогает, а иногда делает ещё хуже - баг с неправильным отображение модели ни только не уходит, изображение становится хуже. Третье, такие модели иногда рендерятся (создание итогового файла stl) с ошибками. В множестве точек, создающих полую обрешётку модели, появляются незакрытые дырки.
Общая рекомендация - не забывайте, что такой параметр в некоторых функциях есть и в случае появления ошибок отображения пробуйте применять его. Ниже приведу несколько картинок, как примерно выглядит модель с данным багом. В данной модели указание convexity=8 даже ухудшало ситуацию (смотри всплывающие подсказки к рисункам).
Функция реализует тела вращения на основе плоских моделей. Плоская модель должна располагаться полностью в положительной части оси X.
Входных параметров всего 3. Угол поворота относительно оси Z - angle (в старых версиях OpenSCAD, если я не ошибаюсь, параметр не поддерживался и всегда вращался на 360 гр.). Convexity - параметр, отвечающий за нормальное отображение в окне просмотра сложных моделей, уже упоминался ранее. Последний параметр $fn - отвечает за степень детализации кривых, по умолчанию его значение низкое и модель получается угловатой, поэтому лучше его указывать.
rotate_extrude(angle=300, convexity=10, $fn=200) translate([0,0,0]) text("\u00A9 Наш Колхоз", language="ru", font="Segoe Script:style=Bold", $fn=30); |
|
rotate_extrude(angle=300, convexity=10, $fn=200) translate([15,0,0]) circle(10); |
Функция surface позволяет строить модели на основе файла с данными, или рисунка в формате ".png".
Параметры функции:
Что должен представлять собой файл данных? Файл с данными должен содержать карту высот и иметь расширение ".dat", создать его можно в обычном Windows блокноте. В файл пишутся только координаты по оси Z, разделённые пробелом. Каждая строка обозначает перебор координаты X, а каждый элемент строки отделённый пробелом - перебор координаты Y. По сути мы имеем таблицу с координатами [ 0, 0, Z(0,0) ], [ 0, 1, Z(0,1) ], [ 0, 2, Z(0,2)], ..., [ 0, N, Z(0,N)] потом перенос строки, и координаты для X=1 [ 1, 0, Z(1,0)], [ 1, 1, Z(1,1) ], [ 1, 2, Z(1,2)], ..., [ 1, N, Z(1,N)] и т.д.. Файл с данными нужно размещать в одной папке вместе с сохраняемым кодом OpenSCAD.
На вид это должно выглядеть как то так:
10.5 12.1 12 13 15.6 20 25.1 26 10 15 15.1 16.1 16.6 17.8 18 19 11 18 14 11 15 10 -5 6 ....
Можно записать данные в блокнот руками, или, если вы знакомы с программированием на каком либо языке, создать небольшую программу, которая бы считала координату Z и записывала её в файл. Я поступил по последнему варианту (не хотелось забивать 10 000 значений) - написал программку на языке PHP, которая выдала мне файл с нужными мне данными и подходящим расширением. Результат того, что у меня получилось - приведён ниже.
Второй вариант построения модели - это взять в качестве исходных данных любой рисунок с расширением .png. Можете нарисовать в Paint, что захотите и сохранить рисунок с расширением png.
Модель строится из соображений, что более тёмный цвет соответствует более глубоким точкам модели, а более светлый цвет - более высоким точкам. Можно инвертировать действие, введя invert=true. В общем проще посмотреть на пример.
surface(file="raschet.dat", center=true, convexity=5); |
||
surface( file="kart_color.png", center=true, invert=true, convexity=5 ); |