Skip navigation

OK2RKB | ENG · GER · RUS · FRA · POL · HUN | Main · IE+ · IE- · Prn · Pda · CSSoff

OK2PPK » Texty » Technika a provoz » Poznámky k OpenSCADu | ---

Poznámky k OpenSCADu

Každý začátek je těžký, a tak i v OpenSCADu člověk při navrhování 3D modelů zpočátku trochu tápe, naráží na problémy a využívá málo z toho, co mu program pro ulehčení tvorby nabízí. Na této stránce jsem zkusil shrnout pár drobností, co třeba někomu dalšímu v začátcích pomohou. Popisované příklady vycházejí z možností verse 2019.5.

Zobrazování v OpenSCADu

Nejprve pár poznámek k chování samotného programu OpenSCAD, kdy se můžete potkat např. s divnými artefakty nebo mizejícími částmi v náhledu, popř. nejde náhled vůbec zobrazit nebo zobrazení trvá dlouho.

Přepnutí na zobrazení Goldfeather

Můžete se potkat s divným chováním náhledu, kdy při změně pohledu na objekt jeho část zmizí (typicky třeba při použití diference) a při dalším pootočení se zase objeví, přitom vyrenderované finální těleso je vpořádku. Něco se o tom dá najít na webu, třeba zde. Souvisí to s inteláckým driverem od grafiky. Sám jsem se s tím potkal a musel jsem provést přenastavení OpenSCADu, nicméně teď, když chystám materiál pro tuto stránku, tak jsem zjistil, že problém vymizel - asi některá z mnoha záplat OS, co mezitím proběhnula, chybu opravila. Pokud tento problém máte, tak sáhněte v OpenSCADu do Předvoleb, vyberte Pokročilé a zaškrtněte volbu Vynutit zobrazení Goldfeather.

Obr.1. Nastavení Goldfeather.

 

Příliš mnoho prvků

U složitějších objektů se vám můžete stát, že se náhled nezobrazí a místo toho se jen na konzoli objeví varování Normalized tree is growing past ... elements. Aborting normalization.

Obr.2. Varování na příliš mnoho prvků.

 

Pak opět jděte do Předvoleb, vyberte Pokročilé a zvyšte hodnotu u nastavení Vypnout renderování při ... prvcích.

Obr.3. Nastavení počtu prvků.

 

Pomalé zobrazování náhledu

S rostoucí složitostí objektu se prodlužuje nejen doba renderování výsledného tělesa, ale pomalé se stává i samotné prohlížení náhledu. Postupně zjistíte, že něco se urychlí tím, že části, které se nezměnily, se načítají z cache, něco se možná podaří obejít tím, že se na některé části použije render(), něco se dá zrychlit tak, že se díly vyexportují do STL a zpět se do modelu načtou pomocí import(), a můžete zkusit hledat na fórech rady od jiných, co znají dobře vnitřnosti OpenSCADu a ví, jaký postup bude nejméně časově náročný. Ale obecně to většinou moc rychlejší asi nebude.

Já jsem narazil na problém se zobrazováním závitových děr, kdy jeden závit byl ještě únosný, ale při více kusech se s náhledem nedalo skoro pracovat. Pomohlo mi na závity aplikovat modifikátor %, kdy se odladěné závity dále již nezpracovávaly a mohl jsem tak dokončit úpravy zbylého tělesa bez věčného čekání na pootočení náhledu. Velký problém zde může způsobit též použití průniků při vytváření více otvorů (viz komentář níže v části zabývající se operací průniku).

Nastavení hodnoty convexity

Některé problémy se zobrazením, kdy při některém nastavení pohledu na náhled objektu zmizí některé části tělesa a při jiném se zobrazuji správně, souvisejí s nastavením hodnoty parametru convexity u některých operací, např. u lineární extruze v kombinaci s diferencí.

Mějme např. takovéto těleso.

difference()
{
  translate([-20,-5,0]) cube([40,30,10]);
  translate([0,0,-0.1]) 
    linear_extrude(height=10.2) 
      polygon([[-15,20],[-15,0],[-5,0],[-5,15],[5,15],[5,0],[15,0],[15,20]]);
}

U jeho náhledu při určitém pohledu zmizí část středního sloupku.

Obr.4. Convexity - artefakt v zobrazování.

 

Stačí u linear_extrude() nastavit parametr convexity

difference()
{
  translate([-20,-5,0]) cube([40,30,10]);
  translate([0,0,-0.1]) 
    linear_extrude(height=10.2, convexity=2) 
      polygon([[-15,20],[-15,0],[-5,0],[-5,15],[5,15],[5,0],[15,0],[15,20]]);
}

a náhled se již zobrazuje bez artefaktů.

Obr.5. Convexity - zobrazení vpořádku.

 

Práce s objekty

Některé funkcionality OpenSCADu vám mohou pomoci ovlivnit, které části tělesa a jak se mají zobrazit a zpracovávat při náhledu a renderování, a nebo zefektivnit zpracování více souborů.

Proměnná $preview

Existuje speciální proměnná $preview, která nabývá hodnoty true při generování náhledu (klávesa F5) a false při renderování (klávesa F6). Lze toho s výhodou využít např. ke zrychlení práce s náhledem tím, že se oproti renderování bude zpracovávat méně detailů.

$fn = $preview ? 15 : 60; //nahled F5 = 15, renderovani F6 = 60

Modifikátory

Předřazením znaků %, #, ! a * lze docílit zprůhlednění nebo vyřazení některé části tělesa ze zobrazení a zpracování. Je to užitečné např. při úpravách tvaru vnitřních dutin, kdy lze takto zobrazit jinak zakryté části apod.

Modifikátor % (background)

Modifikátor % způsobí, že daná část se zobrazí v průhledné šedé barvě a současně je vyřazena ze zpracování. Vyřazení ze zpracování může mít dopad na zobrazení zbytku tělesa.

//difference()
{
  %sphere(20);
  sphere(10);
}

Obr.6. Vliv modifikátoru %.

 

Modifikátor # (debug)

Modifikátor # zobrazí danou část tělesa v průhledné růžové barvě, ale tato část se dále zpracovává obvyklým způsobem.

//difference()
{
  #sphere(20);
  sphere(10);
}

Obr.7. Vliv modifikátoru #.

 

Rozdíl mezi modifikátory % a # není z tohoto obrázku zřejmý, bude názorněji ukázán u příkladu níže v části zabývající se průniky.

Modifikátor ! (root)

Modifikátor ! způsobí, že se jako kořen ve stromě všech částí tělesa použije až takto označená část, a ostatní části se ignorují.

difference()
{
  cube([20,20,10],center=true);
  !union()
  { 
    sphere(10);
    translate([0,0,-5.1]) cylinder(r=10,h=5.1);
  }
}

Obr.8. Vliv modifikátoru !.

 

Modifikátor * (disable)

Modifikátor * vyřadí jím označenou část tělesa ze zpracování.

difference()
{
  cube([20,20,10],center=true);
  *union()
  { 
    sphere(10);
    translate([0,0,-5.1]) cylinder(r=10,h=5.1);
  }
}

Obr.9. Vliv modifikátoru *.

 

Funkce echo

Pokud potřebujete zjistit třeba hodnotu některé proměnné, můžete využít funkci echo(), která údaje vypíše v okně konzole.

a=10;
b=a*tan(30);
l=2*a;

echo(l+b);

Obr.10. Výstup funkce echo() se vypíše na konzoli.

 

Projekce - získání 2D tvaru z 3D tělesa

Pokud potřebujete převést 3D těleso na jeho obrys ve formě 2D tvaru, lze toho dosáhnout za pomoci funkce projection(), která 3D těleso promítne jako 2D objekt v rovině X-Y. A takto získaný 2D objekt pak již můžete po ukončení renderování exportovat jako křivku ve formátu SVG nebo DXF.

Při projekci můžete nastavením parametru cut ovlivnit, které části se budou do plochy X-Y promítat. Při nastavení cut na hodnotu false (což je výchozí nastavení), se do do roviny X-Y promítne celé těleso, tedy i části ležící pod i nad úrovní z=0.

projection() rotate([0,30,0]) cylinder(d=8, h=20, center=true);

Obr.11. Těleso 1, na které bude aplikována projekce.

 

Obr.12. Náhled projekce tělesa 1 s nastavením zobrazení včetně částí nad i pod úrovní z=0.

 

Obr.13. Projekce tělesa 1 po renderování.

 

Při nastavení cut na hodnotu true se do do roviny X-Y promítne jen řez tělesem v úrovni z=0.

projection(cut=true) translate([0,0,5]) rotate([0,30,0]) cylinder(d=8, h=20, center=true);

Obr.14. Těleso 2, na které bude aplikována projekce.

 

Obr.15. Náhled projekce tělesa 2 s nastavením zobrazení pouze částí v úrovni z=0.

 

Obr.16. Projekce tělesa 2 po renderování.

 

Použití projekce je způsob, kterým lze získat podklady pro zhotovení výkresové dokumentace. Posouváním v ose Z a natáčením tělesa se vytvoří potřebné projekce a ty se po vyexportování zpracují v jiném programu. Např. můžete 2D tvar vyexportovat ve formátu DXF, tento načíst do LibreCADu a v něm ho poupravovat a okótovat. Je zde ale jedna nepříjemnost - křivky, tedy i oblouky a kružnice, jsou při exportu nahrazeny jejich interpolací pomocí lomené čáry, tj. nelze s nimi pak dále jednoduše pracovat jako s křivkami.

Dávkové zpracování

Pokud potřebujete zpracovat více souborů, tak můžete využít ovládání programu OpenSCAD z příkazové řádky. Přes příkazovou řádku také můžete vytvořit náhledový obrázek v jiném než defaultním rozlišení.

Výpis nápovědy programu OpenSCAD
Usage: openscad.exe [options] file.scad
Allowed options:
  -o [ --o ] arg               output specified file instead of running the 
                               GUI, the file extension specifies the type: stl,
                               off, amf, 3mf, csg, dxf, svg, png, echo, ast, 
                               term, nef3, nefdbg
                               
  -D [ --D ] arg               var=val -pre-define variables
  -p [ --p ] arg               customizer parameter file
  -P [ --P ] arg               customizer parameter set
  -h [ --help ]                print this help message and exit
  -v [ --version ]             print the version
  --info                       print information about the build process
                               
  --camera arg                 camera parameters when exporting png: 
                               =translate_x,y,z,rot_x,y,z,dist or 
                               =eye_x,y,z,center_x,y,z
  --autocenter                 adjust camera to look at object's center
  --viewall                    adjust camera to fit object
  --imgsize arg                =width,height of exported png
  --render arg                 for full geometry evaluation when exporting png
  --preview arg                [=throwntogether] -for ThrownTogether preview 
                               png
  --view arg                   =view options: axes | crosshairs | edges | 
                               scales | wireframe
  --projection arg             =(o)rtho or (p)erspective when exporting png
  --csglimit arg               =n -stop rendering at n CSG elements when 
                               exporting png
  --colorscheme arg            =colorscheme: *Cornfield | Metallic | Sunset | 
                               Starnight | BeforeDawn | Nature | DeepOcean | 
                               Solarized | Tomorrow | Tomorrow Night | Monotone
                               
  -d [ --d ] arg               deps_file -generate a dependency file for make
  -m [ --m ] arg               make_cmd -runs make_cmd file if file is missing
  -q [ --quiet ]               quiet mode (don't print anything *except* 
                               errors)
  --hardwarnings               Stop on the first warning
  --check-parameters arg       =true/false, configure the parameter check for 
                               user modules and functions
  --check-parameter-ranges arg =true/false, configure the parameter range check
                               for builtin modules
  --debug arg                  special debug info
  -s [ --s ] arg               stl_file deprecated, use -o
  -x [ --x ] arg               dxf_file deprecated, use -o

Vytváření objektů

Přestože OpenSCAD vám umožní přímo vytvářet jen pár základních tvarů těles, tak ve skutečnosti disponuje spoustou užitečných nástrojů, kterými si vytváření složitějších objektů můžete výrazně zjednodušit. A naopak při některých operacích zjistíte, že to v něm není tak jednoduché, jak se na první pohled zdálo.

Zjednodušení následných úprav objektu

Vytváření tělesa v OpenSCADu je velmi podobné programování. A fungují zde tak i podobné principy z pohledu přehlednosti a následné upravitelnosti kódu. Nejjednodušší cesta je samozřejmě začít cpát všechny příkazy, ze kterých se těleso bude tvořit, do jednoho velikého celku bez použití modulů, a jejich parametry zadávat přímo číselnými konstantami.

Jenže i u jednodušších objektů je pak peklo, když je potřeba změnit některý rozměr, na kterém závisí řada dalších parametrů, a s rostoucí složitostí se celý popis tělesa stává nepřehledným, což může být příčinou zavlečení chyb, a následné úpravy tělesa jsou navíc časově náročné.

Výhodnější tedy může být rozdělit si těleso na více menších dílů do modulů a rozměry zadávat pomocí proměnných. A hlavní těleso je též dobré mít jako modul, protože pokud s ním potřebujete následně posunout, pootočit nebo ho třeba vyzkoušet, jak sedí proti dalšímu dílu, tak se to snadněji dělá s odvoláním se na jméno dotyčného modulu, než manipulací s celým jeho kódem.

Parametrizace

Řada rozměrů může záviset na jiných. Pokud je zadáváme přímo jako číselné konstanty v parametrech jednotlivých funkcí a transformací, tak musíme závislosti sami vyčíslit a běžné je, že stejný rozměr musíme zadávat na více místech.

Mějme následující jednoduché těleso. Jedná se o obyčejný otvor, který se má nacházet ve středu kvádru. Zde musíme sami z rozměrů kvádru spočítat polohu otvoru.

//otvor ve stredu kvadru
difference()
{
  cube([10,10,10]);
  translate([5,5,-0.1]) cylinder(d=5,h=10.2);
}

Obr.17. Původní těleso.

 

Můžeme ale popis tělesa parametrizovat, tj. např. polohu otvoru nechat spočítat ze zadaného rozměru kvádru.

l=10;
w=10;
h=10;
d=5;
p=0.1;
difference()
{
  cube([l,w,h]);
  translate([l/2,w/2,-p]) cylinder(d=d,h=h+2*p);
}

Tímto zápisem jsme dosáhli toho, že poloha středu otvoru nyní závisí na zadaném rozměru kvádru. Zápis je samozřejmě delší, než ten původní, ale výhoda se ukáže hned, jakmile budeme potřebovat některý rozměr změnit. Tj. mějme nyní požadavek na změnu rozměru kvádru - má se prodloužit na 20 a snížit na 5, přitom otvor má nadále zůstat v jeho středu. Při prvním způsobu zápisu to znamená spoustu přepisování a hlavně hledání které všechny rozměry závisí na upravených rozměrech kvádru a je je tedy také nutné opravit.

//kvadr prodlouzeny na 20 a snizeny na 5
//otvor zustal ve stredu kvadru
difference()
{
  cube([20,10,5]);
  translate([10,5,-0.1]) cylinder(d=5,h=5.2);
}

Obr.18. Těleso se změněnými rozměry.

 

V případě druhého zápisu je změna triviální, stačí upravit zadaný rozměr kvádru.

l=20;
w=10;
h=5;
d=5;
p=0.1;
difference()
{
  cube([l,w,h]);
  translate([l/2,w/2,-p]) cylinder(d=d,h=h+2*p);
}

U takto jednoduchého tělesa není možná výhoda parametrizace až tak zřejmá, ale stačí si představit více komplikovaný objekt a myslím, že se málokomu bude chtít v něm hledat v desítkách hodnot ty, které se mají upravit, a především si vzpomínat, jak tyto hodnoty vzájemně závisely na jiných a jak se tedy mají znovu správně spočítat. Ikdyž si člověk myslí, že danou věc jednou navrhne a už se k ní nikdy nebude vracet, tak při 3D tisku je dost možné, že se k ní autor bude vracet během pár minut poté, co zjistí, že rozměry při prvním tisku nevyšly dle jeho přání, a je potřeba je trošičku upravit.

Proměnné

Parametrizace je fajn věc, ale použití proměnných v OpenSCADu má svoje úskalí. Tím je fakt, že proměnné jsou vlastně konstantami a nelze je použít úplně stejně jako proměnné v běžných programovacích jazycích. Proměnnou lze přiřadit pouze jednou a pak si už svoji hodnotu drží jako konstantu a to v celém oboru své platnosti.

Pokud se pokusíme v následujícím zápisu měnit rozměr válce následným způsobem pomocí podmiňovacího bloku

valec();
translate([20,0,0]) valec(2);
module valec(m=0)
{
  d=5;
  h=3;  
  if (m>=1)
  {     
    d=d*m;
    h=h*m;  
  }
  cylinder(d=d, h=h);
}

tak zjistíme, že druhý válec se nezměnil. Pokud si vypíšeme hodnoty proměnných v jednotlivých bodech tak zjistíme, že v podmiňovacím bloku se hodnoty d a h nastavily správně na 10 a 6, ale platí jen lokálně v rámci tohoto bloku IF.

Obr.19. Změna rozměru válce neproběhla, oba jsou stejné.

 

Půjde to obejít třeba následujícím zápisem.

valec();
translate([20,0,0]) valec(2);
module valec(m=0)
{
  d=(m>=1)?5*m:5;
  h=(m>=1)?3*m:3;
  
  cylinder(d=d, h=h);
}

Nyní má druhý válec už rozměry změněné.

Obr.20. Změna rozměru válce proběhla úspěšně.

 

Pokud se pokusíte stejnou proměnnou přiřadit ve stejném oboru její platnosti vícekráte, jako je tomu v následujícím příkladu,

d=10;
echo(d);
d=20;
echo(d);

tak obdržíte jednak varování na konzoli a dále se stane zajímavá věc, hodnota proměnné se sice změní, ale změní se v celém oboru její platnosti na poslední přiřazenou hodnotu. V tomto příkladu tedy i první echo() vypíše hodnotu 20.

Obr.21. Varování na konzoli - došlo k přepsání hodnoty proměnné.

 

Moduly

Popis tělesa lze rozdělit do modulů. Mějme následující kód.

$fn=30;

difference()
{   
  difference()
  {
    cube([40,20,15]);
    translate([-0.1,-0.1,5]) cube([32.1,20.2,10.1]);  
  }    

  translate([10,5,0]) intersection()
  {
    union()
    {
      translate([0,0,-0.1]) cylinder(d=3, h=2.2);
      translate([0,0,2]) cylinder(d1=3, d2=6.75, h=3.1);
    }    
    translate([0,0,-0.1]) cylinder(d=6, h=5.2); 
  }    

  translate([22,15,0]) intersection()
  {
    union()
    {
      translate([0,0,-0.1]) cylinder(d=3, h=2.2);
      translate([0,0,2]) cylinder(d1=3, d2=6.75, h=3.1);
    }    
    translate([0,0,-0.1]) cylinder(d=6, h=5.2); 
  }    

  translate([40,10,10]) rotate([0,-90,0]) intersection()
  {
    union()
    {
      translate([0,0,-0.1]) cylinder(d=3, h=5.2);
      translate([0,0,5]) cylinder(d1=3, d2=6.75, h=3.1);
    }    
    translate([0,0,-0.1]) cylinder(d=6, h=8.2); 
  }    
}

Toto těleso vypadá následovně.

Obr.22. Použití modulu.

 

Pokud popis tělesa přepíšeme následujícím způsobem s využitím parametrizace a modulů, je přehlednější a snáze upravitelný.

$fn=30;
p=0.1;

lv=32;  
tv=10;  
l=40;
w=20;
h=5+tv;
x1=10;
y1=5;

teleso();

module teleso()
{
  difference()
  {   
    deska();  
    translate([x1,y1,0]) otvor(h-tv);
    translate([lv-x1,w-y1,0]) otvor(h-tv);
    translate([l,w/2,h-tv/2]) rotate([0,-90,0]) otvor(l-lv);
  }    
}

module deska()
{
  difference()
  {
    cube([l,w,h]);
    translate([-p,-p,h-tv]) cube([lv+p,w+2*p,tv+p]);  
  }    
}    

