Nacházíte se zde: Rhino3D.cz > Články > Rhinoceros > RhinoScript 7. díl: Pole


RhinoScript 7. díl: Pole

Publikováno: 28.7.2005 | Autor: Jan Slanina | Rubrika: Rhinoceros | Komentáře: 1 - Doporučit

Rhino Script - úvodTento díl seriálu o RhinoScriptu bude mimořádně dlouhý, budeme si totiž povídat o statických a dynamických polích. Řekneme si něco o identifikátorech a obálkových kvádrech objektů a nakonec si vytvoříme skript pro změnu velikosti předem neznámého počtu objektů vůči středu jejich obálkového kvádru.

7 Pole

7.1 Sady proměnných

Již víte, že data můžeme uchovávat v proměnných. Ať už se jedná o text, čísla nebo booleovské hodnoty. Pro každé číslo, které potřebujeme uchovat, můžeme vytvořit novou proměnnou typu double. Ve 2. dílu v odstavci 2.4.2 (Proměnné typu long a double) jsme si ukázali příklad 3D kartézské (x,y,z) souřadnice. Hodnoty x, y a z bychom mohli uchovat v samostatných přoměnných, ale to by bylo řešení pouze pro jednoduchý případ. Pokud bychom měli uchovat souřadnice x,y a z pro 500 bodů, nebyl by asi nejlepší nápad vytvořit si k tomuto účelu 1500 proměnných.

7.2.1 Dynamický počet proměnných

Dalším problémem při použití jednoduchých proměnných je dynamické chování skriptů. Představte si, že chcete vytvořit skript, který změní velikost neznámého počtu objektů vůči středu jejich obálkového kvádru. Počet objektů určí až uživatel. Tento počet může sahat od 1 practicky do nekonečna. Každý objekt má obálková kvádr, který obsahuje 8 bodů a každý bod má 3 souřadnice. To znamená, že definice jednoho obálkového kvádru se skádá z 8×3 = 24 proměnných typu double. Těchto 24 proměnných musíme nějak dostat do jediného bloku.


Zde je vizualizace našeho problému:

pole objektů

Problémy začínají právě zde. Místo úprav jediného objektu musíme upravit neznámý počet objektů. Nyní byste samozřejmě mohli přidat metodu Rhino.GetObject() v cyklu, ale to by uživatel musel vybírat každý objekt jednotlivě. My chceme, aby uživatel mohl vybrat všechny objekty najednou před spuštěním skriptu.

Abychom získali ID všech vybraných objektů, použijeme metodu Rhino.SelectedObjects(). Bohužel ale nemůžeme uchovat ID VŠECH vybraných objektů do jediné proměnné typu řetězec. Do jedné proměnné typu řetězec můžeme uložit pouze jeden identifikátor. Před tuto metodu však můžeme napsat jedinou proměnnou:

          strObjekty = Rhino.SelectedObjects()

Tato metoda Rhina tak vrátí pole řetězců místo jediné proměnné typu řetězec. Rozdíl mezi jednou proměnnou a proměnou tvořenou polem je ten, že pole může uchovávat neomezený počet proměnných stejného typu pod jediným názvem proměnné. Abychom mohli rozlišovat mezi jednotlivými prvky pole, potřebujeme samozřejmě čísla indexů. Pokud bychom použili výše uvedený řádek kódu na krychle z našeho příkazu, naše proměnná strObjekty by vypadala takto:

     strObjekty(0) = 9C805F45-ACF5-41D7-8444-87E246139059 (dolní mez)
     strObjekty(1) = 3226D35F-368B-4E12-9DD3-7240791F7B93
     strObjekty(2) = E49F53C9-8800-4011-B5D7-FC54084E4EE2
     strObjekty(3) = 17C905D9-A7CD-46C5-9E95-90C5EDB6CBC5
     strObjekty(4) = 9DF6583D-1D09-4895-8FA8-3806CD2EA618
     strObjekty(5) = 80C96A3E-498C-4D62-ACAE-FAE21EACFD0A
     strObjekty(6) = A77654D8-564D-4733-A36B-F90132DE862F
     strObjekty(7) = 5ED7EA95-7D16-47B4-B2C2-1B32B6AEDD7F
     strObjekty(8) = 8DD99E6F-B50A-4691-B502-7CC87D72E134 (horní mez)

