Bublina - algoritmus koule

Pravidlo č. 1)

Předpočítat co nejvíce hodnot předem. Při vykreslování už jen použijeme vypočtené hodnoty.

 

Celý níže uvedený postup je vlastně 3D koule v prostoru a její jednotlivé pixely přenesené do 2D plochy - na papír.

 

Začneme samotnou kružnicí

Abych dokázal nakreslit kouli, musím umět nakreslit kružnici.

Vyjdu ze vzorce:

r2 = x2 + y2

 

a v cyklu

y=1, y< Poloměr koule*2

 (poloměr koule je dán, je to jediná fixně zadaná hodnota - velikost koule)

vypočítám veškeré hodnoty, které budu používat.

tj.

PoloměrKružnicevŘezu = Math.Sqrt ( PolomerKoule2 - ( PolomerKoule - y)2 )

Říká, kolik bodů je v každém řezu kružnice(*2, jde o poloměr). Pro každý takový bod budu potom počítat velikost kruhové výseče, jak v ose X, tak ose Y. Tj. samotnou deformaci.

 

ObvodKružnicevŘezu = 2 * π * PoloměrKružnicevŘezu

 Aby byla koule koulí a ne bramborou, potřebuji tuto hodnotu. Velikost kruhového oblouku se vztahuje k prostorovému objektu. My máme ale 2D monitory a tak musím ve výsledku obvod kružnice dostat do správného měřítka. Do správného poměru. viz hodnota PoměrX

 

PočetPixelůkZačátkuKružnice = PolomerKoule - PoloměrKružnicevŘezu

Pro samotné vykreslení kružnice. Na této pozici začínám kreslit kouli. 

 

 PoměrX = (PoloměrKružnicevŘezu * 2) / (ObvodKružnicevŘezu / 2)

 Hodnota o které jsem mluvil. Délka kruhové výseče * tento poměř = index do bitmapy.

 

Nyní mám kružnici, přejdu k výpočtu samotných kruhových oblouků.

Kruhový oblouk, to je to zelené a červené :)

 

Bublina Fig1

 

Procházíme všechny řezy koule.Nejprve v ose Y, potom v ose X.

V každém takovém řezu spočítáme velikost kruhového oblouku pro každý bod poloměru kružnice v řezu.

Dále tuto hodnotu vynásobím poměremX a mám ukazatel do bitmapy pro každý bod kružnice.

 

Velice důležité jsou hodnoty p1 a p2, což jsou nezbytné pomocné proměnné, které budou níže použity při překlopení os X a Y.  Jde vlastně o výpočet okrajů. Bude vysvětleno podrobněji níže.

 

Začneme tedy osou Y:

 

Základní cyklus, směr odshora dolů a zleva doprava do půlky koule.

y=1; y< poloměr koule*2

   zde počítám všechny proměnné jako:

PoloměrKružnicevŘezu, ObvodKružnicevŘezu , PočetPixelůkZačátkuKružnice , PoměrX 

 

   x=0; x< PolomerKruznicVrezu

 Procházím všechny body řezu koule a počítám výseče.

 

Ty šipky naznačují jednotlivé cykly.

 

 

Bublina Fig2

Obrázek b) je vlastně pohled shora.

 

Abychom mohli spočítat kruhovou výšeč, musíme pro ně znát jednotlivé uhly.

v jednom cyklu počítáme najednou levou a pravou stranu.

 

Pro levou to je

COS alfa = přilehlá ku přeponě

alfa = ACOS (PoloměrKružnicevŘezu - x) / PoloměrKružnicevŘezu

L = (ObvodKružnicevŘezu / 2π) * alfa

LcacheX[y,  x] = L * PoměrX ; 

 

Pro pravou to je

SIN beta = protilehlá ku přeponě

beta = ASIN (x / PoloměrKružnicevŘezu)

 L = (ObvodKružnicevŘezu / 2π) * beta