module otvor(h)
{
  ds=3;  
  dh=6;  
  hh=3;  
  t=0.6;  
  dp=ds+(dh-ds)*hh/(hh-t);  
  intersection()
  {
    union()
    {
      translate([0,0,-p]) cylinder(d=ds, h=h-hh+2*p);
      translate([0,0,h-hh]) cylinder(d1=ds, d2=dp, h=hh+p);
    }    
    translate([0,0,-p]) cylinder(d=dh, h=h+2*p); 
  }    
}

Moduly lze ale využívat i dalším způsobem - jako operátory. Pokud se za modulem místo středníku umístí objekt, tak se na něj aplikují operace definované v modulu.

presun(10,0) cylinder(d=1, h=2);
presun(10,30) cylinder(d=3, h=2);
presun(10,60) cylinder(d=5, h=2);

module presun(r,a)
{
  rotate([0,0,a]) translate([r,0,0]) children();
}

Obr.23. Modul jako operátor nad jedním tělesem.

 

Za modulem použitým jako operátor může být dokonce v bloku uvedeno více objektů a při definování operací v modulu lze tyto jednotlivé objekty rozlišit pomocí children() a $children.

presun(10,45)
{
  difference()
  {  
    cylinder(d=5, h=2, $fn=30);
    cylinder(d=2, h=2.1, $fn=30);
  }    
  translate([0,0,0.5]) color("pink") cube([5,6,1], center=true);
}    

module presun(r,a)
{
  for(i=[0:1:$children-1])  
    rotate([0,0,a]) translate([r,0,0]) children(i);
}

Obr.24. Modul jako operátor nad více tělesy.

 

Funkce

Kromě modulů si lze popis tělesa zjednodušit a zpřehlednit i využitím funkcí. Případné dílčí výpočty před přiřazením finálního výsledku lze provést pomocí použití zápisu let(přiřazení 1, přiřazení 2, ...) vloženým před finální výsledek. Výsledkem může být samozřejmě i vektor. S funkcemi lze pracovat i rekurzivně.

difference()
{
  cube([40,20,2]);    
  for(i=[0:1:17])
    translate([2+i*2,10+y(i,18,5),-0.1]) 
      cylinder(d=1, h=2.2, $fn=15);  
}    

function y(i,n,h) =
  let(a=i*360/n) sin(a)*h;

Tento příklad vytvoří následující těleso.

Obr.25. Použití funkce.

 

U funkcí (a i u modulů) lze používat rekurzivní volání, tj. funkce může volat sebe samu. Hloubka vnoření se u rekurzivních funkcí ošetří pomocí operátoru podmínky (? :). Následující příklad rekurzivní funkce sečte všechna čísla až do hodnoty n.

function soucet(n) = (n==0) ? 0 : n + soucet(n-1);
echo(soucet(1000)); //500500

Pokud výše uvedený příklad zavoláte s větší hodnotou n, tak skončíte na chybovém hlášení (mně to končilo někde kolem 6.5 tisíce) kvůli omezení danému velikostí zásobníku. OpenSCAD ale u funkcí zná i konstrukci tzv. koncové rekurze. Taková funkce musí volat sebe samu bez toho, že by se výsledek volání ještě nějak dále zpracovával, resp. jinak řečeno zavolání sebe sama je poslední operace. Pak lze díky tomu, že návratovou hodnotou volající funkce je přímo hodnota vrácená volanou funkcí, převést rekurzivní volání na ekvivalent obyčejného cyklu, kde již není hloubka vnoření omezena zásobníkem jako při běžné rekurzi. Následující příklad provede stejný součet jako funkce v předchozím příkladu, ale jako parametr lze použít i mnohem větší číslo. Rozdíl oproti předchozímu příkladu je v tom, že zatímco v předchozím bylo pro vyčíslení návratové hodnoty volající funkce nutné znát i hodnotu proměnné n ve volající funkci, ke které se přičetla hodnota vrácená volanou funkcí, tak v následujícím příkladu stačí pro získání návratové hodnoty volající funkce znát jen hodnotu, kterou vrátí volaná funkce.

function soucet(n,s=0) = (n==0) ? s : soucet(n-1, s+n); 
echo(soucet(100000)); //5.00005e+9

Poslední operací se nemyslí to, že by volání funkce muselo být uvedeno v těle funkce až na posledním místě, pouze musí být poslední provedenou operací v jejich řetězci. Takže následující zápis funkce je tím, co provádí, ekvivalentní předchozímu.

function soucet(n,s=0) = (n>0) ? soucet(n-1, s+n) : s;  
echo(soucet(100000)); //5.00005e+9

Kromě použití modulů a funkcí lze také kód rozdělit do více souborů a pomocí příkazů include a use je skládat dohromady nebo využívat jako knihovny. Use narozdíl od include načte z externího souboru pouze definice modulů a funkcí a nespouští z něho žádné jiné příkazy.

Rozdíl těles (difference)

Pokud odečtete od sebe dvě tělesa např. se stejnou výškou jako v následujícím příkladu

difference()
{
  cube([20,20,10],center=true);
  cylinder(d=15,h=10,center=true);
}

tak na náhledu se vám objeví na obou stranách otvoru artefakty v podobě dvou tenkých ploch.

Obr.26. Odečtením 2 těles se stejnou výškou vznikne artefakt v podobě plochy s nulovou tloušťkou.

 

Pokud se jich chcete zbavit, je potřeba těleso, které odečítáte, udělat s malým přesahem přes stěny tělesa, od něhož je odebíráno. V tomto případě stačí zvětšit lehce výšku válce, který tak přesáhne o malý kousek přes kvádr na obou stranách

difference()
{
  cube([20,20,10],center=true);
  cylinder(d=15,h=10.1,center=true);
}

a v náhledu obě tenké plochy překrývající otvor zmizí.

Obr.27. Pokud je odečítané těleso vyšší, tak artefakt nevznikne.

 

Problém s překrytím otvorů tenkou plochou se u tohoto příkladu projeví jen v náhledu a při renderování zmizí, ale nedokáži jednoznačně říci, zda nemá někdy přece jen negativní vliv na výsledný povrch tělesa, protože občas se potkávám se soubory STL vytvořenými v OpenSCADu, ve kterých jsou v popisu povrchu chyby a typicky PrusaSlicer pak v naslicovaném objektu obvykle vynechá část některé vrstvy nebo zmizí dokonce celý kus tělesa. Asi to budou zřejmě důsledky nějakých numerických chyb souvisejících s přesností výpočtů a s binární reprezentací čísel, a raději tomu předcházím přesazováním dílů objektu přes tebe tak, aby mi pokud možno nikde v tělese nevznikaly nějaké divné části s tloušťkou blížící se nule. K problému s chybami v STL se ještě vrátím na konci této stránky v části zaměřené na jejich opravy.

Sjednocení těles (union)

Tělesa můžete buď sjednotit (union) nebo sloučit (merge). Při sloučení by se měla tělesa spojit do jednoho kompaktního celku, nicméně při sjednocení se vytvoří množina původních těles, mezi kterými mohou být i mezery. OpenSCAD zná pouze operaci sjednocení.

Pokud tedy na sebe postavíte dvě tělesa jako v následujícím příkladu a sjednotíte je, tak nemáte zaručeno, že mezi nimi nezůstala velmi tenká mezera, podobně jako když tělesa odečítáte (viz textu o pár odstavců výše zabývající se rozdílem těles).

$fn=30;
union()
{
  cylinder(d=8, h=2);    
  translate([0,0,2]) cylinder(d1=6, d2=8, h=2);    
}

Na náhledu toto těleso vypadá následovně.

Obr.28. Bez přesazení.

 

Vzhledem k občasným problémům s divnými chybami v popisu povrchu v STL souborech exportovaných z OpenSCADu raději tělesa při sjednocování v případech, kdy by na sebe měla navazovat bez mezer a vytvořit kompaktní objekt, lehce přesazuji přes sebe.

$fn=30;
presazeni=0.1;
union()
{
  cylinder(d=8, h=2);    
  translate([0,0,2-presazeni]) cylinder(d1=6-presazeni, d2=8, h=2+presazeni);    
}

Výsledný objekt vypadá takto, tj. není zřejmý žádný rozdíl proti předchozímu objektu vytvořenému bez přesazení.

Obr.29. S přesazením.

 

Průnik těles (intersection)

Třetí základní operací s množinou těles v OpenSCADu je jejich průnik. Ze začátku tuto opraci člověk možná trochu obchází a používá hlavně rozdíl a sjednocení, ale je to operace velmi užitečná - např. když potřebujete srazit vnější hranu válcového tělesa.

r=10;
h=10;
wh=1; //sirka hrany
hh=2; //vyska hrany
intersection()
{
  cylinder(r=r, h=h);
  cylinder(r1=r-wh, r2=r+wh*((h/hh)-1), h=h);
}

Výsledný objekt vypadá takto.

Obr.30. Sražení hrany pomocí průniku těles.

 

Na tomto příkladu s průnikem lze dobře ukázat rozdíl mezi modifikátorem # a %. Nejprve modifiktáror #.

r=10;
h=10;
wh=1; //sirka hrany
hh=2; //vyska hrany

intersection()
{
  cylinder(r=r, h=h);
  #cylinder(r1=r-wh, r2=r+wh*((h/hh)-1), h=h);
}

Pokud použijete modifikátor #, tak se jím označená část zobrazí v transparentní růžové barvě, ale je dále zpracovávána, takže po provedení průniku je zobrazena i sražená hrana.

Obr.31. Vliv modifikátoru #.

 

U modifikátoru % je tomu jinak.

r=10;
h=10;
wh=1; //sirka hrany
hh=2; //vyska hrany

intersection()
{
  cylinder(r=r, h=h);
  %cylinder(r1=r-wh, r2=r+wh*((h/hh)-1), h=h);
}

Modifikátor % sice také zobrazí danou část v transparentní, pro změnu šedé barvě, ale současně ji vyřadí ze zpracování, takže průnik se neprovede a hrana není sražena.

Obr.32. Vliv modifikátoru %.

 