Výše vidíte pole řetězců. Obsahuje 9 prvků a protože pole vždy začínají od indexu = 0, nejvyšší index je 'počet prvků' mínus jedna. Hodnota indexu 8 je horní mez tohoto pole. Kdykoliv z tohoto pole budeme chtít vyjmout identifikátor, budeme muset zadat název proměnné (strObjekty) následovaný číslem indexu prvku (0-8) zapsaným v závorkách:

     strPrvniObjekt = strObjekty(0)
     strPosledniObjekt = strObjekty(8)

Některé funkce a metody akceptují jako argumenty pole, čímž nám značně usnadňují život:

1    Sub Main()
2       Dim strObjekty
3       Dim strSubObjekt
4
5       strObjekty = Rhino.SelectedObjects()
6       For Each strSubObjekt In strObjekty
7          Rhino.Print (strSubObjekt)
8       Next
9
10   End Sub

Výsledkem mírně odlišného a složitějšího skriptu je následující obrázek:

Ukázka pole

2    Dim strObjekty
3    Dim strZprava
4    Dim strObj
5
6    strObjekty = Rhino.SelectedObjects()
7    strZprava = "Vybrané objekty:" & vbNewLine
8
9    For Each strObj In strObjekty
10      strZprava = strZprava & strObj & vbNewLine
11   Next
12   Rhino.MessageBox(strZprava)

V tomto skriptu jsou dvě nové věci. První je vbNewLine, který jsme připojili ke všem řádkům s řetězcovou proměnnou strZprava. Funkce vbNewLine je stejná jako funkce klávesy Enter. Další nová položka je zajímavější. Používáme zde cyklus For..Each..Next. Tento cyklus je navržen speciálně pro pole. Mezi Each a In zadáte název proměnné, kterou chcete použít v cyklu. Poté za klíčovým slovem In uvedete název pole, které používáte.
Tento cyklus poběží tolikrát, kolik má pole prvků. V našem případě bude tedy zopakován čtyřikrát, protože jsme vybrali 4 kvádry. Pokaždé, když se cyklus rozeběhne, bude do proměnné strObj vložen nový prvek. To je jediný způsob jak lze přistoupit k prvkům pole, aniž bychom napevno specifikovali čísla jejich indexů.
Další ukázka představuje jiný typ cyklu, který vyžaduje čísla indexu...

Je zde plno nových věcí, včetně odchytávání chyb a kontroly typu proměnných. První a poslední řádky (Sub Main() a End Sub) jsme ignorovali, protože jsou stále stejné. Začneme počítat řádky od 2...

2    Dim strObjekty
3    Dim lngPocitadlo
4    Dim strNazev
5    Dim strZprava
6
7    strObjekty = Rhino.GetObjects("Vyberte objekty pro zobrazení názvů...")
8    If Not IsArray(strObjekty) Then Exit Sub
9    strZprava = "Názvy objektů:" & vbNewLine
10
11   For lngPocitadlo = 0 To UBound(strObjekty)
12      strNazev = Rhino.ObjectName(strObjekty(lngPocitadlo))
13      If VarType(strNazev) <> vbString Then
14         strZprava = strZprava & "nepojmenovaný objekt " & vbNewLine
15      Else
16         strZprava = strZprava & strNazev & vbNewLine
17      End If
18   Next
19
20   Rhino.MessageBox (strZprava)

Výsledek činnosti tohoto skriptu:

kvádry

Projděme si znovu skript řádek po řádku...

Řádky 2-5: To už by vám mělo být důvěrně známé. Jednoduše deklarujeme proměnné.

Řádek 7: Používáme metodu Rhino.GetObjects(). Ta nahrazuje metodu Rhino.SelectedObjects(), kterou jsme použili dříve. Tentokrát nemusí uživatel vybírat objekty předem, vyzveme ho k tomu během chodu skriptu.

Řádek 8: To je zcela nové... Ujišťujeme se zde, že proměnná strObjekty je typu pole. Uživatel mohl třeba místo výběru objektů stisknout Esc. S prázdnou proměnnou nemůžeme pracovat, Rhino by při takovém pokusu okamžitě vygneroval chybu.
Funkce IsArray() je nativní funkce vbScriptu a pokud je proměnná mezi závorkami typu pole, vrátí hodnotu vbTrue. Pokud to pole není, vrátí vbFalse.

S ochytáváním chyb jste se již setkali v kapitole 6.2.2, kde jsme kontrolovali, zda vybraný objekt je či není křivka. Každý program a sclipt by měl mít dostatečně vyřešené odchytávání chyb, tak, aby nikdy nevygeneroval chybu. U malých programů, jako jsou naše skripty, je to snadné. Avšak u velkých programů, jako je Rhino, Photoshop nebo Windows je to prakticky nemožné. Správné odchytávání chyb by zabralo 50 či více procent celého zdrojového kódu...

Řádek 10: Do proměnné strZprava vložíme první řádek textu a na konec řádku ihned přidáme vbNewLine.

Řádek 12: Zde začíná náš cyklus For..Next:
Tentokrát jsme použili jednoduchý cyklus (bez 'Each'), což znamená, že si musíme nakódovat podporu pole sami. Nejprve si vynulujeme proměnnou lngPocitadlo (bude to index prvního prvku pole). Chceme provést určitou akci s každým prvkem pole a proto potřebujeme, aby index pole rostl od nuly po horní mez s krokem 1. Během psaní tohoto skriptu samozřejmě nevíme, kolik objektů uživatel vybere. Může to být jakýkoliv počet od jednoho po 2.147.483.648 objektů... Proto musímí být hodnota horní meze dynamická. Když potřebujeme vědět jak je pole velké, použijeme funkci UBound() (UBound je zkratka pro upper bound, horní mez). Tato funkce vrátí hodnotu typu Long, která udává nejvyšší index pole. V našem případě to bude 3 (čtyři objekty mínus jedna, vzpomínáte?).
Velikost kroku udávat nemusíme, protože je to implicitně jednička.

Řádek 13: Zeptáme se Rhina, jaký název objektu reprezentovaného aktuální hodnotou indexu v lngPocitadlo. V našem případě může lngPocitadlo nabývat hodnot 0, 1, 2 nebo 3. Název objektu uschováme do proměnné strNazev.

Řádky 14 - 18: V Rhino nemusí mít objekty povinně název. Je to volitelné. Proto když se v Rhinu ptáme na název a dojdeme na objekt, který žádný název nemá, Rhino nevrátí proměnnou typu řetězec. Místo toho vrátí proměnnou vbNull. V odstavci 2.4.1 jste se dočetli, že existuje několik typů proměnných. Ačkoliv většina z nich pracuje s čísly (datum a čas, měna, hodnoty od 0 do 255 atd. atd.), některé z nich jsou poněkud exotičtější. vbNull je proměnná, která neobsahuje žádná data. Kdykoliv přijde Rhinu do problémů, vrátí vždy proměnnou vbNull. Tuto informaci využíváme pro odchytávání chyb. V tomto řádku kódu však k problému přistupujeme z jiné perspektivy. Místo kontroly, zda strNazev je či není vbNull zkontrolujeme, zda je či není vbString.
VarType() vrátí typ promenné, kterou jste zadali uvnitř závorek.

Operátor <> je také nový. Ve vbScriptu můžeme použít několik srovnávacích operátorů:

    A = B    A je rovno B
    A <> B   A není rovno B
    A > B    A je větší než B
    A >= B   A je větší nebo rovno B
    A < B    A je menší než B
    A <= B   A je menší nebo rovno B

Ačkoliv technicky můžete použít <= nebo > i na nenumerické hodnoty... obvykle mají při práci s řetězci smysl pouze oprátory = a <>.

