logo openscad

OpenSCAD Урок 2. Учимся на простых примерах - функции minkowski, hull, projection. Модели плоских (2D) фигур.

Примеры с функциями minkowski, hull. Дополнительные методы обработки и отладки моделей.

Векторная сумма - minkowski.

Результатом работы функции является Сумма Минковского для нескольких тел. Точки поверхностей N тел векторно суммируются - результатом является некая новая фигура. На слух это воспринимается с трудом, но визуально это достаточно легко понять - поэтому приведу несколько примеров работы с данной функцией.

minkowski(){
  cube([10,10,1], true);
  scale([0.7,0.5,0.3]) sphere(3, $fn=50);
};
sphere_cube sphere+cube_1 sphere+cube_2 sphere+cube_3 result=sphere+cube
minkowski(){
  rotate([0,90,0])cylinder(3,1,2, true, $fn=50);
  cubeM([10,10,1]);   
 }
sphere_cylinder90* sphere+cylinder90*_1 sphere+cylinder90*_2 sphere+cylinder90*_3 result=sphere+cylinder90*
minkowski(){
  cylinder(3,1,2, true, $fn=50);
  cubeM([10,10,1]);   
 }
sphere_cylinder sphere_cylinder_1 sphere_cylinder_2 sphere_cylinder_3 result=sphere_cylinder

Для случая когда одно из слагаемых имеет прямые грани - сумма Минковского выглядит достаточно просто. Если же применять её к сферическим поверхностям с искажённой формой - результат будет сложно представить заранее. Предлагаю вам поэкспериментировать самостоятельно.

Общая оболочка - hull.

Принцип действия полностью соответствует названию. Представьте, что вы размещаете в пространстве две произвольные фигура, а потом обтягиваете их резиновой оболочкой - это и есть функция 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.

Из несимметричных объектов, с помощью вращений и переносов, невозможно получить зеркальную копию. От мучений по постройке зеркальной копии модели нас спасает функция с одноимённым названием 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.

resize - аналог функции scale. Отличие в том, что вместо относительных единиц допустим 0.2 (20%) от исходной величины, задаётся размер по осям XYZ в который нужно вписать объект. Зачем она нужна? Ведь есть scale! Допустим, вы скачали с интернет ресурса - модель, и не знаете её размер. Вам нужно её вписать в определённые рамки - будете подбирать проценты? Не факт, что вы их точно подберёте. Используйте resize.
resize([10,20,30]) cube(5);
resize([10,20,30]) { ... };

Аффинные преобразования - multmatrix.

Функция 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.

Функция 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);
Lavender
Thistle
Plum
Violet
Orchid
Fuchsia
Magenta
MediumOrchid
MediumPurple
BlueViolet
DarkViolet
DarkOrchid
DarkMagenta
Purple
Indigo
DarkSlateBlue
SlateBlue
MediumSlateBlue
Pink
LightPink
HotPink
DeepPink
MediumVioletRed
PaleVioletRed
Aqua
Cyan
LightCyan
PaleTurquoise
Aquamarine
Turquoise
MediumTurquoise
DarkTurquoise
CadetBlue
SteelBlue
LightSteelBlue
PowderBlue
LightBlue
SkyBlue
LightSkyBlue
DeepSkyBlue
DodgerBlue
CornflowerBlue
RoyalBlue
Blue
MediumBlue
DarkBlue
Navy
MidnightBlue
GreenYellow
Chartreuse
LawnGreen
Lime
LimeGreen
PaleGreen
LightGreen
MediumSpringGreen
SpringGreen
MediumSeaGreen
SeaGreen
ForestGreen
Green
DarkGreen
YellowGreen
OliveDrab
Olive
DarkOliveGreen
MediumAquamarine
DarkSeaGreen
LightSeaGreen
DarkCyan
Teal
Cornsilk
BlanchedAlmond
Bisque
NavajoWhite
Wheat
BurlyWood
Tan
RosyBrown
SandyBrown
Peru
Chocolate
SaddleBrown
Sienna
Brown
Maroon
IndianRed
LightCoral
Salmon
DarkSalmon
LightSalmon
Coral
Tomato
LightYellow
LemonChiffon
LightGoldenrodYellow
AntiqueWhite
Linen
LavenderBlush
MistyRose
PapayaWhip
Moccasin
PeachPuff
PaleGoldenrod
Khaki
DarkKhaki
DarkGoldenrod
Goldenrod
Gold
Yellow
DarkOrange
Orange
OrangeRed
Red
Crimson
FireBrick
DarkRed
White
Snow
Honeydew
MintCream
Azure
AliceBlue
GhostWhite
WhiteSmoke
Seashell
Beige
OldLace
FloralWhite
Ivory
Gainsboro
LightGrey
Silver
DarkGray
Gray
DimGray
LightSlateGray
SlateGray
DarkSlateGray
Black