Použití průniku v OpenSCADu v sobě ale skrývá minimálně jednu záludnost. Ta spočívá v tom, že pokud pomocí průniku vytvoříte více objektů, které pak odečtete od nějakého jiného tělesa, tak stačí takto vytvořit pár děr a zobrazení náhledu (F5) na těleso se stane nepoužitelným. Náhled se vytváří velmi dlouho, popř. se může zobrazit i chybové hlášení o příliš mnoho prvcích. Horší je, že ikdyž je vypnuté automatické generování náhledu, tak po jeho vytvoření jakýkoliv pokus o změnu pohledu na objekt (pootočení, přiblížení, apod.) způsobí zoufale pomalé a nekončící překreslování náhledu a většinou nezbyde, než OpenSCAD násilně ukončit. Zajímavé je, že podobné zatuhnutí způsobí i pokus o editaci souboru v okně editoru. Nicméně, pokud se provede renderování (F6), tak po jeho doběhnutí lze s objektem otáčet, posouvat ho, apod. bez nějakých prodlev.

Problém je způsoben tím, že OpenSCAD umí vnitřně pracovat pouze s primitivními negativními objekty. Komplexní negativní těleso se musí rozložit na jednotlivá primitiva a tato se musí zpracovat zvláště. U operace průniku to matematicky bude vypadat následovně. Mějme tělesa A, B a C a od tělesa A odečtěme průnik těles B a C. Tj. provádíme výpočet A - B∩C, těleso B∩C ale není primitivní a tak se ve skutečnosti musí provést výpočet postupem A-B + A-C. Na následujícím obrázku je to znázorněno pro jednoduchost v rovině (2D).

Obr.69. Odečtení průniku 2 těles od jiného tělesa.

 

Zatím se nic zlého zdánlivě neděje. Představme si, že A je nějaká deska, do které chceme vytvořit otvor vzniklý průnikem těles B a C. A nyní chceme vytvořit ještě druhý otvor vzniklý opět průnikem z těles D a E. Provádíme tedy výpočet A - B∩C - D∩E, který se opět bude muset rozepsat pro primitivní tělesa do tvaru A-B-D + A-B-E + A-C-D + A-C-E. Pokud bude těleso A navíc tvořeno z více těles, např. jako sjednocení těles A1 a A2, tak předchozí výpočet se bude muset rozepsat na A1-B-D + A1-B-E + A1-C-D + A1-C-E + A2-B-D + A2-B-E + A2-C-D + A2-C-E. Počet výpočtů, které se musí provést, tak s počtem negativních těles vzniklých pomocí průniku enormě roste a s tím se výrazně prodlužuje doba vytváření náhledu. Reálný dopad je ten, že ikdyž se jedná o naprosto triviální objekt vytvořený pouze z pár primitivních objektů, tak jakmile je základ otvoru vytvořen pomocí intersection, tak už při několika otvorech pocítíte zpomalení při vytváření náhledu a pokud jich budete mít zhruba kolem deseti, tak můžete narazit na extrémní zpomalení.

Řešením je obejít se u negativních těles bez operace intersection, může ji jít nahradit např. pomocí difference. Na následujících dvou příkladech si můžete dopad intersection na zpomalení vytváření náhledu vyzkoušet. První příklad vytvoří v desce sadu otvorů, jejichž základ vznikl pomocí intersection. Upozorňuji, že záleží na výkonu vašeho počítače, tj. může být potřeba počet otvorů zmenšit nebo zvětšit, aby jste úplně nezatuhli nebo aby bylo zadrhávání při prohlížení náhledu patrné.

difference()
{
  cube([50,20,5]);
  for(x=[10:10:40],y=[5:10:15])
    translate([x,y,-0.1]) 
      intersection()
      {
        translate([-3,-1.5,0]) cube([6,3,5.2]);
        cylinder(d=6, h=5.2, $fn=6);
      } 
}

Testovací těleso vypadá takto:

Obr.70. Testovací model na vyzkoušení vlivu průniku na rychlost generování náhledu.

 

Následující druhý příklad vytvoří stejné těleso, ale operace průniku je v něm nahrazena diferencí. V tomto případě se náhled zobrazuje plynule bez zjevného zpomalení.

difference()
{
  cube([50,20,5]);
  for(x=[10:10:40],y=[5:10:15])
    translate([x,y,-0.1]) 
      difference()
      {
        cylinder(d=6, h=5.2, $fn=6);
        translate([-3.1,1.5,-0.2]) cube([6.2,1.6,5.4]);
        translate([-3.1,-3.1,-0.2]) cube([6.2,1.6,5.4]);
      }
}

Druhou možností je otvory vytvářené za pomoci intersection použít, ale pokud způsobují neúměrné zpomalení vytváření náhledu, tak to obejít tím, že se jejich tvar odladí postupně po jednotlivých otvorech, kdy ostatní vždy vyřadíme třeba modifikátorem % nebo nějakým jiným pro nás akceptovatelným způsobem, a všechny otvory se pak zapnou jen při renderování (F6).

Cykly

Velmi užitečnou operací pro zjednodušení návrhu je cyklus. Mějme např. takovýto příklad, kde se mají v základním tělese pod pravidelným úhlem vytvořit otvory.

difference()
{
  cylinder(d=40, h=5);
  translate([10,0,-0.1]) cylinder(d=5, h=5.2); 
  rotate([0,0,120]) translate([10,0,-0.1]) cylinder(d=5, h=5.2); 
  rotate([0,0,-120]) translate([10,0,-0.1]) cylinder(d=5, h=5.2); 
}

Výsledný objekt vypadá takto.

Obr.33. Pravidelně rozmístěné otvory.

 

Jednodušší je otvory vytvořit pomocí cyklu následujícím způsobem.

difference()
{
  cylinder(d=40, h=5);
  for(a=[0:120:359]) rotate([0,0,a]) translate([10,0,-0.1]) cylinder(d=5, h=5.2);
}

Operaci cyklu je možné zadat nejen v podobě rozsahu, ale i jako vektor. To může být např. výhodné, pokud je potřeba nějakou část rozmístit nepravidelně jako v následujícím příkladu. Ještě bych zde upozornil, že při práci s vektory je možné použít tzv. tečkovou notaci a první tři prvky vektoru je možné získat zjednodušeným zadáním ve tvaru vektor.x, vektor.y a vektor.z.

difference()
{
  cube([30,20,5]);
  for(p=[[5,5,2],[6,10,3],[15,8,5],[22,14,8]]) 
    translate([p.x,p.y,-0.1]) cylinder(d=p.z, h=5.2, $fn=15);
}

Výsledný objekt vypadá následovně.

Obr.34. Otvory rozmístěné na základě seznamu jejich souřadnic.

 

Při zpracování cyklu představuje každý krok z pohledu proměnných samostatnou oblast jejich platnosti, tj. lze je v každém kroku znovu přiřadit, a objekty z jednotlivých kroků se spojují pomocí sjednocení. Existuje ještě druhá varianta operace cyklu intersection_for(), při které se objekty z jednotlivých kroků spojují pomocí průniku.

Polygon

Pomocí polygonu je možné snadno zadat složitější 2D tvar, ze kterého se pak pomocí lineární či rotační extruze získá z něho odvozené 3D těleso. Pokud se zadá pouze vektor se seznam bodů, tak tyto se propojí do polygonu v pořadí, jak byly zadány. Druhou možností je zadat v prvním parametru vektor se soupisem všech bodů a ve druhém parametru vektor s popisem cesty v podobě pořadových čísel souřadnic bodů v prvním vektoru. Pokud se u druhé možnosti zadá více než jedna cesta, tak první cesta vytoří základní tvar a ostatní cesty definují tvary, které se mají od základního tvaru odečíst.

polygon(
  [[0,0],[20,0],[25,25],[0,20],[5,5],[10,8],[5,11]],
  [[0,1,2,3],[4,5,6]]
);

Výsledný 2D tvar.

Obr.35. Polygon s více cestami.

 

Polyhedron

Některá složitější tělesa lze vytvořit jako polyhedron. Jako první parametr se mu zadá vektor obsahující seznam souřadnic všech vrcholů a druhý parametr představuje vektor s popisem všech stěn polyhedronu, přitom každá stěna se zadá jako vektor obsahující seznam všech vrcholů, které stěnu definují. Vrcholy se zadávají ve formě pořadového čísla jejich souřadnic v prvním parametru.

Zatímco souřadnice vrcholů i stěny lze zadat v libovolném pořadí, tak pořadí vrcholů v popisu stěn je kritické. Body musí být uvedeny zasebou v pořadí, jak stěny opisují a musí opisovat všechny stěny ve stejném směru. Pokud byste si polyhedron představili jako slepitelný papírový model a tento před ohnutím a slepením byl ve formě rovného archu papíru, tak všechny stěny by se zadávaly při stejném směru otáčení. Doporučuje se zadávat body ve směru otáčení hodinových ručiček a to při pohledu na každou stěnu zvenku tělesa směrem dovnitř.

S tím doporučením se to má asi takto (ve verzi 2019.05). Směr otáčení při zadávání vrcholů ve stěnách určuje směr normály stěny, který bude při tomto otáčení směrem ven z polyhedronu. Když budete vrcholy řadit proti směru otáčení hodinových ručiček a zadáte stejným způsobem všechny stěny a normály budou tedy směřovat dovnitř, tak se vám po vyrenderování (F6) zobrazí těleso opět normálně a půjde vyexportovat třeba do STL a pak i normálně použít ve sliceru pro vytvoření GCODE pro tiskárnu. V režimu zobrazení (F5) se vám náhled (F9) ukáže také normálně, ale ve společném zobrazení (F12) už uvidíte všechny stěny s otočeným pořadím vykreslené fialově. Ale pokud takovýto polyhedron začnete kombinovat třeba rozdílem, průnikem apod. s dalšími tělesy, tak sice povrch bude zobrazen i renderován normálně, ale zobrazení náhledu bude plné artefaktů, kde nebudou vykresleny části tělesa. Pokud budete mít jednotlivé stěny zadané s různým směrem pořadí bodů, tak samotný polyhedron se zase zobrazí normálně a půjde i vyrenderovat, ale pokud ho budete kombinovat s dalšími tělesy, tak budou v náhledu opět artefakty a výsledné těleso se vyrenderuje špatně a v okně konzoly obdržíte varování "Object may not be a valid 2-manifold and may need repair!" U jednoduchých těles si tedy algoritmy, které vytvářejí náhled na objekt nebo renderují jeho povrch, dokáží s případným chaosem ve směrech normál poradit, ale u složitějších konstrukcí objektů tomu tak není a jediný univerzálně správný způsob je tedy - všechny stěny stejně a ve směru hodinových ručiček.