Na řádku 14 jsme použili srovnávací operátor 'není rovno', což znamená, výraz bude vyhodnocen jako pravdivý, pokud strNazev není proměnná typu vbString. Z toho plyne, že daný objekt nemá název a bude považován za "nepojmenovaný".

Pokud má objekt název, přidáme do strZprava proměnnou strNazev místo "nepojmenovaný".

Řádek 19: Když dojde skript na tento řádek, vrátí se na řádek 13 a proměnná lngPocitadlo bude zvýšena o jedničku.

Řádek 21: Poté co byly do proměnné strZprava přidány všechny názvy, zobrazíme tento řetězec v okně se zprávou.

7.2.2 Numerická pole

Než se budeme moci vrátit zpět k našemu původnímu problému se změnou velikosti sady objektů vůči jejich středům, musíme se seznámit s numerickými poli. Když uchováváme proměnné typu řetězec do pole, nechceme obvykle nic jiného, než prostý seznam. Nicméně při uchovávání čísel můžeme najednou vyjádřit jakýkoliv druh geometrie.
Již víte, že metody Rhino.GetObjects() a Rhino.SelectedObjects() vrátí pole řetězců nebo proměnnou vbNull. Metoda Rhino.GetPoint() vrátí pole 3 proměnných typu double:

2    Dim dblBod
3    Dim x, y, z
4    Dim strZprava
5
6    dblBod = Rhino.GetPoint("Vyberte bod!")
7    If Not IsArray(dblBod) Then Exit Sub
8
9    x = dblBod(0)
10   y = dblBod(1)
11   z = dblBod(2)
12
13   strZprava = "Souřadnice vybraného bodu jsou "
14   strZprava = strZprava & x & "," & y & "," & z
15   Rhino.Print(strZprava)

Krok 1:

vyberte bod

Krok 2:

zadání bodu

Krok 3:

souřadnice bodu

Řádek 2: Inicializujeme proměnnonu dblBod. Všimněte si, že v tomto místě není rozdíl mezi normální proměnnou a proměnnou typu pole. Pokud použijete 'normální' proměnnou jako návratovou adresu pro funkci nebo metodu, která vrací pole, není nutné podnikat další kroky během jejich inicializace. Pokud však plánujete naplnit pole vylstními daty, je syntaxe mírně odlišná. Probereme si to v následujících odstavcích.

Řádek 3: Zde inicializujeme 3 proměnné najednou. Přidáním čárek mezi názvy proměnných se zbavíme nutnosti používat samostané řádky pro každý příkaz Dim. Ačkoliv technicky byste mohli inicializovat všechny své proměnné v jediném řádku, bývá zvykem seskupovat pouze srovnatelné proměnné:

Špatně!    Dim strIDKrivky,dblDelka,x,y,z,i,lngPocitadlo,lngMnozstvi

           Dim x, y, z
Správně    Dim i, j
           Dim dblPrvniDelka, dblDruhaDelka
           Dim dblPocatecniBod, dblKoncovyBod

Mimoto naše proměnné x, y a z nesplňují názvové konvence. Nezačínají trojpísmennou předponou, která by indikovala jejich typ, ale svým názvem naznačují, k čemu budou použity.

Při psaní složitých skriptů s množstvím řádků to ale zvyšuje jejich čitelnost. Protože pracujeme s 3D CAD programem, můžeme bezpečně předpokládat, že proměnné x, y a z budou nejspíše použity pro uchování souřadnic. Písmena i a j se zase často používají pro názvy inkrementálních proměnných:

    For i = 0 To UBound(strObjekty)-1
       For j = i to Ubound(strObjekty)
          'Zde budou nějaké příkazy...
       Next
    Next

Uvědomte si, že když obejdete názvové konvence, tak riskujete, že že zvolíte názvy, které nejsou v rámci syntaxe vbScriptu platné. Názvy proměnných nesmí být totožné se syntaktickými slovy, jako je 'Loop', 'Left', 'Trim' a 'LCase' a to uvádíme pouze několik z mnoha stovek...
Naštěstí používáme editor ConTEXT, jehož funkce pro zvýrazňování automaticky převede všechna syntaktická slova vbScriptu na tučné písmo.

