Ukázková zkoušková úloha: Geometrické konstrukce
Představte si, že píšete knihu o geometrii a potřebujete do ní přidat obrázky různých geometrických konstrukcí. Protože obrázků potřebujete hodně a nechcete je kreslit ručně, napište program, který je za vás vygeneruje.
Vstup programu je popis geometrické konstrukce (body, přímky, kružnice) a výstupem by měl být obrázek. Pro kreslení použijeme nějakou knihovnu, abychom to nemuseli dělat ručně, například v C# můžeme použít třídu Graphics
ze System.Drawing
a její metody DrawLine
(čára mezi dvěma body), DrawEllipse
(kružnice), FillEllipse
(bod = vyplněný kruh), …
Příklad výstupu (převzatý z Gergelitsová, Holan: The Golden Ratio Determined Using a Ruler and Compass):
Části řešení
- upřesnění zadání
- postřehy
- volba algoritmu
- reprezentace dat
- dekompozice
- diskuze – co šlo dělat jinak
Upřesnění zadání
Geometrická konstrukce je popsaná pomocí následujících operací:
- bod zadaný pomocí souřadnic (např.
point A 0 1
), - přímka zadaná pomocí dvou bodů (např.
line p1 A B
), - kružnice zadaná pomocí středu a poloměru – poloměr je vzdálenost dvou bodů (např.
circle k1 A A B
), - kružnice zadaná pomocí dvou bodů – střed a bod ležící na kružnici (např.
circle k2 B A
), - bod jako průsečík dvou přímek nebo kružnic (např.
point C p1 k2
).
Řešení (část)
Rovnice přímky ze dvou bodů
Nechť máme body \[ A = (A_x, A_y),\quad B = (B_x, B_y). \]
- Výpočet směrnice: \[ m = \frac{B_y - A_y}{B_x - A_x} \]
- Směrnicová rovnice přímky: \[ y= m(x - A_x) + A_y \]
- Převod na obecný tvar \((a x + b y + c = 0)\): \[ m x - y + (A_y - m A_x) = 0 \]
- Odstranění zlomků násobením \((B_x - A_x)\): \[ (B_y - A_y) x + (- B_x + A_x) y+\bigl(A_y(B_x - A_x)-A_x(B_y-A_y)\bigr)=0 \]
- Koeficienty obecné rovnice přímky: \[ a = B_y - A_y,\quad b = A_x - B_x,\quad c = B_x A_y - A_x B_y \]
Rovnice kružnice ze středu a poloměru
Nechť střed kružnice je \( S = (S_x, S_y) \) a poloměr \(r\). Pak platí \[ (x - S_x)^2 + (y - S_y)^2 = r^2 \]
Pokud známe bod \(P=(P_x,P_y)\) na kružnici (místo poloměru), pak \[ r = \sqrt{(P_x - S_x)^2 + (P_y - S_y)^2} \]
Průsečík dvou přímek
Mějme dvě přímky \[ p_1: a_1 x + b_1 y + c_1 = 0, \quad p_2: a_2 x + b_2 y + c_2 = 0 \] Řešíme soustavu lineárních rovnic
- Spočítáme determinant \[ D = \begin{vmatrix} a_1 & b_1\\ a_2 & b_2 \end{vmatrix} = a_1 b_2 - a_2 b_1 \] Pokud \(D = 0\), přímky jsou rovnoběžné nebo totožné (tedy nemají jeden průsečík).
- Použijeme Cramerovo pravidlo \[ x = \frac{ \begin{vmatrix} -c_1 & b_1\\ -c_2 & b_2 \end{vmatrix} }{D} = \frac{b_1 c_2 - b_2 c_1}{D} \] \[ y = \frac{ \begin{vmatrix} a_1 & -c_1\\ a_2 & -c_2 \end{vmatrix} }{D} = \frac{a_2 c_1 - a_1 c_2}{D} \]
Průsečík kružnice a přímky
Nechť máme kružnici \[ (x - S_x)^2 + (y - S_y)^2 = r^2 \] a přímku \[ a x + b y + c = 0 \]
A) Obecná přímka (nenulové \(b\))
- Vyjádříme \(y\) z přímky: \[ y = m x + k, \quad m = -\frac{a}{b}, k = -\frac{c}{b}. \]
- Dosadíme do rovnice kružnice: \[ (x - S_x)^2 + (m x + k - S_y)^2 = r^2 \]
- Rozepíšeme: \[ x^2 - 2S_x x + S_x^2 + m^2 x^2 + 2m(k - S_y)x + (k - S_y)^2 = r^2. \]
- Sestavíme kvadratickou rovnici \[ (1 + m^2)x^2 + (-2S_x + 2m(k - S_y))x + (S_x^2 + (k - S_y)^2 - r^2) = 0 \]
- Řešíme standardně pomocí diskriminantu \[ x = \frac{-B \pm \sqrt{B^2 - 4AC}}{2A},\quad y = m x + k \] kde \[ A = 1 + m^2,\quad B = -2S_x + 2m(k - S_y),\quad C = S_x^2 + (k - S_y)^2 - r^2 \]
B) Vertikální přímka \((b=0)\)
- Rovnice přímky je: \(x = -\tfrac{c}{a}\)
- Dosadíme do rovnice kružnice: \[ \Bigl(-\tfrac{c}{a} - S_x\Bigr)^{2} + (y - S_y)^{2} = r^{2} \]
- Upravíme na kvadratickou rovnici: \[ y^2 - (2S_y)y + \Bigl(S_y^2 - r^2 + (-\tfrac{c}{a} - S_x)^2\Bigr) = 0 \]
- Řešíme standardně pomocí diskriminantu
Průsečík dvou kružnic
Nechť máme kružnice
\[
(x - S_x)^2 + (y - S_y)^2 = s^2,
\quad
(x - R_x)^2 + (y - R_y)^2 = r^2
\]
- Odečteme druhou rovnici od první \[ (x - S_x)^2 + (y - S_y)^2 \;-\; (x - R_x)^2 - (y - R_y)^2 = s^2 - r^2 \]
- Po roznásobení a upravení dostaneme lineární rovnici (kvadratické členy se odečtou):
\[
x\,(R_x - S_x) + y\,(R_y - S_y)
- \frac{s^2 - r^2 + R_x^2 + R_y^2 - S_x^2 - S_y^2}{2} = 0 \]
- Tato rovnice představuje přímku. Můžeme tedy spočítat její průsečík s libovolnou z původních kružnic (algoritmem výše) a dostaneme průsečík dvou kružnic.