Commit d5228013 authored by Radek Ošlejšek's avatar Radek Ošlejšek
Browse files

Adjusted assignement. Circumcircle renamed to Circular. Added UML model.

parent 8b08a6ef
## Čtvrtá iterace
Cvičení zaměřené na statické metody, implementaci a použití rozhraní.
Cvičení zaměřené na statické metody, implementaci a použití rozhraní. Cílový UML diagram tříd vypadá následovně:
1. Vytvořte třídu `SimpleMath` v balíku `cz.muni.fi.pb162.project.utils`.
* Třída bude implementovat pouze _statické_ metody.
* Statická metoda `double minX(Triangle triangle)` vrátí nejmenší X-ovou souřadnici.
* Statická metoda `double minY(Triangle triangle)` vrátí nejmenší Y-ovou souřadnici.
![UML diagram tříd](images/04-class-diagram.png)
1. Vytvořte třídu `SimpleMath` v balíku `cz.muni.fi.pb162.project.utils` obsahující výhradně _statické_ metody (tzv. _utility class_)
* `double minX(Triangle triangle)` vrátí nejmenší X-ovou souřadnici.
* `double minY(Triangle triangle)` vrátí nejmenší Y-ovou souřadnici.
* Obdobně pro metody `maxX` a `maxY`.
* Trojúhelník neobsahuje `null` prvky.
......@@ -16,43 +18,45 @@ Cvičení zaměřené na statické metody, implementaci a použití rozhraní.
![šířka objektů](images/04a.png)
* Využijte statické metody ze třídy `SimpleMath`.
3. V balíku `utils` vytvořte třídu `Gauger` ("měřidlo") se dvěma statickými přetíženými metodami `printMeasurement`:
3. V balíku `utils` vytvořte třídu `Gauger` (_měřidlo_), která umožní "změřit" objekty a vypsat informace o jejich výšce a šířce. Třída bude obsahovat dvě statické přetížené metody `printMeasurement`:
* První metoda vezme libovolný měřitelný objekt (tj. libovolný objekt implementující rozhraní `Measurable`) a
* na standardní výstup vypíše _"Width: \<w\>"_, kde \<w\> je hodnota šířky,
* na další řádek vypíše _"Height: \<h\>"_, kde \<h\> je hodnota výšky.
* Druhá metoda vezme trojúhelník (objekt typu `Triangle`) a
* na standardní výstup vypíše informace o objektu, viz metoda `toString()`,
* Druhá metoda bude speciálně pro trojúhelník (objekt typu `Triangle`). Vezme trojúhelník a
* na standardní výstup vypíše informace o trojúhelníku, viz metoda `toString()`,
* na další řádek vypíše _"Width: \<w\>"_, kde \<w\> je opět hodnota šířky,
* na další řádek vypíše _"Height: \<h\>"_, kde \<h\> je opět hodnota výšky.
* Vyhněte se opakování kódu tím, že druhá varianta metody bude volat tu první. Pozor ale, ať nevolá sebe sama.
Došlo by k zacyklení (`StackOverflowException`).
4. Třída `Circle` bude implementovat rozhraní `Circumcircle` (opsaná kružnice).
Opsanou kružnicí je kružnice sama, proto netřeba implementovat žádné nové metody.
Přidejte jenom anotaci `@Override`.
4. Třída `Circle` bude implementovat rozhraní `Circular` - kruhový tvar vyjádřený svým středem a poloměrem.
Kružnice přímo představuje kruhový tvar, proto netřeba implementovat žádné nové metody. Je ale nutné přidat anotaci `@Override`.
5. V balíku `geometry` vytvořte třídu `Square`, která reprezentuje čtverec otočený o 45°:
5. V balíku `geometry` vytvořte třídu `Square`. V našem pojetí nebude čtverec vyjádřený jako čtveřice vrcholů (jako je tomu u trojúhelníku),
ale jako kruhový tvar, jehož vrcholy můžeme kdykoliv vypočítat ze středu a poloměru (opsané kružnice).
Podobnost kruhu a čtverce zní možná trochu podivně, ale na auto si také můžete nasadit "čtveratá" kola namísto "kruhových".
Auto stále pojede, jen to bude o dost víc drncat :-)
* Třída bude implementovat rozhraní `Circular`:
* První konstruktor vezme jako vstupní parametry souřadnice středu opsané kružnice a **průměr** opsané kružnice.
* Druhý konstruktor vezme jako vstupní parametr objekt typu `Circumcircle` (obsahuje souřadnice středu a **poloměr**) a bude volat první konstruktor.
* Třída bude taky implementovat rozhraní `Circumcircle`:
* Metoda `Vertex2D getVertex(int index)` vrátí vrchol na daném indexu v pořadí: levý, dolní, pravý, horní.
Jestli je index mimo rozsah, vrátí metoda `null`.
* Druhý konstruktor vezme jako vstupní parametr objekt typu `Circular` (obsahuje souřadnice středu a **poloměr**) a bude volat první konstruktor.
* Metoda `Vertex2D getVertex(int index)` vrátí souřadnice `index`-tého vrcholu. Souřadnice se vypočítají automaticky ze středu a poloměru tak,
že budou reprezentovat čtverec otočený o 45°: Na indexu 0 je levý vrchol, 1 = dolní vrchol, 2 = pravý vrchol a 3 = horní vrchol.
Pokud je index mimo rozsah, vrátí metoda `null`.
* Nezapomeňte na metodu `toString()`:
"Square: vertices=[ax, ay] [bx, by] [cx, cy] [dx, dy]"
přičemž zpráva obsahuje jen 3 mezery mezi vrcholy.
6. V balíku `geometry` vytvořte třídu `Snowman`:
* Sněhulák se skládá ze **čtyř** opsaných kružnic.
Počet kružnic ale půjde lehce změnit v době překladu.
* Konstruktor bude jako svůj první parametr brát parametr typu `Circumcircle` (spodní kružnice), a jako druhý
parametr zmenšovací faktor (poloměru kružnice) pro kružnice nad ní (reálné číslo o rozsahu `(0..1>`).
6. V balíku `geometry` vytvořte třídu `Snowman` (_sněhulák_):
* Nás sněhulák se skládá ze **čtyř** jakýchkoliv kruhových (circular) objektů, tj. kružnic, čtverců, atd. postavených na sebe.
Počet půjde lehce změnit v době překladu. Sněhulák pro jednoduchost nemá ruce. Směrem nahoru se "koule" sněhuláka zmenšují.
* Konstruktor bude jako svůj první parametr brát parametr typu `Circular`, který představuje spodní kouli.
* Jako druhý parametr konstruktoru bude zmenšovací faktor (reálné číslo o rozsahu `(0..1>`). O tento faktor se budou zmenšovat horní části sněhuláka.
V případě, že vstupní parametr nebude z požadovaného rozsahu, použije se neveřejná pojmenovaná konstanta `0.8`.
* První kružnice je první argument konstruktoru, druhá bude položená na první s poloměrem zmenšeným o zmenšovací
faktor, třetí i čtvrtá kružnice bude vytvořena stejným způsobem.
* Celý sněhulák vznikne v konstruktoru, nebojte se ale kód rozdělit do menších privátních metod.
* Metoda `Circumcircle[] getBalls()` vrátí pole kružnic, od nejspodnější po nejvyšší (nejmenší).
* Celý sněhulák vznikne v konstruktoru. Bude složen z kruhového objektu, který jsme dostali. Nad ním budou kružnice (`Circle`) postupně se zmenšující o daný faktor.
* Nebojte se kód konstruktoru rozdělit do menších privátních metod.
* Metoda `Circular[] getBalls()` vrátí pole všech "koulí" od nejspodnější po nejvyšší.
7. Demo vytvoří čtverec se středem `[0, 0]`, průměrem kružnice `100` a vypíše o něm informace na standardní výstup.
......@@ -65,6 +69,5 @@ Cvičení zaměřené na statické metody, implementaci a použití rozhraní.
`Double.POSITIVE_INFINITY`/`Double.NEGATIVE_INFINITY`.
- Při implementaci metod rozhraní používejte anotaci `@Override`.
- Při volání `printMeasurement` je nutno přetypovat objekt na rozhraní. Dojde k tzv. "ořezání" metod.
- Konstruktor `Square` bere konkrétní implementace rozhraní `Circumcircle`, představte si tam např. `Circle`.
- V `Square` v metodě `toString` se dá použít `Stringbuilder` a pak metoda `String#trim()`.
- `Snowman` bude obsahovat konstantu udávající počet kružnic.
package cz.muni.fi.pb162.project.demo;
import cz.muni.fi.pb162.project.geometry.Circumcircle;
import cz.muni.fi.pb162.project.geometry.Snowman;
import cz.muni.fi.pb162.project.geometry.Square;
import cz.muni.fi.pb162.project.geometry.Vertex2D;
......@@ -13,6 +12,7 @@ import java.awt.Color;
import java.awt.Graphics;
import java.awt.Polygon;
import java.util.AbstractMap;
import cz.muni.fi.pb162.project.geometry.Circular;
/**
* Class drawing 2D objects.
......@@ -96,12 +96,12 @@ public final class Draw extends JFrame {
}
private void paintSnowman(Snowman snowman) {
for(Circumcircle c : snowman.getBalls()) {
for(Circular c : snowman.getBalls()) {
paintCircumcircle(c);
}
}
private void paintCircumcircle(Circumcircle c) {
private void paintCircumcircle(Circular c) {
int radius = (int) Math.rint(c.getRadius());
int x = PANEL_WIDTH - ((int) Math.rint(HALF_WIDTH - c.getCenter().getX()) + radius);
int y = (int) Math.rint(HALF_HEIGHT - c.getCenter().getY()) - radius;
......
......@@ -5,7 +5,7 @@ package cz.muni.fi.pb162.project.geometry;
*
* @author Marek Sabo
*/
public interface Circumcircle {
public interface Circular {
/**
* Returns the middle point of the circle.
......
......@@ -18,7 +18,7 @@ public class CircleTest {
private static final double RADIUS = 2.5;
private Circle circle;
public static void assertCircle(Circumcircle actual, Circumcircle expected) {
public static void assertCircle(Circular actual, Circular expected) {
assertThat(actual.getRadius()).isCloseTo(expected.getRadius(), within(0.001));
assertThat(actual.getCenter()).isEqualToComparingFieldByField(expected.getCenter());
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment