POPIS ŘEŠENÍ

 

Uložení dat v paměti

Hlavním problémem je uložení dat v paměti. Je důležité si uvědomit, že data budou co chvíli prohledávána, aby mohla být uživateli prezentována na obrazovku. Data se také budou často měnit, přidávat a rušit, což se nesmí projevit na rychlosti či dokonce způsobit zhroucení programu. Množství dat se také může rychle zvětšovat, takže informace musí být uloženy úsporně. Ideálním způsobem uložení dat je tedy spojový seznam, který si z paměti ukrojí právě tolik, kolik je potřeba. V Cuprexu se jedná vždy o obousměrný spojový seznam, aby bylo možné položky kdykoliv a kdekoliv rušit bez nutnosti znovu prohledávat celý seznam. Pro uložení dat je definována třída TCuprex, která vlastní hlavy všech seznamů dat, má metody pro vytváření a rušení dat a metody pro ukládání a načítání dat ze souboru. Tato třída se automaticky vytváří při otevření MDI editoru s parametrem názvu souboru. Jestliže soubor není nalezen, vytvoří se nový.

 

TBOD:

Základním prvkem v Cuprexu je bod. Bod představuje díru pro vývod součástky nebo třeba jen roh vodivé cesty, správnější by tedy bylo označovat bod jako uzel. V položce bod jsou uloženy souřadnice bodu, průměr díry a průměr vodivé plošky, atribut, ukazatel na skupinu bodů, do níž bod patří a samozřejmě ukazatelé na další a předchozí bod.

Body jsou uloženy v prvním spojovém seznamu jehož hlava je označena jako HlavniBod a je přístupná ze třídy TCuprex.

 

TSPOJ:

Definuje propojení kterýchkoliv dvou bodů. Spoj ukazuje na dva body ze seznamu bodů, takže stačí přesunout jeden bod a všechny spoje, které k němu směřují se také změní, aniž by k tomu bylo zapotřebí nějaký algoritmus. Dále spoj obsahuje informaci o tloušťce, atribut a ukazatel na další a předchozí spoj. Spoj nepatří do žádné skupiny, je zcela závislý na bodech.

Hlava seznam spojů je označena jako HlavniSpoj a je přístupná ze třídy TCuprex..

 

TOBRYS:

Nese informaci o obrysu součástky resp. skupiny, do které patří. Obsahuje další spojový seznam tzv. uzlů s hlavou HlavniUzel. Samotné uzly tvoří vrcholy uzavřeného polygonu. Všechny obrysy jsou uloženy v seznamu s hlavou HlavniObrys, přístupnou ze třídy TCuprex..

 

TUZEL:

Uzel v Cuprexu představuje část obrysu – jeden vrchol mnohoúhelníka, tvořícího obrys součástky, což je vlastně skupina bodů. Obrys bude vždy uzavřený, neboť poslední čára obrysu je vedena mezi posledním a prvním uzlem. Jak bylo popsáno výše, spojový seznam uzlů je uložen v každé položce TObrys, jeho hlava je HlavniUzel.

 

TSKUPINA:

Skupina reprezentuje seskupení bodů, například seskupení vývodů v jedné součástce. Samotná skupina neodkazuje na žádný bod ani spoj nebo obrys. Každý bod nebo obrys sám „ví“, k jaké skupině patří. Skupina má většinou jeden nebo více obrysů, ale také nemusí mít žádný. Každá skupina má své jméno a atribut, přičemž jméno je libovolný řetězec znaků, sloužící pouze pro identifikaci skupiny ze strany uživatele. Pro samotný Cuprex není jméno nijak důležité. Zajímavější je, že skupiny se mohou do sebe vnořovat jako uzly stromového seznamu. Skupina tedy obsahuje kromě ukazatelů na další a předchozí skupinu ukazatele na nadskupinu a podskupinu, resp. první podskupinu, neboť se samozřejmě jedná o další spojový seznam. Vrchol celého stromu je označen jako HlavniSkupina, je přístupný opět ze třídy TCuprex.

 

takhle nějak vypadá propojenost mezi daty Cuprexu

 

Zobrazení dat na obrazovce

Zobrazování dat má také svá úskalí. Musí proběhnout rychle, protože lze očekávat, že bude probíhat často. Nemá smysl pokoušet se zobrazovat data, která se nevejdou na obrazovku ani zobrazovat data, která se od posledního zobrazení nezměnila. Tyto dvě myšlenky respektuje při zobrazování i Cuprex, takže rychlost zobrazování je únosná.

 

V Delphi se k malování nabízí třída TCanvas, obsahující základní metody pro malování. Objekt Canvas obsluhuje třída TCanvasWriter, s metodou CuprexNaCanvas, jejímž parametrem je právě Canvas komponenty, na kterou chci Cuprex zobrazit. Dalším parametrem je záznam Pohled, obsahující základní informace o pohledu, jako jsou pozice pozorovatele, zvětšení, odkazy na aktivní entity, jež je třeba zvýraznit, informace o mřížce a jiné. Před zavoláním metody CuprexNaCanvas volám metodu SetOutputArea, která nastaví hranice, kam se má na Canvasu kreslit. Tento přístup je výhodný zejména při použití více pohledů a při tisku.

Při vykreslení celého Cuprexu je nutné projet seznamy bodů, spojů a obrysů, přičemž požadavek o nakreslení čáry směřuji na metodu LineScaled třídy TCanvasWriter.

Metoda LineScaled provede toto:

-         nalezne průsečíky zamýšlené čáry s okraji kreslící plochy (pokus jsou)