Jednotlivé stěny nemusí být ploché, ale je potřeba počítat s tím, že ve výsledku budou takovéto nerovné stěny nahrazeny sítí plochých trojúhelníků.

Kromě chybného směru pořadí vrcholů vedoucího na objekt, který má prohozenou vnitřní a vnější stranu některé stěny, může další problémy způsobit chybné zadání vrcholu, který k daně stěně vůbec nepatří, chyba v pořadí vrcholů v jedné stěně, vynechání některého vrcholu nebo celé stěny apod. Výsledkem může být neuzavřený povrch polyhedronu nebo polyhedron různě zhroucený nebo zdeformovaný. Obtížně se pak hledá chyba a vyplatí se např. nakreslit si tvar složitějšího polyhedronu třeba na papír včetně očíslování vrcholů a popis stěn pak provádět podle tohoto nákresu. Částečně si můžete při ladění takovéto chyby pomoci - v režimu zobrazení (F5) se přepnete na "Zobrazit vše společně" (F12) a pak se vám všechny stěny polyhedronu s chybným pořadím zvýrazní fialovou barvou. Zpět na náhled se pak přepnete F9.

polyhedron(
 points=[[0,0,0],[10,0,0],[0,20,0],[0,0,15]],
 faces=[[0,1,2],[0,3,1],[1,3,2],[0,2,3]]
);

Výsledné těleso vypadá takto.

Obr.36. Polyhedron.

 

Polygon v kombinaci s lineární či rotační extruzí nebo polyhedron mohou u složitějších těles tvarovaných podle křivek, kde se jimi nahradí např. velké množství dílčích kvádrů či válců, ze kterých bylo těleso po malých částech skládáno, značným způsobem zrychlit jak zobrazení náhledu, tak i renderování povrchu. V kombinaci s vytvářením vektorů pomocí cyklů jsou to velmi užitečné nástroje a vyplatí se naučit se je využívat.

Vektory

Při práci s polygony a polyhedrony je často potřeba programově generovat vrcholy a stěny, ze kterých budou vytvořeny. Kromě funkce concat() pro spojování vektorů podporuje OpenSCAD i výrazy ve vektorech (jsou vložené mezi hranaté závorky) včetně cyklů. Takže vektory lze vytvářet např. následovně:

a=[[0,1],[2,3]];
b=[[4,5],[6,7]];

v=[for(i=[0:2:10]) i];
echo(v); // [0, 2, 4, 6, 8, 10]

v=[for(i=a) i,for(i=b) i];
echo(v); // [[0, 1], [2, 3], [4, 5], [6, 7]]

v=[[0,0], each a, each b];
echo(v); // [[0, 0], [0, 1], [2, 3], [4, 5], [6, 7]]

v=[for(n=[0:3]) let(a=n*30) [cos(a)*10, sin(a)*10]];
echo(v); // [[10, 0], [8.66025, 5], [5, 8.66025], [0, 10]]

v=[for(x=0,y=0;x<4;x=x+1,y=y-1) [x,y]];
echo(v); // [[0, 0], [1, -1], [2, -2], [3, -3]]

v=[for(m=[1:2],p=a) p*m];
echo(v); // [[0, 1], [2, 3], [0, 2], [4, 6]]

v=[each[1:2:10]];
echo(v); // [1, 3, 5, 7, 9]

v=[for(a=[0:15:90]) if(a%30==0) 0 else a];
echo(v); // [0, 15, 0, 45, 0, 75, 0]

OpenSCAD také kromě násobení a dělení vektoru číslem podporuje i sčítání a odčítání vektorů, násobení vektorů maticemi a násobení matic. Jako ukázka použití podobných maticových operací je v následujícím příkladu provedeno pootočení několika bodů a jejich současné posunutí do výšky. Vektor p1 představuje např. seznam vrcholů profilu závitu, zadaných svým poloměrem a výškou. Vektor m3 představuje transformační matici, kterou bude každý bod pootočen o úhel a a posunut do výšky o hodnotu h, tj. např. to může představovat posunutí vrcholů profilu závitu po šroubovici. Vektor p1 se musí napřed upravit do tvaru vhodného pro vynásobení maticí m3. Nejprve se vynásobením maticí m1 převede na vektor p2, kdy se údaje o každém vrcholu profilu ve tvaru [R,Z] upraví na tvar [R,Z,0] a následně se přičtením vektoru [0,0,1] změní údaje o vrcholech na tvar [R,Z,1], které jsou uloženy ve vektoru p3. Samotné posunutí všech vrcholů profilu se pak provede vynásobením matic p3 a m3.

p1=[[10,0],[20,5],[10,10]]; //[[r1,z1],[r2,z2]...]
m1=[[1,0,0],
    [0,1,0]];
a=30;
h=5;
m3=[[cos(a),sin(a),0],
    [0,0,1],
    [0,0,h]];

//prevod na tvar [[r1,z1,0],[r2,z2,0]...]
p2=p1*m1;
echo(p2); //[[10, 0, 0], [20, 5, 0], [10, 10, 0]

//prevod na tvar [[r1,z1,1],[r2,z2,1]...]
p3=p2+[for(v=p2)[0,0,1]];
echo(p3); // [[10, 0, 1], [20, 5, 1], [10, 10, 1]

//prevod na tvar [[r1*cos(a),r1*sin(a),z1+h],[r2*cos(a),r2*sin(a),z2+h],...]
p4=p3*m3;
echo(p4); //[[8.66025, 5, 5], [17.3205, 10, 10], [8.66025, 5, 15]]

Při výpočtech s vektory v rovině nebo v prostoru je možné v OpenSCADu s výhodou využít funkcí atan2(), norm() a cross(), které vám mohou pomoci tochu zkrátit a zpřehlednit zápis některých výrazů.

Šestihran z válce

Šestihranná díra na matici je při 3D tisku různých krabiček často potřebná součást tělesa. Při prvních pokusech s OpenSCADem člověk většinou rychle pochopí, že má k dispozici kvádr, válec a kouli, ale než pokročí k další metě v podobě polygonů a lineární extruze, tak samozřejmě narazí na problém jak takový šestihran namodelovat. Je to naštěstí triviální. Existují tři speciální proměnné $fn, $fa a $fs pomocí kterých můžete určit z kolika nebo jak velkých segmentů se bude skládat pravidelný mnohohran, kterým se interpoluje kružnice, která je základem objektů jako je circle, cylinder a sphere. A použít proměnnou $fn určující počet segmentů se na vytvoření šestihranu přímo nabízí. Šestihran lze tedy snadno vytvořit následovně nastavením počtu segmentů u válce na 6.

cylinder(d=20,h=5,$fn=6);

Výsledek vypadá takto.

Obr.37. Šestihran vytvořený z válce nastavením proměnné $fn.

 

Podobně lze snadno vytvořit třeba trojhran a čtyřhran, a protože válec může mít spodní a horní průměr odlišný, tak takto jednoduše vytvoříte i různé jehlany.

Kružnice, jejíž průměr (poloměr) se zadává v objektech jako je circle, cylinder a sphere, je opsaná kružnice vůči mnohohranu, který ji interpoluje. Takže pokud potřebujete udělat např. otvor na matici, tak musíte zadat průměr opsané kružnice úměrně větší. Podobně pokud potřebujete vytisknout válcový otvor, do kterého se má vejít válcový díl s určitým průměrem, tak může být potřeba zadat průměr otvoru o něco větší. V reálu totiž nelze používat hodnotu $fn příliš vysokou, většinou se pohybuje někde v desítkách, protože s rostoucím počtem segmentů roste i počet detailů objektu a prodlužuje se nepříjemně doba renderování. Válcový díl je pak ohraničen kružnicí, která je vepsaná do mnohohranu, který bude při tisku tvořit stěny otvoru.

Dalším faktorem ještě je, že se zřejmě otvor o něco zmenší při samotném tisku jednak tím, že na vnitřní straně kruhového otvoru je při extruzi dráha kratší než na vnější straně oblouku, takže na vnitřní straně může být extrudováno o něco více materiálu, než by bylo třeba a tento se rozteče směrem dovnitř, a dále profil extrudované stopy není ideální obdélník, ale bude to trochu soudeček. Tyto a další problémy už souvisí s kvalitou a nastavením dané tiskárny, jejím firmwarem a nástrojem, který se použije pro slicování, ale problém s opsanou a vepsanou kružnicí lze jednoduše vyčíslit. Pokud n je počet segmentů mnohohranu interpolujícího kružnici, ri je poloměr do něho vepsané kružnice a ro je poloměr jemu opsané kružnice, tak řešíme pravoúhlý trojúhelník s přeponou ro, odvěsnou ri a jejich vzájemným úhlem (360°/n)/2 = 180°/n. A pro tento trojúhelník platí, že cos(180°/n) = ri/ro, tj. průměr opsané kružnice je ro = ri/cos(180°/n).

r=10;
n=7;
ri=cos(180/n)*r;
color("green") cylinder(r=r,h=1,$fn=180);
color("yellow") cylinder(r=r,h=1.1,$fn=7);
color("red") cylinder(r=ri,h=1.2,$fn=180);

Žlutě je zobrazen objekt znázorňující tvar mnohostěnu, červeně tvar vepsaného válce a zeleně tvar opsaného válce.

Obr.38. Žlutě n-stěn, zeleně opsaný a červeně vepsaný válec.

 

Ukázka s příkladem, kdy potřebujeme, aby se do vytištěného otvoru vešel válec s průměrem 5.