Řádek 6: zde použijeme metodu Rhino.GetPoint(). Uživteli musíme oznámit, co má dělat. Tato zpráva bude zobrazena v příkazovém řádku. Naší zprávou je "Vyberte bod!". Pokud se uživatel bude touto zprávou řídit, vybere bod pomocí myši. V takovém případě vrátí metoda pole se souřadnicemi x,y a z tohoto bodu. Pokud se uživatel rozhodne že bod nevybere, bude proměnné dblBod přiřazeno vbNull.

Řádky 9 - 11: Protože víme, že proměnná dblBod uchovává souřadnici, víme také, že obsahuje 3 prvky a proto má rozsah od nuly do dvou. Z této proměnné můžeme data vyjmout a vložit je do samostatné proměnné jednoduše pomocí operátoru pro rovnost (=).

Řádek 13: Blok textu umístíme přímo do naší - zatím stále prázdné - řetězcové proměnné strZprava. Pokud použijeme vbNewLines v řetězci, který je předáván do příkazového řádku (pomocí metody Rhino.Print()), bude text rozdělen do několika řádků. Ale pozor, příkazový řádek má většinou 2 řádky na výšku, a tak by mohla část řetězce „odcestovat" mimo zobrazovací plochu...

Řádek 14: K našemu existujícímu řatězci připojíme proměnné x,y a z. Všimněte si, že tyto proměnné jsou číselné a ne textové. Jekmile je však připojíme do řetězce, stanou se také textovými. Také přidáme dvě čárky pro oddělení hodnot x,y a z.

Řádek 16: Vypíšeme text na obrazovku.

7.2.3 Zahnízděná pole

Protože jsou souřadnice jádrem Rhina, musíte s nimi pracovat s naprostou jistotou. Mnoho metod vyžaduje nebo vrací souřadnice, máte tedy bohatou zásobárnu, na které se můžete cvičit.

Náš původní problém (kapitola 7.2.1) bude vyžadovat použití metody Rhino.BoundingBox(), která může být dobrým odrazovým můstkem.

zahnízděná pole

Na výše uvedeném obrázku vidíte, jak Rhino pracuje s daty obálkového kvádru (angl. bounding box). Obálkový kvádr se v Rhinu skládá z 8 rohových bodů. Tento kvádr je obvykle orientován podle globálního souřadnicového systému, takže můžeme při práci s obálkovými kvádry učinit několik předpokladů:

  • roh 0 bude mít nejnižší hodnoty x,y a z
  • roh 6 mít nejvyšší hodnoty x,y a z
  • hrany 0-1, 3-2, 4-5 a 7-6 budou rovnoběžné s x-ovou osou scény
  • hrany 1-2, 0-3, 5-6 a 4-7 budou rovnoběžné s y-ovou osou scény
  • hrany 0-4, 1-5, 2-6 a 3-7 budou rovnoběžné s z-ovou osou scény
  • úsečka je nejdelší možnou úsečkou uvnitř kvádru (tělesová úhlopříčka)
  • všechny nezbytné informace lze získat ze 2 protějších rohů

Na obrázku byly pole souřadnic reprezentovány mřížkou 1×3. Zde ukázané souřadnice odpovídají krychli s délkou hrany jedna jednotka a s jedním rohem v počátku souřadnic (0,0,0).

S daty pro BoundingBox je ta potíž, že zde máme osm sad 3D souřadnic, které musíme vrátit, místo jenom jedné. V podstatě jsme zde postaveni před stejný problém jako v kapitole 7.2.1. Tehdy bylo naším řešením vložit souřadnice do pole. Nemáme důvod, proč bychom nyní toto řešení nepoužili znovu...

(připoutejte se... vstupujeme do vyšší úrovně abstrakce)

Uchování několika polí bodů v novém (kmenovém) poli funguje stejně jako u normálních proměnných. Ale... zatím ještě nevíme, jak vytvářet vlastní pole.

