OpenSCAD je 3D modelovací software, ve kterém se modely nekreslí, ale programují. Výtečně se proto hodí na parametrické a generativní modelování. Udělal jsem parametrický model, který na sebe umí vrstvit texty v různých barvách a velikostech. Výsledný model se pak dá použít třeba na klíče nebo zajímavě vypadající tabulky.
Celé to začalo ve chvíli, kdy "můj" Theophilos (jsem členem syndikátu, v jehož barvách běhá) vyhrál Velkou pardubickou. Chtěl jsem na paměť jeho úžasného výkonu něco vytvořit. A napadl mne vícebarevný přívěšek v barvách našeho syndikátu, bílé a zelené. Přidal jsem k tomu ještě červenou barvu čapky a zasedl k OpenSCADu. Výsledek vypadal takto:
Římská číslice CXXIX odpovídá 129. ročníku Velké pardubické.
A když už jsem to celé dělal, tak proč ne rovnou univerzálně, aby se dala vytisknout jakákoliv kombinace slov? Na ukázku třeba heslo "HORSE POWER":
Vrstev může být i víc než dvě. Model jich zvládá neomezené množství. Nicméně za hraniční obecně pokládám tři vrstvy, více jich už bude nečitelných. Zkusil jsem třeba heslo "1918 CZECH REPUBLIC" v národních barvách:
OpenSCAD kód
Takto vypadá OpenSCAD kód mého modelu:
/* [Base] */
base_color = "#333333";
base_paddding = 2;
base_height = 2;
/* [Text layers] */
layer_heights = [1, 1];
layer_text_strings = [ "HORSE", "POWER"];
layer_text_sizes = [22, 17];
layer_colors = [ "#FF6600", "#EEEEEE"];
font_name = "Arial Rounded MT Bold";
/* [Hanging hole] */
hole_position = [55, 5];
hole_diameter = 5;
// Create base
color(base_color) linear_extrude(base_height) difference() {
offset(base_paddding) union() {
for(i = [0:len(layer_heights) - 1]) text(text = layer_text_strings[i], font = font_name, size = layer_text_sizes[i], halign = "center", valign = "center");
if(hole_diameter > 0) translate(hole_position) circle(d = hole_diameter, $fn = 32);
}
if(hole_diameter > 0) translate(hole_position) circle(d = hole_diameter, $fn = 32);
}
// Create text layers
translate([0, 0, base_height]) for(i = [0:len(layer_heights) - 1]) {
lh = csum(layer_heights, i);
color(layer_colors[i]) linear_extrude(lh) text(text = layer_text_strings[i], font = font_name, size = layer_text_sizes[i], halign = "center", valign = "center");
}
// Helper function to compute total layer height
function csum(items, i, val = 0, n = 0) = n >= i ? val + items[n] : csum(items, i, val + items[n], n + 1);
Pojďme se podívat na jednotlivé jeho části. Na začátku je deklarace proměnných, které určují, jak bude model vypadat.
/* [Base] */
base_color = "#333333";
base_paddding = 2;
base_height = 2;
První sada proměnných popisuje základnu, na které písmena leží:
base_color
popisuje barvu, která se ukáže v náhledu. Informace o barvě není součástí modelu, použije se jenom při náhledu.base_padding
je vzdálenost, o kterou bude základna přečnívat písmena. Hodnotu je nutné určit experimentálně na základě textu a použitého fontu. Podstatné je, aby se písmena "slila" a vytvořila jeden tvar.base_height
je výška základny.
/* [Text layers] */
layer_heights = [1, 1];
layer_text_strings = [ "HORSE", "POWER"];
layer_text_sizes = [22, 17];
layer_colors = [ "#FF6600", "#EEEEEE"];
font_name = "Arial Rounded MT Bold";
Druhá sada proměnných popisuje textové vrstvy - jejich výšku (layer_heights
), text (layer_text_strings
), velikost písma (layer_text_sizes
) a barvy (layer_colors
). Ve všech případech se jedná o seznam (pole), který obsahuje tolik prvků, kolik je vrstev - zde dvě. Pořadí vrstev a velikost písma je nutné nakombinovat podle textu, aby to hezky vypadalo.
Proměnná font_name
je název použitého písma. Já používám Arial Rounded MT Bold, protože ze zkušenosti vím, že jeho zaoblené rohy vypadají při tisku dobře.
/* [Hanging hole] */
hole_position = [55, 5];
hole_diameter = 5;
Poslední sada proměnných popisuje průměr díry na pověšení (hole_diameter
) a její umístění relativně vůči středu (hole_position
). Díra musí být umístěna mimo text a její umístění záleží na účelu a zobrazeném textu. Pokud v modelu nemá díra být, stačí nastavit její průměr na nulu.
// Create base
color(base_color) linear_extrude(base_height) difference() {
offset(base_paddding) union() {
for(i = [0:len(layer_heights) - 1]) text(text = layer_text_strings[i], font = font_name, size = layer_text_sizes[i], halign = "center", valign = "center");
if(hole_diameter > 0) translate(hole_position) circle(d = hole_diameter, $fn = 32);
}
if(hole_diameter > 0) translate(hole_position) circle(d = hole_diameter, $fn = 32);
}
Následuje kód pro vytvoření základny. Nejprve napíšeme jednotlivé textové vrstvy "přes sebe" a přidáme k nim pozici díry. Pomocí union()
tvary sloučíme do jednoho a pomocí offset()
k výslednému tvaru přidáme padding. Pomocí difference()
odečteme z tvaru kruhový otvor. Vše navrhujeme ve 2D, do správné výšky to vytáhneme pomocí linear_extrude
.
// Create text layers
translate([0, 0, base_height]) for(i = [0:len(layer_heights) - 1]) {
lh = csum(layer_heights, i);
color(layer_colors[i]) linear_extrude(lh) text(text = layer_text_strings[i], font = font_name, size = layer_text_sizes[i], halign = "center", valign = "center");
}
Další část vytvoří jednotlivé textové vrstvy. Smyčka je velice podobná té předchozí, ale každou vrstvu vytvoříme v jiné výšce, aby bylo možné v průběhu tisku měnit filament a tím i barvu výtisku.
// Helper function to compute total layer height
function csum(items, i, val = 0, n = 0) = n >= i ? val + items[n] : csum(items, i, val + items[n], n + 1);
K určení celkové výšky vrstvy slouží funce csum
, která sečte definované výšky vrstev.
Výsledný model
Můžete si stáhnout model, kterým to všechno začalo, oslavu Theophilova vítězství. K dispozici je ve formátu STL, který ale neobsahuje informace o změně filamentu (je nutné ho změnit ve výšce 1,4 a 2,0 mm při výšce vrstvy 0,2 mm). Všehcny tyto informace včetně tiskového profilu pro PrusaSlicer pak obsahuje formát 3MF.
Všechny tři zmíněné modely v podobě OpenSCAD kódu a .json
parametrizačního souboru (pro verzi 2019.05) si můžete stáhnout jako ZIP archiv.