r=5;
n=6;
ro=r/cos(180/n);
difference()
{
  cylinder(d=15,h=2,center=true);
  cylinder(r=ro,h=2.2,$fn=n,center=true);
}    
#cylinder(r=r,h=2.2,$fn=180,center=true);

Zobrazení vzájemné polohy otvoru a válce, který se má do otvoru vejít.

Obr.39. Žlutě otvor tvořený n-stěnem, červeně válec, který se má do otvoru vejít.

 

Při skutečném 3D tisku má člověk již většinou pro často používané velikosti otvorů vyzkoušené, o kolik je potřeba zadaný rozměr otvoru opravit, závisí to i na tom, jak volné či pevné má být uložení dílu v otvoru. Nicméně jak je vidět z výše uvedeného, lze se v případě nejistoty odpíchnout i od vypočítatelné hodnoty.

Lineární extruze

Pomocí lineární extruze lze snadno vytvořit složitější těleso z 2D tvaru, určeného třeba polygonem. Je dobré se podívat na popis této funkcionality, protože toho umí mnohem více, než jen triviální vytažení do výšky. Ale současně pokud zajásáte po zjištění, že je možné použít parametr twist v domění, že toto řeší problém s extruzí po křivce jako šroubovice, která je základem pro vytváření závitů, tak nejásejte předčasně, není to tak jednoduché a závity, které by po celé dráze šroubovice udržely svůj profil, touto cestou snadno nevytvoříte.

linear_extrude(height=30, scale=[5,1/5], slices=30) resize([2,10]) circle(d=10, $fn=30);

Výsledné těleso.

Obr.40. Lineární extruze z 2D tvaru.

 

Rotační extruze

Další velmi silný nástroj je rotační extruze. Základem je 2D tvar, který vytváříte v rovině X-Y. Tento tvar je při extruzi použit tak, že je otočen do roviny X-Z a poté obtočen kolem osy Z. Tím vznikne výsledné rotační těleso s průřezem, který odpovídá zadanému 2D tvaru.

Platí zde určitá omezení. Ve verzi OpenSCADu, která byla použita pro tyto příklady, je možné, aby 2D tvar přesahoval do kvadrantů s y < 0. Projeví se to tak, že dotyčná část tělesa bude vytvořena pod úrovní z=0. Ale ve starších verzích programu došlo v tomto případě k prohození vnější a vnitřní strany tělesa. V ose X lze 2D tvar vytvořit buď v kvadrantech s x >= 0 nebo x <= 0, ale ne v obou současně. Ve starší verzi 2015.03-2 způsobuje použití kvadrantu s x <= 0 při následné kombinaci výsledného tělesa s jinými tělesy chyby v zobrazení náhledu (renderování povrchu proběhne vpořádku).

rotate_extrude($fn=8) tvar2d();
color("pink") tvar2d();
module tvar2d()
{
  translate([7,15]) circle(d=5, $fn=15);
}

Výsledné těleso, růžově je zobrazen 2D tvar použitý jako základ této rotační extruze.

Obr.41. Rotační extruze, růžově je zobrazen extrudovaný 2D tvar.

 

V novějších verzích OpenSCADu lze u rotační extruze použít i parametr angle, který udává, v jak velkém úhlu od osy X se má těleso extrudovat. Bez tohoto parametru se vždy etruduje v celém rozsahu 360°.

rotate_extrude(angle=60, $fn=60) 
  translate([7,2.5]) 
    difference() 
    {
      circle(d=5, $fn=60);
      circle(d=4, $fn=60);
      translate([-0.25,0]) square([0.5,2.6]);
    }

Těleso rotačně extrudované pouze v úhlu 60°.

Obr.42. Rotační extruze se zadaným úhlem extruze.

 

Pokud nastavujete pomocí $fn pro rotační extruzi počet úseků a potřebujete vědět, jak budou tyto úseky natočeny podél osy Z, tak pokud výchozí 2D tvar bude mít body v kvadrantech s x >= 0, tak první úsek bude začínat od osy -X, a při bodech s x <= 0 bude začínat od osy +X. Ale pokud použijete parametr angle, tak pro body s x >= 0 bude začínat rotační těleso na ose +X a bude se otáčet kolem osy Z proti směru hodinových ručiček a pro body s x <= 0 bude začínat od osy -X a směr otáčení bude také ve směru hodinových ručiček. Zajímavá situace nastane, pokud použijete parametr angle a současně nastavíte $fn na nějakou malou (kvůli viditelnosti) hodnotu (např. 5). Potom pokud budete angle měnit v krocích 360°/$fn, tak pokud očekáváte výřez o délce angle z rotačního tělesa interpolovaného ze $fn úseků na 360°, tak ho dostanete. Pokud ale nastavíte angle na jinou hodnotu než celistvý násobek 360°/$fn, tak dostanete výřez s rotačním tělesem rozděleným na jiný počet jinak velkých úseků.

Text

V OpenSCAdu lze vytvářet i text. Vzásadě můžete zkusit využít třeba i import křivky a její lineární extruzi nebo zkusit využít funkci surface(), ale pokud vám jako základ postačuje využít fonty písma, tak nejjednodušší cesta je přes funkci text().

Při 3D tisku písmen vytvářených z fontů je trochu problém s tím, že při potřebné velikosti znaků tyto mají příliš mnoho detailů a jsou příliš útlé na to, aby třeba při použití trysky s průměrem 0.4mm šly vytisknout bez chyb. A tak vám mohou po naslicování některé části znaků zmizet, protože je nejde při požadované tloušťce stěny vytvořit, nebo se kolem otvorů tvořených písmeny objeví otvory v napojení mezi perimetry a výplněmi, protože se do nich opět tryska už nevejde apod. Lze to trochu řešit volbou nějakého vhodnějšího fontu, např. bezpatkového, a případně lze využít funkci offset() a pomocí ní si znak zesílit, tak jako na následující ukázce.

offset(delta=0.5)
text("8", size=20, halign="center", valign="center", spacing=1, 
     font="Liberation Sans:style=Bold");  
translate([17,0])
color("red") text("8", size=20, halign="center", valign="center", spacing=1, 
       font="Liberation Sans:style=Bold");

Červeně je původní znak bez použití jeho zesílení pomocí ofsetu.

Obr.43. Zvětšení písma pomocí offset().

 

Další problém s písmem je, že ho máte v rovině a nápis je rovně. Pokud potřebujete nápis do oblouku nebo dokonce na nějakém nerovném povrchu, tak si musíte pomoci sami. Text se musí rozdělit na jednotlivé znaky a tyto každý zvláště vyextrudovat a poté natočit do správné polohy. Umístění nápisu na zakřivený povrch lze pak částečně obejít tím, že se nápis naskládá na těleso znak po znaku, znaky se pootočí vůči povrchu tak, aby jejich poloha odpovídala normále k povrchu v daném místě, a nakonec se celý nápis ořízne tělesem, které kopíruje povrch v požadované výšce nad ním nebo pod ním. Není to ideální, protože každý znak zůstává v základu vytvořený v rovině a nekopíruje tak věrně zakřivený povrch, na který se má umístit, ale pro běžné použití to vesměs postačuje.

intersection()
{
  union()
  {
    cylinder(d=30, h=14);
    rotate([0,0,-40]) pismeno("A");
    pismeno("B");
    rotate([0,0,40]) pismeno("C");
  }
  cylinder(d=32, h=14); 
}

module pismeno(t)
{
  translate([0,-13,2]) rotate([90,0,0]) 
    linear_extrude(height=3, convexity=2) text(t, size=10, halign="center", 
                   font="Liberation Sans:style=Bold");
}

Text na povrchu válce.

Obr.44. Zaoblené písmo.

 

Obalování - hull

Pokud je potřeba získat poněkud méně "krabiciodní" vzhled než ten, který získáte vršením obyčejných kvádrů a válců, tak je možné využít obalování pomocí funkce hull(). Má to ale své nevýhody a problémy. Jednak hull() není "zadarmo", ale za jeho využití zaplatíte prodloužením doby potřebné jak na renderování, tak i na zobrazení náhledu, a toto prodloužení může být u členitějších těles s hodně detaily už citelné, A dále dobře to funguje, pokud obalujete těleso, kde jsou pouze vypoukliny, ale pokud jsou na tělese výdutě, tak tyto vám obalování pochopitelně zaplní. A samozřejmě napřed musíte aplikovat obalení a až poté do tělesa dělat otvory, jinak by byly taktéž zaplněny.

hull() 
{
  cylinder(d=5, h=2, $fn=6);
  translate([20,0,0]) cylinder(d=10, h=8, $fn=8);
}

Výsledné těleso.

Obr.45. Obalení pomocí hull().

 

Obalování je např. užitečné při přípravě krabiček se zaoblenými rohy a hranami. Ale pozor na rozměry případného válce či koule, které použijete jako základ. Kružnice, které je vytváří, jsou interpolovány jako mnohohran a proto pokud potřebujete, aby stěna vzniklá jejich obalením byla na přesně určené pozici, tak se musíte zamyslet nad polohou vrcholů tohoto mnohohranu - povrch vzniklý obalením bude vycházet právě z těchto vrcholů nebo z nich odvozených hran. Jinak se vám stane, že stěna je o kousek mimo, a když na ni napojujete další části objektu nebo do ní děláte otvory, tak vám tam mohou vzniknout tenké mezery mezi částmi tělesa nebo přepážky v otvorech. A pokud by např. koule tvořící rohy krabičky byly pootočené svými vrcholy každá jinak, tak stěny mohou být lehce zešikma a mohou být zakřivené.

U válce může stačit nastavit vhodný počet segmentů a válec pootočit tak, aby se vrcholy nacházely ve správné pozici vůči vytvářené stěně. U koule je to problematičtější, pootáčení nevyřeší velikost ve všech třech osách, asi jediná možnost, jak najednou nastavit správně polohy všech tří stěn, bude aplikovat na kouli resize a ve směru všech tří os si rozměr vynutit. Nicméně koule pak budou lehce zdeformované. Při využití na zaoblení rohů to vesměs nehraje při 3D tisku roli a taková drobnost se ztratí. Zůstává zde jen otázka, jestli kulové zaoblení půjde vůbec na spodní straně správně vytisknout, protože to obvykle znamená, že v jeho nejnižších vrstvách vznikne převis pod úhlem, při kterém se perimetry následující vrstvy nebudou mít k čemu přichytit. Tj. může to vést na nutnost použití podpor.

