05. Geometria na kružnici
Úloha 1
Na rozcvičenie, vytvorte program, ktorý vygeneruje 2 náhodné pozície na obrazovke, na prvú pozíciu vykreslí zelený krúžok, na druhú pozíciu červený krúžok. Použite vektory.

Rozšírte program tak, aby medzi týmito dvomi pozíciami nakreslil 5 menších bodov:

Úloha 2
Program v Úlohe 1 funguje tak, že má daný počet dielikov a podľa neho vyrátava dĺžku jedného dieliku medzi a
a b
. Čo ak by sme chceli, aby bola pevne daná vzdialenosť dielikov a podľa nej by sme vypočítali počet dielikov?

Budeme potrebovať vypočítať dĺžku trasy medzi a
a b
a vydeliť ju dĺžkou jedného dielika.
Na výpočet celej dĺžky medzi a a b použijeme funkciu mag:
float celaDlzka = PVector.sub(b,a).mag();
Potom vypočítame počet krúžkov ako celá deleno dĺžka dielika. A k tomu ešte pripočítame 1, lebo počet krúžkov je o 1 viac ako počet dielikov:
int n = int( celaDlzka/dlzkaDielika) + 1;
Tu je celý kód:
// Dlzka jedneho dielika
float dlzkaDielika = 10;
size(400, 400);
background(0);
// Dve nahodne pozicie: a, b
PVector a = new PVector(random(width), random(height));
PVector b = new PVector(random(width), random(height));
// Vykreslenie a
fill(0,255,0);
circle(a.x, a.y, 30);
// Vykreslenie b
fill(255, 0, 0);
circle(b.x, b.y, 30);
// Vypocet poctu kruzkov medzi a a b
float celaDlzka = PVector.sub(b,a).mag();
int n = int( celaDlzka/dlzkaDielika) + 1;
// Jeden dielik cesty medzi a a b
PVector d = PVector.sub(b,a).div(n-1);
// Vykreslenie postupne kruzkov medzi a a b
for (int i = 0; i < n; i++)
{
// Pozicia i-teho kruzku: p = a + d*i
PVector p = PVector.add(a, PVector.mult(d, i));
// Vykreslenie kruzku
fill(255);
circle(p.x, p.y, 10);
}
Geometria na kružnici
Doterajšie úlohy boli zamerané na pohyb a rozmiestňovanie bodov na úsečke, alebo smerom, ktorý je zarovnaný s osami X a Y. Napríklad takto sme vykreslili 10 čísel vedľa seba:
size(400, 200);
background(0);
int n = 10; // Pocet cisel
float dx = 30; // Dielik o ktory sa posuvame na osi x
for (int i = 0; i < n; i++)
{
float x = dx * i; // x pozicia
float y = 100; // y pozicia
text( i, x, y); // Vypisanie textu i na poziciu x,y
}

Keby sme chceli tieto čísla vypísať nie vedľa seba horizontálne, ale dokola na kružnicu, tak nám už doterajšie znalosti nevystačia a musíme sa naučit niečo nové. Skúste tento kód:
size(400, 400);
background(0);
int n = 10; // Pocet cisel
float du = 0.4; // Dielik o ktory sa posuvame po kruznici
PVector c = new PVector(width/2, height/2); // Stred
float r = 150; // Polomer
for (int i = 0; i < n; i++)
{
float x = c.x + r * cos(du * i);
float y = c.y + r * sin(du * i);
text( i, x, y);
}

Karteziánske a polárne súradnice
Doteraz sme na zadefinovanie pozície nejakého objektu používali súradnice x,y a vystačili sme si s tým. X znamenalo ako ďaleko je bod od ľavého okraja obrazovky. Y znamenalo ako ďaleko je bod od horného okraja obrazovky. Tomu sa hovorí aj pravouhlé alebo karteziánske súradnice:

Pri rozmiestňovaní bodov na kružnicu nám prídu vhod iné súradnice. Nie také, ktoré sú pravouhlé, ale také, ktoré vyjadrujú vzdialenosť bodu od stredu kružnice a uhol o koľko je bod otočený:

Súradnice, ktoré popisujú polohu bodu pomocou stredu kružnice, polomeru tejto kružnice a uhla na tejto kružnici, sa volajú aj polárne.
Ak máte takto pomocou stredu C, uhla u, a polomeru r vyjadrenú polohu bodu, tak vieme robiť veci ako:
otáčať bodom, ak meníme hodnotu uhla u.
približovať a vzdaľovať bod k stredu, ak meníme hodnotu polomera r.
Keď chceme vykresľovať na obrazovku, tak budeme ale tak či tak potrebovať z polárnych súradníc na kruhu prejsť do karteziánskych na obrazovke, lebo obrazovka pozostáva z pixelov v pravouhlej karteziánskej mriežke a Processing od nás očakáva súradnice príkazov ako rect()
, ellipse()
alebo text()
v tejto pixelovej mriežke.
Ak poznáme stred C, polomer r a uhol u, tak z toho vieme vypočítať hodnoty x,y na obrazovke nasledovne:
float x = C.x + r * cos(u);
float y = C.y + r * sin(u);
Úloha 3
Tu je jednoduchý program na vyskúšanie. Meňte v programe hodnoty stredu polomeru r a uhla u a sledujte ako sa mení výsledok.
size(400, 400);
background(0);
fill(255);
// Polarne suradnice bodu
PVector C = new PVector(width/2, height/2); // Stred je v strede obrazovky
float r = 50; // Polomer
float u = 4; // Uhol
// Vypocet pozicie na obrazovke
float x = C.x + r * cos(u);
float y = C.y + r * sin(u);
// Vykreslenie bodu
circle(x, y, 10);
text("P", x-10,y-10);
// Pre nazornost vykreslime aj stred a kruznicu:
text("C", C.x, C.y);
stroke(#FFAB03);
noFill();
circle(C.x, C.y, 2*r);

Nájdite také hodnoty u
a r
, aby ste umiestnili bod P na nasledujúce pozície:
Koľko má kruh dokola?
Asi ste prišli na to, že na pravom okraji kružnice je uhol u = 0
. Na spodný okraj to bolo ťažšie nájsť, ale ak ste prišli na niečo ako u = 1.55
, tak ste skoro trafili.
Celý kruh dokola má 360°, ale Processing nefunguje v stupňoch. Processing funguje v tzv. radiánoch, alebo inými slovami, dokola celého kruhu nie je uhol veľký 360 ale je to uhol veľký 2*PI
. Polovica kruhu je PI
a štvrtina kruhu je PI/2
. Celý kruh má dokola 2*PI
a je to taký istý uhol ako 0
.

Rozmiestnenie na kružnici
Keď už vieme, aký veľký uhol je dokola celej kružnice, môžeme tento uhol rozdeliť na rovnaké uhlové dieliky a rozmiestňovať objekty na kružnici:
size(400, 400);
background(0);
fill(255);
PVector C = new PVector(width/2, height/2);
float r = width/3;
int n = 18; // Pocet objektov
float du = 2*PI/n; // Jeden dielik
for (int i = 0; i < n; i++)
{
float u = i*du; // Uhol je i krat dielik
float x = C.x + r * cos(u);
float y = C.y + r * sin(u);
circle(x,y,10);
}

Úloha 4
Upravte predošlý program tak, aby namiesto krúžkov vypisoval čísla od 1 do 12

Otáčanie po kružnici
V predošlej úlohe ste vytvorili niečo ako ciferník hodín. Lenže ozajstné hodiny majú hore číslo 12 a tieto naše hodiny majú hore číslo 10. Potrebovali by sme pootočiť súradnice po kružnici tak, aby 12ka bola hore.
Keď vo výpočte súradníc:
float x = C.x + r * cos(u);
float y = C.y + r * sin(u);
Pridáme dovnútra funkcií cos
a sin
nejaký uhol navyše, docielime otočenie o tento uhol. Napríklad tu sme pridali uhol PI/4
, čo je 45°:
float x = C.x + r * cos(u + PI/4);
float y = C.y + r * sin(u + PI/4);

Úloha 5
Skúšajte pridávať rôzne uhly. Do ktorého smeru otáčajú hodiny kladné uhly? Do ktorého smeru otáčajú kružnicu záporné uhly?
Úloha 6
Vymyslite, o aký uhol potrebujeme pootočiť náš program, aby mali hodiny 12ku hore:

Animácia po kružnici
Keď vieme pridávaním uhla otáčať polohy bodov na kružnici, vieme tento pridávaný uhol v animácii aj meniť a docieliť tak otáčanie. Tu je jednoduchý skeč so setup()
a draw()
, ktorý vykreslí zatiaľ len statický bod:
PVector C;
float u = 0;
float r = 150;
void setup()
{
size(400,400);
C = new PVector(width/2, height/2);
}
void draw()
{
background(0);
float x = C.x + r * cos(u);
float y = C.y + r * sin(u);
circle(x,y,20);
}

Uhol u
môžem teraz v draw()
postupne zvyšovať a sledujme animáciu:
void draw()
{
background(0);
float x = C.x + r * cos(u);
float y = C.y + r * sin(u);
circle(x,y,20);
u = u + 0.05;
}

Úloha 7
Upravte predošlý program tak, aby sa bod otáčal v opačnom smere a pomalšie:

Úloha 8
Napíšte nový skeč, ktorý vykreslí na obvode kružnice 15 bodov. Pridajte do cos()
a sin()
animovaný uhol tak, aby sa otáčali:

Pohyb po špirále
Keď už vieme kružnicu, je jednoduché naučiť sa aj špirálu. Špirála je ako kružnica, ale postupne sa jej zväčšuje polomer. Začnime od programu z Úlohy 7:
PVector C;
float u = 0;
float r = 150;
void setup()
{
size(400,400);
C = new PVector(width/2, height/2);
}
void draw()
{
background(0);
float x = C.x + r * cos(u);
float y = C.y + r * sin(u);
circle(x,y,20);
u = u - 0.01;
}
A upravme tento program tak, aby polomer r
začínal nie na hodnote 150
, ale na 0
:
PVector C;
float u = 0;
float r = 0;
A postupne v draw()
ho budeme zväčšovať, podobne ako meníme u
:
void draw()
{
background(0);
float x = C.x + r * cos(u);
float y = C.y + r * sin(u);
circle(x,y,20);
u = u - 0.01;
r = r + 0.2;
}
Docielime tak, že sa bod nepohybuje po kružnici, ale po špirále:

Úloha 9
Upravte Úlohu 8 tak, aby sa body nehýbali po kružnici, ale po špirále:

Spájanie bodov
Už vieme, že ak si kruh rozdelíme na n
dielikov, tak vo for
cykle vieme vypočítať i-tu pozíciu v poradí takto:
float du = 2*PI/n;
for (int i = 0; i < n; i++)
{
float x = C.x + r * cos(i*du);
float y = C.y + r * sin(i*du);
circle(x,y,20);
}
Vieme tak vykresliť izolovaných n
bodov na kružnici. Čo ak ich chceme pospájať? To znamená, že nakresliť čiaru medzi i
-tym bodom a i+prvým
bodom.
Vytvoríme si druhú dvojicu súradníc a vypočítame ich polohu tak, že namiesto i
použijeme (i+1)
:
float du = 2*PI/n;
for (int i = 0; i < n; i++)
{
float x1 = C.x + r * cos(i*du);
float y1 = C.y + r * sin(i*du);
float x2 = C.x + r * cos((i+1)*du);
float y2 = C.y + r * sin((i+1)*du);
line(x1, y1, x2, y2);
}
Úloha 10
Vytvorte skeč, ktorý nakreslí po obvode kružnice n
bodov a pospája ich čiarami.

Úloha 11
Vytvorte program, ktorý vykreslí päťuholník:

Úloha 12
Upravte uhly tak, aby mal päťuholník vrchol nahor:

Pospájaná špirála
Keď sme chceli vypočítať nasledujúci bod po i
-tom bode, tak sme vo vzorci na výpočet súradníc zväčšili i
na i+1
. Ak by tieto body boli na špirále, tak musíme pri druhom bode zväčšiť aj r:
size(400, 400);
background(0);
stroke(255);
PVector C = new PVector(width/2, height/2);
float r = 0;
int n = 20;
float du = 2*PI/n;
float dr = 5; // O kolko sa zvacsuje r v kazdom kroku
for (int i = 0; i < n; i++)
{
float x1 = C.x + r * cos(i*du);
float y1 = C.y + r * sin(i*du);
float x2 = C.x + (r+dr) * cos((i+1)*du);
float y2 = C.y + (r+dr) * sin((i+1)*du);
line(x1, y1, x2, y2);
r = r + dr;
}

Úloha 13
Upravte for
cyklus v programe tak, aby nešiel iba do i<n
ale až do i<3*n
. Čo to urobí so špirálou?

Skúšajte rôzne kombinácie počtu otáčok a hrúbky špirály dr
.

Last updated