Hlavní navigace

Knihovna ClanLib (20)

27. 9. 2004
Doba čtení: 4 minuty

Sdílet

Minule jsme při popisu třídy CL_Font narazili na třídu CL_Rect, což je, jak už bylo řečeno, třída reprezentující obdélník. Dnes si tuto třídu přiblížíme podrobně, protože při programování aplikací ClanLibu vlastních narazíme na potřebu nějakým způsobem reprezentovat obdélník velmi často.

CL_Rect

Třída CL_Rect má čtyři atributy typu int, kterými jsou left, top, right a bottom. Jedná se o souřadnice (levého horního a pravého dolního rohu), kterými je příslušný obdélník zadán:

Z těchto souřadnic již CL_Rect umí dopočítat šířku a výšku, které získáme po řadě metodami:

int get_width();
int get_height();

Rozměry můžeme získat také jako CL_Size pomocí metody:

CL_Size get_size();

Další velmi užitečnou metodou je

bool is_inside(const CL_Point &p);

Tato metoda vrátí true v případě, že zadaný bod je uvnitř tohoto obdélníku, jinak vrátí false. Bod zadáváme jako CL_Point. Chceme-li tedy zjistit, zda je bod (X, Y) součástí obdélníku O, zeptáme se třeba takto (zejména v případě, kdy si tento bod nereprezentujeme jako CL_Point):

if (O.is_inside(CL_Point(X, Y))) { ... }

Můžeme také zjistit, zda je jiný obdélník uvnitř našeho obdélníku (true) pomocí

bool is_overlapped(const CL_Rect &r);

Jinou metodou, která se může hodit, je

CL_Rect get_rot_bounds(const CL_Point &hotspot, float angle); 

Tato metoda vrací obdélník opsaný obdélníku vzniklému otočením našeho obdélníku okolo bodu hotspot o úhlel angle (ve stupních). Samozřejmě opsaným obdélníkem je myšlen takový opsaný obdélník, který má hrany rovnoběžné se souřadnými osami, viz obrázek:

Pokud chceme změnit rozměry obdélníku, avšak zachovat levý horní roh, můžeme použít metodu

void set_size(const CL_Size &size);

Ke zjištění průniku našeho obdélníku s jiným obdélníkem můžeme použít metodu

CL_Rect calc_union(const CL_Rect &rect);

Ta vrátí příslušný obdélník odpovídající hledanému průniku. V případě, že se obdélníky neprotínají, bude mít výsledek buď left větší než right, nebo top větší než bottom. Metoda callc_union totiž přesněji řečeno vrací obdélník, jehož left je větší z leftů příslušných obdélníků (obdobně je to s top, right a bottom). Snad vše objasní obrázek:


Pokud chceme napravit situace typu levá souřadnice je víc vpravo než pravá souřadnice, které mohou vzniknout například použitím calc_union(), můžeme použít metodu

void normalize();

Tato metoda v případě potřeby prohodí left a right nebo top a bottom.

Třída CL_Rect má konstruktor bez parametrů, který vytvoří prázdný objekt, aniž by jakkoliv inicializoval hodnoty. Dalšími konstruktory jsou:

CL_Rect(int new_left, int new_top, int new_right, int new_bottom);
CL_Rect(const CL_Point &p, const CL_Size &size); 

Ty již samozřejmě vytvoří objekty odpovídající zadaným obdélníkům. Nechybí pochopitelně ani kopírovací konstruktor.

Kromě již popsaných metod definuje třída CL_Rect také několik užitečných operátorů definovaných následovně:

CL_Rect &operator+=(const CL_Rect &r)
{ left += r.left; top += r.top; right += r.right; bottom += r.bottom; return *this; } 

Cílové souřadnice obsahují součty zdrojových. To odpovídá posunutí danému vektorem s počátkem v (0, 0) a koncem v (r.left, r.top) a zvětšení hran o hrany r.

CL_Rect &operator-=(const CL_Rect &r)
{ left -= r.left; top -= r.top; right -= r.right; bottom -= r.bottom; return *this; } 

Cílové souřadnice obsahují rozdíl zdrojových souřadnic (naše – předaná). Tj. posunutí v opačném směru a zmenšení hran.

CL_Rect &operator+=(const CL_Point &p)
{ left += p.x; top += p.y; right += p.x; bottom += p.y; return *this; } 

X-ové (resp. y-ové) souřadnice zvětšíme o x-ovou (resp. y-ovou) souřadnici předaného bodu. To odpovídá posunutí danému vektorem s počátkem v (0, 0) a koncem v (p.x, p.y).

CL_Rect &operator-=(const CL_Point &p)
{ left -= p.x; top -= p.y; right -= p.x; bottom -= p.y; return *this; } 

Totéž co předchozí, avšak odečítáme, tj. posunujeme v opačném směru.

CL_Rect operator+(const CL_Rect &r) const
{ return CL_Rect(left + r.left, top + r.top, right + r.right, bottom + r.bottom); }

CL_Rect operator-(const CL_Rect &r) const
{ return CL_Rect(left - r.left, top - r.top, right - r.right, bottom - r.bottom); }

CL_Rect operator+(const CL_Point &p) const
{ return CL_Rect(left + p.x, top + p.y, right + p.x, bottom + p.y); }

CL_Rect operator-(const CL_Point &p) const
{ return CL_Rect(left - p.x, top - p.y, right - p.x, bottom - p.y); } 

Obdoby += resp -=, které nemodifikují náš objekt:

bool operator==(const CL_Rect &r) const
{ return (left == r.left && top == r.top && right == r.right && bottom && r.bottom); } 

Vrací true, pokud se všechny souřadnice shodují.

bool operator!=(const CL_Rect &r) const
{ return (left != r.left || top != r.top || right != r.right || bottom != r.bottom); } 

Vrací true, pokud se některá dvojice odpovídajících souřadnic nerovná.

root_podpora

Závěr

Myslím, že používání tříd jako CL_Rect může programování s ClanLibem velice zrychlit a zefektivnit, proto doufám, že se vám výše uvedené informace budou alespoň občas hodit. Podobných tříd jako CL_Rect nabízí ClanLib mnohem více. Příkladem budiž například CL_Rectf, což je obdoba CL_Rect pracující s typem float namísto int (názvy metod i jejich význam se shodují, takže jsme se naučili používat vlastně dvě třídy namísto jedné). Dalšími takovými třídami jsou CL_Point, CL_Size a jiné. Jejich popis budu podle uvážení čas od času zařazovat, abyste o nic nepřišli :-).

Příště bychom se už myslím mohli opět vrátit k tvorbě GUI.

Byl pro vás článek přínosný?