OpenSCAD: редактор 3D-моделей для программистов Печать
Добавил(а) microsin   

OpenSCAD это бесплатный 3D-редактор, модели в котором создаются при помощи написания скриптов. Мне он понравился потому, что не очень сложен в освоении (мне буквально за выходные удалось изучить его основные возможности и даже в качестве тренировки создать модель панели для холодильника Samsung, см. врезку далее). Требования к компьютеру у OpenSCAD невысокие, есть порты под MacOS, FreeBSD и Linux. Если Вы любите программировать, и не получилось сходу освоить какой-нибудь профессиональный 3D-редактор, то как альтернатива OpenSCAD определенно стоит внимания.

OpenSCAD main window

Возможности OpenSCAD:

1. Позволяет экспортировать модель во многие форматы, включая STL, OFF, AMF, 3MF, DXF, SVG, CSG. Можно экспортировать растровую картинку в формате PNG.
2. Поставляется с многочисленными примерами, позволяющие быстрее закончить процесс обучения. Есть подробный wiki-справочник по функциям [2] и форум поддержки.
3. Консоль позволяет проанализировать процесс компиляции, и в неё можно командой ECHO выводить отладочные сообщения.
4. Язык скриптов очень простой, самая большая трудность в нем заключается только в освоении его операторов, которые надо просто запомнить, или пользоваться справочником. В скрипт можно вставлять комментарии на русском языке. Стиль комментариев такой же, как у языка C.

Недостатки OpenSCAD (по чисто моему ИМХО) перечислены ниже.

1. Нет способа измерения размеров на синтезированной модели. Чтобы обойти этот недостаток, я экспортировал модель в формат STL (F7) и загружал STL в редактор SketchUp, и уже там пользовался инструментами измерения размеров.
2. Также нет возможности вставить направляющие параллельно осям или под нужным углом, на необходимом расстоянии. Это затрудняет процесс создания модели.
3. Нет способа экспорта модели в чертеж.
4. Компилятор скрипта дает в консоли очень лаконичные сообщения об ошибках, фактически указывающих только строку, где есть ошибка.

[Особенности OpenSCAD]

Научиться пользоваться OpenSCAD довольно просто, если разобрать примеры. Принцип создания модели такой же, как в других 3D-редакторах - модель строится из простых примитивов (цилиндр, шар, призма, куб, параллелепипед и т. п.), путем их слияния/наложения или вычитания друг из друга (вычитание осуществляет оператор difference). Отличие только в том, что в OpenSCAD это делается с помощью скриптового языка.

Однако есть некоторые неочевидные моменты, о которых нужно помнить.

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

2. При написании скрипта легко сделать ошибки в модели, которые можно обнаружить только измеряя физические размеры на ней. К сожалению, в OpenSCAD такого инструментария не предусмотрено. Поэтому для проверки модели используйте экспорт в STL и сторонний софт. Я использовал SketchUp Free [3].

3. Хотя заявлено, что OpenSCAD система безразмерная, привязка к абсолютным размерам в ней все-таки есть. К примеру, единица длины в OpenSCAD точно соответствует 1 мм в модели STL, когда она экспортирована.

4. Криволинейные фигуры (например круги и эллипсы) аппроксимируются отрезками с фиксированной длиной 1. Поэтому модель цилиндра с диаметром порядка нескольких миллиметров получается довольно грубая. Например, цилиндр диаметром 1.5 выглядит как пятигранная призма (создана оператором circle(d=1.5);):

OpenSCAD cylinder rude

Для обхода этого недостатка есть небольшая хитрость. Создается цилиндр с диаметром в 10 раз больше, после чего он масштабируется с коэффициентом 0.1. Например:

   scale(0.1,0.1,0.1)
   circle(d=15); 

Созданный таким способом цилиндр выглядит намного лучше:

OpenSCAD cylinder fine

5. OpenSCAD позволяет синтезировать плоские 2D примитивы (например, оператором polygon; есть и другие 2D-операторы, см. справочник [2]). Однако они могут использоваться только для разработки, как направляющие для создания объемных объектов (оператором linear_extrude). Скрипт, где есть плоские объекты, отрендерить в объемную модель (F6), и тем более экспортировать в STL (F7) не получится.

/*================================================
   Проект для каркаса LED-индикатора холодильника
   Samsung RL34ECSW.
   http://microsin.net/adminstuff/hardware/samsung-rl34ecsw-led-repair.html
================================================*/
include < 7seg-digit.scad>
 
// Основные размеры коробки:
sizeX = 62;
sizeY = 63;
sizeZ = 15;
extWall = 1;
 
// Параметры для нижних пазов в юбке:
u=28;
d=34;
h=sizeZ-12.7;
sk=(d-u)/2;
 
module body()
{
   difference()
   {
   color ("grey")
      translate([0,0,-sizeZ])
      cube (size =[sizeX, sizeY, sizeZ], center = false);
        
   color ("yellow")
      translate([extWall,extWall,-(sizeZ+extWall)])
      cube (size =[sizeX-extWall*2,
                   sizeY-extWall*2,
                   sizeZ], center = false);
 
   // Вырезы в юбке снизу и сверху:
   slotDownVert();
   // Вырез в юбке снизу слева:
   slotDL(1.5,3-1,-(12.7+h));
   // Вырез в юбке сверху справа:
   slotUR(sizeX-1.5,sizeY+1,-(12.7+h));
   // Узкие пазы справа внизу:
   paz(54.2,-1,-(sizeZ+1));
   // Узкие пазы слева вверху:
   paz(2.2,sizeY-2,-(sizeZ+1));
   // Вырез в юбке слева вверху по горизонтали:
   slotUh(2,sizeY-1,-(12.7+h));
   // Вырез в юбке справа вввеху по горизонтали:
   slotUh(sizeX+1,sizeY-1,-(12.7+h));
   // Вырез в юбке слева внизу по горизонтали:
   slotDh(-1, 1, -(12.7+h));
   // Вырез в юбке справа внизу по горизонтали:
   slotDh(sizeX-2, 1, -(12.7+h));
   }
 
   // Направляющие штифты:
   pin(0.8,0.8,-(sizeZ+2));
   pin(sizeX-0.8,sizeY-0.8,-(sizeZ+2));
 
   // Защелки:
   latchRD(55,0,-sizeZ);
   latchLU(3,sizeY-extWall,-sizeZ);
}
 
module paz(x,y,z)
{
   translate([x,y,z])
   cube (size=[0.8,3,6+1], center = false);
   translate([x+4.8,y,z])
   cube (size=[0.8,3,6+1], center = false);
}
 
module slotUh(x,y,z)
{
   translate([x,y,z])
   rotate(a=[90, 0, -90])
   linear_extrude(height = 3, center = false)
   polygon(points=[[0,-1],[0,0],[0,h],[22.5,h],[22.5+sk,0],[22.5+sk,-1]]);
}
 
module slotDh(x,y,z)
{
   translate([x,y,z])
   rotate(a=[0, 0, 180])
   slotUh(0,0,0);
}
 
module slotDownVert()
{
   shiftX = (sizeX-d)/2;
   
   translate([shiftX,sizeY+1,-(12.7+h)])
   rotate(a=[90, 0, 0])
   linear_extrude(height = 1+sizeY+1, center = false)
   polygon(points=[[0,-1],[0,0],[sk,h],[sk+u,h],[sk+u+sk,0],[sk+u+sk,-1]]);
}
 
module slotDL(x,y,z)
{
   translate([x,y,z])
   rotate(a=[90, 0, 0])
   linear_extrude(height = 3, center = false)
   polygon(points=[[0,-1],[0,0],[0,h],[3,h],[3+sk,0],[3+sk,-1]]);
}
 
