Nacházíte se zde: Rhino3D.cz > Články > Rhinoceros > RhinoScript 6. díl: Řízení toku


RhinoScript 6. díl: Řízení toku

Publikováno: 20.7.2005 | Autor: David Rutten | Rubrika: Rhinoceros | Komentáře: 0 - Doporučit

Rhino Script - úvodV 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.

: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 do Rhino.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 metodu Rhino.Command přidat metodu Rhino.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

Nahoru ↑