7.2.4 Použití uživatelských polí

Předpokládejme, že vytváříme skript, který vyžaduje, aby uživatel vybral v pohledu 10 bodů. Mohli bychom nadeklarovat 10 proměnných a naplnit je pomocí metody Rhino.GetPoint(). To by však vyžadovalo poměrně dost řádků kódu. Místo toho tento problém vyřešíme pomocí cyklu a pole:

2   Dim i
3   Dim arrBody(9)
4
5   For i = 0 To 9
6      arrBody(i) = Rhino.GetPoint("Zadejte bod číslo " & CStr(i+1))
7      If Not IsArray(arrBody(i)) Then Exit Sub
8   Next
9   Rhino.AddPointCloud(arrBody)

Řádek 2: Inicializujeme inkrementální proměnnou i

Řádek 3: Inicializujeme uživatelské pole o 10 prvcích (0,1,2,3,4,5,6,7,8 & 9). Místo "str", "dbl" nebo "bln" použijeme předponyu "arr". opět... tyto předpony jsou pouze pro lidi, čtenáře skriptu. Pomáhají nám rozlišit proměnné a porozumět kódu. Pokud chcete vymýšlet své vlastní předpony jako "txt", "info" nebo "www", nikdo vám v tom bránit nebude. Další výhodou použití předpon je, že tak snižujeme nebezpečí, že názvy proměnných již mají nějaký význam jako klíčové slovo. Pokud bychom použili proměnnou s názvem Mid nebo Left, dostali bychom se do problémů, protože tyto názvy jsou již obsazeny funkcemi.

Pokud přidáme číslo do závorek přímo za název proměnné, automaticky tak inicializujeme pole se zadaným počtem prvků plus jeden. Musíte zadat kladné celé číslo. Tomu říkáme pevné pole. Jeho velikost už později nemůžete změnit. Vždy bude mít přesně 10 prvků. Dynamická pole si ukážeme v dalším příkladu.

Řádek 5: Zahájíme cyklus a zajistíme, aby běžel přesně desetkrát. Přidaná výhoda cyklu For..Next je zde v tom, že máme numerickou proměnnou (i), ze které můžeme přečíst, kolikrát jsme v daný okamžik prošli cyklem.

Řádek 6: Použijeme informaci, uloženou v proměnné i, abychom pokaždé vygenerovali jinou zprávu v příkazovém řádku:

    i = 0   Zadejte bod číslo 1
    i = 1   Zadejte bod číslo 2
    i = 2   Zadejte bod číslo 3
      ...   ...
    i = 9   Zadejte bod číslo 10

Také uložíme výstup metody Rhino.GetPoint() do prvku pole arrBody. Zde to tedy máte. Pole uložená v polích. Říkáme jim také zahnízděná pole.

OK... slíbil jsem vám další příklad:

2    Dim i
3    Dim dblDocasnePole
4    Dim arrBody()
5
6    i = -1
7    Do
8       dblDocasnePole = Rhino.GetPoint("Vyberte bod, který bude přidán k řešení ")
9       If IsArray(dblDocasnePole) Then
10         i = i+1
11         ReDim Preserve arrBody(i)
12         arrBody(i) = dblDocasnePole
13      Else
14         Exit Do
15      End If
16   Loop
17
18   If i = -1 Then Exit Sub
19   Rhino.AddPointCloud(arrBody)

Jediný rozdíl mezi tímto a předchozím skriptem je v tom, že tento skript umožňuje vybrat libovolný počet bodů místo pevného počtu. To je to, co rozumíme pod pojmem dynamické chování. Pokud však chceme kódovat dynamické skripty, musíme brát v úvahu všechny možnosti a proto musíme počítat s rozsáhlejším odchytáváním chyb.

Nejprve na řádku 4 inicializujeme dynamické pole místo pevného. Uděláme to tak, že nezadáme počet prvků. Toto pole bude od této chvíle dynamické a proto můžeme změnit jeho velikost (horní mez), kdykoliv se nám zlíbí.