module slotUR(x,y,z)
{
   translate([x,y,z])
   mirror(0,0,1)
   slotDL(0,0,0);
}
 
// Знак "минус" перед нижними цифрами:
module segmentG(x,y,z)
{
   up = 2.0;
   right = 6;
   skosA = 1.1;
   skosB = 0.72;
   depth = 5;
   color ("yellow")
      translate([x,y,z])
      linear_extrude(height = depth, center = false)
      polygon(points=[[0,1],[skosA,up],[right-skosB,up],[right,1],[right-skosA,0],[skosB,0]]);
}
 
module squares()
{
   shiftX = 12;
   cubeX = 5;
   cubeY = 4.5;
   cubeZ = 3;
   interval = 1;
   
   Y1 = 3.5;
   translate([shiftX,Y1,-2])
      cube(size=[cubeX,cubeY,cubeZ]);
   Y2 = Y1 + (cubeY + interval);
   translate([shiftX,Y2,-2])
      cube(size=[cubeX,cubeY,cubeZ]);
   Y3 = Y2 + (cubeY + interval);
   translate([shiftX,Y3,-2])
      cube(size=[cubeX,cubeY,cubeZ]);
   //echo (Y3 + cubeY);
}
 
module guides(transp)
{
color ("grey", transp)
translate([27,43,0])
    square(size=[20,16]);
color ("grey", transp)
translate([27,23.2,0])
    square(size=[20,16]);
}
 
module digits(depthZ)
{
   // Знак минус напротив нижних цифр:
   segmentG(21.3,29.5,-depthZ);
   // Две верхние цифры:
   7dig(26,42.4,-depthZ);
   7dig(36,42.4,-depthZ);
   // Две нижние цифры:
   7dig(26,22.5,-depthZ);
   7dig(36,22.5,-depthZ);
}
 
module squares(depthZ)
{
   shiftX = 12;
   cubeX = 5;
   cubeY = 4.5;
   interval = 1;
   
   Y1 = 3.5;
   Y2 = Y1 + (cubeY + interval);
   Y3 = Y2 + (cubeY + interval);
 
   translate([shiftX,Y3+0.85,-depthZ])
   rotate(a=[90, 0, 90])
   linear_extrude(height = 5, center = false)
   polygon(points=[[0,0],
                   [-(cubeY+0.2-2.8)/2,4.55+0.5],
                   [-(cubeY+0.2-2.8)/2+cubeY+0.2,4.55+0.5],
                   [2.8,0]]);
   translate([shiftX,Y2+0.85,-depthZ])
   rotate(a=[90, 0, 90])
   linear_extrude(height = 5, center = false)
   polygon(points=[[0,0],
                   [-(cubeY+0.2-2.8)/2,4.55+0.5],
                   [-(cubeY+0.2-2.8)/2+cubeY+0.2,4.55+0.5],
                   [2.8,0]]);
   translate([shiftX,Y1+0.85,-depthZ])
   rotate(a=[90, 0, 90])
   linear_extrude(height = 5, center = false)
   polygon(points=[[0,0],
                   [-(cubeY+0.2-2.8)/2,4.55+0.5],
                   [-(cubeY+0.2-2.8)/2+cubeY+0.2,4.55+0.5],
                   [2.8,0]]);
}
 
// Внутренние перегородки:
module wallInt()
{
   wallthick = 0.7;  // толщина внутренней стенки
   // Отступ левой стенки 1:
   shiftX1 = 11.8 - wallthick;   
   // Отступ левой стенки 2:
   shiftX2 = 23.3 - wallthick;
   // Отступ правой стенки:
   shiftX3 = 47.4;
   // Отступ правых горизонтальных ребер:
   shiftX4 = shiftX3+0.01;
   
