OpenSCAD: редактор 3D-моделей для программистов |
![]() |
Добавил(а) microsin |
OpenSCAD это бесплатный 3D-редактор, модели в котором создаются при помощи написания скриптов. Мне он понравился потому, что не очень сложен в освоении (мне буквально за выходные удалось изучить его основные возможности и даже в качестве тренировки создать модель панели для холодильника Samsung, см. врезку далее). Требования к компьютеру у OpenSCAD невысокие, есть порты под MacOS, FreeBSD и Linux. Если Вы любите программировать, и не получилось сходу освоить какой-нибудь профессиональный 3D-редактор, то как альтернатива OpenSCAD определенно стоит внимания. Возможности OpenSCAD: 1. Позволяет экспортировать модель во многие форматы, включая STL, OFF, AMF, 3MF, DXF, SVG, CSG. Можно экспортировать растровую картинку в формате PNG. Недостатки OpenSCAD (по чисто моему ИМХО) перечислены ниже. 1. Нет способа измерения размеров на синтезированной модели. Чтобы обойти этот недостаток, я экспортировал модель в формат STL (F7) и загружал STL в редактор SketchUp, и уже там пользовался инструментами измерения размеров. [Особенности 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);): Для обхода этого недостатка есть небольшая хитрость. Создается цилиндр с диаметром в 10 раз больше, после чего он масштабируется с коэффициентом 0.1. Например: scale(0.1,0.1,0.1) circle(d=15); Созданный таким способом цилиндр выглядит намного лучше: 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. |