hull() 
{
  for(z=[2,8]) for(x=[2,28]) for(y=[2,18])
  translate([x,y,z]) resize([4,4,4]) sphere(d=4, $fn=16);
}

Box se zaoblenými rohy vytvořený z osmi koulí obalených pomocí hull().

Obr.46. Zaoblený box pomocí hull()

 

Zaoblení - minkowski

Na zaoblení hran a rohů tělesa lze využít také funkci minkowski(), ale je to časově extrémně drahá funkcionalita, asi nejnáročnější ze všeho ostatního v OpenSCADu, její nasazení jak při generování náhledu, tak i při renderování okamžitě nepříjemně pocítíte.

Nicméně pokud potřebujete připravit u tvarově složitého objektu povrch se zaoblenými rohy i hranami, je to cesta, jak toho z hlediska složitosti kódu jednoduše dosáhnout. Následující příklad ukazuje stejný box se zaoblenými rohy a hranami, jako byl vytvořen v předchozím příkladu pomocí hull(), a je vidět, že zápis se zjednodušil.

translate([2,2,2]) minkowski()
{
  cube([26,16,6]);
  resize([4,4,4]) sphere(d=4, $fn=16);
}

Box se zaoblenými rohy vytvořený pomocí minkowski().

Obr.47. Použití transformace minkowski().

 

Zaoblení - offset

Pomocí hull() nelze vyřešit zaoblení tělesa s výdutěmi. Pokud použijete offset() se zápornou hodnotou r, tak můžete dosáhnout toho, že u ostrých výdutí na 2D tvaru vytvoříte zaoblení s požadovaným poloměrem, a pokud takový 2D tvar následně extrudujete do 3D tělesa a obalíte pomocí minkowski, lze nepříliš složitým popisem tělesa dosáhnout zaoblení i v místech výdutí. K příkladu níže jenom doplním, že samořejmě je potřeba nastavit správné rozměry výchozího 2D tvaru vůči nastavení poloměru zaoblení u ofsetu a vůči poloměru koule, která se použije jako tvar pro zaoblení 3D tělesa, protože u vnitřního vrcholu 2D tvaru použitý stejný záporný ofset a stejný poloměr koule způsobí, že ve výsledku bude v tomto místě opět ostrý přechod.

translate([0,0,1]) minkowski() 
{
  linear_extrude(height=3) offset(r=-2, $fn=16)
    polygon([[-1,-1],[3,-1],[10,5],[17,-1],[21,-1],[21,16],[-1,16]]);
  resize([2,2,2]) sphere(d=2, $fn=16);
}

Objekt zaoblený včetně výdutě.

Obr.48. Zaoblení vyduté části s využitím transformace offset().

 

Slicujeme

Při výrobě modelů FFF 3D tiskem je nedílnou součástí návrhového procesu i tzv. slicování, kdy se 3D model rozřeže na tenké plátky o výšce odpovídající tloušťce jedné tiskové vrstvy, a pro každý takovýto dílčí plátek se naplánuje pohyb tiskové hlavy. Návrh samotného 3D modelu tedy musí vycházet z reálných možností tiskárny, tj. z použitého průměru trysky, výšky vrstvy, vlastností filamentu a faktu, že extrudované vlákno se musí k něčemu přichytit a nelze tedy tisknout jen tak "do vzduchu" bez řady omezení. To znamená, že už při návrhu je potřeba hlídat tloušťku stěn, výškovou polohu jednotlivých částí modelu, sklon převisů a délky a tvar prvků s charakterem mostu. Kromě toho je potřeba naplánovat i natočení objektu při tisku s ohledem na dosažení požadovaných vlastností, protože pevnost vytištěného dílu může být různá v závislosti na směru extrudování vlákna.

Další komplikací pak může být fakt, že návrh 3D modelu a jeho slicování se často provádí ve dvou různých programech, a přenos dat z jednoho do druhého např. přes oblíbený formát dat STL, nemusí vždy proběhnout bez problémů. Typické nedorozumění může vzejít z bezrozměrného charakteru dat STL, kdy jedna strana může při návrhu používat palce a druhá milimetry. Toto lze většinou jednoduše vyřešit použitím správného měřítka ve sliceru. Horší, ale bohužel běžná situace je, když popis 3D modelu v souboru STL obsahuje chyby.

Změna rozměru u svislého otvoru

Typická součást různých krabiček a technických dílů vyráběných 3D tiskem je svisle umístěný otvor, který přechází v určité výšce nad tiskovou podložkou z většího na menší průměr, např. šroub s maticí nebo hlavou umístěný v otvoru ze strany, od které se těleso tiskne. V následujícím příkladu je to válcový otvor, který se ve výšce 4 zmenší z průměru 7 na průměr 3. Popis příkladu přechodu je tento

$fn=30;
tp=0.01;

prechod(7,3,4,6,0.3);

module prechod(d1,d2,h1,h2,tv)
{
  cylinder(d=d1, h=h1);
  cylinder(d=d2, h=h1+h2);
}

a přechod vypadá takto.

Obr.49. Tvar neošetřeného válcového přechodu.

 

Nyní uděláme otvor ve tvaru výše uvedeného přechodu.

$fn=30;
tp=0.01;

difference()
{
  cylinder(d=10, h=10);
  translate([0,0,-tp]) prechod(7,3,4+tp,6+tp,0.3);
}

module prechod(d1,d2,h1,h2,tv)
{
  cylinder(d=d1, h=h1);
  cylinder(d=d2, h=h1+h2);
}

Vytvořené těleso pro tisk s přechodem z válcového otvoru z jednoho průměru na druhý vypadá následovně.

Obr.50. Válcový otvor s neošetřeným přechodem.

 

Pokud dáte takto udělané těleso naslicovat, tak vám slicer navrhne něco následujícího.

Obr.51. Neošetřený přechod válcového otvoru po naslicování.

 

Je zřejmé, že perimetry spodní části otvoru s menším průměrem by se tisknuly zcela do vzduchu, a i kdybychom jako první tisknuli výplně, tak tyto by se také neměly kolem menšího průměru k čemu přichytit a vlákna by též propadla dolů. Po několika vrstvách by se tisk zřejmě chytil, protože část otvoru by zaplnila různě propadlá vlákna, na která by se nakonec již perimetry i výplně zachytily, ale vypadalo by to hnusně a hranice přechodu by byla hodně nepřesná, takže hlava šroubu nebo matice by asi nebyly v poloze, ve které měly být.

Toto lze samozřejmě obejít použitím podpor, ale pokud je vytváříte na jednomateriálové tiskárně, tedy bez možnosti použít na ně rozpustný materiál, tak u filamentů jako je třeba PETG bude problém ty podpory z hlubších a přitom průměrem menších otvorů dostat.

Další možností je samozřejmě si předtisknout jen menší otvor i místo velkého a velký následně zahloubit, nebo obráceně vytisknout jen větší otvor a menší následně vyvrtat, ale to bude mít vliv na pevnost výtisku, protože při vrtání se odstraní perimetry a vrtaný otvor se vede přes výplně, které obvykle bývají i docela řídké. A také je to přidaná výrobní operace navíc.

Pokud se upraví tvar otvoru tak, aby se sliceru trochu pomohlo s plánováním pohybů tiskárny, tak lze takovéto otvory tisknout v dobré kvalitě a bez použití podpor. V otvoru se udělá následující přechod z jednoho průměru na druhý, který se výškově sesynchronizuje s plánovanou tloušťkou tisknutých vrstev. Nejprve se přes větší otvor udělá obdélníkový otvor, který má jednu stranu odpovídající průměru většího otvoru a druhou stranu odpovídající průměru menšího otvoru. Jeho výška bude 1 tisková vrstva. Nad tímto otvorem se udělá čtvercový otvor s rozměry stran stejnými jako je průměr menšího otvoru a opět s výškou jedné tiskové vrstvy. Dále se už pokračuje válcovým otvorem s menším průměrem. Tvar tělesa představující budoucí otvor může být vytvořen třeba následovně.

$fn=30;
tp=0.01;
prechod(7,3,4,6,0.3);

module prechod(d1,d2,h1,h2,tv)
{
  cylinder(d=d1, h=h1);
  cylinder(d=d2, h=h1+h2);
  translate([0,0,h1-tp]) intersection()
  { 
    translate([-d1/2,-d2/2,0]) cube([d1,d2,tv+tp]);
    cylinder(d=d1, h=tv+tp);
  }
  translate([-d2/2,-d2/2,h1+tv-tp]) cube([d2,d2,tv+tp]);
}

A jeho vzhled je takovýto.

Obr.52. Tvar ošetřeného válcového přechodu.

 

Nyní si uděláme otvor s tímto přechodem.

$fn=30;
tp=0.01;

difference()
{
  cylinder(d=10, h=10);
  translate([0,0,-tp]) prechod(7,3,4+tp,6+tp,0.3);
}

module prechod(d1,d2,h1,h2,tv)
{
  cylinder(d=d1, h=h1);
  cylinder(d=d2, h=h1+h2);
  translate([0,0,h1-tp]) intersection()
  { 
    translate([-d1/2,-d2/2,0]) cube([d1,d2,tv+tp]);
    cylinder(d=d1, h=tv+tp);
  }
  translate([-d2/2,-d2/2,h1+tv-tp]) cube([d2,d2,tv+tp]);
}

Těleso s tímto otvorem vypadá zespodu následovně.

Obr.53. Válcový otvor s ošetřeným přechodem.

 

Po naslicování se můžeme podívat, jak je pohyb tiskárny naplánován nyní. Nejprve se tisknou perimetry obdélníkového otvoru. Tyto se přichytí na perimetry většího otvoru a přes volný prostor se tisknou jako most, tedy může zde samozřejmě dojít k chybičce, ale vzásadě je to normálně proveditelný tisk. Po vytištění perimetrů se zbytek krajů původního otvoru překryje výplní, která se sice zase tiskne jako most, ale na krajích se má k čemu přichytit.