   // Вертикальная левая стенка 1:
   color("red")
   translate([shiftX1,0.01,-10.01])
   cube(size=[1,33,10]);
   // Горизонтальная левая стенка:
   color("red")
   translate([shiftX1,32.8-wallthick,-10.01])
   cube(size=[12.4,1,10]);
   // Вертикальная левая стенка 1:
   color("red")
   translate([shiftX2,32.8-wallthick,-10.01])
   cube(size=[1,30.8,10]);
   // Вертикальная правая стенка:
   color("red")
   translate([shiftX3,0.01,-10.01])
   cube(size=[1,62.98,10]);
   
   // Горизонтальное правое ребрышко 1:
   color("red")
   translate([shiftX4,11.5,-3.51])
   cube(size=[14.6-0.02,1,3.5]);
   // Горизонтальное левое ребрышко 1:
   color("red")
   translate([0.01,11.5,-3.51])
   cube(size=[12.1-0.02,1,3.5]);
   // Горизонтальное правое ребрышко 2:
   color("red")
   translate([shiftX4,32.2,-3.51])
   cube(size=[14.6-0.02,1,3.5]);
   // Горизонтальное правое ребрышко 3:
   color("red")
   translate([shiftX4,51.6,-3.51])
   cube(size=[14.6-0.02,1,3.5]);
   // Горизонтальное левое ребрышко 2:
   color("red")
   translate([0.01,51.6,-3.51])
   cube(size=[23.6-0.02,1,3.5]);
}
 
module pin(x,y,z)
{
   translate([x,y,z])
   linear_extrude(height = sizeZ+1.9, center = false)
   scale(0.1,0.1,0.1)
   circle(d=15);
}
 
module latchRD(x,y,z)
{
   translate([x,y,z-4])
   cube(size=[4,1,5]);
   translate([x+4,y+1,z-4])
   rotate(a=[90, 0, 270])
   linear_extrude(height = 4, center = false)
   polygon(points=[[0,0],[0,2.2],[1.9,2.2],[1.9,1],[1,0]]);
}
 
module latchLU(x,y,z)
{
   translate([x,y,z-4])
   cube(size=[4,1,5]);
   translate([x,y,z-4])
   rotate(a=[90, 0, 90])
   linear_extrude(height = 4, center = false)
   polygon(points=[[0,0],[0,2.2],[1.9,2.2],[1.9,1],[1,0]]);
}
 
module holes()
{
   digits(4.55);
   // Квадратики:
   squares(4.55);
}
 
// Внутренний выступ вокруг цифр и квадратиков.
module InternalLedge()
{
   skos = 3.34;
   top = 20;
   height = 17.6;
   depth = 4.5;
 
   // Вокруг цифр:
   translate([25.2,21.6,-depth])
   linear_extrude(height = depth, center = false)
   polygon(points=[[0,0],[skos, height],
                   [skos+top,height],[top,0]]);
   translate([25.2,41.6,-depth])
   linear_extrude(height = depth, center = false)
   polygon(points=[[0,0],[skos, height],
                   [skos+top,height],[top,0]]);
   translate([20,28.5,-depth])
   linear_extrude(height = depth, center = false)
   polygon(points=[[0,0],[0.7, 4],
                   [0.7+7,4],[7,0]]);
 
   // Между верхними и нижими цифрами:
   translate([23,39,-depth])
   cube (size =[25, 3, depth], center = false);
   
   // Вокруг квадратиков:
   translate([11,2,-depth])
   cube (size =[8, 19, depth], center = false);
}
 
difference()
{
   union()
   {
      // Корпус и цифры:
      body();
      InternalLedge();
      wallInt();
   }
   holes();
}

Модель довольно сложная, её лучше печатать минимальной толщиной слоя. Желательно использовать пластик не PLA, а какой-нибудь более эластичный пластик, иначе защелки и штифты направляющих будут отламываться.

[Ссылки]

1. OpenSCAD The Programmers Solid 3D CAD Modeller site:openscad.org.
2. OpenSCAD CheatSheet.
3. SketchUp Free site:sketchup.com.
4. Ремонт индикаторной панели Samsung RL34ECSW.