Pokud chceme změnit velikost dynamického pole, musíme použít klíčové slovo ReDim. Syntaxe klíčového slova ReDim je identická jako u normálního klíčového slova Dim. Hlavní rozdíl je v tom, že Dim se umisťuje vždy na začátek skriptu, zatímco ReDim se může objevit kdekoliv.

Na rozdíl od Dim je u ReDim navíc volitelný argument Preserve. Pokud jej použijeme, tak zajistíme, že si pole během změny velikosti zachová co nejvíce informací. Pokud argument Preserve neuvedeme, pak ReDim vytvoří nové prázdné pole zadané velikosti (stejně jako Dim).

Kdykoliv uživatel vybere bod, přidáme v tomto skriptu přidáme k dynamickému poli další prvek. Ihned poté vložíme pole se souřadnicemi bodu (dblDocasnePole) do tohoto nového - a stále prázdného - prvku.

V tomto případě musíme použít Do..Loop, protože nechceme omezit počet bodů, které uživatel vybere. Proto potřebujeme, aby tato smyčka běžela do nekonečna.

Řádek 18 obsahuje odchytávání chyb, které prověří, zda vůbec uživatel vybral nebo nevybral bod. Pokud nebyl vybrán žádný bod, pak bude stále -1 (až do řádku 6).

7.3 Výsledný skript

Nyní, když už známe dostatek informací o polích a obálkových kvádrech, můžeme konečně začít kódovat skript, který potřebujeme. Měli jsme za úkol vytvořit skript, který změní velikost neomezeného počtu objektů v určitém měřítku vůči středu obálkového kvádru každého z objektů.

Tento problém samozřejmě můžeme řešit více než jedním způsobem, my si probereme ten nejpřímočařejší...

Nejprve se podíváme na kroky, jejichž postupným vykonáním naplníme naše zadání:

krok A     Inicializujeme všechny proměnné
krok B     Vyzveme uživatele k výběru objektů
krok C     Zkontrolujeme, zda uživatel udělal to, o co byl žádán
krok D     Vyzveme uživatele k zadání měřítka
krok E     Zkotrolujeme, zda uživatel zadal platné měřítko

krok F     Vypneme překreslování všech pohledů
                 (zvýšíme tím rychlost skriptu)

krok G     Zahájíme cyklus, který poběží pro každý objekt jednou
krok H     Vyžádáme si od Rhina data o obálce objektu
krok I       Zkontrolujeme, zda Rhino provedl, o co jsme jej žádali
krok J     Vypočítáme těžiště obálkového kvádru
krok K     Sestavíme řetězec, který použijeme jako argument Rhino.Command()
                 (tento řetězec bude založen na nativním příkazu _Scale.)
krok L     Ujistíme se, zda je aktuální objekt vybrán
krok M    Odešleme příkaz
                 Poslední řádek smyčky

krok N     Zapneme překreslování pohledů
krok O     Informujeme uživatele, že jsme skončili

Vypadá to, že to bude pěkně dlouhý skript. Jakmile začnete psát dlouhé skripty, je užitečné, abyste je opatřovali komentáři. Ostatní díky tomu lépe zachytí nit našeho uvažováníand a vy samotní svému skriptu po určité přestávce lépe porozumíte.

Řádky komentářů vždy začínají apostrofem. Komentáře můžete přidat i k řádkům s aktivním kódem. Nikdy však nesmí být na začátku řádku...

Špatně!   'nechť x je polovina v            x = v/2
Dobře!            x = v/2            'nechť x je polovina v

    1   Sub Main()
A   2     Dim arrObjekty, obj
A   3     Dim dblMeritkoZvetseni
A   4     Dim arrObalkovyKvadr
A   5     Dim arrMinRoh
A   6     Dim arrMaxRoh
A   7     Dim minX, minY, minZ
A   8     Dim maxX, maxY, maxZ
A   9     Dim midX, midY, midZ
A   10    Dim strPrikaz
    11
B   12    arrObjekty = Rhino.GetObjects("Vyberte objekty pro změnu měřítka...")
C   13    If Not IsArray(arrObjekty) Then Exit Sub
    14