Obr.54. Ošetřený přechod válcového otvoru po naslicování - 1.část.

 

Následně se tiskne čtvercový otvor. Stejně jako u obdélníkového se i nyní mají perimetry k čemu přichytit a taktéž je tomu u výplní.

Obr.55. Ošetřený přechod válcového otvoru po naslicování - 2.část.

 

Nyní se již pokračuje původně požadovaným válcovým otvorem, jeho perimetry se mohou nyní zachytit za perimetry čtvercového otvoru, takže výtisk je proveditelný. Výplně jsou pak již zcela bez problémů. Pokud by menší otvor byl hodně velký, tak samozřejmě může vzniknout v této fázi ještě problém, že kruhový perimetr už bude v rozích hodně daleko od perimetrů čtvercového otvoru a tryska při kruhovém pohybu strhne vlákno zasebou a toto se více propadne. Pak by asi bylo dobré sem vložit ještě další jeden přechod v podobě osmihranu, který by donutil tiskárnu zde nejprve natáhnout přes prázdný prostor rohů vlákna rovně a teprve o ně by se v následující vrstvě opřela stěna vlastního válcového otvoru. Typicky ale člověk tiskne podobné otvory pro šroubky M3, M4 apod., kde to není nutné.

Obr.56. Ošetřený přechod válcového otvoru po naslicování - 3.část.

Otvory, které takto ošetřujete, nemusí být jen válcové, může to být třeba přechod z šestihranného otvoru pro matici na válcový otvor, nebo z válcového otvoru pro hlavu šroubu na závit apod.

Ještě dodatečná poznámka - v příkladu byla pro vytvoření jedné vrstvy přechodu použita operace intersection. To může mít při více použitých otvorech dost negativní vliv na dobu vytváření náhledu (viz komentář výše u popisu operace průniku) a může být vhodnější místo ní použít diferenci, kdy se stejný tvar snadno získá oříznutím boků válce dvěma kostkami.

Oprava vadného STL

Při exportu 3D modelu do formátu STL a 3MF (a nemám důvod si myslet, že to u AMF a OFF bude jiné) dělá OpenSCAD občas chyby. Některé slicovací programy si s tím poradí, a některé si na tom vylámou zuby.

Obr.57. Původní STL po naslicování v PrusaSliceru 2.1.1. Slicer sice hlásí, že je těleso vpořádku, ale objevily se v něm chybné spáry.

Problémy s chybnými STL má typicky PrusaSlicer (v 2.1.1). Běžná situace je, že po načtení STL oznámí, že je model vpořádku a náhled objektu zobrazí bez chyb. Ale po naslicování někdy zmizí celé části objektu nebo se v něm objeví různé spáry a díry. Zajímavé je, že když si k danému objektu v OpenSCADu vyexportujete i 3MF a do PrusaSliceru zkusíte načíst 3MF soubor, tak je např. oznámeno, že objekt nebyl vpořádku a bylo opraveno nějaké množství chyb, ale po naslicování je objekt kompletní. Už jsem se ale potkal se situací, že nešel zpracovat ani 3MF. Když ale vezmete takovýto vadný STL a načtete ho do Sli3rPE (tj. předchůdce PrusaSliceru) nebo do i hodně staré Cury (a podle odezev lidí i do Simplify3D), tak si s ním tyto slicery poradí bez problémů a objekt vám naslicují vpořádku.

Obr.58. Původní 3MF po naslicování v PrusaSliceru 2.1.1. Slicer hlásí opravené chyby a těleso vypadá vpořádku.

U PrusaSliceru v této situaci někdy pomůže použít v něm na takovýto STL opravu (volba v menu Soubor / Opravit soubor STL...), kdy se vám STL po opravě uloží jako soubor OBJ, který následně naimportujete místo původního STL. Jenže tato oprava někdy také nepomůže a ani opravený soubor nelze použít.

Někdy lze zdroj těchto problémů dohledat "mezi klávesnicí a židlí", kdy si člověk při návrhu nepohlídá nějaké drobnosti a vytvoří non-manifold objekt, tj. je dobré si v první řadě zkontrolovat, že v návrhu není skutečně nějaká zřejmá chyba. Ale část těchto problémů zřejmě souvisí s přesností výpočtů a tam je těžké to nějak obejít. V některých případech mi pomohlo udělat v části tělesa, kde se chyby objevovaly, nějaké drobné změny v rozměrech, třeba i jen v setinách či tisícinách, a problém vymizel, někdy stačilo objekt v OpenSCDAu jen pootočit na podložce. Ale pokud se jedná o složitější objekt s dlouhou dobou renderování, tak je to zdržující a zdlouhavý proces "ladění" bez jistého výsledku.

V diskusích jak kolem OpenSCADu, tak i kolem PrusaSliceru lze občas najít dotaz někoho, kdo na podobný problém narazil, ale končí to vesměs stejně, dotazovatel je poslán "k šípku", ze strany sliceru s tím, že má vadné STL, a ze strany návrhového systému s tím, že má chybu v modelu, nebo maximálně s připuštěním, že nějaké problémy s přesností výpočtů by v tom mohly být. (Doplněno 9.3.21: S příchodem nové verze OpenSCAD 2021.01 to vypadá, že došlo k nějaké opravě nebo vylepšení renderování povrchů a jejich exportu, protože u modelů, kde jsem jednoznačně věděl, že je ve starších verzích exportován vadný STL či 3MF, tak jdou exportovaná data nyní bez problémů a bez dodatečných oprav naslicovat.)

Nezbývá tedy než zkusit použít program nějaké třetí strany, který umí vadný STL opravit. V diskuzích jsem vesměs narazil na postupy používající komerční programy, které byly před lety v omezeném režimu i volně dostupné, ale nyní již jejich výrobce změnil přístup. A druhým omezením je, že se jednalo často o programy dostupné jen na platformě voken. Nicméně potkal jsem nedávno postup opravy STL využívající známý multiplatformní opensource 3D návrhový program Blender. Opravu v něm jsem vyzkoušel a je to funkční, rychlé a snadné. Akorát je to takovéto příslovečné "jítí s kanónem na vrabce".

Opravu jsem zkoušel s verzí Blender 2.79 a 2.91. Novější verze má přepracované celé ovládací prostředí a nešla mi spustit na jednom starším PC s win7, ale jinak postup je na starším i novější ovládacím prostředí obdobný a z obou se získá opravený STL, který již PrusaSlicer zpracuje bez problémů.

Program není nutné instalovat, můžete si ho stáhnout i v portable verzi jako balík ZIP, který si vybalíte kam chcete (v2.79 má po vybalení asi 320MB). Pokud chcete, aby si ukládal i nastavení do tohoto adresáře, tak si v něm po vybalení ZIPu najděte tzv. local adresář (to je ten, jehož název tvoří číslo verze programu, tj. např. "2.79"), a v něm si udělejte podadresář s názvem "config". Do něho se pak bude nastavení ukládat. Po spuštění je potřeba povolit add-ons "3D Print Toolbox". V menu File / User preferences přejdeme na kartu Add-ons a nalistujeme položku Mesh 3D Print Toolbox a zapneme ji zaškrtnutím políčka na levé straně. Následně uložíme nastavení.

Obr.60. Přidání Add-ons Mesh 3DPrint Toolbox v Blenderu 2.79.

Oprava je pak jednoduchá. V Blenderu přes menu File / Import načteme vadný STL. Na levé straně vybereme záložku 3D Printing a na zobrazeném panelu stiskneme tlačítko Make Manifold. V horní části okna uprostřed se nachvíli zobrazí informace o počtu změněných prvků. Následně provedeme na stejném panelu přes tlačítko Export uložení opraveného souboru STL (uloží se pod názvem untitled-původní název). Kromě toho je možné si nechat stiskem tlačítka Check All vypsat na spodku panelu v částí Výstup údaje o zjištěných problémech, případně si nastavit parametry pro kontrolu a opravu. Na příkladu, který jsem zkoušel, jsem provedl na modelu opravu stiskem Make Manifold dvakrát po sobě, ale již po první opravě šel exportovaný STL v PrusaSliceru již naslicovat bez problémů. Třetí oprava po sobě v Blenderu již nehlásila žádné provedené modifikace.

Obr.61. Oprava STL v Blenderu 2.79. Check All - výstup.

Obr.62. Oprava STL v Blenderu 2.79. Make Manifold - info po prvním spuštění (provedeny opravy).

Obr.63. Oprava STL v Blenderu 2.79. Check All - výstup.

 

Obr.64. Oprava STL v Blenderu 2.79. Make Manifold - info po druhém spuštění (provedeny další opravy).

Obr.65. Oprava STL v Blenderu 2.79. Check All - výstup.

Obr.66. Oprava STL v Blenderu 2.79. Make Manifold - info po třetím spuštění (již žádná změna).

 

Obr.59. STL opravený v Blenderu po naslicování v PrusaSliceru 2.1.1. Slicer nehlásí žádné chyby a těleso vypadá vpořádku.

V novějším rozhraní (v 2.91) je postup podobný, ale při defaultním nastavení prostředí po prvním spuštění jsou některé věci na obrazovce jinde. Aby se zobrazila záložka s panelem dotyčného nástroje, je potřeba vlevo v horní části v menu Pohled zaškrtnout položku Sidebar a vlastní panel s ovládacími prvky se vám pak objeví po pravé straně jako záložka 3D Print. Ostatní je podobné jako ve starší verzi, akorát informace o počtu provedených změn se zobrazí uprostřed v liště na spodku okna.

Obr.67. Zapnutí Sidebar v Blenderu 2.91.

Obr.68. Oprava STL v Blenderu 2.91.

Nejsem aktivní zkušený uživatel Blenderu a používám ho pouze na takovouto opravu STL, takže výše popsaný postup vychází z toho, jak vypadá výchozí prostředí tohoto programu po jeho prvním spuštění bez nějakých dalších změn ze strany uživatele (akorát je zapnutá čeština a přidán dotyčný nástroj).

Toto byla poslední z poznámek k OpenSCADu. Kompletní popis všech funkcionalit, pomocí kterých v něm můžete tělesa vytvářet, najdete např. na této stránce.

Nahoru