k hodnotě L ale ještě připočteme 1/4 obvodu kružnice, protože potřebujeme celou délku oblouku, viz dlouhá zelená čára.

 

ukládáme do bufferu takto:

LcacheX[y,  x + PoloměrKružnicevŘezu] = (L + ObvodKružnicevŘezu /4)  * PoměrX ; 

 

Už nyní bychom mohli výsledek zobrazit. Kulovitý efekt se projeví již nyní. My se ale s deformací jen v ose X nespokojíme a zdeformujeme i Y :) Viz obrázek c)

 

Bublina Fig3

 

Výpočet je naprosto identický, jen osově převrácený. Má to ale jeden háček a to jsou okraje.

Musí být vypočítány kvůli správnému uložení na pozici bufferu.

 

 

Spodní okraj je stejný pro celý cyklus.

SpodníOkraj = PoloměrKoule - PoloměrKružnicevŘezu

Levý okraj se počítá extra pro každý bod zvlášt

 

Modifikovaný výpočet délky kruhového oblouku

 

Oblouk podle spodní části obrázku

Pro to je

COS alfa = přilehlá ku přeponě

alfa = ACOS (PoloměrKružnicevŘezu - x) / PoloměrKružnicevŘezu

LevýOkraj = PoloměrKoule  - SQRT ( PoloměrKoule2 - ( r- x )2  )

L = (ObvodKružnicevŘezu / 2π) * alfa

LcacheY[SpodníOkraj  + x, y - LevýOkraj ] = L * PoměrY + SpodníOkraj  

zde si povšimněte prohození os. X ukládám do Y a Y do X.

 

 

Oblouk podle horní části obrázku

SIN beta = protilehlá ku přeponě

beta = ASIN (x / PoloměrKružnicevŘezu)

LevýOkraj = PoloměrKoule  - SQRT ( PoloměrKoule2 - x2  )

L = (ObvodKružnicevŘezu / 2π) * beta

 

k hodnotě L ale ještě připočteme 1/4 obvodu kružnice, protože potřebujeme celou délku oblouku, viz dlouhá zelená čára.

 

ukládáme do bufferu takto:

LcacheY[SpodníOkraj + x +   PoloměrKružnicevŘezu, y - LevýOkraj ] = (L + ObvodKružnicevŘezu /4)  * PoměrY +  SpodníOkraj

 

Je to trochu komplikované, člověk se v tom snadno ztratí. Sám jsem musel využít mozkovou kapacitu do posledního neuronu, abych to všechno vymyslel :) Pro lepší pochopení ještě jedno schéma.

 

Algoritmus počítá kruhové oblouky a ukládá je do dvou rozměrného pole[y,x]

jenže to X začíná v poli na hodnotě 0 a tak jsou ty oblouky v poli uložené tak, jak ukazuje zelená čára níže.

Tak jak je ukládám, tak je potom i čtu a samotnou kouli vykresluji.

Když počítám tu obrácenou osu, musím toto uložení / vykreslování respektovat, musím posunout okraje. Ty deformace v obou osách musí odpovídat identické hodnotě X, Y.

 

Ještě k samotnému vykreslování.

Jak už obrázek napovídá, jsou to dva vnořené cykly.

y=1; y< poloměr koule*2

x=0; x< PolomerKruznicVrezu

Lx = lcacheX[ y, x ];
Ly = lcacheY[ y, x ];

barva = BmpArraySrc[PoziceY + Ly  , PoziceX + Lx + PočetPixelůkZačátkuKružnice ]

 

 Závěrem : Možná by bylo lepší, ukládat ty oblouky do pole ne od 0, ale na pozici, kde začíná kružnice. Odpadly by pak komplikace s okraji. Asi ano. No, to už nechám k posouzení koňovi. Za mě hotovo

 

Bublina Fig4

 

 

 

 




Kontakt T: 224 550 551 M: 724 085 607 E: info@bura.cz

© Bura.cz