D   15    dblScalingFactor = Rhino.GetReal("Měřítko zvětšení?")
E   16    If IsNull(dblScalingFactor) Then Exit Sub
E   17    If dblScalingFactor <= 0 Then Exit Sub
E   18    If dblScalingFactor = 1 Then Exit Sub
    19
F   20    Rhino.EnableReDraw(vbFalse)
    21
G   22    For Each obj in arrObjekty
H   23      arrObalkovyKvadr = Rhino.BoundingBox(obj)
I   24      If IsArray(arrObalkovyKvadr) Then
J   25        arrMinRoh = arrObalkovyKvadr(0)
J   26        minX = arrMinRoh(0)
J   27        minY = arrMinRoh(1)
J   28        minZ = arrMinRoh(2)
    29
J   30         arrMaxRoh = arrObalkovyKvadr(6)
J   31        maxX = arrMaxRoh(0)
J   32        maxY = arrMaxRoh(1)
J   33        maxZ = arrMaxRoh(2)
    34
J   35        midX = (minX+maxX) / 2
J   36        midY = (minY+maxY) / 2
J   37        midZ = (minZ+maxZ) / 2
    38
K   39        strPrikaz = "_Scale "
K   40        strPrikaz = strPrikaz & midX & "," & midY & "," & midZ & " "
K   41        strPrikaz = strPrikaz & dblScalingFactor
    42
L   43        Rhino.UnselectAllObjects
L   44        Rhino.SelectObject(obj)
M   45        Rhino.Command strPrikaz
    46      End If
    47    Next
    48
N   49    Rhino.EnableRedraw(vbTrue)
O   50    Rhino.Print "Hotovo!"
    51  End Sub

Když pacujeme se zahnízděnými poli (jako jsou obálkové kvádry), je také možné přistupovat k hodnotám přímo místo použití druhé proměnné, jak jsme to dělali v předešlém skriptu:

    arrMaxRoh = arrObalkovyKvadr(6)
    maxX = arrMaxRoh(0)
    maxY = arrMaxRoh(1)
    maxZ = arrMaxRoh(2)

Mohli bychom to napsat také takto:

    maxX = arrObalkovyKvadr(6)(0)
    maxY = arrObalkovyKvadr(6)(1)
    maxZ = arrObalkovyKvadr(6)(2)

V podstatě bychom také mohli použít výsledek obálkového kvádru přímo ve výpočtu:

    midX = (arrObalkovyKvadr(0)(0) + arrObalkovyKvadr(6)(0)) / 2
    midY = (arrObalkovyKvadr(0)(1) + arrObalkovyKvadr(6)(1)) / 2
    midZ = (arrObalkovyKvadr(0)(2) + arrObalkovyKvadr(6)(2)) / 2

Tím zkrátíme algoritmus ze 13 řáků na 4 a ušetříme 7 proměnných. Mějte ale na paměti, že zkracování kódu zároveň snižuje jeho čitelnost. Rozhodnutí je na vás. Tento druh optimalizace neovlivní rychlost skriptu.

Všechny objekty v Rhinu mají ID (identifikátor). Tyto řetězce jsou vytvořeny, když vytvoříte objekt. ID kódy jsou vždy jedinečné, ale mohou se změnit, pokud vkládáte, upravujete nebo importujete objekty. Během trvání skriptu však můžeme předpokládat, že zůstanou stejné.
Uvědomte si, že sub-objekty, jako jsou stěny těles, hrany a řídicí body nemají ID. Tyto entity tedy nemůžete ve skriptech použít.

Přeložil Jan Slanina

Nahoru ↑

Diskuse k článku

  • [1] jk – 23. 01. 2010, 23:10

    reagovat

    Zahnizdena pole je supr preklad nested arrays (skoro tak dobry jako singleton - jedinacek) asi to zacnu pouzivat :) , ctenari to spis budou znat jako vnorene pole.
    Abych jen nerypal, mam dotaz: Ma rhinoscript tridy a podporuje klasicke OOP?