Модификаторы *, !, #, %.

В OpenSCAD есть 4 модификатора: Пример кода.
difference(){
  cube(10,true);
  cube([5,5,20],true); // * ! # %
};
Без модификатора.

*...;
*{...}
!...;
!{...}
#...;
#{...}
%...;
%{...}
Без модификаторов. Модификатор звёздочка (умножение) *. Модификатор восклицательный знак !. Модификатор решётка #. Модификатор процент %.

Плоские модели.

Проекция и сечение модели - projection.

Функция реализует проекцию и сечение. Проекция модели осуществляется НА плоскости 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);
};
Исходная модель. Сечение модели при смещении Z=5. Сечение модели при смещении Z=2. Сечение модели при смещении Z=-2. Сечение модели при смещении Z=-5.

Объекты 2D square(), circle(), polygon()

Плоские примитивы в 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.

Функция служит для создания плоской модели текста. Если же вам нужен объёмный текс - вам помогут 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.

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

Исходные параметры:

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

Зелёный - исходный многоугольник. Жёлтый - результат работы функции.

Увеличение контура фигуры на 2 и скругление внешних углов. Уменьшение контура фигуры на 2 и скругление внутренних углов. Увеличение контура фигуры на 2. Уменьшение контура фигуры на 2. Увеличение контура фигуры на 2 и срез внешних углов. Уменьшение контура фигуры на 2 и срез внутренних углов.

Небольшой совет: если вы хотите закруглить и внешние, и внутренние углы - примените функцию 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);
};
Обратите внимание что один из радиусов должен быть больше второго в 2 раза

Преобразование плоских (2D) фигур в объёмные (3D).

Выдавливаем объёмные фигуры из плоских - функция linear_extrude.

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)]
] );
Выдавливание 6 конечной звезды с вращением и изменением размера

Обещанное отступление про параметр convexity.

Уже после написания данной урока - наткнулся на необходимость указывать параметр convexity в нескольких своих моделях. Насколько я понимаю, convexity призван помочь графическому движку openscad правильно отобразить 3D модель на 2D мониторе. Условно графический движок иногда не совсем может "сообразить" какую грань объекта показать пользователю впереди, а какую позади. Соответственно чем больше в модели "складок" тем сложнее справится графическому движку.

Из полученного опыта хотелось бы выделить. Первое, случаи, в которых необходимо указывать параметр convexity - достаточно редки. Возникают они при использовании linear_extrude, rotate_extrude. В моделях с относительно сложной геометрией, наличием множества отверстий или граней. Второе, опыт говорит о том, что указание параметра convexity иногда помогает, а иногда делает ещё хуже - баг с неправильным отображение модели ни только не уходит, изображение становится хуже. Третье, такие модели иногда рендерятся (создание итогового файла stl) с ошибками. В множестве точек, создающих полую обрешётку модели, появляются незакрытые дырки.

Общая рекомендация - не забывайте, что такой параметр в некоторых функциях есть и в случае появления ошибок отображения пробуйте применять его. Ниже приведу несколько картинок, как примерно выглядит модель с данным багом. В данной модели указание convexity=8 даже ухудшало ситуацию (смотри всплывающие подсказки к рисункам).

Ошибка в отображении модели. Картинка 1 здесь convexity=0. Ошибка в отображении модели. Картинка 2 здесь convexity=0. Ошибка в отображении модели. Картинка 1 здесь convexity=8. Ошибка в отображении модели. Картинка 2 здесь convexity=8.

Тела вращения - функция rotate_extrude.

Функция реализует тела вращения на основе плоских моделей. Плоская модель должна располагаться полностью в положительной части оси 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);
Поверхность полученная вращением текста Наш Колхоз вокруг оси Z
rotate_extrude(angle=300, convexity=10, $fn=200)
translate([15,0,0]) circle(10);
Тор - полученный вращением круга вокруг оси Z

Создаём модель на основе файла с данными или рисунка - функция surface.

Функция 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
);
Рисунок на основе которого строится модель Выпуклая модель на основе рисунка с расширением .png.

OpenSCAD Урок 1. Обучение 3D моделированию. Изучаем основные функции (команды) языка. Разбираем пример модели.

На главную.

DimsT
Функция mirror() без параметров даёт варнинги. Я тут эмпирически вычислил, что надо использовать mirror([x,y,z]) и зеркалить она умеет по всем трём измерениям. К примеру mirror([1,0,0]) отзеркалит по оси x.

2020-10-28 02:41:50
Неизвестный
нранлгр

2020-11-15 08:46:28
HAK
отличная статья

2020-12-27 05:12:04
помойкин
сайт ахунный

2022-11-17 11:56:50
platon-gandon
пизда

2024-02-15 02:03:59
kiza
отличная статья, большое спасибо!

2024-06-22 07:25:31