RhinoScript 6. díl: Řízení toku
Publikováno: 20.7.2005 | Autor: David Rutten | Rubrika: Rhinoceros | Komentáře: 0 - Doporučit
:6 Řízení toku
6.1 Různé typy řízení toku
V jednom z prvních dílů jsme zmínili rozdíly mezi makry a skripty. Jedním ze tří hlavních rozdílů je, že skripty nemají pevnou sekvenci vykonávání příkazů. Řádky kódu lze přeskakovat (vyloučit z vykonání), jiné lze opakovat (cykly) a v kódu můžeme také skákat dopředu i zpět.
Začneme u přeskakování řádků...
6.2.1 Podmíněný příkaz
Předpokládejme, že chceme ze scény Rhina smazat nějaký objekt. Pochopitelně jej však nemůžeme smazat, pokud neexistuje. Nejdříve se tedy musíme ujistit zda objekt existuje a založit další tok našeho skriptu na této informaci.
V angličtině:
If the objects exists, then delete it.
(Pokud objekt existuje, pak jej smaž.)
Ve vbScriptu:
If Rhino.IsObject(strIDObjektu) Then Rhino.DeleteObject(strIDObjektu)
O.K... to je snadné. Nejdříve předáme identifikátor objektu (to je řetězec) metodě Rhina a tato metoda vrací booleovskou hodnotu, která udává, zda ve scéně existuje či neexistuje zadané ID. Pokud ID existuje, vrátí hodnotu vbTrue
, jinak vrátí vbFalse
. Všimněte si, že na uchování výsledku testu Rhino.IsObject
nepotřebujeme samostatnou proměnnou... můžeme jej použít přímo v podmíněném příkazu.
Pokud je sada booleovských dat (v této chvíli je v sadě pouze jeden objekt) vyhodnocena jako pravda, bude vykonán kód, který následuje za klíčovým slovem Then
.
Podívejme se na příklad se dvěma podmíněnými příkazy.
V angličtině:
If the object is a closed curve or if the object is non-planar then delete it.
(Pokud je objekt uzavřená křivka nebo pokud je objekt nerovinný, pak jej smaž.)
Ve vbScriptu:
If Rhino.IsCurveClosed(strID) Or Not Rhino.IsCurvePlanar(strID)
Then Rhino.DeleteObject(strID)
Jak vidíte, řáedk je příliš dlouhý na to, aby se vešel na ejden řádek. Použijeme proto jiný zápis příkazu If..Then
:
If Rhino.IsCurveClosed(strID) Or Not Rhino.IsCurvePlanar(strID) Then
Rhino.DeleteObject(strID)
End If
Příkaz If..Then
je zdaleka nejpoužívanějším příkazem v programování. Je relativně snadné jej použít, protože jeho syntaxe je tak podobná anglickému jazyku. Zatím jsme však viděli pouze jednoduchou konstrukci If..Then
. Zde je o něco složitější:
V angličtině:
If this curve is shorter than 15 cm then something went wrong and we should stop everything.
If however the curve is equal to or longer than 15 cm then move it 2cm to the left and 1cm upwards
then make a copy of the curve.
(Pokud je tato křivka kratší než 15 cm, pak je něco špatně a měli bychom vše zastavit.
Pokud je však délka křivky rovná nebo větší než 15 cm, pak ji přesuň o 2 cm doleva a o 1 cm nahoru
a poté ji zkopíruj.)
Ve vbScriptu:
1 If Rhino.CurveLength(strIDKrivky) < 15 Then
2 Exit Sub
3 Else
4 Rhino.UnselectAllObjects()
5 Rhino.SelectObject (strIDKrivky)
6 Rhino.Command ("_Move 0,0,0 2,0,1")
7 Rhino.CopyObject (strIDKrivky)
8 End If
Na řádku 1 porovnáváme délku křivky s minimální délkou pomocí symbolu 'menší než' (<). Délka křivky je buď menší než 15 (vbTrue
) nebo větší/rovna (vbFalse
). Pokud je podmínka vyhodnocena jako pravda, znamená to, že křivka byla kratší než 15 a budou vykonány řádky kódu, následující za klíčovým slovem 'Then
'. V našem případě proběhne příkaz 'Exit Sub
', který způsobí úplné ukončení procedury. Žádný jiný řádek kódu už nebude vykonán.
Pokud však bude podmínka vyhodnocena jako FALSE
(větší nebo rovno 15), pak bude vykonána posloupnost příkazů, následujících za klíčovým slovem 'Else
'.
Nejprve bude zrušen výběr všech objektů na scéně pomocí metody Rhina bez argumentů. Poom bude vybrán jeden objekt pomocí jiné metody Rhina s jedním argumentem (ID objektu).
Nyní je naše křivka jediným vybraným objektem na scéně a my můžeme bezpečně použít metodu Rhino.Command
. Tato metoda simuluje chování normálního příkazu. Proto bude řetězec, který jste museli zadat jako argument této metody, poslán do příkazového řádku.
Všechny vybrané objekty na scéně budou přesunuty o dvě jednotky doleva a o 1 jednotku vzhůru, pokud spustíte řádek 6. Metoda Rhino.Command
je v podstatě úplně stejná, jako byste měli makro.
Syntaxe makra: Syntaxe RhinoScriptu:
_Line 0,0,0 2,0,0 Rhino.Command " _Line 0,0,0 2,0,0"
_Line 2,0,0 2,2,0 Rhino.Command "_Line 2,0,0 2,2,0"
_Line 2,2,0 0,2,0 Rhino.Command "_Line 2,2,0 0,2,0"
_Line 0,2,0 0,0,0 Rhino.Command "_Line 0,2,0 0,0,0"
_SelCrv Rhino.Command "_SelCrv"
_Join Rhino.Command "_Join"
6.2.2 Syntaxe příkazu If..Then..Else
Příkaz If
je součástí jazyka vbScript a má proto pevnou syntaxi:
If <podmínka> Then
Příkaz(y)
Else
Příkaz(y)
End If
První řádek obsahuje klíčová slova If
a Then
a booleovskou podmínku, která bude vyhodnocena. Klíčové slovo Then
je posledním slovem na tomto řádku. Další řádky budou odsazeny jedním tabulátorem a mohou obsahovat cokoliv, co potrebujete. Počítač nebude číst tabulátory, stejně jako nečte prázdné řádky ani text komentářů. Tabulátory jsou zde proto, aby byl text čitelnější pro lidi.
Po dokončení prvního bloku kódu máte možnost přidat druhý blok Else
. Klíčové slovo Else
je jediným slovem na tomto řádku a má stejné odsazení jako klíčové slovo If
. Následující řádky obsahují další blok kódu.
Po zapsání všech řádků kódu ukončete příkaz If
klíčovými slovy End If
. Je velice důležité, abyste ukončili VŠECHNY příkazy ještě před koncem procedury. Jinak by nastala fatální chyba.
Přečtěte si tento složitý kód a pokuste se porozumět tomu, jak funguje:
1 Sub Main()
2 Dim strIDKrivky
3
4 Rhino.UnselectAllObjects()
5 strIDKrivky = Rhino.GetObject("Vyberte rovinnou křivku")
6
7 If Not Rhino.IsCurve(strIDKrivky) Then
8 Rhino.Print ("Nevybrali jste křivku!")
9 Exit Sub
10 End If
11
12 If Rhino.IsCurvePlanar(strIDKrivky) Then
13 If Not Rhino.IsCurveClosed(strIDKrivky) Then
14 Rhino.CloseCurve(strIDKrivky)
15 Rhino.Print ("Vybraná křivka byla uzavřena")
16 End If
17
18 Rhino.Command ("_Extrude 10")
19 Rhino.Print ("Křivka byla vytažena")
20 Else
21 Rhino.Print ("Vybraná křivka není rovinná")
22 End If
23
24 End Sub
Na základě této procedury se pokuste odpovědět na následující otázky:
1) Co se stane, když místo křivky vybereme plochu (řádek 5)?
2) Co se stane, když vybereme nerovinnou, uzavřenou křivku?
3) Pokud je během vykonávání skriptu spuštěn řádek 9, jaké můžeme očekávat změny ve scéně Rhina?
4) Najdete v tomto kódu nějakou chybu?
Odpovědi:
1)
Řádek 7 bude vyhodnocen jako nepravda. Uživateli se zobrazí varovná zpráva a provádění skriptu bude zastaveno.
2)
Řádek 12 bude vyhodnocen jako nepravda, uživatel bude informován o tom, že vybral nerovinnou křivku. Skript bude ukončen bez přidání nebo změny geometrie.
3)
Nebyla přidána ani smazána žádná geometrie. Bude zrušen výběr všech vybraných objektů (pokud vůbec byly nějaké vybrané).
4)
Připouštím, že je to trochu chyták. Některé chyby nebudete schopni najít, protože jsme se určitými věcmi ještě nezabývali. Zde je úplný seznam toho, co by se mohlo pokazit:
- Pokud uživatel nevybere objekt, když je k tomu vyzvýn (neexistují žádné vybratelné objekty nebo uživatel stiskne Escape), pak nebude proměnná
strIDKrivky
obsahovat platný ID kód. Výsledkem bude chyba, pokud se pokusíme předat tento neplatný kód doRhino.IsCurve()
. - Na řádku 4 zrušíme výběr všech objektů. Když spustíme příkaz
Extrude
, není stále vybrán žádný objekt. Proto musíme před metoduRhino.Command
přidat metoduRhino.SelectObject(strIDKrivky)
.
Metoda Rhino.GetObject
ve skutečnosti akceptuje více než jeden argument. Existuje také několik volitelných argumentů, které - pokud se je rozhodneme implementovat - sníží výrazně naše pracovní zatížení. Můžeme například omezit výběr pouze na objekty typu křivka.
6.3.1 Cykly
Zatímco příkaz If
nám umožní vyloučit určité řádky kódu z provádění, cykly nám umožní provádět určité řádky více než jednou. Probereme si 2 typy cyklů:
For..Next
Do..Loop
6.3.2 Cykly For..Next
Tento typ cyklu používáme tehdy, když chceme vykonat určité řádky s daným počtem opakování:
Přidejte 5 čajových lžiček skořice
Zde chceme přidat 5 lžiček skořice. Musíme edy nastavit cyklus For..Next
tak, aby běžel 5x a poté se přesunout na další řádek kódu. Cyklus For..Next
má následující obecnou syntaxi:
For <Num. proměnná> = <PočátečníHodnota> To <KoncováHodnota> [Step <HodnotaKroku>]
Příkaz(y)
Next
V našem případě by byl výsledkem tento kód:
Dim lngPocitadlo
For lngPocitadlo = 1 To 5 Step 1
'Přidat čajovou lžičku skořice
Next
Když bude cyklus spuštěn, přiřadí proměnné lngPocitadlo
hodnotu 1. Až při vykonávání skript dojde na klíčové slovo Next
, skočí zpět na začátek cyklu. Proměnná lngPocitadlo
bude zvýšena o zadanou velikost kroku. Všimněte si,že velikost kroku je volitelná. Pokund nespecifikujete hodnotu Step
v hlavičce cyklu, použije se hodnota kroku 1. V našem případě jsme hodnotu kroku ani definovat nemuseli.
Pokud je numerická proměnná lngPocitadlo
zvýšená o hodnotu kroku a stane se větší než koncová hodnota, pak bude cyklus přerušen a vykoná se následující řádek za klíčovým slovem Next
.
Poté co spustíte cyklus For..Next
, můžete jej kdykoliv přerušit pomocí příkazu Exit For
. Pokud Rhino nalezne klíčová slova Exit For
, ukončí cyklus a vykoná následující řádek pod klíčovým slovem Next
.
6.3.3 Příkaz Do..Loop
Cyklus Do..loop
používáme tehdy, když nevíme, kolikrát chceme určitou část kódu opakovat. Do..loop
používá vyhodnocení podmínky k určení, zda má nebo nemá znovu opakovat dotyčné příkazy. Tuto podmínku můžete vložit do hlavičky/patičky cyklu a můžete jej také zastavit příkazem Exit Do
:
1 Sub Main()
2 Dim strIDKrivky
3
4 strIDKrivky = Rhino.GetObject("Vyberte křivku")
5 Rhino.UnselectAllObjects
6 Rhino.SelectObject(strIDKrivky)
7
8 Do Until Rhino.IsCurvePlanar(strIDKrivky)
9 Rhino.Command ("_Scale1D 0,0,0 1/10 0,0,10")
10 Loop
11
12 Rhino.Print("Křivka byla promítnuta do konstrukční roviny")
13 End Sub
To je zajímavá konstrukce... Uvnitř cyklu redukujeme z-ovou souřadnici křivky na 1/10 původní hodnoty (_Scale1D
, měřítko = 0.1 podél z-ové osy). Poté v hlavíčce křivku vyhodnotíme z hlediska rovinnosti (řádek 8).
Pokud byla křivka rovinná už od začátku, cyklus bude celý přeskočen a bude vykonán první řádek, který po něm následuje (11). Pokud však křivka rovinná není, bude zploštěna a opět zkontrolována. Tento proces bude pokračovat tak dlouho, dokud křivka nebude rovinná v rámci absolutní tolerance. Pokud tento skript otestujete v Rhinu, tak zjistíte, že pro výchozí absolutní toleranci 0.01 může cyklus proběhnout třeba i 20-krát.
Pokud má proběhnout opravdu náročný výpočet, není výjimkou cyklus o několika tisících opakováních. Je proto moc důležité, aby byl cyklus kódován velice efektivním způsobem.
Zde je další ukázka cyklu Do..Loop
s mírně odlišnou syntaxí. Pokuste se pochopit, co dělá:
1 Sub Main()
2 Dim strIDKrivky
3 Dim dblMinLength
4
5 strIDKrivky = Rhino.GetObject("Vyberte křivku")
6 dblMinLength = Rhino.GetReal("Zadejte minimální délku křivky ")
7 Rhino.UnselectAllObjects()
8 Rhino.SelectObject(strIDKrivky)
9
10 Do While Rhino.CurveLEngth(strIDKrivky) >= dblMinLength
11 Rhino.Command("_Scale 0,0,0 1.05")
12 Loop
13
14 End Sub
Přeložil Jan Slanina
Související články
- RhinoScript 1. díl: Makra a posloupnosti příkazů - 10.06.2005
- RhinoScript 2. díl: Skripty - 22.06.2005
- RhinoScript 3. díl: Rozvržení skriptu - 29.06.2005
- RhinoScript 4. díl: Operátory a funkce - 06.07.2005
- RhinoScript 5. díl: Pokročilé proměnné - 13.07.2005
- RhinoScript 6. díl: Řízení toku - 20.07.2005
- RhinoScript 7. díl: Pole - 28.07.2005
- RhinoScript příloha A: Pokročilý podmíněný tok - 22.07.2005
- RhinoScript 8. dil: Uživatelské funkce - 29.08.2005