FAKULTA ELEKTROTECHNIKY A KOMUNIKAČNÍCH TECHNOLOGIÍ VYSOKÉ UČENÍ TECHNICKÉ V BRNĚ
Programování a počítače 2 Počítačová cvičení pro obor B-EST
Autor textu: doc. Ing. Jiří Šebesta, Ph.D.
2015 Komplexní inovace studijních programů a zvyšování kvality výuky na FEKT VUT v Brně OP VK CZ.1.07/2.2.00/28.0193
2
FEKT VUT v Brně
Obsah ÚVOD .........................................................................................................................................3 1
ZPRACOVÁNÍ OBRÁZKŮ VE FORMÁTU BMP .......................................................3
2
OBJEKTOVÉ TŘÍDY V C++ ..........................................................................................9
3
PŘETÍŽENÍ ČLENSKÝCH METOD TŘÍD A DĚDIČNOST ...................................13
4
FORMULÁŘOVÁ APLIKACE V C++ PRO WINDOWS..........................................18
5
GRAFICKÁ APLIKACE PRO WINDOWS S OVLADAČEM GDI .........................21
6
MANIPULACE S MATICEMI A 2D GRAFY V MATLABU....................................24
7
MODEL FYZIKÁLNÍHO JEVU A 3D GRAFY V MATLABU .................................27
8
PARAMETRICKÉ 3D GRAFY V MATLABU ............................................................30
9
MODEL KOMUNIKAČNÍHO SYSTÉMU V MATLABU .........................................36
10 GRAFICKÉ UŽIVATELSKÉ ROZHRANÍ V MATALABU .....................................39 ODPOVĚDI KE KONTROLNÍM OTÁZKÁM...................................................................42
Programování a počítače 2. Počítačová cvicení pro obor B-EST.
3
Úvod Tato skripta jsou určena pro studenty předmětu Programování a počítače 2 pro obor Elektronika a sdělovací technika, zkr. BPC2E. Obsahují podrobné návody k počítačovým cvičením uvedeného předmětu. Předmět bezprostředně navazuje na předmět Programování a počítače 1, jehož hlavní náplní bylo seznámit posluchače kurzu se základy programovacího jazyka C dle standardu ANSI. První cvičení je ještě zaměřeno na klasický jazyk C a jeho využití při manipulaci s binárními soubory. Následující čtyři cvičení jsou věnovány objektově orientovanému programování s využitím jazyka C++. Z toho první dvě úlohy jsou orientovány na objasnění základních pojmů a přístupů objektově orientovaného programování, zatím co druhé dvě úlohy jsou pak zaměřeny na řešení jednoduchých formulářových aplikací s využitím Microsoft Visual studia. Další skupina úloh zahrnuje základní vzorové úlohy v Matalbu, postupující od jednoduchých manipulací s maticemi, přes dvoudimezionání a třídimenzionální grafy až po ukázku sestavení modelu komunikačního systému včetně sestavení grafického uživatelského rozhraní pro tento model. Základy Matlabu, který je obecně nástrojem pro modelování systémů a signálů s prvky programovaní, jsou nutné jako prerekvizita k řadě navazujících předmětů oboru Elektronika a sdělovací technika. Jmenujme např. předmět Signály a systémy nebo Číslicové zpracování signálů. Každá úloha obsahuje zadání a rozbor veřejně přístupné úlohy, kterou si studenti mohou nachystat v rámci domácí přípravy. Druhou částí je zadání B, které je přístupné vždy až na začátku vlastního cvičení. Třetí částí je bonusová úloha, která je nadstavbou pro samostatné zdokonalení studenta v dané problematice. Rozbory jednotlivých úloh obsahují rovněž části stěžejního zdrojového kódu s vysvětlením. Na závěr každé kapitoly je uvedena doporučená literatura a tři kontrolní otázky, jejichž odpovědi jsou uvedeny v závěrečné kapitole těchto skript. Součástí úloh je i předpřipravený kód, někdy je to pouze kostra, v jiných případech to může být poměrně rozsáhlý zdrojový kód, který je nutné prostudovat a doplnit. Zdrojové kódy k jednotlivým úlohám jsou k dispozici na www stránkách: http://www.urel.feec.vutbr.cz/~sebestaj/BPC2E/cviceni.htm.
1 Zpracování obrázků ve formátu BMP Cílem je seznámit se s programováním binárních souborů, v případě tohoto cvičení pak s bitmapovými obrázky. Úloha A. Pro tuto úlohu je připraven zdrojový kódu programu k příkladu souboru bpc2e_c01a.c, kde je připravena kompletní úloha, která vygeneruje nekompresovaný bitmapový obrázek (viz obr. 1.1). Na začátku programu jsou kompletně připraveny potřebné hlavičky pro BMP soubory s plným 24bitovým rozlišení barev (RGB barvy po 8 bitech) bez komprese. Pro definici parametrů obrázku v hlavičkách souboru jsou využity předdefinované struktury BITMAPFILEHEADER a BITMAPINFOHEADER z knihovny windows.h. Popis jednotlivých proměnných těchto struktur je uveden v tabulkách 1.1 a 1.2. Jediný parametr obrázku, který je třeba nastavit je šířka a výška v pixelech pomocí maker WIDTH a HEIGHT:
4
FEKT VUT v Brně
// size of picture definition #define WIDTH 512 #define HEIGHT 512
Tab 1.1. Definice proměnných struktury BITMAPFILEHEADER. Název položky
Délka položky
bfType
2 byty
bfSize
4 byty
bfReserved1
2 byty
bfReserved2
2 byty
bfOffBits
4 byty
Význam Identifikátor formátu BMP. Aktuální verze formátu BMP zde obsahuje ASCII kód znaků "BM", tj. 0×42 a 0×4D. Celková velikost souboru s obrazovými údaji. Některé aplikace tuto položku ignorují a dosazují zde nulu. Rezerva pro pozdější použití. V současné verzi formátu BMP zde musí být uložena nulová hodnota. Rezerva pro pozdější použití. V současné verzi formátu BMP zde musí být uložena nulová hodnota. Posun struktury BITMAPFILEHEADER od začátku vlastních obrazových dat.
Tab 1.2. Definice proměnných struktury BITMAPINFOHEADER. Název položky
Délka položky
biSize biWidth biHeight
4 byty 4 byty 4 byty
biPlanes
2 byty
biBitCount
2 byty
biCompression
4 byty
biSizeImage
4 byty
biXPelsPerMete r
4 byty
biYPelsPerMete r
4 byty
biClrUsed
4 byty
biClrImportant
4 byty
Význam Celková velikost datové struktury BITMAPINFOHEADER Šířku obrázku v pixelech Výšku obrázku v pixelech Počet bitových rovin pro výstupní zařízení. V BMP vždy hodnota 1. Položka existuje z historických důvodů. Celkový počet bitů na pixel. Podle počtu barev zde mohou být hodnoty 1, 4, 8 nebo 24 (to odpovídá postupně 2, 16, 256ti barvám popř. plnobarevnému režimu). Typ komprimační metody obrazových dat. Musí být nastavené na jednu z hodnot: 0 (BI_RGB), 1 (BI_RLE8) nebo 2 (BI_RLE4). Velikost obrazu v bytech. Pokud je bitmapa nekomprimovaná, může zde být nulová hodnota, protože ji je možno vypočítat z rozměrů obrázků a počtu bitů na pixel. Horizontální rozlišení výstupního zařízení v pixelech na metr. Většina aplikací nemá potřebné informace o výstupním zařízení, a proto do této položky vkládá hodnotu 0. Vertikální rozlišení výstupního zařízení v pixelech na metr. Většina aplikací nemá potřebné informace o výstupním zařízení, a proto do této položky vkládá hodnotu 0. Celkový počet barev, které jsou použité v dané bitmapě. Jestliže je tato hodnota nastavena na nulu, bitmapa používá maximální počet barev. Počet barev, které jsou důležité pro vykreslení bitmapy. Pokud je tato hodnota nulová, jsou všechny barvy důležité. Tento údaj je používán při zobrazování na zařízeních, které mají omezený počet současně zobrazitelných barev.
Ostatní položky struktur jsou již předdefinovány, pro BITMAPFILEHEADER: bmp_fh.bfType = 19778; // BITMAPFILEHEADER specification bmp_fh.bfSize = WIDTH * HEIGHT * 3 + 54; bmp_fh.bfReserved1 = 0; bmp_fh.bfReserved2 = 0; bmp_fh.bfOffBits = 54;
5
Programování a počítače 2. Počítačová cvicení pro obor B-EST.
i pro BITMAPINFOHEADER: bmp_ih.biSize = 40; // BITMAPINFOHEADER specification bmp_ih.biWidth = WIDTH; bmp_ih.biHeight = HEIGHT; bmp_ih.biPlanes = 1; bmp_ih.biBitCount = 24; bmp_ih.biCompression = 0; bmp_ih.biSizeImage = WIDTH * HEIGHT * 3; bmp_ih.biXPelsPerMeter = 0; bmp_ih.biYPelsPerMeter = 0; bmp_ih.biClrUsed = 0; bmp_ih.biClrImportant = 0; Hlavičky jsou následně ve správném pořadí nahrány do souboru test.bmp pomocí funkce fwrite(): fwrite(&bmp_fh, BITMAPFILEHEADER fwrite(&bmp_ih, BITMAPINFOHEADER
sizeof(bmp_fh),
1,
fBMP);
//
write
sizeof(bmp_ih),
1,
fBMP);
//
write
V poslední části programu jsou ve dvou vnořených cyklech definovány barvy jednotlivých pixelů a nahrávány do souboru. Pixelová data jsou BMP dvacetičtyřbitovém souboru nahrávána v pořadí RGB (každá barva má 1 byte, a její úroveň od 0 do 255 jako unsigned char) a to postupně po řádcích od levého dolního rohu po pravý horní roh. Každý pixel je definován tripletem těchto úrovní pro červenou, zelenou a modrou složku barvy pixelu. Tento triplet je shrnut ve struktuře bmp_rgb typu RGBTRIPLE. Ve vnořených cyklech se postupně definují a ukládají opět pomocí funkce fwrite() jednotlivé pixely. V příkladu je vidět, že složka červené a modré je vždy nulová, zatímco úroveň zelené barvy je závislá na poloze pixelu. Výsledkem je tedy obrázek s měnící se úrovní zelené barvy od levého dolního rohu po pravý horní roh (viz. obr. 1.1), protože hodnota úrovně zelené barvy je přímo úměrně závislá na součtu indexů řádku a sloupce pro daný pixel: // part for bitmap content definition for(h = 0; h < HEIGHT; h++) // rows in bitmaps from bottom to top { for (v = 0; v < WIDTH; v++) // columns in bitmaps from left to right { bmp_rgb.rgbtRed = 0x00; bmp_rgb.rgbtGreen = (h+v)%256; bmp_rgb.rgbtBlue = 0x00; fwrite(&bmp_rgb, sizeof(bmp_rgb), 1, fBMP); } } Tzn., že všechny pixely, kde součet h+v je konstantní budou mít stejnou barvu. Pochopitelně je třeba omezit úroveň barvy na rozsah 0 až 255, což lze provést snadno operací zbytku po celočíselném dělení 256. Zkuste pro začátek vymyslet jiný vztah pro výpočet úrovně zelené barvy pixelu, např. při aplikaci následujícího vztahu:
6
FEKT VUT v Brně
bmp_rgb.rgbtGreen = (cos(2*6.28*v/(1.0*WIDTH))+1)*127; získáte krásnou fotografii svislých trubek včetně jasového přechodu do stínu (viz. obr. 1.2). Zkuste zapřemýšlet proč? Nezapomeňte na přilinkování knihovny math.h.
Obr. 1.1. Výsledný bitmapový obrázek podle vzoru z příkladu A.
Obr. 1.2. Výsledný experimentální obrázek při aplikaci funkce kosinus.
Programování a počítače 2. Počítačová cvicení pro obor B-EST.
7
Vaším samostatným úkolem je upravit právě část kódu pro definici pixelů obrázku tak, aby výsledkem byl obrázek podle obr. 1.3.
Obr. 1.3. Požadovaný výsledný bitmapový obrázek pro příklad A. Hodnocení: 1,5 bodu. Úloha B. Zadáno cvičícím na začátku cvičení. Hodnocení: 1,5 bodu. Bonusová úloha Pro nadšené programátory i další zájemce je tu opět připravená bonusová úloha. V souboru TPR.bmp je uložen výřez terénního reliéfu jistého území v 256 úrovních šedi od černé definující nejnižší výškovou hladinu až po bílou definující nejvyšší výškovou hladinu. Cílem úlohy je sestavit program, který pro definovanou hladinu moře odpovídající příslušné hodnotě úrovně šedi vygeneruje nový obrázek mapy souše a moře. V řešení může být souše definována zelenou barvou, moře logicky modrou barvou. Číselným parametr hladiny moře v rozsahu 0 až 255 nechť je argumentem při spouštění programu. Parametrem při spouštění může být také jméno výstupního BMP souboru. Terénní reliéf ve stupních šedi je na obrázku 1.4. Jsou zde patrná vyvýšená místa i místa nižší, která připomínají říční odtoky z horské oblasti. Příklad výsledné BMP mapy souše a moře je uveden pro daný reliéf a hladinu moře 80 na obrázku 1.5.
8
FEKT VUT v Brně
Kontrolní otázky 1.1) Jaké jsou hodnoty položek ve struktuře typu RGBTRIPLE při plnobarevném bitmapovém formátu obrázku, pokud definují barvu pixelu v úrovni šedi? 1.2) Co reprezentuje sizeof() ve funkci fwrite()? 1.3) Kolik barev je možné nadefinovat při plnobarevném bitmapovém formátu obrázku?
Obr. 1.4. Terénní reliéf v úrovních šedi.
Obr. 1.5. Vygenerovaná mapa souše a moře pro hladinu moře 80.
Programování a počítače 2. Počítačová cvicení pro obor B-EST.
9
Literatura [1.1] [1.2] [1.3]
WRÓBLEWSKI, P. Algoritmy. Datové struktury a programovací techniky. Brno: Computer Press, 2004. KERNIGHAN, B. W., RITCHIE, D. M. Programovací jazyk C. Brno: Computer Press, 2006. SOBOTA, B., MILIÁN, J. Grafické formáty. České Budějovice: KOOP nakladatelství, 1996.
2 Objektové třídy v C++ Cílem je seznámit se základy objektového programování a sestavování vlastních tříd v C++. Úloha A. Pro tuto úlohu je připraven funkční zdrojový kód k příkladu bpc2e_c02a.cpp. V tomto programu jsou deklarovány a definovány metody tříd pro objekt typu bod class Point, přičemž jako privátní proměnné jsou specifikovány souřadnice bodu ve 2D prostoru X a Y a jako metody jsou připraveny inline funkce pro přístup k privátním souřadnicím bodu:
// CLASS POINT class Point // coordinates X,Y { public: void SetPoint(uch x, uch y) {X = x; Y = y;} void SetX(uch x) {X = x;} void SetY(uch y) {Y = y;} uch GetX()const {return X;} uch GetY()const {return Y;} private: uch X; uch Y; }; Další deklarovaná a definovaná třída je pro objekt typu úsečka class Line, která využívá již definované třídy Point pro krajní body úsečky (opět privátní proměnné) a skupinu přístupových metod k těmto krajním bodům: // CLASS LINE class Line // points P1, P2 { public: void SetLine(Point p1, Point p2) {P1 = p1; P2 = p2;} Point GetP1()const {return P1;} Point GetP2()const {return P2;} private: Point P1; Point P2;
10
FEKT VUT v Brně
}; A nakonec třída pro objekt typu trojúhelník class Triangle, který využívá jak objektů třídy Point, tak i Line: // CLASS TRIANGLE class Triangle // points P1, P2, P3 { public: void SetTriangle(Point p1, Point p2, Point p3); Line GetL12()const {return L12;} Line GetL23()const {return L23;} Line GetL31()const {return L31;} private: Point P1; Point P2; Point P3; Line L12; Line L23; Line L31; }; void Triangle::SetTriangle(Point p1, Point p2, Point p3) { P1 = p1; P2 = p2; P3 = p3; L12.SetLine(P1, P2); L23.SetLine(P2, P3); L31.SetLine(P3, P1); } Prostudujte uvedený zdrojový kód, především pak provázanost objektů daných tříd. Všechny tyto třídy mají nadefinovány potřebné přístupové metody pro nastvaní a zjištění proměnných příslušných objektů. Poslední deklarovanou třídou je class Canvas, která reprezentuje kreslící plátno s definovatelnými rozměry: // CLASS CANVAS class Canvas // height, width, array of character as a pixels of canvas { public: int SetCanvas(uch width, uch high); // set size of canvas uch GetWidth() const {return W;} // return width of canvas uch GetHeight() const {return H;} // return height of canvas void ClearCanvas(void); // clear canvas void PrintCanvas(void); // display canvas on the screen void AddFrame(char pattern); // add frame in the edges of canvas
11
Programování a počítače 2. Počítačová cvicení pro obor B-EST.
int AddPoint(Point point, char pattern); point int AddLine(Line line, char pattern); int AddTriangle(Triangle tri, char pattern); triangle
//
add
// add line // add
private: uch H; uch W; char Canv[200][200]; }; int Canvas::SetCanvas(unsigned height) { … }
char
width,
unsigned
char
void Canvas::ClearCanvas(void) { … } … Protože pro jednoduchost pracujeme stále v konzolových aplikacích, jeden bod (pixel) plátna je reprezentován jedním zobrazitelným znakem. Statická proměnná Canv[200][200] je výsledným 2D polem pro vkládání kreslených znaků (můžeme si představit, že představují barvu bodu nebo typ čáry). Finální rozměr plátna je určen proměnnými W a H (v příkladu rozměr 160 x 80). Ve třídě Canvas jsou kromě očekávaných metod pro inicializaci, smazání a zobrazení plátna na konzoli ještě metody pro vložení rámu na plátno a vložení výše zmíněných objektů typu bod, úsečka a trojúhelník. Poměrně komplikovaně vypadá metoda pro vložení úsečky. Důvodem je ošetření všech možností, které mohou nastat z hlediska souřadnic koncových bodů tak, aby se úsečka vykreslovala vždy správně „plnou“ čarou. Jak bude vypadat výsledný bod (pixel) na plátně je dáno znakem pattern. Ve funkci main() je pak ukázáno vytváření objektů a volání příslušných metod předdefinovaných tříd. Výsledkem je obrázek skládající se ze tří bodů, dvou úseček a trojúhelníku (obr. 2.1). Souřadnice {0,0} jsou v levém dolním rohu (viz metoda Canvas::PrintCanvas()). Vaším úkolem je sestavit vlastní novou třídu pro obecný čtyřúhelník a ve třídě Canvas doplnit metodu pro jeho vložení na plátno. Ve funkci main() pak proveďte vygenerování a vykreslení dvou čtyřúhelníků a dvou trojúhelníku a jejich vykreslení podle obr. 2.2, volba souřadnic koncových bodů úseček není kritická. Hodnocení: 1,5 bodu. Úloha B. Zadáno cvičícím na začátku cvičení. Hodnocení: 1,5 bodu.
12
FEKT VUT v Brně
Obr. 2.1. Výsledný obrázek podle vzoru z příkladu A.
Obr. 2.2. Požadovaný výsledný obrázek využívající třídu pro obecný čtyřúhelník pro příklad A. Bonusová úloha Pro zájemce a nadšené programátory je tu opět připravená bonusová úloha, která tentokráte navazuje na úlohu A. Cílem je vytvořit třídu pro vykreslování číslic podobně jako na sedmisegmentovém displeji (nebo na kalkulačce). Vhodné je jako objekt této třídy definovat jednu číslici s umístěním a velikostí. Na obrázku 2.3 je ukázka výsledku pro různé velikosti, pro jeden pixel je použit předdefinovaný znak BLOCK. (znak s ASCII kódem 219). Výhodné je si v třídě pro digitální číslo definovat proměnnou typu char, jejíž jednotlivé bity
Programování a počítače 2. Počítačová cvicení pro obor B-EST.
13
budou odpovídat příslušným segmentům (bude-li daný bit roven „1“ bude segment vykreslen, v případě, že bude tento bit roven hodnotě „0“, příslušný segment vykreslen nebude). Překódování číslice do této proměnné je možné provádět přímo při inicializaci proměnných vytvořeného objektu a pak předávat vykreslovací metodě ve třídě Canvas.
Obr. 2.3. Příklad výsledku bonusové úlohy. Kontrolní otázky 2.1) Co způsobí následující kód ve funkci main(): Point P; int ax; ax = P.X;? Předpokládáme, že třída Point je definována shodně jako v úloze A. 2.2) K čemu slouží modifikátor const v hlavičce metody, např. uch GetX()const;? 2.3) Jaké členy (položky) byste definovali ve třídě pro objekt typu kružnice a současně typu kruhu? Literatura [2.1] [2.2] [2.3]
WRÓBLEWSKI, P. Algoritmy. Datové struktury a programovací techniky. Brno: Computer Press, 2004. VIRIUS, M. Od C k C++ . České Budějovice: KOOP nakladatelství, 2002. PROKOP, J. Algoritmy v jazyku C a C++. Praha: GRADA, 2008.
3 Přetížení členských metod tříd a dědičnost Cílem je seznámit se dalšími atributy objektového programování, které jsou zaměřené na přetěžování členských metod a využitím dědičnosti.
14
FEKT VUT v Brně
Úloha A. Pro tuto úlohu je připraven zdrojový kódu rozpracovaného programu k příkladu v souboru bpc2e_c03a.cpp. Úloha řeší jednoduchý objektový projekt pro správu studentů. V uvedeném zdrojovém souboru je nejprve vytvořena třídy class Date pro objekt typu datum: // CLASS DATE class Date // day, month, year { public: int SetDate(char* new_date); // in form DD.MM.YYYY char* GetDate() const; int GetDayVal() const {return Day + 31*Month + 366*Year;} protected: int Day; int Month; int Year; }; int Date::SetDate(char *new_date) { … } char* Date::GetDate() const { … } a následně třída class PersID pro objekt typu rodné číslo:
// CLASS PERSID class PersID:public Date // child of Date + Tail, Sex { public: int SetPID(char* new_pid); char* GetPID() const; char GetSex() const {return Sex;} private: int Tail; // PID tail char Sex; // Sex 'f' - woman, 'm' - man }; int PersID::SetPID(char *new_pid) { … }
Programování a počítače 2. Počítačová cvicení pro obor B-EST.
15
char* PersID::GetPID() const { … } Ze zdrojového textu programu je patrné, že třída PersID je vytvořena jako dědic třídy Date. Je to logické, protože rodné číslo nese datum narození a doplňující unikátní čtyřmístné číslo (za lomítkem). V obou třídách jsou připraveny přístupové metody zahrnující komplexní ochranu vstupujících dat (až na kontrolu 29. února v nepřestupné roky). Vašim prvním úkolem je doplnit třídu Date o přetíženou funkci (metodu) pro nastavení vstupního data. V třídě je vyřešena funkce pro nastavení data zadaného jako řetězec v klasickém tvaru DD.MM.YYYY, (kde DD je číselná hodnota dne v měsíci, MM je pořadí měsíce v roce a YYYY je rok. Hlavička této metody je následující: int Date::SetDate(char *new_date); Doplňte tedy třídu Date o přetíženou metodu, která je přístupovou metodou pro nastavení položek data, přičemž den, měsíc a rok jsou tři nezávislé parametry metody. Hlavička takové přetížené metody by měla mít tvar: int Date::SetDate(int new_d, int new_m, int new_y); V této metodě proveďte podobné ošetření jako v případě již definované metody int Date::SetDate(char *new_date). Ve funkci main() pak ověřte, že obě přetížené metody jsou funkční. Například při následujícím testu: char txt1[100]; Date D;
// object of date
D.SetDate("12.6.2015"); strcpy(txt1, D.GetDate()); cout << endl << txt1 << endl; D.SetDate(12, 12, 2000); strcpy(txt1, D.GetDate()); cout << endl << txt1 << endl; by se měly všechny položky data u obou objektů správně vložit a výsledkem by měl být výpis podle obrázku 3.1.
Obr. 3.1. Výpis dat zadaných různými způsoby pomocí přetížených metod do objektu typu Date. Prozatím nepoužitý kód zakomentujte blokovým komentářem /*…*/). Dále si prostudujte příklad vytvoření potomka třídy PersID z rodičovské třídy Date. To se totiž bude hodit ve druhé části úkolu, kdy je třeba z definované třídy Person (osoba) vytvořit dědičnou třídu
16
FEKT VUT v Brně
Student. Třída Person obsahuje chráněné proměnné jméno, příjmení, adresa a rodné číslo (s výhodou je využito výše definované třídy PersID – pozor toto není dědičnost – jen využití jiné komponenty – tedy třída ve třídě, někdy je to označováno jako kompozice):
// CLASS PERSON class Person // FName, SName, Addr, PID { public: int SetPerson(char* new_fname, char* new_sname, char* new_addr, char* new_pid); char* GetPerson() const; // int GetBirthDateVal() const; protected: char FName[10]; char SName[10]; char Addr[30]; PersID PID; }; int Person::SetPerson(char* new_fname, char* new_sname, char* new_addr, char* new_pid) { … } char* Person::GetPerson() const { … } Odvozená třída Student pak má privátní položky Spec (obor), SYear (rok studia), Qual (el. kvalifikace – získaný paragraf) a datum platnosti kvalifikace QValid (opět třída Date ve třídě): // CLASS STUDENT class Student // child of Person + Spec, SYear, Qual, QValid { public: // ADD METHODS private: char Spec[6]; // int SYear; // int Qual; // Date QValid; // }; // TO DO METHODS
specialization, e.g. BEST study year degree (paragraph) of el. qualification date of validity of el. qualification
17
Programování a počítače 2. Počítačová cvicení pro obor B-EST.
Vaším úkolem je, jak je patrné z uvedeného zdrojového kódu pro třídu Student, definovat kýženou dědičnost a doplnit přístupové metody podobně jako v případě třídy Person. Použití přístupových metod je patrné z funkce main(), kde je nadeklarováno fixně 10 studentů v poli Student S[10] (jde tedy o pole objektů). Všechny datové položky (členy) jsou ve funkci main() naplněny, níže je uveden příklad pro prvního studenta Jaroslava Nováka s indexem 0: S[0].SetPerson("Jaroslav", "Novak", "V "960105/1361"); S[0].SetStudent("BEST", 1, 4, "13.6.2015");
lesiku
128
…",
V metodě SetStudent() se již využívá nové přetížené metody pro nastavení data. V reálném použití by se mohly údaje o studentech načítat ze souboru a noví studenti přidávat z klávesnice a pochopitelně s dynamickým přidáváním objektů typu student. V funkci main() je rovněž připraven cyklus, který vytiskne údaje o všech studentech: cout << endl << "List of students:" << endl; for(i = 0; i < num_st; i++) { strcpy(txt1, S[i].GetPerson()); strcpy(txt2, S[i].GetStudent()); cout << i+1 << ". " << "\t" << txt1 << " endl; }
" << txt2 <<
Ze zdrojového kódu je tedy zřejmé, že je nutné sestavit přístupové metody třídy Student, a to pro vkládání dat do objektu typu Student metodu SetStudent() a pro čtení dat z objektu typu Student metodu GetStudent(). Obě tyto metody přistupují pouze k novým členům ve třídě Student, pro děděné členy lze s výhodou použít metody ze třídy Person. Po správném doplnění kódu příkladu byste měli získat výpis studentů s údaji podle obrázku 3.2.
Obr. 3.2. Výpis seznamu studentů včetně osobních a studijních údajů pro příklad A. Hodnocení: 1,5 bodu. Úloha B. Zadáno cvičícím na začátku cvičení. Hodnocení: 1,5 bodu.
18
FEKT VUT v Brně
Bonusová úloha Pro doplňující bonusovou úlohu byla vybrána klasická aplikace výběru objektů na základě hodnoty jednoho vybraného parametru (člena) objektu. Pro řešení tohoto úkolu je již potřeba mít k dispozici hotové řešení zadání A. Cílem je doplnit funkci main() o algoritmus, který na základě zadané el. kvalifikace (získaný paragraf studentem) vypíše pouze studenty, kteří mají el. kvalifikaci shodnou se zadanou hodnotou. Pro zadání výběrové el. kvalifikace využijte standardní vstup cin. Vzor kódu je uveden níže, přičemž stačí nasměrovat vstup do deklarované celočíselné proměnné: int num; cout << "Insert par. of el. qualification: "; cin >> num; Doplňte tedy funkci main() o výběr studentů dle požadované el. kvalifikace. S výhodou využijte přístupové inline metody GetQual(). Studenty splňující zadané kritérium el. kvalifikace včetně jejich personálních a studijních údajů vytiskněte. Příklad výpisu pro zadanou kvalifikaci s paragrafem 4 je uveden na obrázku 3.3.
Obr. 3.3. Výpis seznamu studentů včetně osobních a studijních údajů, kteří mají el. kvalifikaci dle paragrafu 4. Kontrolní otázky 3.1) Jak program pozná, kterou z přetížených metod má v dané situaci použít? 3.2) Jakým způsobem lze ověřit správné zadání rodného čísla? 3.3) Jakým způsobem lze modifikovat zděděnou členskou metodu? Literatura [3.1] [3.2] [3.3]
DOSTÁL, R. C/C++. Hotová řešení. Brno: Computer Press, 2010. VIRIUS, M. Od C k C++ . České Budějovice: KOOP nakladatelství, 2002. PROKOP, J. Algoritmy v jazyku C a C++. Praha: GRADA, 2008.
4 Formulářová aplikace v C++ pro Windows Cílem je seznámit se s vytvářením jednoduchých aplikací v C++ typu WindowsForm pro OS Windows s využitím integrovaného prostředí Microsoft Visual Studia.
Programování a počítače 2. Počítačová cvicení pro obor B-EST.
19
Úloha A. Pro tuto úlohu tentokrát nejsou připraveny žádné zdrojové kódy. Cílem je, abyste si vyzkoušeli kompletní návrh jednoduchého projektu v MSVS2013, počínaje nastavení formulářové aplikace, přes definici vizuální podoby programu, až po doplnění automaticky vygenerovaného kódu k vizuální podobě programu o požadované ošetření událostí (vlastní metody pro dané ovládací prvky). Požadovaná aplikace by měla být jednoduchou kalkulačkou pro komplexní čísla se základními operacemi pro dvě komplexní čísla (součet, rozdíl, násobek a podíl). Připravte si v MSVS 2013 (případně i jiné verzi) projekt formulářové aplikace typu WidowsForm (podle postupu z přednášek). Ve druhém kroku vytvořte vizuální podobu formuláře aplikací vhodných ovládacích prvků (inspirujte se projektem BPC2E_Ex114 z přednášek). Bude potřeba ve formuláři aplikace definovat čtyři editační okna (TextBox) pro vstup reálné a imaginární části dvou vstupních čísel (např. A a B) a 2 textová pole (Label) pro zobrazení výsledku operace. Další textová pole je vhodné definovat pro pomocné texty jako je „real.“, „imag.“ apod. Formulář dále doplňte o čtyři tlačítka pro jednotlivé matematické operace. V závěrečné fázi doplňte projekt o metody událostí kliknutí na tlačítka pro jednotlivé matematické operace. Tedy pro implementovaná tlačítka vygenerujte funkce pro ošetření události „kliknutí na tlačítko“ metody OnClick, do nichž vložte kód pro načtení hodnot vstupních čísel z editačních oken, výpočet dané komplexní operace voláním vaší knihovní funkce a zobrazení výsledků v textových polích. Pro čtení hodnot z editačních TextBoxů a pro tisk hodnot do textových polí výsledků Label je výhodné sestavit jednoduché funkce (podobně jako ve vzorovém projektu z přednášky BPC2E_Ex114). V těchto funkcích je potřeba použít konverzi proměnné objektového řetězce třídy String na vhodný číselný formát, např. double. K tomuto účelu lze využít konverzní metody ToDouble, jejímž parametrem je položka ovládacích prvku nesoucí řetězec typu String, například takto: A_real = System::Convert::ToDouble(this->text_Are->Text); kde A_real je proměnná typu double, do níž konvertujeme řetězec z TextBoxu text_Are (editační okno pro reálnou část prvního operandu) a Text je položka nesoucí řetězec zapsaný do daného editačního okna, který je typu String. Protože při operacích nad komplexními čísly jsou výsledkem dvě hodnoty, reálná a imaginární část výsledné hodnoty, použijte v knihovních funkcích pro výpočty nad komplexními čísly předávání výsledku odkazem. Volání takové knihovní funkce může vypadat například takto: cmul(&re, &im, get_Are(), get_Aim(), get_Bre(), get_Bim()); Proměnné re a im jsou výstupy komplexní operace a funkce get_Xyy() zajišťují návratové hodnoty typu double, které jsou konvertovány z řetězců typu String z editačních oken. Číselné hodnoty re a im je pak třeba překonvertovat pomocí metody ToString() na typ String pro zobrazení v příslušném grafickém objektu na formuláři aplikace (u objektu typu Label je cílem položka Text): this->Resre->Text =
System::Convert::ToString(re);
kde Resre je objekt typu Label. Příklad funkční podoby formulářové aplikace je uveden na obrázku 4.1.
20
FEKT VUT v Brně
Obr. 4.1. Příklad formulářového okna pro komplexní kalkulačku. Hodnocení: 1,5 bodu. Úloha B. Zadáno cvičícím na začátku cvičení. Hodnocení: 1,5 bodu. Bonusová úloha Sestavte jednoduchou formulářovou aplikaci pro Windows, která náhodně vygeneruje losování dvou tahů sportky. Připravte si vhodný formulář, který bude obsahovat dvě tlačítka pro spuštění náhodného generování a textová pole label pro jednotlivá vylosovaná čísla. V projektu rovněž sestavte nezávislou funkci, která vygeneruje vektor sedmi celých čísel v rozsahu 1 až 49, přičemž žádné se nesmí opakovat. Použijte starý známý algoritmus z jazyka C s aplikací funkcí srand() a rand() z knihovny stdio.h a pomocné funkce time(NULL) z knihovny time.h pro vstupní hodnotu inicializace semínka náhodného generátoru. Pro jednoduchost můžete tuto pomocnou funkci vložit přímo do hlavičkového souboru formuláře za #pragma endregion. Protože generujete vektor sedmi čísel, musíte použít předávání tohoto vektoru odkazem. V této funkci současně proveďte i třídění pro prvních šest čísel od nejmenšího po největší (dodatkové na sedmé pozici nesmí být zahrnuto) tak, aby zobrazení vylosovaných čísel vypadalo podobně jako u zobrazení rekapitulace losování v televizním přenosu. Jako reakci na stisk tlačítka zavolejte uvedenou funkci a výsledná tažená čísla vložte do příslušných objektů label. Výsledné okno aplikace s vygenerovanými tahy sportky je uvedeno na obrázku 4.2. Je možné si ze cvičných důvodů nadefinovat i vlastní jiný formulář aplikace.
Obr. 4.2. Příklad zobrazení výsledků generátoru pro sportku ve formuláři. Kontrolní otázky 4.1) Proč se ve formulářové aplikaci pro kalkulačku nad komplexními čísly používá ke zobrazení racionálního čísla desetinná čárka? 4.2) Bylo by vhodné pro nějaký účel definovat ve formulářové aplikaci pro kalkulačku nad komplexními čísly určitou vlastní třídu? Popište její členy a metody.
Programování a počítače 2. Počítačová cvicení pro obor B-EST.
21
4.3) K čemu slouží ve zdrojovém kódu hlavičkového souboru formuláře kód using namespace? Literatura [4.1] [4.2] [4.3]
DOSTÁL, R. C/C++. Hotová řešení. Brno: Computer Press, 2010. FORD, S. 266 tipů a triků pro Microsoft Visual Studio. Brno: Computer Press, 2009. VIRIUS, M. Od C k C++ . České Budějovice: KOOP nakladatelství, 2002.
5 Grafická aplikace pro Windows s ovladačem GDI Cílem cvičení je procvičit si práci s 2D grafickým ovladačem GDI, který je nejjednodušším nástrojem pro tvorbu grafických aplikací ve Windows.
Úloha A. Sestavte a odlaďte aplikaci jednoduché formulářové aplikace pro Windows, ve které se bude graficky zobrazovat průběh měsíčních teplot během zvoleného roku. Vaším prvním dílčím úkolem je doplnit funkci pro načtení teplot GetTemp(), která je připravena v knihovně temp.h a která využívá globální proměnnou double temp[16][12], definující pole teplot s průměrnými měsíčními teplotami od roku 1995 (první řádek, sloupce jsou měsíce). Připravený formulář aplikace MyForm.h obsahuje objekt typu NumericUpDown pojmenovaný NUD pro definici roku (od 1995 do 2010 včetně). Formulář aplikace dále obsahuje objekt typu PictureBox se jménem PB pro zobrazení teplotního grafu (viz obr. 5.1). Ten má již předpřipravené grafické výstupy pro tisk mřížky tabulky s popisem os ve funkci pro událost Paint(): System::Void PB_Paint(System::Object^ sender, System…::PaintEventArgs^ e) { int n, year; double temp[12]; array
^ GraphPoints = gcnew array(12); Graphics ^ g = e->Graphics; Pen^ GridPen = gcnew Pen(Color::Black,1.0f); Pen^ FramePen = gcnew Pen(Color::Black,3.0f); SolidBrush^ PointBrush = gcnew SolidBrush(Color::Blue); Pen^ GraphPen = gcnew Pen(Color::Blue,2.0f); System::Drawing::Font^TextFont = gcnew System::Drawing::Font("Arial", 12); SolidBrush^ TextBrush = gcnew SolidBrush( Color::Black ); e->Graphics->DrawRectangle(FramePen, 100, 50, 550, 300); // frame for (n=0; n<12; n++) // vertical lines e->Graphics->DrawLine(GridPen, 100+n*50, 50, 100+n*50, 355);
22
FEKT VUT v Brně e->Graphics->DrawString("JAN", TextFont, TextBrush, 80, 360); … for (n=0; n<13; n++) // horizontal lines e->Graphics->DrawLine(GridPen, 95, 50+n*25, 650, 50+n*25); e->Graphics->DrawString("+40°C", TextFont, TextBrush, 40, 40); … // to do - printing temperature curve
} V první části jsou nadefinovány objekty kreslících nástrojů, jako jsou pera, štětce a fonty písma. Následuje vykreslení obdélníku pro umístění grafu a systém vertikálních a horizontálních čar definujících mřížku grafu. K příslušným čarám jsou pak dodefinovány texty pro zkratky měsíců a hodnoty teplot. Tuto část je možné dále zjednodušit definicí pole řetězců a aplikací cyklu. Pro názornost je ponecháno uvedené řešení s výpisem jednotlivých textů nezávisle. Váš další úkol je doplnění této funkce o zobrazení průběhu teploty pro daný rok, kód se umístí místo komentáře // to do - printing temperature curve. Pro vykreslení využijte metodu e DrawCurve(), která křivku teplot automaticky vyhladí pomocí metody splinů. Tato metoda má jeden ze vstupních parametrů pole bodů array^ (tedy pole bodů, kterými bude křivka proložena). Toto pole bodů je třeba nejprve deklarovat následujícím způsobem: array^ GraphPoints = gcnew array(12); Touto konstrukcí je deklarováno pole bodů s názvem GraphPoints s počtem dvanácti bodů (počet bodů křivky je v kulatých závorkách). K jednotlivým položkám pak přistupujeme standardně jako u pole struktur nebo objektů (objekt Point obsahuje dvě položky X (souřadnice bodu x) a Y (souřadnice bodu y), např. GraphPoints[3].X = 120; vloží na pozici souřadnice x třetího (resp. čtvrtého) bodu hodnotu 120. Přepočet teplot a měsíců na souřadnice proveďte na základě rozboru kódu pro generování mřížky tabulky. Při vykreslování grafu vhodným způsobem zvýrazněte prokládané body např. pomocí metody FillEllipse(). Posledním úkolem je sestavení funkce pro událost změny roku v NUD, kde je třeba vždy při změně volat překreslení grafu s teplotami pro vybraný rok konstrukcí: this->PB1->Refresh(); kde PB je objekt příslušné PictureBoxu, který chceme překreslit. Voláním této metody se zavolá výše uvedená funkce PB_Paint() a provede se komplexní překreslení grafu.
Programování a počítače 2. Počítačová cvicení pro obor B-EST.
23
Obr. 5.1. Grafické zobrazení průběhu teplot v roce 2003. Hodnocení: 1,5 bodu. Úloha B. Zadáno cvičícím na začátku cvičení. Hodnocení: 1,5 bodu. Bonusová úloha Upravte úlohu podle zadání A tak, abyste získali zobrazování teplotního grafu pomocí sloupcového (bar) grafu a to včetně výpisu příslušné teplotě k danému sloupci. Teploty větší než 0°C se budou zobrazovat červenými sloupci nad hodnotou 0°C a teploty záporné modrými sloupci pod úrovní 0°C. Příklad grafického výstupu je uveden na obrázku 2. Nejlépe je ve formuláři projektu z úlohy A vytvořit nový druhý objekt typu PictureBox a sloupcové grafy vykreslovat současně s teplotní křivkou. Pro sloupcové grafy využijte metodu FillRectangle(). Pokud chcete i teplotu číselně vypsat nad, případně pod, sloupec, využijte opět metodu DrawString(), přičemž požadovaný řetězec typu String z hodnoty v poli teplot temp[] získáte aplikací konverzní metody ToString: temp[n].ToString(" 0.0") kde n je index vypisovaného prvku pole a jako parametr je uveden řetězec specifikující požadovaný formát (rozlišení čísla) po konverzi (v našem případě výpis na jedno desetinné místo).
24
FEKT VUT v Brně
Obr. 5.2. Grafické zobrazení průběhu teplot v roce 2008 pomocí sloupcového grafu. Kontrolní otázky 5.1) Popište, co definují parametry v metodě: GridPen = gcnew Pen(Color::Black,1.0f);?
Pen^
5.2) K čemu slouží metoda Refresh() v objektech typu PictureBox? 5.3) Proč jsou při volání metod při kreslení grafických objektů použity šipky, např. e->Graphics->DrawRectangle(FramePen, 100, 50, 550, 300);? Literatura [5.1] [5.2] [5.3]
ECKEL, B. Myslíme v jazyku C++. Knihovna programátora. Praha: GRADA, 2000. FORD, S. 266 tipů a triků pro Microsoft Visual Studio. Brno: Computer Press, 2009. VIRIUS, M. Od C k C++ . České Budějovice: KOOP nakladatelství, 2002.
6 Manipulace s maticemi a 2D grafy v Matlabu Cílem cvičení je procvičit si manipulaci s maticemi a vektory v Matlabu a sestavování a 2D grafů. Úloha A. Sestavte matlabovský skript, který vygeneruje tři grafy vycházející ze změřených průměrných teplot za určité období. V předpřipraveném skriptu bpc2e_c06.m je definována matice Temp obsahující průměrné měsíční teplotami od roku 1995 (první řádek, sloupce jsou měsíce) měřené ve 13 h na jisté meteorologické stanici. Dále je ve skriptu definován vektor LTAvT obsahující dvanáct hodnot průměrných měsíčních teplot z dlouhodobého měření. V první fázi upravte teploty v tabulce Temp v osmém řádku od měsíce března do září včetně o deset stupňů Celsia níže. V této době byl měřicí systém porouchaný a měřil teploty o 10°C vyšší. Úpravu proveďte jednoduše pomocí standardní
Programování a počítače 2. Počítačová cvicení pro obor B-EST.
25
dvojtečkové notace. Dalším podúkolem je vygenerování grafu (viz obr. 6.1), kde budou vyneseny všechny závislosti naměřené teploty v průběhu 12 měsíců pro všechny roky měření z tabulky Temp do společného grafu modrou křivkou a současně červeně vyneste křivku průměrné měsíční teploty z uvedeného měření. Nepoužívejte žádné konstrukce cyklů a využijte výhod Matlabu pro manipulaci s maticemi. Modré křivky v grafu lze vygenerovat jen jedním voláním funkce plot(). Pro červenou křivku bude nutné volat funkci plot() podruhé. Aby se červený graf vykreslil do stejného grafu s modrými křivkami a přitom nedošlo k překreslení celého grafu s modrými křivkami, nastavte před vynášením červené křivky atribut grafu hold na hodnotu on. Po vykreslení červené křivky průměrné hodnoty teploty nastavte atribut hold opět na off. Pro výpočet průměrné hodnoty teploty aplikujte funkci sum(). Dále vygenerujte druhý graf, který zobrazí teploty pro všechny měsíce měřeného období za sebou (modře) a rovněž odchylku od dlouhodobého průměru (zelená křivka), viz obr. 6.2. Pro tento úkol použijte funkci reshape() na pole Temp.
Obr. 6.1. Grafické zobrazení měsíčních teplot pro všechny roky.
Obr. 6.2. Grafické zobrazení měsíčních teplot a odchylek od dlouhodobého průměru za sebou.
26
FEKT VUT v Brně
Opět se vyhýbejte aplikaci cyklů, v Matlabu ztrácejí často smysl a zbytečně prodlužují výpočty. U obou grafů specifikujte další parametry jako jsou mřížky, popisy os i název grafu. Pro definici rozsahu vykreslení x-ové osy můžete použít funkci xlim(), popis najdete v nápovědě Matlabu. Standardně si Matlab volí rozsah os sám, někdy to však kazí interpretaci grafických výsledků. Hodnocení: 1,5 bodu. Úloha B. Zadáno cvičícím na začátku cvičení. Hodnocení: 1,5 bodu. Bonusová úloha Vykreslete bodový graf odchylek od dlouhodobého průměru pro jednotlivé měsíce pro měřené období (modré kroužky) a rovněž průměrnou hodnotu odchylky tečkovanou červenou křivkou se čtvercovými body, viz obr. 6.3.
Obr. 6.3. Grafické zobrazení měsíčních odchylek teplot pro všechny roky a průměrná odchylka. Kontrolní otázky 6.1) K čemu slouží příkaz hold u definice grafů? 6.2) Co provede následující konstrukce v Matlabu: A = reshape(B',1,[]);? 6.3) Co provede následující konstrukce v Matlabu: A = B(2:4,5:6);?
Programování a počítače 2. Počítačová cvicení pro obor B-EST.
27
Literatura [6.1] [6.2]
DOŇAR, B., ZAPLATÍLEK, K. MATLAB pro začátečníky. Praha: BEN – Technická literatura, 2003. KATTAN, P. I. MATLAB for Beginners. A Gentle Approach. Lousiana: Peter I. Kattan, 2009.
7 Model fyzikálního jevu a 3D grafy v Matlabu Cílem cvičení je procvičit si práci s 3D grafy v Matlabu. Úloha A. Sestavte matlabovský skript, který vygeneruje graf závislosti dálky šikmého vrhu jako 3D graf pro parametry počáteční rychlosti v rozsahu od 0 do 100 km/h a pro počáteční úhel šikmého vrhu v rozsahu 0° do 90°. Pro dálku šikmého vrhu odvozením podle obrázku 7.1 platí:
v02 ⋅ sin 2α d= g
(7.1)
kde g je tíhové zrychlení na povrchu Země 9,81 m/s2. Skript musí generovat tři typy 3D grafů: povrchový (pomocí funkce surf(), viz obr. 7.3), síťový (pomocí funkce mesh(), viz obr. 7.4) a konturový (pomocí funkce contour(), viz obr. 7.5).
Obr. 7.1. Šikmý vrh – situační nákres. Obecně funkce mesh(), surf() a contour() mají tři parametry, případně čtyři při využití neprimární palety barev. Např. funkce surf(X, Y, Z, C) vykreslí povrchový graf Z = f(X,Y), kde X, Y jsou matice vygenerované funkcí meshgrid(), Z je matice výsledné 3D funkce. C definuje barevnou paletu, není-li definováno, použije se aktuální, jak bylo uvedeno výše. Matice X a Y vygenerované funkcí meshgrid() určují síť bodů, které se pak mohou použít jako vstupní hodnoty pro výpočet funkce. Tzn., že tyto matice mají rozměr podle zvolené mřížky a jednotlivé prvky pole obsahují skutečné vstupní hodnoty pro danou proměnnou. Matice X má pak pro daný sloupec všechny hodnoty stejné odpovídající hodnotě x v kartézské souřadné soustavě. Obdobně matice Y má pro daný řádek všechny
28
FEKT VUT v Brně
hodnoty stejné odpovídající hodnotě y v kartézské souřadné soustavě. Níže je uveden příklad, který vygeneruje povrchový graf funkce z = x2+y2 včetně aplikace funkce meshgrid(), titulku grafu a popisu os a to se standardní barevnou paletou, výsledek je na obrázku 7.2: [x,y] = meshgrid(-5:0.1:5); Z = x.^2+y.^2; figure() surf(X,Y,Z) title('z=x^2+y^2') xlabel('x') ylabel('y') zlabel('z') z=x 2+y 2
50
40
z
30
20
10
0 5 5 0 0 -5
y
-5 x
Obr. 7.2. Povrchový graf pro skript z příkladu.
d = f(v0, alfa)
70 80 70
60
60 50
d [m]
50 40
40 30 20
30
10 20
0 80 100
60 60 40
20 alfa [°]
10
80 40
0
20 0
0
v0 [km/h]
Obr. 7.3. Povrchový graf pro dálku šikmého vrhu.
29
Programování a počítače 2. Počítačová cvicení pro obor B-EST.
d = f(v0, alfa)
80
d [m]
60
40
20
0
100 80
80 60
60 40
40 20
20 0
0
alfa [°]
v0 [km/h]
Obr. 7.4. Síťový graf pro dálku šikmého vrhu. Velikost ok mřížky je třeba volit rozumně tak, aby graf nebyl příliš diskretizovaný a současně aby nebyla síť tak hustá, že se slijí hrany (sítě) černé barvy v jeden černý obraz. Barevnou intenzitní paletu ve formě sloupku pro osu z lze aktivovat příkazem colorbar. d = f(v0, alfa) 90 10
80
30
20
10
70
30
40
20
50
50
40
70
40
10
alfa [°]
60
60
30
30
60 50
20
20
40 30
10
10
20
10
0
0
10
20
30
40
50 v0 [km/h]
60
70
80
90
Obr. 7.5. Konturový graf pro dálku šikmého vrhu. Hodnocení: 1,5 bodu. Úloha B. Zadáno cvičícím na začátku cvičení. Hodnocení: 1,5 bodu.
100
30
FEKT VUT v Brně
Bonusová úloha Vygenerujte smíšený graf závislosti dálky šikmého vrhu podle zadání A obsahující síťový graf spolu s konturovým pomocí funkce meshc(). Výsledek je zřejmý z obrázku 7.6. Upravte rovněž barevnou paletu podle obrázku. Barvy jsou vzestupně plná černá, plná modrá, plná zelená a plná červená. Nezapomeňte i na popisy os a titulek grafu. d = f(v0, alfa)
70 80 60
70 60
50
d [m]
50 40
40 30
30 20 20
10 0 0
80
20
10
60
40
40
60 20
80 100
0
0 alfa [°]
v0 [km/h]
Obr. 7.6. Kombinovaný graf síťový a konturový. Kontrolní otázky 7.1) Jakou barvu bude mít graf, pokud bude ve skriptu pro generování u grafu definována barevná paleta následovně: colormap([0 1 0])? 7.2) Jak lze nastavit osu z u grafu tak, aby rozsah osy z odpovídal přesně od minma do maxima funkční hodnoty Z (Z je matice výsledné dvourozměrné funkce)? 7.3) Co zajistí u 2D grafu příkaz hidden off? Literatura [7.1] [7.2]
DOŇAR, B., ZAPLATÍLEK, K. MATLAB pro začátečníky. Praha: BEN – Technická literatura, 2003. KATTAN, P. I. MATLAB for Beginners. A Gentle Approach. Lousiana: Peter I. Kattan, 2009.
8 Parametrické 3D grafy v Matlabu Cílem cvičení je procvičit si práci se soubory a parametrickými 3D grafy v Matlabu. Úloha A. Protože budete řešit transformaci z kartézských do sférických souřadnic, ve kterých budete vykreslovat grafy, resp. objekty, jako parametrické 3D funkce s definicí barvy povrchu a protože to představuje jistou představivost ve 3D prostoru a tedy pro matlabovské začátečníky jistý obtížný kousek, je součástí zadání i názorný příklad, viz bpc2e_c08ex.m.
Programování a počítače 2. Počítačová cvicení pro obor B-EST.
31
V tomto příkladu je nejprve pomocí meshgridu vytvořena sít v kartézské soustavě, kde lon (zeměpisku délka) koresponduje s osou x a lat (zeměpisná šířka) s osou y: [lon,lat] = meshgrid(-180:0.5:180, -90:0.5:90); Máme tedy síť, která má definovaná oka s délkou 0,5 a je položená na rovné zemi (v soustavě x, y). Následně je vygenerována matice c jako funkce lon+lat, to znamená, že její hodnota bude stoupat s rostoucí hodnotou lon i lat: c = lon+lat; Pro nízké indexy řádků i sloupců se budou její hodnoty pohybovat okolo -270, tedy -180 + (90), naopak pro nejvyšší indexy se budou hodnoty v matici C blížit +270. Pokud použijeme následující skript pro vykreslení síťového grafu pomocí funkce mesh(): figure(1) mesh(lon,lat,0*lon,c) xlabel('lon') ylabel('lat') axis equal colormap('Lines') view(0,90) získáme graf 8.1. Souřadnice x a y tedy odpovídají lon i lat. Třetí matice odpovídající ose z je nulová (násobení je zde kvůli zajištění rozměru nulové matice). Ve funkci mash() matice c figuruje jako čtvrtý parametr, což znamená, že hodnotou c pro dané lon a lat je nějaká barva z vybrané palety. Protože je z vždy nulové graf leží v rovině xy a jenom se mění jeho barva podle matice c a vybrané palety colormap(). Pro ilustraci je vybrána paleta Lines, proto tolik proužků, ale zkuste si jinou paletu, např. Winter, která lépe ukáže, jak roste c pro dané místo (souřadnice) sítě umístěné v rovině xy. Máme tedy vytvořen určitý vzor, který je rozložený na podlaze (z = 0) jako koberec. A nyní přichází kýžená transformace, kdy pro parametry lon a lat definujeme transformované proměnné x, y a z ve sférických souřadnicích. Z hlediska představivosti jde jen o to, že vezmeme původní síť (koberec položený na zemi) a stočíme jej do koule, přičemž musíme někde oka (koberec) trochu roztáhnout, jinde přitlačit k sobě. Výsledkem je kouli v 3D soustavě a příslušné barevné proužky teď figurují na povrchu koule. V našem případě máme poloměr koule r = 1, obecně však pro uvedenou transformaci platí:
x = r ⋅ cos(α ) ⋅ cos( β ) y = r ⋅ sin(α ) ⋅ cos( β ) z = r ⋅ sin( β )
(8.1)
kde α odpovídá námi definované proměnné lon a β proměnné lat. Hodnota r určuje poloměr výsledné koule. V testovacím příkladě je síť tak hustá, že se nám jednotlivé hrany slévají dohromady. Zkuste navrhnout síť řidší a uvidíte, že transformace do koule v některých místech oka roztáhne a jinde smrskne (to je kvůli sinům a kosinům v transformačním vztahu).
32
FEKT VUT v Brně
Obr. 8.1. Barevný plot na zemi. Sestavíme-li skript pro transformaci kulových souřadnic: x = cos(lon*pi/180).*cos(lat*pi/180); y = sin(lon*pi/180).*cos(lat*pi/180); z = sin(lat*pi/180); a aplikujeme již skutečné 3D zobrazení (z již není nulové, viz třetí vztah v transformaci) pomocí funkce mesh(): figure(2) mesh(x,y,z,c) title('Striped ball') xlabel('x') ylabel('y') zlabel('z') axis equal colormap('Lines') view(45,20) Získáme krásnou barevnou mičudu, na které je vidět zhuštění původního 2D zobrazení v oblasti pólů a zředění okolo rovníku. Vašim úkolem je na základě uvedeného příkladu sestavit matlabovský skript, který vygeneruje grafy rozložení teploty v severním Atlantiku. Abyste mohli oddělit oceány od souše, je k dispozici binární soubor earth.dat obsahující jednobajtové hodnoty, kdy 1 odpovídá moři a 0 souši na zemském povrchu. Rozdělení je po 0,5° jak v zeměpisné délce <180°, +180°>, tak i v zeměpisné šířce <-90°, +90°>. Řádky odpovídají zeměpisné šířce, sloupce zeměpisné délce. Sestavte skript, který zobrazí masku souší a moří Země, viz obr. 8.3. Jde v podstatě o řešení z ukázkového příkladu s vlastní paletou o dvou barvách. Data ze souboru masky souší a moří načtete následujícím skriptem: fid1 = fopen('earth.dat', 'r') e_mask = fread(fid1, [361 721]); fclose(fid1)
Programování a počítače 2. Počítačová cvicení pro obor B-EST.
33
Obr. 8.2. Barevný plot srolovaný do mičudy pomocí transformace. Proveďte jak zobrazení rozložené do roviny xy (obr. 8.3a) tak i zobrazení po transformaci, čímž získáte vykreslený globus souší a moří. Pro další úkol je v souborech NATemp1985.dat a NATemp2010.dat uložena mapa teploty severního Atlantiku měřená v roce 1985 a 2010 v zeměpisné délce <-135°, +35°> a v zeměpisné šířce <+15°, +90°>. Rozdělení je opět po 0,5° a stejné uspořádání dat jako pro masku souší a moří avšak jako hodnoty ve formátu float odpovídající průměrné teplotě v daném roce. Souše mají přidělenu fixní hodnotu -10. Sestavte výřezy grafů teploty vod v severním Atlantiku pro oba roky i rozdíl (pro zjištění globálního oteplování), viz obr. 8.4. V závěrečné části proveďte transformace do sférických souřadnic a zobrazte teploty moří na povrchové mapě Země, u rozdílové hodnoty zobrazte jen měřenou oblast (máte jen kousek plotu na kousek koule), viz obr. 8.5. Pro zobrazení stačí používat funkci mesh(), protože síť je dostatečně hustá. Jak je patrné z výsledků i severní Atlantik se nám pomalu ohřívá. Kdo za to může?
Obr. 8.3. Maska souší a moří Země.
34
FEKT VUT v Brně
Obr. 8.4. Teplota moře ve 2D.
Bonusová úloha V rámci bonusové úlohy upravte kód příkladu A tak, že transformaci budete definovat jako vlastní funkci. Řešení ověřte na stejných datech, musíte získat shodné výsledky. Kontrolní otázky 8.1) Kam se bude vykreslovat graf při definici: subplot(1,2,2)? 8.2) K čemu slouží příkaz: axis equal? 8.3) K čemu slouží funkce view()u zobrazování grafů jaké má parametry?
Programování a počítače 2. Počítačová cvicení pro obor B-EST.
35
Obr. 8.5. Teplota moře ve 3D. Hodnocení: 3 body. Literatura [8.1] [8.2] [8.3]
DOŇAR, B., ZAPLATÍLEK, K. MATLAB pro začátečníky. Praha: BEN – Technická literatura, 2003. DOŇAR, B., ZAPLATÍLEK, K. MATLAB – začínáme se signály. Praha: BEN – Technická literatura, 2006. KATTAN, P. I. MATLAB for Beginners. A Gentle Approach. Lousiana: Peter I. Kattan, 2009.
36
FEKT VUT v Brně
9 Model komunikačního systému v Matlabu Cílem cvičení je vyzkoušet si sestavit skripty v Matlabu pro model jednoduchého komunikačního systému pro přenos obrázků. Úloha A. Sestavte model komunikačního systému, který pracuje s modulací 8PSK a který přenáší komprimované BMP obrázky. Pro kompresi (zdrojové kódování) a zpětnou dekompresi (zdrojové dekódování) BMP obrázků použijte následující algoritmus: Nejprve z jednotlivých barevných složek vytvořte matici C, která je součtem všech tří RGB složek pro jednotlivé pixely (elementy matice). Následně vytvořte matici pro červenou a zelenou složku jako poměr úrovně červené ku součtu všech složek (R/C) a podobně pro zelenou matici úrovní (G/C). Pokud byste to samé provedli i pro modrou matici úrovní, součet všech třech poměrových matic by byl 1 (tedy 100%). Tzn., že poměrovou matici modré lze dopočítat z poměrových matic červené a zelené. Celá komprese spočívá v tom, že C matice nese celkovou úroveň jasu a poměrové matice procentuální zastoupení barev. Jasovou matici C podělte 3, čímž získáte rozsah pro jas 0 až 255 (osmibitovou hodnotu) pro každý pixel. Z této matice vytvořte finální matici jasu pro přenos rádiovým kanálem tak, že použijete jen šest nejvyšších bitů (jas bude komprimován na 64 úrovní). Pro poměrovou složku červené a zelené vytvořte zředěné matice tak, že obrázek rozdělíte na bloky 4x4 pixelů a budete uvažovat průměrnou poměrnou úroveň červené, resp. zelené pro tento blok pixelů. Výsledné poměrové matice budou mít 4x méně řádků i 4x méně sloupců (celková redukce je 16x). Následně tyto matice ořežte na 6 nejvyšších bitů (např. tak, že poměr 0 až 100% vynásobíte 26 a zanedbáte desetinnou část). Tím je hotová celá komprese. Inverzním způsobem a dopočítáním složky modré získáte zpět komprimovaný BMP obrázek, tento proces bude třeba provést po demodulaci signálu. Nejlépe bude řešit zdrojové kódování a dekódování jako vlastní matlabovské funkce, které se budou volat ve skriptu modelu. Důvod je i ten, že můžete provést test správné činnosti kompresoru a rekonstrukce komprimovaného BMP obrázku bez modulace a demodulace. Pro testování máte připravený obrázek mkid.bmp o velikosti 200 x 200 pixelů s roztomilou dětskou tvářičkou. Na obrázku 9.1a je původní BMP fotka a na obrázku 9.1b komprimovaná (rekonstruovaná). Rozdíl je takřka neznatelný, přičemž kompresní poměr je docela velký. Původní obrázek potřebuje 200x200x3x8 bitů (tři barevné složky s rozlišením 8 bitů) = 960000 bitů, komprimovaný 200x200x1x6bitů pro jas plus 50x50x2x6 bitů pro dvě poměrové barevné složky bloků 4x4 pixely, tedy celkem 270000 bitů. Kompresní poměr je 960000/270000 = 3,56.
Obr. 9.1a. Originální fotka.
Obr. 9.1b. Rekonstruovaná komprimovaná fotka.
Programování a počítače 2. Počítačová cvicení pro obor B-EST.
37
Náš primitivní algoritmus je celkem dobrý komprimátor bez újmy na kvalitě obrázku s více než tři a půl násobnou redukcí datového objemu. Pro výstup z kodéru rozdělte šestibity (informace o jasu pixelu a dvou barvách bloku 4x4 pixelů) po trojicích a vygenerujte vektor tříbitových hodnot (tedy 0 až 7) pomocí funkcí reshape(). Skladbu, tedy kde bude ve vektoru vyšší část jasu, nižší část jasu a vyšší a nižší část té které barvy, si vymyslete sami. Pochopitelně, že s danou skladbou musí pracovat i příslušný algoritmus dekodéru obrázku. Rozdělení na trojice bitů souvisí s následně použitou modulací. Ve druhé fázi příkladu bude třeba navrhnout modulátor a demodulátor pro modulaci 8PSK. Symboly v I/Q diagramu (viz přednáška) mají shodnou amplitudu (uvažujte 1 V) a jsou rozlišeny jen různou počáteční fází. Protože různých počátečních fází je 8, je tato modulace definována jako osmistavová modulace s fázovým klíčováním 8PSK (Phase Shift Keying). Výhodou této modulace je, že amplituda je konstantní a mění se jen fáze nosné. Protože máme osm různých stavů, jeden symbol umožňuje přenést trojici bitů (tribit) užitečných dat. Mapování do I/Q diagramu pro tuto modulaci je uvedeno na obrázku 9.2. Mapování je zjednodušeno (není optimální) tak, aby bylo velmi jednoduché modulátor a demodulátor realizovat. Navíc náš kódovaný obrázek nese jas pro jednotlivé pixely a barevné složky pro bloky 4x4 v šesti bitech, tzn., že pro modulaci se každý šestibit (jas nebo barevná procentuální úroveň) rozdělí na dvě trojice bitů (nižší a vyšší) a přenáší se jako dva nezávislé 8PSK symboly, viz požadavek na rozdělení u kodéru a dekodéru. Sestavte funkci pro mapování symbolu vstupního vektoru podle obrázku 9.2. Černě jsou u symbolů definovány mapovací tribity, modře pak jejich hodnoty v dekadické soustavě. Lze velmi snadno odvodit, že fáze symbolu (ve stupních) je závislá na hodnotě dat D (dekadicky vyjádřeného tribitu) podle vztahu:
ϕ = 45 ⋅ (D − 4) + 22,5 .
(9.1)
Obr. 9.2. Mapování symbolů 8PSK. Pro demodulaci je třeba definovat rozhodovací hranice. U 8PSK signálu nás tedy bude zajímat jen fáze. Rozhodovací hranice jsou na obrázku 9.3 v I/Q diagramu pro přijatý signál (vzorky) definován červenými čarami. S využitím funkce angle() a round() pro celý 8PSK demodulátor vektoru signálu pak stačí dva řádky matlabovského skriptu. Sestavte kompletní skripty modelu komunikačního systému a proveďte několik experimentů pro různé úrovně šumu. Vzhledem k použitému způsobu komprimace obrázku se začnou se zvyšující úrovní šumu v obrázku objevovat chyby v podobě chyb na úrovni pixelů a kostečkování (podobně jako u digitální televize), viz obr 9.4.
38
FEKT VUT v Brně
Obr. 9.3. Rozhodovací hranice pro 8PSK demodulátor.
Signal with AWGN noise 2 1.5 1
Q
0.5 0 -0.5 -1 -1.5 -2 -2
-1.5
-1
-0.5
0 I
0.5
1
1.5
2
a) úroveň šumu 0,10 – signál na vstupu demodulátoru v I/Q rovině a rekonstruovaný obrázek Signal with AWGN noise 2 1.5 1
Q
0.5 0 -0.5 -1 -1.5 -2 -2
-1.5
-1
-0.5
0 I
0.5
1
1.5
2
b) úroveň šumu 0,15 – signál na vstupu demodulátoru v I/Q rovině a rekonstruovaný obrázek
Programování a počítače 2. Počítačová cvicení pro obor B-EST.
39
Signal with AWGN noise 2 1.5 1
Q
0.5 0 -0.5 -1 -1.5 -2 -2
-1.5
-1
-0.5
0 I
0.5
1
1.5
2
c) úroveň šumu 0,20 – signál na vstupu demodulátoru v I/Q rovině a rekonstruovaný obrázek Obr. 9.4. Výsledky přenosu BMP obrázku komunikačním systémem s 8PSK modulací. Hodnocení: 3 body. Bonusová úloha Vytvořte vlastní řešení zdrojového kódování (komprimace obrázku) a proveďte obdobnou sadu experimentů jako v příkladě A. Kontrolní otázky 9.1) Definujte kompresní poměr u komprimačních metod. 9.2) Jak by se v přenášeném obrázku projevil delší rušivý puls, když by byla obrayová data přenášena sekvenčně po řádcích? 9.3) K čemu slouží v Matlabu funkce size()? Literatura [9.1] [9.2] [9.3]
DOŇAR, B., ZAPLATÍLEK, K. MATLAB pro začátečníky. Praha: BEN – Technická literatura, 2003. DOŇAR, B., ZAPLATÍLEK, K. MATLAB – začínáme se signály. Praha: BEN – Technická literatura, 2006. DOBEŠ, J., ŽALUD, V. Moderní Radioelektronika. Praha: BEN – Technická literatura, 2006.
10 Grafické uživatelské rozhraní v Matalabu Cílem cvičení je vytvořit grafické uživatelské rozhraní pro simulaci komunikačního systému pro přenos obrázků z minulého cvičení.
40
FEKT VUT v Brně
Úloha A. Sestavte grafické uživatelské rozhraní podle obrázku 10.1. Uvažujeme komunikační systém s modulací 8-PSK, tedy osmistavovou fázovou modulaci, z minulého cvičení, přičemž simulace bude vždy provedena pro dvě různé úrovně šumu pro přehledné porovnávání. Naše GUI bude obsahovat pět grafů (první pro zobrazení originálního obrázek, dále pak dvojici grafů pro zobrazení zašuměného signálu v I/Q rovině signálu a dvojici grafů pro výsledné dekódované obrázky dítěte). Uživatelské rozhraní bude dále obsahovat pak dvě posuvné lišty (slider) pro nastavení úrovně šumu v rozsahu 0 až 1, jedno tlačítko, kterým se spustí simulace a několik statických textů pro popisy a zobrazení nastavené úrovně šumu a zobrazení výsledné symbolové chybovosti. Celý projekt pro model komunikačního systému je již hotový jako soubor funkcí. Celý proces simulace komunikačního systému pro přenos obrázku je zřejmý z těla funkce BMPTransf8PSK(), která definuje celý proces přenosu obrázku: function BMPTransf8PSK(OutFileName, NoisePower) OutData = BMPCoderR2C4('mkid.bmp'); OutSig = Mod8PSK(OutData, NoisePower); figure() plot(OutSig,'b.') grid on xlim ([-2 2]) ylim ([-2 2]) xlabel('I') ylabel('Q') title('Signal with AWGN noise') DemData = Demod8PSK(OutSig); BMPDecoderR2C4(DemData, OutFileName, 200); Funkce má dva vstupní parametry, první OutFileName definuje jméno souboru, do něhož bude uložen výsledný obrázek po přenosu (simulaci) a druhým parametrem NoisePower definujeme výkon aditivního šumu (ve W), přičemž modulací užitečného signálu formátem 8PSK získáme výkon 1 W. Uvnitř těla funkce BMPTransf8PSK se nejprve volá funkce pro kódování pevně daného vstupního obrázku BMPCoderR2C4('mkid.bmp'), následně je volána funkce pro modulaci a přimíchání aditivního šumu. Modulovaný signál včetně šumu je dále zobrazen v grafu jako I/Q konstelační diagram (v praxi by to odpovídalo měření na přijímací straně). Následuje funkce demodulace Demod8PSK() a dekódování BMPDecoderR2C4(), která kromě vlastního dekódování uloží výsledný obrázek do souboru definovaného proměnnou OutFileName. Uvedené konstrukce funkce lze tedy plně využít i v rámci grafického rozhraní. Pro zobrazení obrázku v objektu grafu axes použijte funkci image(). Ovládání funkčního GUI spočívá v nastavení dvou úrovní šumu pomocí dvou posuvných lišt, přičemž hodnota se zobrazuje v příslušném statickém textu. Tyto hodnoty jsou pak vstupem simulace, která se spustí tlačítkem SIMULATE. V dolní části pod příslušnými obrázky se pak navíc zobrazí hodnota symbolové chybovosti SER (Symbol Error Rate), která je podílem chybně přenesených symbolů ku celkovému počtu přenesených symbolu. Pro určení hodnoty SER je vše potřebné ve vektorech OutData a DemData ve funkci BMPTransf8PSK(), tyto
Programování a počítače 2. Počítačová cvicení pro obor B-EST.
41
vektory stačí jen porovnat co do obsahu. S využitím jednoduchých matematických funkcí je to záležitost jednoho řádku v matlabovském skriptu.
Obr. 10.1. GUI pro simulaci komunikačního systému pro přenos obrázků s ukázkovými výsledky. Hodnocení: 1,5 bodu. Úloha B. Zadáno cvičícím na začátku cvičení.
42
FEKT VUT v Brně
Hodnocení: 1,5 bodu. Bonusová úloha Vytvořte jednoduché grafické rozhraní pro simulátor šikmého vrhu s možnosti volby typu výstupních grafů a rozsahů parametrů simulace. Kontrolní otázky 10.1) K čemu slouží ve skriptu pro grafické jméno_objektu_Callback()?
uživatelské
rozhraní
funkce
typu
10.2) K čemu slouží ve skriptu pro grafické jméno_objektu_CreateFcn()?
uživatelské
rozhraní
funkce
typu
10.3) Jak je definován parametr symbolové chybovosti SER? Literatura [10.1] DOŇAR, B., ZAPLATÍLEK, K. MATLAB pro začátečníky. Praha: BEN – Technická literatura, 2003. [10.2] DOŇAR, B., ZAPLATÍLEK, K. MATLAB – tvorba uživatelských aplikací. Praha: BEN – Technická literatura, 2004. [10.3] DOŇAR, B., ZAPLATÍLEK, K. MATLAB – začínáme se signály. Praha: BEN – Technická literatura, 2006.
Odpovědi ke kontrolním otázkám 1.1) Jaké jsou hodnoty položek ve struktuře typu RGBTRIPLE při plnobarevném bitmapovém formátu obrázku, pokud definují barvu pixelu v úrovni šedi? Hodnoty položek ve struktuře typu RGBTRIPLE při plnobarevném bitmapovém formátu obrázku definují barvu pixelu v úrovni šedi, pokud jsou všechny tři položky shodné, od hodnoty 0 reprezentující černou barvu po hodnotu 255 reprezentující bílou barvu. 1.2) Co reprezentuje sizeof() ve funkci fwrite()? sizeof() je operátor (není to funkce), který definuje velikost typu proměnné (i typu struktura) v Bytech. V závorce je uvedena proměnná, jejíž velikost je zjišťována. 1.3) Kolik barev je možné nadefinovat při plnobarevném bitmapovém formátu obrázku? U plnobarevného bitmapového formátu obrázku lze nadefinovat přibližně 16,8 miliónu různých barev. Každá barevná složka má rozlišení 8 bitů, pro tři složky RGB je celkové rozlišení barvy 24 bitů, celkem je tedy k dispozici 224 možných kombinací barev, tj. 16777216, přičemž neexistuje různé uspořádání složek barev, které by se jevilo jako stejný barevný odstín.
Programování a počítače 2. Počítačová cvicení pro obor B-EST.
43
2.1) Co způsobí následující kód ve funkci main(): Point P; int ax; ax = P.X;? Předpokládáme, že třída Point je definována shodně jako v úloze A. Překladač ohlásí chybu, protože člen X je ve třídě Point definován jako privátní a lze k němu mimo třídu přistupovat jen pomocí přístupových metod, v uvedeném případě kopírování do proměnné ax lze použít metodu GetX(). 2.2) K čemu slouží modifikátor const v hlavičce metody, např. uch GetX()const;? Modifikátor const zakazuje uvedené metodě měnit privátní členy třídy, lze je pouze číst. 2.3) Jaké členy (položky) byste definovali ve třídě pro objekt typu kružnice a současně typu kruhu? Postačuje položka (člen) pro střed a poloměr vhodného číselného typu a např. znaková položka definující, zda je objekt kružnicí (např. znak e jako empty) nebo kruhem (např. znak f jako filled). 3.1) Jak program pozná, kterou z přetížených metod má v dané situaci použít? Vždy se použije ta z přetížených metod, která má typy parametrů shodné s parametry volané matody. 3.2) Jakým způsobem lze ověřit správné zadání rodného čísla? Zbytek po celočíselném dělení celého rodného čísla včetně koncovky hodnotou 11 musí být roven 0. Celeé rodné číslo je tedy dělitelné 11 beze zbytku. 3.3) Jakým způsobem lze modifikovat zděděnou členskou metodu? Tak, že předefinujeme v dceřiné třídě, přičemž musí mít stejné typy parametrů. Pokud budou typy nebo počet parametrů jiný vznikne k děděné metodě nová metoda přetížená. 4.1) Proč se ve formulářové aplikaci pro kalkulačku nad komplexními čísly používá ke zobrazení racionálního čísla desetinná čárka? Je to dáno národním nastavením v operačním systému Windows, na kterém běží příslušná aplikace. 4.2) Bylo by vhodné pro nějaký účel definovat ve formulářové aplikaci pro kalkulačku nad komplexními čísly určitou vlastní třídu? Popište její členy a metody. Ano, členy by byla reálná a imaginární část komplexního čísla. Třída by měla obsahovat členské metody pro přístup ke členům a to včetně například metod pracujících s polární definicí komplexního čísla (amplituda a fáze). 4.3) K čemu slouží ve zdrojovém kódu hlavičkového souboru formuláře kód using namespace? using namespace slouží ke specifikaci aktuální třídy použité v projektu tak, by nemusela být k metodám dané třídy použita celá třídní specifikace (od předků po vlastní třídu), pak není třeba volat členy způsobem rodič._třída::třída::metoda(), ale jen metoda().
44
FEKT VUT v Brně
5.1) Popište, co definují parametry v metodě Pen(): Pen^ GridPen = gcnew Pen(Color::Black,1.0f);? Parametr Color::Black definuje černou barvu pera, jedná se numerativní typ třídy Color definující barvu nástroje (pera). Parametr 1.0f definuje tloušťku čáry pera. 5.2) K čemu slouží metoda Refresh() v objektech typu PictureBox? Metoda Refresh() v objektech typu PictureBox slouží k překreslení obrázku v PictureBoxu podle kódu metody Paint()definované pro příslušný objektu PictureBox. 5.3) Proč jsou při volání metod při kreslení grafických objektů použity šipky, např. e->Graphics->DrawRectangle(FramePen, 100, 50, 550, 300);? Protože objekty generované v rámci této metody jsou definovány jako dynamické objekty (s referencí). 6.1) K čemu slouží příkaz hold u definice grafů? Příkaz hold s atributem on povolí opětovné kreslení do grafu, s atributem off se vždy celý graf překreslí novým výsledkem. 6.2) Co provede následující konstrukce v Matlabu: A = reshape(B',1,[]);? Provede se transpozice matice B a ze všech prvků této transponované matice se vytvoří řádkový vektor, který se uloží do proměnné A. Má-li matice B rozměr m×n, matice A, resp. vektor bude mít rozměr m⋅n × 1. 6.3) Co provede následující konstrukce v Matlabu: A = B(2:4,5:6);? Z matice B se vykopírují prvky z druhého až čtvrtého řádku a současně pátého až šestého sloupce a uloží se do matice A. 7.1) Jakou barvu bude mít graf, pokud bude ve skriptu pro generování u grafu definována barevná paleta následovně: colormap([0 1 0])? Graf bude jednobarevný a vykreslený plnou zelenou barvou. 7.2) Jak lze nastavit osu z u grafu tak, aby rozsah osy z odpovídal přesně od minma do maxima funkční hodnoty Z (Z je matice výsledné dvourozměrné funkce)? zlim([min(min(Z))
max(max(Z))])
7.3) Co zajistí u 2D grafu příkaz hidden off? Nebudou se zakrývat z daného pohledu části grafické závislosti (např. křivky v kombinovaném síťovém a konturovém grafu) schované za jinou částí grafické závislosti.
45
Programování a počítače 2. Počítačová cvicení pro obor B-EST.
8.1) Kam se bude vykreslovat graf při definici: subplot(1,2,2)? V daném případě se vykreslují dva grafy vedle sebe, přičemž aktuálně se bude vykreslovat graf pravý. 8.2) K čemu slouží příkaz: axis equal? Tímto příkazem se zajistí stejné měřítko na osách aktuálního grafu. 8.3) K čemu slouží funkce view()u zobrazování grafů jaké má parametry? Funkce view(az, el) slouží k definici pohledu na graf z místa o azimutu az (natočení roviny xy) elevaci el (sklon vůči rovině xy). 9.1) Definujte kompresní poměr u komprimačních metod. Kompresní poměr je podíl velikosti (objemu v B) nekomprimovaných vstupních dat ku velikosti komprimovaných výstupních dat. 9.2) Jak by se v přenášeném obrázku projevil delší rušivý puls, když by byla obrazová data přenášena sekvenčně po řádcích? Chyba se projeví v delším úseku řádku reprezentovaného výškou obrazového bloku, např. v deseti po sobě následujících. Jedná se o tzv. shlukovou chybu. K eliminaci a rozprostření shlukových chyb se v komunikačních systémech používá metoda označovaná jako interleaving, kdy dochází k definovanému proházení symbolů celého snímku před přenosem kanálem. 9.3) K čemu slouží v Matlabu funkce size()? Funkce size() vrací rozměry matice (i vícedimenzionálních). 10.1) K čemu slouží ve skriptu pro grafické jméno_objektu_Callback()?
uživatelské
rozhraní
funkce
typu
Tyto funkce jsou volány při události vzniknuvší v souvislosti s daným objektem. Např. kliknutí na tlačítko, posunutí posuvnému na liště apod. Proto slouží ke specifikaci procesu, který se má provést při události nad příslušným objektem. 10.2) K čemu slouží ve skriptu pro grafické jméno_objektu_CreateFcn()?
uživatelské
rozhraní
funkce
typu
Tyto funkce jsou volány při vytváření (generování) příslušného objektu. Charakterem odpovídají konstruktoru v C++. Proto obvykle slouží k dodefinování parametrů objektů při jejich generování. 10.3) Jak je definován parametr symbolové chybovosti SER? Symbolová chybovost SER vyjadřuje podíl počtu chybně přenesených symbolů ku celkovému počtu přenesených symbolu za určitý čas (např. přenos celé zprávy, obrázku apod.).