-         jestliže zamýšlená čára má průsečík s okrajem, ořízne vnější část čáry

-         nakonec zavolá metodu Canvasu pro nakreslení upravené čáry

S použitím tohoto postupu se CanvasWriter nepokouší kreslit čáry, které jsou mimo, takže ušetří nepatrný čas.

CanvasWriter má pro zobrazení další metodu a sice ZmenyNaCanvas. Tato metoda kreslí jen ty entity, u nichž došlo ke změně zvýraznění. Pokud však nějakou entitu posuneme, je nutné nakreslit celý Cuprex znovu, protože než by program zjistil, jaké další entity posunutím utrpěly je Cuprex dávno překreslen.

 

Základní jednotka, měřítko zobrazení

Důležitou funkcí každého grafického editoru je funkce ZOOM, protože na některé entity je někdy nutné podívat se zblízka. Cuprex má dvojí pojetí souřadnic, jednak pro vnitřní uchování – Sour, potom pro zobrazení – Pix. Pro přepočet souřadnic na obrazovku se používá metoda CanvasWriteru: SourNaPohled, která přepočítá souřadnice podle jednoduchého vztahu:

 

Pix = Round( (Sour * Měřítko) / (100% * UnitsInPixel) )

 

kde UnitsInPixel je počet základních jednotek na jeden pixel při měřítku zobrazení 100%.

Dále se podle potřeby přičte čí odečte poloha pohledu v souřadnicích. Typ Pix má jednotku pixel, typ Sour (dříve real nyní longint) je v mikrometrech. U plošného spoje by menší jednotka asi byla zbytečná a při rozsahu longint se s touto jednotkou dá teoreticky vytvořit plošný spoj velikosti stovek metrů.

 

Zaměřování entit myší

Když uživatel pohne s myší, automaticky se zvýrazní nejbližší spoj, nejbližší bod a nejbližší obrys. Tato samozřejmost si ve skutečnosti vyžádá prohlédnutí celého seznamu bodů, spojů a obrysů, přičemž pro každý prvek je vypočtena vzdálenost myši od entity a ta entita, která je myši nejblíže je vybrána jako aktivní.

Například nalezení nejbližšího spoje probíhá takto:

-         deklarujeme minimální vzdálenost bodu od entity Rmin

-         aktivní spoj nastavíme na nil

-         postupně prohledáváme celý seznam spojů a pro každý spoj:

o       derivací stanovíme nejmenší vzdálenost R myši od spoje

o       jestliže je tato vzdálenost menší než Rmin, aktivní spoj je současný a Rmin = R

 

Další zaměření, jímž uživatel dává najevo, že o entitu projevil zájem je označení. Oproti hledání nejbližších entit jde o primitivní přiřazení, kdy se aktivní entitě přidá atribut caSelected, při dalším vykreslení je entita zvýrazněna (jinak než při nalezení). U spojů existuje ještě jeden způsob zvýraznění, kde se zvýrazní celá větev, což může pomoci zorientovat se v rozsáhlejších spojích. Takové zvýraznění je provedeno rekurzí, přičemž se vždy ke koncovým bodům spoje hledají další spoje, které bod také používají. Pokud takový spoj není označen, označí se a hledají se zase spoje k jeho bodům.

Veškeré zaměřování zajišťuje opět třída TCanvasWriter.

 

Přesun entit

Přesun entit po Cuprexu je vlastně jen změna jejich souřadnic. Uživatel může přesunovat entity libovolných typů, aniž by na entitu cokoliv ukazovalo. Ukazuje se pouze na souřadnice entit. Je-li entita zaměřena, ukazatelé AktivniX a AktivniY se nasměrují na jejich souřadnice. Při přesunu se ukazatelé na aktivní souřadnice zamknou tak, že se proměnná AktivniXYLocked nastaví na TRUE a to proto, aby Vám dragovaná entita „nepadala“ z ruky. Během přesunu se pouze nastavují souřadnice myši, převedené na Sour, jako AktivniX^ a AktivniY^. Po přesunu se AktivniXYLocked odemkne.

 

Uspořádání tříd

Po spuštění programu objekt Application vytvoří objekt CuprexMAIN, což je hlavní formulář. Jedná se o MDI formulář, který umožňuje otevírání více souborů do jednotlivých MDI oken. Po otevření nebo vytvoření nového souboru CuprexMAIN vytvoří CuprexEDITOR (MDI child) s parametrem jména souboru. CuprexEDITOR hned po vytvoření vytvoří MyCuprex, také s parametrem souboru, který dostal, dále vytvoří CanvasWriter, což je třída sloužící k zobrazení dat na libovolný Canvas, aby CanvasWriter věděl, co má zobrazovat, předá mu odkaz na MyCuprex. Nakonec vytvoří MyPohledAsistent - minitřídu, starající se o jednotlivé pohledy. PohledAsistent si uchovává spojový seznam otevřených pohledů a vznikl z potřeby hromadného překreslení všech pohledů.

Pakliže uživatel otevře nový pohled, zavolá se PohledAsistent, aby pohled vytvořil. Když ho vytvoří, předá mu na sebe odkaz, takže pohled při změně ví na koho se obrátit. Dále Pohled obdrží ukazatel na CanvasWriter, z něhož může vymámit ukazatel na Cuprex. Pohled po svém vytvoření dynamicky vytvoří komponentu WorkBox a předá jí ukazatel na CanvasWriter. WorkBox je třída komponenty, odvozené z třídy TCustomControl, na její Canvas se zobrazuje Cuprex.

 

tento obrázek neznázorňuje hierarchii tříd, nýbrž jejich uspořádání a postup jejich vytváření.